Skip to Main Content

SQL & PL/SQL

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

ORA-02291 during MERGE on self-referenced table

932227Apr 21 2012 — edited Apr 22 2012
Hello,

I encountered error ORA-02291 when I tried to use MERGE statement on the table with "self-referenced" foreign key. Using the foreign key deferrable did not help. The only one thing, which helped me, was using errorlog table. See the demonstration:


Working as common user:

SQL> CONNECT scott/tiger

-----

First of all, I create table and (not deferrable) constraints:

CREATE TABLE fkv (
id NUMBER(1) CONSTRAINT nn_fkv_id NOT NULL,
parent_id NUMBER(1) CONSTRAINT nn_fkv_paid NOT NULL
);
ALTER TABLE fkv ADD CONSTRAINT pk_fkv_id PRIMARY KEY (id);
ALTER TABLE fkv ADD CONSTRAINT fk_fkv_paid FOREIGN KEY (parent_id) REFERENCES fkv(ID) NOT DEFERRABLE;

-----

INSERT is working well:

INSERT INTO fkv (
id,
parent_id
)
SELECT
1,
1
FROM
DUAL;

COMMIT;

1 rows inserted.
commited.

-----

MERGE statement using UPDATE branch is working well too:

MERGE INTO fkv USING (
SELECT
1 AS ID,
1 AS PARENT_ID
FROM
DUAL
) a
ON (
fkv.id = a.id
)
WHEN MATCHED THEN
UPDATE SET
fkv.parent_id = a.parent_id
WHERE
A.ID IS NOT NULL
DELETE WHERE a.id IS NULL
WHEN NOT MATCHED THEN
INSERT (
ID,
parent_id
)
VALUES (
A.ID,
A.PARENT_ID);

COMMIT;

1 rows merged.
commited.

-----

And now is coming the strange behaviour:

MERGE INTO fkv USING (
SELECT
2 AS id,
2 AS PARENT_ID
FROM
DUAL
) a
ON (
fkv.id = a.id
)
WHEN MATCHED THEN
UPDATE SET
fkv.parent_id = a.parent_id
WHERE
A.ID IS NOT NULL
DELETE WHERE a.id IS NULL
WHEN NOT MATCHED THEN
INSERT (
ID,
parent_id
)
VALUES (
A.ID,
A.PARENT_ID);

SQL Error: ORA-02291: integrity constraint (SCOTT.FK_FKV_PAID) violated - parent key not found

ROLLBACK;

rollback complete.

-----

Ok, even it is not a good solution, I try deferrable constraint:

ALTER TABLE fkv DROP CONSTRAINT fk_fkv_paid;
ALTER TABLE fkv ADD CONSTRAINT fk_fkv_paid FOREIGN KEY (parent_id) REFERENCES fkv(id) DEFERRABLE INITIALLY DEFERRED;

table FKV altered.
table FKV altered.

MERGE INTO fkv USING (
SELECT
2 AS id,
2 AS PARENT_ID
FROM
DUAL
) a
ON (
fkv.id = a.id
)
WHEN MATCHED THEN
UPDATE SET
fkv.parent_id = a.parent_id
WHERE
A.ID IS NOT NULL
DELETE WHERE a.id IS NULL
WHEN NOT MATCHED THEN
INSERT (
ID,
parent_id
)
VALUES (
A.ID,
A.PARENT_ID);

1 rows merged.

COMMIT;

SQL Error: ORA-02091: transaction rolled back
ORA-02291: integrity constraint (SCOTT.FK_FKV_PAID) violated - parent key not found

... deffered constraint did not help :-(

-----

Let's try another way - errorlog table; for the first with the not deferrable constraint again:

ALTER TABLE fkv DROP CONSTRAINT fk_fkv_paid;
ALTER TABLE fkv ADD CONSTRAINT fk_fkv_paid FOREIGN KEY (parent_id) REFERENCES fkv(ID) NOT DEFERRABLE;

table FKV altered.
table FKV altered.

BEGIN
sys.dbms_errlog.create_error_log (
dml_table_name => 'FKV',
err_log_table_name => 'ERR$_FKV'
);
END;

anonymous block completed

-----

Toys are prepared, let's start with error logging:

MERGE INTO fkv USING (
SELECT
2 AS id,
2 AS PARENT_ID
FROM
DUAL
) a
ON (
fkv.id = a.id
)
WHEN MATCHED THEN
UPDATE SET
fkv.parent_id = a.parent_id
WHERE
A.ID IS NOT NULL
DELETE WHERE a.id IS NULL
WHEN NOT MATCHED THEN
INSERT (
ID,
parent_id
)
VALUES (
A.ID,
A.PARENT_ID)
LOG ERRORS INTO err$_fkv;

1 rows merged.

-----

Cannot belive, running SELECT for confirmation:

SELECT * FROM err$_fkv;
SELECT * FROM fkv;

no rows selected

ID PARENT_ID
-- --
1 1
2 2

-----

Ok, COMMIT:

COMMIT;

commited.

-----

SELECT for confirmation again:

SELECT * FROM err$_fkv;
SELECT * FROM fkv;

no rows selected

ID PARENT_ID
-- --
1 1
2 2



Using deffered constraint and error logging is working well too.

Metalink and Google did not help me. I am using databases 10.2.0.5 and 11.2.0.3.

Has somebody encountered this problem too or have I missed something?

Thank you

D.
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on May 20 2012
Added on Apr 21 2012
3 comments
1,590 views