【问题标题】:Find bad dynamic SQL statements containing syntax errors in Oracle在 Oracle 中查找包含语法错误的不良动态 SQL 语句
【发布时间】:2016-04-23 19:36:37
【问题描述】:

我想知道如果在调用动态 SQL 的 PL/SQL 程序单元中没有适当的异常处理,是否有办法找到在运行期间执行中断的动态 SQL 语句。

procedure will_crash is
begin
   -- 1000 dynamic sql statements here ..

   execute immediate 'updaXte dual set X = ''Z'' ' ;

   -- ... and 1000 more dynamic sql statements here ..
   commit;
end;  --> NO proper exception handling for logging the last sql statement

如果一个夜间计划的程序单元包含数百条动态sql语句,我想找出哪个没有调试就坏了。 Oracle 是否在其系统视图中记录任何内容?

【问题讨论】:

  • 定义“破碎”。很可能,没有。如果我们谈论的是简单的语法错误,那将不会被记录。如果“夜间调度程序单元”是通过数据库调度的,并且错误一直传播到调用者,则会记录错误堆栈(取决于您使用的调度机制)。该堆栈跟踪将包含一个行号,它可以帮助您假设您确实有数千行代码,而不是构建数千个不同 SQL 语句的循环。
  • 我将我的包与 execute_immediate 过程一起使用 - 包装 dbms_sql/execute immediate。它具有执行前的 sql 文本、执行时间、执行后的 sql%rowcount 和 explain_plan 的内置日志记录。如果出现错误,它会记录错误堆栈、代码等。
  • 这是一个好方法,但我的问题专门针对没有适当异常处理的场景。我很好奇 Oracle 中是否存在能够跟踪此类不良 SQL 语句的内部 LOG。

标签: oracle logging dynamic-sql


【解决方案1】:

在您的示例中,根本不需要使用动态 SQL,因此最简单的解决方案是将其重写为

procedure will_crash is
begin
   -- 1000 dynamic sql statements here ..

   updaXte dual set X = ''Z''; -- Error at compile time!!

   -- ... and 1000 more dynamic sql statements here ..
   commit;
end;  --> NO proper exception handling for logging the last sql statement

如果实际过程使用动态SQL,因为SQL语句保存在其他地方(变量或SQL表),并且我们只讨论语法错误,您可以在执行语句之前使用DBMS_SQL包实现您的目标。 这是一个例子:

DECLARE

    lc_good   VARCHAR2(200) := 'SELECT 1 FROM dual';
    lc_bad    VARCHAR2(200) := 'SEL1ECT a FROM dual';
    lc_cursor NUMBER;

BEGIN

    lc_cursor := SYS.DBMS_SQL.OPEN_CURSOR;

    BEGIN
        SYS.DBMS_SQL.PARSE(lc_cursor, lc_good, DBMS_SQL.V7);
        dbms_output.put_line('Statement 1 is GOOD');
    EXCEPTION
        WHEN OTHERS THEN
            dbms_output.put_line('Statement 1 is BAD: ' || SQLERRM);
    END;

    BEGIN
        SYS.DBMS_SQL.PARSE(lc_cursor, lc_bad, DBMS_SQL.V7);
        dbms_output.put_line('Statement 2 is GOOD');
    EXCEPTION
        WHEN OTHERS THEN
            dbms_output.put_line('Statement 2 is BAD: ' || SQLERRM);
    END;

    SYS.DBMS_SQL.close_cursor(lc_cursor);

END;

函数输出如下:

Statement 1 is GOOD
Statement 2 is BAD: ORA-00900: ...

请注意,代码只解析 SQL 语句,不执行它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多