在检查if条件之前评估PL / SQL for循环?

时间:2015-06-11 00:46:48

标签: plsql

这是一个简单的脚本来检查表FOO是否存在,哪个工作正常!

declare
n number;

begin

select count(*) into n from user_tables where table_name = 'FOO';

if n>0 then
    dbms_output.put_line('FOO exists.');
else
    dbms_output.put_line('FOO not exists.');
end if;

end;

运行输出是“FOO not exists。”,这是我的预期。现在我想在表中存在一些流程逻辑。

declare
n number;

begin

select count(*) into n from user_tables where table_name = 'FOO';

if n>0 then
    dbms_output.put_line('FOO exists.');
    FOR r in (select name from FOO) loop
        dbms_output.put_line(r.name);
    end loop;
else
    dbms_output.put_line('FOO not exists.');
end if;

end;

现在它给出了错误:

    FOR r in (select name from FOO) loop
                               *
ERROR at line 10:
ORA-06550: line 10, column 43:
PL/SQL: ORA-00942: table or view does not exist

但为什么呢? FOO不存在。并且if块不应该像我上面的第一个脚本一样执行。

或者for循环是否必须在执行之前进行评估,因此是错误?

2 个答案:

答案 0 :(得分:0)

执行脚本时,对象引用必须有效,除非您引用引用字符串中的对象,例如在动态SQL中。

例如,您可以将脚本更改为:

declare
n number;
v_sql_count varchar2(200);
v_sql_names varchar2(200);
TYPE namesTable IS TABLE OF VARCHAR2(200);
v_names namesTable;

begin

v_sql_count := 'select count(*) from user_tables where table_name = ''FOO''';
v_sql_names := 'select name from FOO';

execute immediate v_sql_count into n;

if n>0 then
    dbms_output.put_line('FOO exists.');
    execute immediate v_sql_names bulk collect into v_names;
    FOR r in v_names.first .. v_names.last loop
        dbms_output.put_line(v_names(r));
    end loop;
else
    dbms_output.put_line('FOO not exists.');
end if;

exception when others then
  dbms_output.put_line('SQLERR: ' || SQLERRM);
end;

两个查询(一个用于计数,一个用于获取名称列)被写为字符串然后执行。由于引用了无效名称,因此它们不会被视为无效对象引用,脚本将会运行。

答案 1 :(得分:0)

您可以使用REF CURSOR根据动态查询打开游标:

DECLARE

    n number;

    TYPE cursor_type IS REF CURSOR;
    c_foo_query cursor_type;
    v_result varchar2(4000);

BEGIN

    SELECT COUNT(*)
      INTO n
      FROM user_tables
      WHERE table_name = 'FOO';

    IF ( n>0 )
    THEN

        dbms_output.put_line('FOO exists.');

        OPEN c_foo_query FOR 'SELECT name FROM foo';
        LOOP
            FETCH c_foo_query INTO v_result;
            EXIT WHEN c_foo_query%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE (v_result);
        END LOOP;
        CLOSE c_foo_query;

    ELSE

        dbms_output.put_line('FOO not exists.');

    END IF;

 END;
 /