首页 文章

存储过程不返回受影响的行

提问于
浏览
0

这是(确切地说)我的一个存储过程 . 它在执行时不会返回受影响的行 . 所以我尝试运行整个查询,提供参数的给定值,然后返回一(1)个受影响的行 . 我想知道为什么它在存储过程中不会返回受影响的行 . 我还删除了SET NOCOUNT ON,这样就不会阻止额外的结果集干扰SELECT语句 . 请帮忙 .

这是执行语句

exec STOREPROCEDURENAME @levelnumber=1,@laborlevelid=7,@laborlevelreferenceid=0
go

和存储过程的内容

@levelnumber int = 0, 
@laborlevelid int = 0,
@laborlevelreferenceid int = 0

UPDATE LaborLevelReference SET
        LaborLevelID1 = (CASE WHEN @levelnumber = 0 THEN @laborlevelid ELSE LaborLevelID1 END),
        LaborLevelID2 = (CASE WHEN @levelnumber = 1 THEN @laborlevelid ELSE LaborLevelID2 END),
        LaborLevelID3 = (CASE WHEN @levelnumber = 2 THEN @laborlevelid ELSE LaborLevelID3 END),
        LaborLevelID4 = (CASE WHEN @levelnumber = 3 THEN @laborlevelid ELSE LaborLevelID4 END),
        LaborLevelID5 = (CASE WHEN @levelnumber = 4 THEN @laborlevelid ELSE LaborLevelID5 END),
        LaborLevelID6 = (CASE WHEN @levelnumber = 5 THEN @laborlevelid ELSE LaborLevelID6 END),
        LaborLevelID7 = (CASE WHEN @levelnumber = 6 THEN @laborlevelid ELSE LaborLevelID7 END),
        LaborLevelID8 = (CASE WHEN @levelnumber = 7 THEN @laborlevelid ELSE LaborLevelID8 END),
        LaborLevelID9 = (CASE WHEN @levelnumber = 8 THEN @laborlevelid ELSE LaborLevelID9 END),
        LaborLevelID10 = (CASE WHEN @levelnumber = 9 THEN @laborlevelid ELSE LaborLevelID10 END)
    WHERE LaborLevelReferenceID = @laborlevelreferenceid

