【发布时间】:2014-09-18 13:10:44
【问题描述】:
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$ 字段中。
注意:根据documentation我可以使用1 = 2:
要将所有源行插入表中,您可以在 ON 子句条件中使用常量过滤谓词。一个常量过滤谓词的示例是 ON (0=1)。
【问题讨论】:
标签: sql oracle11g merge-statement