从不存在的表中选择

时间:2017-01-25 15:32:16

标签: sql oracle plsql

我有一个关于ORACLE的问题,我编写了一个PLSQL代码来检查表是否存在,如果它存在,那么我从这个表中选择一些东西......伪代码就像:

if(表存在)    从表格中选择......

问题是,如果表不存在,我总是会收到错误,即使从未满足if条件且从不执行select语句。

我认为这是因为我的代码在编译时被检查:"选择..."然后如果表不存在则会输出错误。我怎样才能解决这个问题?这里是我的代码的样子(我使用了通用名称):

     DECLARE
          v_table_exists NUMBER;
       BEGIN

          SELECT NVL(MAX(1), 0)
            INTO v_table_exists
            FROM ALL_TABLES
           WHERE TABLE_NAME = 'TABLE_TEST';

          IF v_table_exists = 1 THEN
             INSERT INTO MY_TABLE(COLUMN1, COLUMN2, COLUMN3, COLUMN4)
             SELECT 1234,
                    5678,
                    T.COLUMN_TEST1,
                    T.COLUMN_TEST2


    FROM  TABLE_TEST T
          WHERE T.FLAG = 1;
      END IF;
   END;

3 个答案:

答案 0 :(得分:6)

问题恰恰在于,您的过程无法编译,因为它引用了一个不存在的对象;你可能需要一些动态SQL;例如:

create or replace procedure checkTable is
    vCheckExists  number;
    vNum          number;
begin
    -- check if the table exists
    select count(1)
    into vCheckExists
    from user_tables
    where table_name = 'NON_EXISTING_TABLE';
    -- 
    if vCheckExists = 1 then
        -- query the table with dynamic SQL
        execute immediate 'select count(1) from NON_EXISTING_TABLE'
        into vNum;
    else
        vNum := -1;
    end if;

    dbms_output.put_line(vNum);
end;

即使表不存在,程序也会编译;如果你现在打电话,你会得到:

SQL> select count(1) from NON_EXISTING_TABLE;
select count(1) from NON_EXISTING_TABLE
                     *
ERROR at line 1:
ORA-00942: table or view does not exist


SQL> exec checkTable;
-1

PL/SQL procedure successfully completed.

然后,如果您创建表并再次调用该过程:

SQL> create table NON_EXISTING_TABLE(a) as select 1 from dual;

Table created.

SQL> exec checkTable;
1

PL/SQL procedure successfully completed.

与我展示SELECT的方式相同,您可以执行UPDATE或任何您需要的SQL查询;如果您执行与SELECT不同的操作,则必须删除INTO子句。

例如,假设你需要插入另一个表,上面的代码应该这样编辑:

if vCheckExists = 1 then
    execute immediate 'insert into target(a, b, c) select a, 1, 100 from NON_EXISTING_TABLE';
end if;

答案 1 :(得分:1)

如果表不存在,则需要在动态SQL(DBMS_SQL)或EXECUTE_IMMEDIATE中完成所有操作,否则您的代码将永远不会编译(或包将被无效)。

DBMS_SQL示例

EXECUTE_IMMEDIATE示例

答案 2 :(得分:0)

根据this article,在Oracle Database Server中,确实在编译时检查了静态SQL,以确保存在引用的对象。

因此,我建议您通过varchar使用动态SQL而不是静态SQL。