8

PL/SQLまたはSQLの動的SQL文でエラーの位置を見つけるにはどうすればよいですか?

SQL*Plus から、無効な SQL DML ステートメントなどのエラーの位置を確認できます。

SYS@orcl> SELECT
       2    X
       3  FROM
       4    TABLEX
       5  /
  TABLEX
  *
ERROR at line 4:
ORA-00942: table or view does not exist

SQL*Plus はエラーを行番号とともに表示し、エラーが見つかった行にアスタリスクを表示してマークします。

動的 SQL に変換すると、エラー コード (SQLCODE) とエラー メッセージ (SQLERRM) を取得できます。

SYS@orcl> SET SERVEROUTPUT ON
SYS@orcl> BEGIN
       2    EXECUTE IMMEDIATE 'SELECT X FROM TABLEX';
       3  EXCEPTION
       4    WHEN OTHERS THEN
       5      DBMS_OUTPUT.PUT_LINE('SQLCODE:' || SQLCODE);
       6      DBMS_OUTPUT.PUT_LINE('SQLERRM:' || SQLERRM);
       7  END;
       8  /
SQLCODE:-942
SQLERRM:ORA-00942: table or view does not exist

しかし、動的 ​​SQL 文字列内のエラーの位置を取得するにはどうすればよいでしょうか?

Oracle は、エラーに関する興味深い情報を含む SQL Communications Area (SQLCA) を提供しているようです。特に:

  • SQLCODE および SQLERRM フィールド (それぞれの PL/SQL 関数で取得されたデータのソースである可能性があります)
  • 「解析エラーオフセット」を与える SQLERRD(5) 要素がある SQLERRD フィールド。

PL/SQLまたはSQLからSQLERRDにアクセスできますか? もしそうなら、どのように?そうでない場合、PL/SQL または SQL からエラーの場所を特定できる他の手法は何ですか?

(ここでhttp://docs.oracle.com/cd/B28359_01/appdev.111/b31231/chapter8.htm#BABIGBFF SQLCA が文書化され、Pro*C でアクセスされます。)

( SQLCA.SQLERRD を宣言する方法についての回答は、SQLERRD が PL/SQL で定義されていないため、アクセスできないことを示しているようです。)

( Why doesn't Oracle tell you WHICH table or view does not exist?の議論では、トレース ファイルを使用して不正な SQL を表示し、一部の開発ツールでエラーの場所を表示するためのいくつかの提案を提供しています。)

4

2 に答える 2

3

dbms_utilityでエラー メッセージを抽出するためのパッケージを取得しました

begin 
    .. generate error
exception when others then 
    dbms_output.put_line(
        dbms_utility.format_call_stack()      || chr(10) || 
        dbms_utility.format_error_backtrace() || chr(10) || 
        dbms_utility.format_error_stack())
end;
于 2013-04-24T09:02:17.310 に答える
3

動的 PL/SQL を使用してステートメントを実行すると、関連する行番号がエラー スタックに格納されます。

たとえば、次のステートメントには 4 行目にエラーがあります。

declare
    v_count number;
    v_bad_sql varchar2(32767) := 
        'SELECT
            X
          FROM
            TABLEX';
begin
    execute immediate v_bad_sql into v_count;
exception when others then
    begin
        execute immediate
            'begin for i in ( '||v_bad_sql||') loop null; end loop; end;';
    exception when others then
        dbms_output.put_line(sqlerrm);
    end;
end;
/

ORA-06550: line 4, column 4:
PL/SQL: ORA-00942: table or view does not exist
ORA-00942: table or view does not exist
ORA-06550: line 1, column 18:
PL/SQL: SQL Statement ignored
ORA-00942: table or view does not exist

この方法にはいくつかの欠点があります。

  1. 例外をキャッチしてSQLを再試行するには、余分な醜いコードが必要です。
  2. この例は、選択に対してのみ機能します。挿入、更新、削除、マージ、動的 PL/SQL などのために微調整する必要があります。通常、SQL ステートメントの種類を知っておく必要があります。運が悪ければ、ステートメントを解析する必要がありますが、これは非常に困難な場合があります。
  3. PL/SQL文全体が1行にある場合、列番号が間違っています。
于 2013-04-24T06:32:54.417 に答える