【问题标题】:Select from table that does not exist从不存在的表中选择
【发布时间】:2017-06-10 20:42:46
【问题描述】:

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

如果(表存在) 从表中选择......

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

我认为这是因为在编译时检查了我的代码:“select from..”,然后如果表不存在则打印错误。我该如何解决这样的问题?...这是我的代码的样子(我使用了通用名称):

     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;

【问题讨论】:

标签: sql oracle plsql


【解决方案1】:

问题恰恰在于您的过程 con 没有被编译,因为它引用了一个不存在的对象;为此,您可能需要一些动态 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;

【讨论】:

  • 你能看看我的例子吗(我编辑了我的问题)..所以我需要用立即执行来编写整个语句..
【解决方案2】:

一切都需要在动态 SQL (DBMS_SQL) 或 EXECUTE_IMMEDIATE 中完成,否则如果表不存在,您的代码将永远无法编译(或包将无效)。

DBMS_SQL 示例

EXECUTE_IMMEDIATE 示例

【讨论】:

    【解决方案3】:

    根据this article,在Oracle 数据库服务器中,静态SQL 确实在编译时检查以确保引用的对象存在。

    所以我建议你使用动态 SQL 而不是静态 SQL,例如通过 varchar。

    【讨论】:

    • 你能看看我的例子吗?所以我需要在 EXECUTE IMMEDIATE ('MY STATEMENT') 中写下我的整个 INSERT INTO STATEMENT 对吗?
    猜你喜欢
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多