1
CREATE TABLE test (c1 NUMBER(10) NOT NULL);

exec DBMS_ERRLOG.CREATE_ERROR_LOG ( 'test', 'err_test');

test他のテーブルからいくつかの値をテーブルに挿入し、エラーをログに記録したいと考えています。また、err_test テーブルに挿入できなかったレコードの ID をログに記録したいと考えています。疑似コードでは、これは次のようになります。

INSERT INTO test(c1)
SELECT some_nr AS special_nr FROM some_table_which_has_an_unique_id_for_each_number
LOG ERRORS INTO err_test('Could not insert record with id:' || some_table.id /* where id is the id number of the special_nr */ ) REJECT LIMIT UNLIMITED;

src.idが不明であるため、上記は明らかに機能しません。しかし、挿入ステートメントとして機能するマージ ステートメントを使用して、上記の挿入を行うことができます。

MERGE INTO test trg
USING (SELECT NULL AS special_nr, 17 AS id FROM DUAL ) src
ON      (1 = 2) -- force INSERTS (!!) Not using INSERT statement because in err log extra data is needed.
WHEN NOT MATCHED THEN 
        INSERT  (trg.c1)
        VALUES  (src.special_nr)
LOG ERRORS INTO err_test('Could not insert record with id:' || src.id) REJECT LIMIT UNLIMITED;

上記を実行した後、エラーは err_table に記録されませんが、ユーザーに返されます。

    ORA-01489: result of string concatenation is too long
    ORA-01400: cannot insert NULL into ("SCV_DPN"."TEST"."C1")

弦が長すぎる?次に、err_mesg$ の連結なしで試します。

MERGE INTO test trg
USING (SELECT NULL AS special_nr, 17 AS id FROM DUAL ) src
ON      (1 = 2) -- force INSERTS (!!) Not using INSERT statement because in err log extra data is needed.
WHEN NOT MATCHED THEN 
        INSERT  (trg.c1)
        VALUES  (src.special_nr)
LOG ERRORS INTO err_test(src.id) REJECT LIMIT UNLIMITED;

アウチ:

    ORA-38908: internal error occurred during DML Error Logging
    ORA-01024: invalid datatype in OCI call
    ORA-01400: cannot insert NULL into ("SCV_DPN"."TEST"."C1")      

それはさらに良くなります:

MERGE INTO test trg
USING (SELECT NULL AS special_nr, 17 AS id FROM DUAL ) src
ON      (1 = 2) -- force INSERTS (!!) Not using INSERT statement because in err log extra data is needed.
WHEN NOT MATCHED THEN 
        INSERT  (trg.c1)
        VALUES  (src.special_nr)
LOG ERRORS INTO err_test('Could not insert record with id:' || nvl(src.id, -1)) REJECT LIMIT UNLIMITED;

今私は蹴られました:

    ORA-03113: end-of-file on communication channel
    Process ID: 25352
    Session ID: 171 Serial number: 979  

何が起きてる?1 = 2が犯人のようです。

MERGE INTO test trg
USING (SELECT NULL AS special_nr, 17 AS id FROM DUAL ) src
ON      (src.id IS NULL) -- force INSERTS (!!) Not using INSERT statement because in err log extra data is needed.
WHEN NOT MATCHED THEN 
        INSERT  (trg.c1)
        VALUES  (src.special_nr)
LOG ERRORS INTO err_test('Could not insert record with id:' || src.id) REJECT LIMIT UNLIMITED;

正常に動作し、(!!) エラーがerr_table

    ORA_ERR_NUMBER$     ORA_ERR_MESG$                                                   ORA_ERR_ROWID$  ORA_ERR_OPTYP$  ORA_ERR_TAG$                            C1
    1400                ORA-01400: cannot insert NULL into ("SCV_DPN"."TEST"."C1")                      I               Could not insert record with id:17          

今では問題なく動作します。

誰かがここで何が起こっているのかを説明したり、ソーステーブルからの追加情報をORA_ERR_MESG$フィールドに記録する必要がある上記の問題を解決するためのより良いアプローチを提供したりできますか?

注:私が使用できるドキュメントによると1 = 2すべてのソース行をテーブルに挿入するには、ON句条件で定数フィルター述語を使用できます。定数フィルター述語の例は、ON (0=1) です。

4

1 に答える 1

1

考えられる原因の 1 つを見逃していると思います: タグ パラメータに行の値を含めることです。この機能が、使用しようとしている機能を提供することを意図しているとは思いません。その趣旨のドキュメントは見つかりませんが、イニシャルmerge(連結エラーのあるもの) への単純な変更で確認できるようです:

MERGE INTO test trg
USING (SELECT NULL AS special_nr, 17 AS id FROM DUAL ) src
ON      (1 = 2) -- force INSERTS (!!) Not using INSERT statement because in err log extra data is needed.
WHEN NOT MATCHED THEN 
        INSERT  (trg.c1)
        VALUES  (src.special_nr)
LOG ERRORS INTO err_test('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') REJECT LIMIT UNLIMITED;

タグが最初に提供された連結値の長さを超えているにもかかわらず、この SQL は成功しています。

より詳細なログを取得するには、挿入を含むカーソル for ループを使用することをお勧めします。少し遅くなるかもしれませんが、エラーが発生したときに必要なだけ詳細をログに記録できます。


ドキュメントはこの結論を支持しているように見えますが、それはあからさまに述べられているというよりも暗示されています。エラー ログに許可されている「単純な式」について説明すると、「式は、テキスト リテラル、数値リテラル、またはバインド変数などの一般的な SQL 式のいずれかです」と記載されています。

于 2014-09-18T13:32:38.597 に答える