这是(确切地说)我的一个存储过程。它在执行时不会返回受影响的行。所以我尝试运行整个查询,提供参数的给定值,然后返回一(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
答案 0 :(得分:1)
虽然本主题涉及如何针对大型记录集优化数据库DML操作的更大讨论,但此方法适用于不同大小的记录卷,甚至还有一个很好的功能集,其中包含一个名为的DML选项SAVE EXCEPTIONS ,它使数据库操作能够跳过SKIP并继续经历遇到EXCEPTIONS的单个DML事务。
我已经改编了一个脚本,并添加了一些额外的解释性符号来说明这是如何工作的。如果您希望从我使用的来源中获得一些额外的阅读材料,请参阅以下链接,了解有关Oracle DML Bulk Binds and Record Processing的讨论。
使用DDL Below创建用于存储来自我们的过程的批量绑定DML命令的数据的测试表:
CREATE TABLE "EXCEPTION_TEST"
( "ID" NUMBER(15,0) NOT NULL ENABLE,
CONSTRAINT "EXCEPTION_TEST_PK" PRIMARY KEY ("ID") ENABLE
)
/
主键是单列。它具有一个指定的NOT NULL约束,该约束将是稍后用于生成多个异常的属性。
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操作的完成。
以下是使用 SAVE EXCEPTIONS 批量DML选项时要记住的一些注意事项:
生成的集合的 error_index 值中的元信息: SQL%BULK_EXCEPTIONS 基于来自初始游标查询的循环迭代计数数据
即,您仍然需要以某种方式关联循环迭代#51(error_index = 51)中的错误与实际DML目标表中存在的任何标识键对齐。我建议至少在DML游标中仔细一致地使用ORDER BY子句,以便循环迭代始终与相同的索引/键值匹配。
SAVE EXCEPTIONS和BULK DML处理备选方案的功能还有一些额外的扩展,这些扩展可以证明可以提供超过大批量DML操作的传统方法的额外实用程序。其中包括:错误阈值限制(即,在处理预定义数量的DML异常时退出)和批量处理循环大小定义。
答案 1 :(得分:0)
感谢您努力帮助我。但问题不在于查询或存储过程本身。我发现最终的错误是我的愚蠢。我将错误的值传递给参数。
@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
毕竟是我的错。谢谢你的努力!