2 回答

  • 0

    批量绑定(BULK COLLECT&FORALL)和Oracle中的记录处理

    虽然本主题涉及如何针对大型记录集优化数据库DML操作的更大讨论,但此方法适用于可变大小的记录卷,甚至还有一个很好的功能集,其中包含一个名为 SAVE EXCEPTIONS 的DML选项,它可以启用数据库操作到SKIP并继续经历遇到EXCEPTIONS的单个DML事务 .

    我已经改编了一个脚本并添加了一些额外的解释性符号来说明它是如何工作的 . 如果您想从我使用的源代码中获得一些额外的读数,请参阅以下链接以获取有关Oracle DML Bulk Binds and Record Processing的讨论 .

    示例表:exception_test

    使用DDL Below创建用于存储我们的过程的Bulk Binding DML命令中的数据的测试表:

    CREATE TABLE  "EXCEPTION_TEST" 
       (     "ID" NUMBER(15,0) NOT NULL ENABLE, 
         CONSTRAINT "EXCEPTION_TEST_PK" PRIMARY KEY ("ID") ENABLE
       )
    /
    

    主键是单列 . 它具有指定的NOT NULL约束,该约束将是稍后用于生成多个异常的属性 .

    存储过程:proc_exam_save_exceptions

    create or replace PROCEDURE proc_exam_save_exceptions IS
    
    -- Declare and Instantiate Data Types
      TYPE t_tab IS TABLE OF exception_test%ROWTYPE;
      l_tab          t_tab := t_tab();
      l_error_count  NUMBER;
    
      ex_dml_errors EXCEPTION;
      PRAGMA EXCEPTION_INIT(ex_dml_errors, -24381);
    
    BEGIN
    
      -- Fill the collection.
      FOR i IN 1 .. 2000 LOOP
        l_tab.extend;
        l_tab(l_tab.last).id := i;
      END LOOP;
    
    
      -- Cause a failure or two.
      l_tab(50).id   := NULL;
      l_tab(51).id   := NULL;
      l_tab(1250).id := NULL;
      l_tab(1252).id := NULL;
    
      EXECUTE IMMEDIATE 'TRUNCATE TABLE exception_test';
    
      -- Perform a bulk operation.
      BEGIN
    
        FORALL i IN l_tab.first .. l_tab.last SAVE EXCEPTIONS
          INSERT INTO exception_test
          VALUES l_tab(i);
    
    
      EXCEPTION
    
        WHEN ex_dml_errors THEN
          l_error_count := SQL%BULK_EXCEPTIONS.count;
          DBMS_OUTPUT.put_line('Number of failures: ' || l_error_count);
          FOR i IN 1 .. l_error_count LOOP
    
            DBMS_OUTPUT.put_line('Error: ' || i || 
              ' Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
              ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
    
          END LOOP;
       END;
    END;
    

    第一个循环实例化一个集合类型变量(嵌套表)并使用非null值初始化它 . 请注意此过程的块:

    -- Cause a failure or two.
    l_tab(50).id   := NULL;
    l_tab(51).id   := NULL;
    l_tab(1250).id := NULL;
    l_tab(1252).id := NULL;
    

    其中使用NULL值更改索引位置50,51,1250和1252以强制针对表exception_test上的ID列的表约束的DML错误 . 编译此过程并从命令行执行它会在DBMS OUT显示中显示一条反馈消息,用于标识每个循环迭代的内部计数失败的DML操作...

    测试存储过程

    调用该过程以迭代定义的DML循环并验证BULK EXCEPTION HANDLING功能是否正常工作 .

    -- Command to Call Procedure
    
    begin
       proc_exam_save_exceptions();
    end;
    

    以下是此过程执行的输出:

    Number of failures: 4
    Error: 1 Array Index: 50 Message: ORA-01400: cannot insert NULL into ()
    Error: 2 Array Index: 51 Message: ORA-01400: cannot insert NULL into ()
    Error: 3 Array Index: 1250 Message: ORA-01400: cannot insert NULL into ()
    Error: 4 Array Index: 1252 Message: ORA-01400: cannot insert NULL into ()
    
    Statement processed.
    
    0.05 seconds
    

    对目标表的附加查询显示,在循环迭代过程中引入的DML错误不会中断其他循环及其分配的DML操作的完成 .

    Sample Verification of Skipped Exception Values

    补充说明和讨论

    以下是使用 SAVE EXCEPTIONS Bulk DML选项时要记住的一些分离注意事项:

    • 结果集合的error_index值中的元信息: SQL%BULK_EXCEPTIONS 基于数据的初始游标查询的循环迭代计数 .

    即,您仍然需要以某种方式关联循环迭代#51(error_index = 51)中的错误与实际DML目标表中存在的任何标识键对齐 . 我建议至少在DML游标中仔细一致地使用ORDER BY子句,以便循环迭代始终与相同的索引/键值匹配 .

    • 对SAVE EXCEPTIONS和BULK DML处理备选方案的功能有一些额外的扩展,可能证明可以提供超过传统大卷DML操作方法的额外实用程序 . 其中包括:错误阈值限制(即,在处理预定义数量的DML异常时退出)和批量处理循环大小定义 .
  • 1

    感谢您努力帮助我的努力 . 但问题不在于查询或存储过程本身 . 我发现最终的错误是我的 STUPIDITY . 我将错误的值传递给参数 .

    @levelnumber int = 0, 
    @laborlevelid int = 0,
    @laborlevelreferenceid int = 0
    

    这是我能够跟踪的sql profiler执行语句

    exec STOREPROCEDURENAME @levelnumber=1,@laborlevelid=7,@laborlevelreferenceid=0
    go
    

    在我的程序函数中,我已经互换了 @levelnumber@laborlevelreferenceid 它们应该是这样的

    exec STOREPROCEDURENAME @levelnumber=0,@laborlevelid=7,@laborlevelreferenceid=1
    go
    

    存储过程不会返回任何受影响的行,因为没有 LaborLevelReferenceID (这是我的主键和自动增量)等于 0

    It was after all my fault. Thanks for the effort guys!

相关问题