PLSQL IMPLICIT CURSOR在CURSOR之后找不到数据

时间:2018-04-22 13:30:21

标签: oracle stored-procedures plsql cursor implicit

我有一个正常工作的主光标。

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 || '---');

外,一切正常

我没有得到任何数据。我得到正确的行数。插入它。

1 个答案:

答案 0 :(得分:2)

问题是游标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';启用了PL / SQL编译器警告(或IDE中的等效首选项设置),那么您会看到:

PLW-05016: INTO clause should not be specified here

我还将commit移到了最后,所以你只提交一次。

总结下面的注释,Cursor FOR循环构造为您声明,打开,提取和关闭游标,并且可能更快,因为它以100个批次(或类似 - 我在最近的版本中未测试)获取。更简单的代码具有更少的错误机会,并且将来更容易维护,例如,如果您需要向游标添加列。

请注意原始版本:

for loop_emp in (...)
loop
    ...
end loop loop_emp;

这是误导性的,因为loop_emp记录的名称,而不是光标或循环。编译器忽略了end loop之后的文本,尽管它至少应该警告你。如果您想为循环命名,可以在其上方使用label like <<LOOP_EMP>>。 (我总是将循环记录命名为r,类似于您经常在数字循环中看到的i。)