PLSQL IMPLICIT CURSOR 在 CURSOR 之后找不到数据
PLSQL IMPLICIT CURSOR No Data Found After CURSOR
我有一个工作正常的主光标。
declare
v_firm_id number;
amount number;
v_total_sum TABLE_TEMP.TOTAL_SUM%TYPE;
CURSOR MT_CURSOR IS
SELECT firm_id FROM t_firm;
BEGIN
OPEN MT_CURSOR;
LOOP
FETCH MT_CURSOR INTO v_firm_id;
EXIT WHEN MT_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(to_char(sysdate, 'mi:ss') ||'--- '|| v_firm_id)
INSERT INTO TABLE_TEMP(TOTAL_SUM) VALUES(v_firm_id)
COMMIT;
END LOOP;
DBMS_LOCK.SLEEP(20);
BEGIN
FOR loop_emp IN
(SELECT TOTAL_SUM INTO v_total_sum FROM TABLE_TEMP)
LOOP
dbms_output.put_line(to_char(sysdate, 'mi:ss') ||'--- '|| v_total_sum || '-TEST--');
END LOOP loop_emp;
END;
end;
一切正常,除了 dbms_output.put_line(v_total_sum || '---');
我在那里没有得到任何数据。我得到正确的行数。它插入了。
问题是游标 FOR 循环有一个冗余的 into
子句,它似乎被编译器默默地忽略了,因此从未使用过 v_total_sum
。
试试这个:
begin
for r in (
select firm_id from t_firm
)
loop
insert into table_temp (total_sum) values (r.firm_id);
end loop;
dbms_lock.sleep(20);
for r in (
select total_sum from table_temp
)
loop
dbms_output.put_line(r.total_sum || '---');
end loop;
commit;
end;
如果这是一个存储过程而不是匿名块,并且您使用 alter session set plsql_warnings = 'ENABLE:ALL';
(或 IDE 中的等效首选项设置)启用了 PL/SQL 编译器警告,那么您会看到:
PLW-05016: INTO clause should not be specified here
我还把 commit
移到了最后,所以你只提交一次。
总结下面的评论,游标 FOR 循环构造为您声明、打开、获取和关闭游标,并且可能更快,因为它以 100 个(或类似的 - 我最近没有测试过)版本)。更简单的代码出现错误的可能性更小,并且将来更容易维护,例如,如果您需要向游标添加一列。
注意原始版本有:
for loop_emp in (...)
loop
...
end loop loop_emp;
这是一种误导,因为 loop_emp
是 记录 的名称,而不是游标或循环。编译器忽略了 end loop
之后的文本,尽管它至少应该警告您。如果您想为循环命名,可以在其上方使用 label like <<LOOP_EMP>>
。 (我总是将我的循环记录命名为 r
,类似于您经常在数字循环中看到的 i
。)
我有一个工作正常的主光标。
declare
v_firm_id number;
amount number;
v_total_sum TABLE_TEMP.TOTAL_SUM%TYPE;
CURSOR MT_CURSOR IS
SELECT firm_id FROM t_firm;
BEGIN
OPEN MT_CURSOR;
LOOP
FETCH MT_CURSOR INTO v_firm_id;
EXIT WHEN MT_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(to_char(sysdate, 'mi:ss') ||'--- '|| v_firm_id)
INSERT INTO TABLE_TEMP(TOTAL_SUM) VALUES(v_firm_id)
COMMIT;
END LOOP;
DBMS_LOCK.SLEEP(20);
BEGIN
FOR loop_emp IN
(SELECT TOTAL_SUM INTO v_total_sum FROM TABLE_TEMP)
LOOP
dbms_output.put_line(to_char(sysdate, 'mi:ss') ||'--- '|| v_total_sum || '-TEST--');
END LOOP loop_emp;
END;
end;
一切正常,除了 dbms_output.put_line(v_total_sum || '---');
我在那里没有得到任何数据。我得到正确的行数。它插入了。
问题是游标 FOR 循环有一个冗余的 into
子句,它似乎被编译器默默地忽略了,因此从未使用过 v_total_sum
。
试试这个:
begin
for r in (
select firm_id from t_firm
)
loop
insert into table_temp (total_sum) values (r.firm_id);
end loop;
dbms_lock.sleep(20);
for r in (
select total_sum from table_temp
)
loop
dbms_output.put_line(r.total_sum || '---');
end loop;
commit;
end;
如果这是一个存储过程而不是匿名块,并且您使用 alter session set plsql_warnings = 'ENABLE:ALL';
(或 IDE 中的等效首选项设置)启用了 PL/SQL 编译器警告,那么您会看到:
PLW-05016: INTO clause should not be specified here
我还把 commit
移到了最后,所以你只提交一次。
总结下面的评论,游标 FOR 循环构造为您声明、打开、获取和关闭游标,并且可能更快,因为它以 100 个(或类似的 - 我最近没有测试过)版本)。更简单的代码出现错误的可能性更小,并且将来更容易维护,例如,如果您需要向游标添加一列。
注意原始版本有:
for loop_emp in (...)
loop
...
end loop loop_emp;
这是一种误导,因为 loop_emp
是 记录 的名称,而不是游标或循环。编译器忽略了 end loop
之后的文本,尽管它至少应该警告您。如果您想为循环命名,可以在其上方使用 label like <<LOOP_EMP>>
。 (我总是将我的循环记录命名为 r
,类似于您经常在数字循环中看到的 i
。)