匿名 PL/SQL 块检查异常

Posted

技术标签:

【中文标题】匿名 PL/SQL 块检查异常【英文标题】:Anonymous PL/SQL block checked exception 【发布时间】:2015-04-01 13:20:14 【问题描述】:

我试图在我的匿名 PL/SQL 块中捕获异常

DECLARE
    ...

BEGIN
FOR herstell_row IN (
    ...
) 
LOOP
    ...

    DECLARE
        table_does_not_exists exception;
        pragma exception_init( table_does_not_exists, -942 );
    BEGIN
        INSERT INTO SMART_MONITORING_MACHINE_NAV_B (
            MACHINE, 
            NAVIGATION_LEVEL_ID
        ) 
        SELECT 
            old_binding.MACHINE, 
            pv_id 
        FROM 
            SMART_MACHINE_NAV_BINDING old_binding
        WHERE
            old_binding.NAVIGATION_LEVEL_ID = herstell_row.HENAME1;
    EXCEPTION
        WHEN table_does_not_exists THEN null;
    END;

END LOOP;
END;

我知道表 SMART_MACHINE_NAV_BINDING 在我的情况下不存在,所以我需要嵌套匿名块来忽略它的代码。但我总是得到这个错误:

错误报告 - ORA-06550:第 41 行,第 14 列: PL/SQL: ORA-00942: 表或视图不存在 ORA-06550:第 33 行,第 10 列: PL/SQL:忽略 SQL 语句

【问题讨论】:

错字:你在table_does_not_exist*s*中有一个额外的s 您在代码中使用的所有数据库对象都必须在运行时存在,否则您将收到此类错误。为什么要从不存在的表中进行选择? @Dmitry 这是一个迁移脚本。它在部署我们较新的应用程序版本期间执行。有些系统有这个表,有些系统没有。 【参考方案1】:

你不能编译不存在表的代码,但你可以尝试使用EXECUTE EMMEDIATE执行它:

DECLARE
    ...

BEGIN
FOR herstell_row IN (
    ...
) 
LOOP
    ...

    DECLARE
        table_does_not_exists exception;
        pragma exception_init( table_does_not_exists, -942 );
    BEGIN
      execute immediate 
        'INSERT INTO SMART_MONITORING_MACHINE_NAV_B (
            MACHINE, 
            NAVIGATION_LEVEL_ID
        ) 
        SELECT 
            old_binding.MACHINE, 
            pv_id 
        FROM 
            SMART_MACHINE_NAV_BINDING old_binding
        WHERE
            old_binding.NAVIGATION_LEVEL_ID = :P' using herstell_row.HENAME1;
    EXCEPTION
        WHEN table_does_not_exists THEN null;
    END;

END LOOP;
END;

这里也不需要异常,你可以使用系统视图检查表是否存在:

declare
  table_created number;
begin
  select count(*)
    into table_created
    from all_tables
   where table_name = ...
     and owner = ...;

  if table_created > 0 then
     execute immediate 'insert into ...';
  end if;
end;

更多关于EXECUTE IMMEDIATE声明的信息:http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/executeimmediate_statement.htm#LNPLS01317

【讨论】:

【参考方案2】:

Oracle 不知道这个错误 table_does_not_exists 它是用户定义的,所以你应该在其他人的时候处理,例如。

Exception
  When Others then
     null;
  -- or at this time you can raise your error table_does_not_exists
    raise table_does_not_exists;
  -- and handle it in another parent block
end;
Exception
   when table_does_not_exists then
     null;
end;

【讨论】:

以上是关于匿名 PL/SQL 块检查异常的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL 过程块

检查 PL/SQL 异常块中的特定错误代码

PL/SQL语法简介(匿名PL/SQL块)

PL/SQL 异常处理

从 pl/sql 异常块中“一次”关闭所有游标

PL/SQL编程_概述