运行 sql 使用立即执行访问内部错误代码

Accessing an inner error code when running sql using execute immediate

我正在 运行 从脚本中获取下面的 PL/SQL 块。如您所见,它添加了一列,并且应该捕获任何异常 - 其中,将在列中抛出的异常已经存在。

现在如果我 运行 这个和列已经存在,我得到一个错误:

Error code: -1735

Error message: ORA-01735: invalid ALTER TABLE option

这一切都很好,但是如果我 运行 内部 SQL 而不是;那是 execute immediate 后面的 SQL 本身,我得到的是这条消息,更准确地说:

ORA-01430: column being added already exists in table

第一个错误的错误代码为 -1735,我可以用下面代码中注释掉的 when 子句来捕捉;如果没有注释掉,结果将是:

Some other error occurred

不能 能够捕获 -1430 异常,尽管这似乎是异常的根本原因。

所以我的问题是:在这种情况下,有什么方法可以访问这个 "inner" 异常吗?(在这种情况下,这甚至是一个有效的术语吗?)在其他情况下words,可以修改它以提供更具体的错误消息吗?

DECLARE
    column_exists exception;
    pragma exception_init (column_exists , -1430);

    general_error exception;
    pragma exception_init (general_error , -1735);
BEGIN
    execute immediate 'ALTER TABLE my_table 
        ADD (some_column VARCHAR2(10 CHAR));';
EXCEPTION 
    -- I expected / wanted this to catch my error in order
    -- to let me output a more specific message:
    WHEN column_exists THEN    
        DBMS_OUTPUT.PUT_LINE('The column or index already exists');

 -- Note: Commented out, but would otherwise catch the general error.
 -- (I tested it here just to confirm that I can catch exceptions this way)
 --   WHEN general_error THEN    
 --       DBMS_OUTPUT.PUT_LINE('Some other error occurred');

 -- General catch: Generates the first message quoted above:
    WHEN OTHERS THEN    
        DBMS_OUTPUT.PUT_LINE('Error code: ' || SQLCODE);
        DBMS_OUTPUT.PUT_LINE('Error message: ' || SQLERRM);
END;
/

这是我稍微修改一下你的代码后得到的:

在第 9 行中,有一个分号应该被删除,因为 EXECUTE IMMEDIATE 不允许,这里:

ADD (some_column VARCHAR2(10 CHAR));';
                                   ^
                                   |
                            remove it

样本table:

SQL> CREATE TABLE test
  2  AS
  3     SELECT * FROM dept;

Table created.

您的代码:

SQL> DECLARE
  2     column_exists  EXCEPTION;
  3     PRAGMA EXCEPTION_INIT (column_exists, -1430);
  4
  5     general_error  EXCEPTION;
  6     PRAGMA EXCEPTION_INIT (general_error, -1735);
  7  BEGIN
  8     EXECUTE IMMEDIATE 'ALTER TABLE test
  9          ADD (loc VARCHAR2(10 CHAR))';   --> remove ; here
 10  EXCEPTION
 11     -- I expected / wanted this to catch my error in order
 12     -- to let me output a more specific message:
 13     WHEN column_exists
 14     THEN
 15        DBMS_OUTPUT.PUT_LINE ('The column or index already exists');
 16     -- Note: Commented out, but would otherwise catch the general error.
 17     -- (I tested it here just to confirm that I can catch exceptions this way)
 18     --   WHEN general_error THEN
 19     --       DBMS_OUTPUT.PUT_LINE('Some other error occurred');
 20
 21     -- General catch: Generates the first message quoted above:
 22     WHEN OTHERS
 23     THEN
 24        DBMS_OUTPUT.PUT_LINE ('Error code: ' || SQLCODE);
 25        DBMS_OUTPUT.PUT_LINE ('Error message: ' || SQLERRM);
 26  END;
 27  /
The column or index already exists

PL/SQL procedure successfully completed.

SQL>

现在,我不确定多余的分号是否属于这种情况。如有必要,将其删除并重新表述问题。