我们能否找到导致ORA-00942表存在问题的表或视图不存在。:

时间:2019-05-02 13:46:56

标签: oracle plsql error-handling dynamic-sql

我有一个带有CTAS查询的普通PLSQL块。

BEGIN
EXECUTE IMMEDIATE'
CREATE TABLE ZZZ_TEMP NOLOGGING PARALLEL AS
SELECT /*+ PARALLEL(a,4) */
        *
    FROM
        HI0XXX001.HI_TABLE_NAME a
    LEFT JOIN
        HR_001_GROUP B
    ON
        a.EMPLOYERGROUP_UD =B.ACC_NUM
    LEFT JOIN
        HR_002_GROUP l
    ON
        a.EMPLOYERGROUP_UD =l.EMPLOYERGROUP_UD
    AND
        a.GRP_CON_UD_COV_CONTRACT_NAME=l.GRP_CON_UD_COV_CONTRACT_NAME
    ';
EXCEPTION WHEN OTHERS THEN Dbms_Output.put_line(SQLERRM);
END;

让我们假设HR_002_GROUP表在我运行此块的模式中不存在。有什么方法可以显示错误消息,指出HR_002_GROUP表不存在?

我发布的查询只是一个示例方案。我们使用ETL结构工作,并且有大量的查询脚本行,可将数百万个数据从多个HI表之一插入到带有前缀VH的另一个小表中。我有大约15-30桌左联接。选择每个左联接要知道哪个表实际上导致了错误,这是很费时间的。

1 个答案:

答案 0 :(得分:4)

使用DBMS_SQL代替本机动态SQL,然后使用DBMS_SQL.LAST_ERROR_POSITION()标识语句中出现错误的部分。

DBMS_SQL不如本地动态SQL方便,但功能也更强大。有几个陷阱需要提防。第一个是过程DBMS_SQL.PARSE不仅解析命令,还将自动运行DDL命令。

下面的代码尝试使用其他两个表创建一个表,其中一个显然不存在。正则表达式用于输出每个字符  从错误的位置到第一个空格。 (此代码基于this answer.

declare
    v_cursor_id integer := dbms_sql.open_cursor ();
    v_sql varchar2(32767) := q'[
        create table zzz_temp as
        select *
        from dual
        join some_schema.fake_table
            on dual.dummy = fake_table.dummy
    ]';
begin
    dbms_sql.parse(v_cursor_id, v_sql, dbms_sql.native);
    dbms_sql.close_cursor(v_cursor_id);
exception
    when others then
        dbms_output.put_line
        (
            sqlerrm||chr(10)||
            'Error occurred here: '||
            regexp_substr
            (
                srcstr   => v_sql,
                pattern  => '\w+',
                position => dbms_sql.last_error_position()
            )
        );
        dbms_sql.close_cursor(v_cursor_id);
end;
/

DBMS_OUTPUT:

ORA-00942: table or view does not exist
Error occurred here: fake_table

其他一些随机代码建议:

  1. 使用PARALLEL(4)代替PARALLEL(A, 4)。语句级并行性几乎总是比对象级并行性更好。如果您并行运行一个表,则可能要并行运行整个查询。
  2. 尝试避免使用WHEN OTHERS。尽可能使用更具体的错误处理程序。