CREATE TABLE test (c1 NUMBER(10) NOT NULL);
exec DBMS_ERRLOG.CREATE_ERROR_LOG ( 'test', 'err_test');
I want to insert into table test
some values from an other table, and log the errors. I also want to log the ids of records which could not be inserted into the err_test table. In pseudocode this would result in something like this:
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;
The above obviously doesn't work because src.id
is unknown. But I can do the above insert with a merge statement that acts as an insert statement:
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;
After executing the above, the error is not logged in the err_table, but thrown back to the user:
ORA-01489: result of string concatenation is too long
ORA-01400: cannot insert NULL into ("SCV_DPN"."TEST"."C1")
String too long? Then I try without the concatenation in the 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;
Auch:
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")
It becomes even better:
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;
Now I am kicked:
ORA-03113: end-of-file on communication channel
Process ID: 25352
Session ID: 171 Serial number: 979
What's going on here? Seems the 1 = 2
is the culprit, because
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;
works as it should and (!!) logs the error in the 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
Now it works without issues.
Can someone explain to me what is going on here and/or also give a better approach for solving the above problem where extra information from the source table has to be logged in the ORA_ERR_MESG$
field.
Note: According to the documentation I can use 1 = 2
:
To insert all of the source rows into the table, you can use a constant filter predicate in the ON clause condition. An example of a constant filter predicate is ON (0=1).