Integrity constraint violated - Parent key not found - sql

I am creating two tables each having one primary key column and another column that is used to link both tables using a foreign key.
create table t1(a number not null primary key,
b number);
create table t2 ( c number ,
d number not null primary key);
alter table t1 add foreign key (b) references t2(d);
alter table t2 add foreign key (c) references t1(a);
Now when I try to insert values in any one of the table I get the error as below
ORA-02291: integrity constraint (SQL_KVQVOPFDDGLIGJGJSPOQZZIPN.SYS_C0049615414) violated - parent key not found ORA-06512: at "SYS.DBMS_SQL", line 1721
How can I insert the data on both columns of table t1 at once?

Constraints should be created as deferrable initially deferred, otherwise it won't work because one table references another and vice versa. In Oracle database versions which didn't support deferred constraints, you should have dropped foreign key constraints, insert rows (paying attention that foreign keys won't be violated) and then reinforce those constraints.
So:
SQL> create table t1(a number not null primary key,
2 b number);
Table created.
SQL> create table t2 ( c number ,
2 d number not null primary key);
Table created.
SQL> alter table t1 add constraint fk12 foreign key (b)
2 references t2(d) deferrable initially deferred;
Table altered.
SQL> alter table t2 add constraint fk21 foreign key (c)
2 references t1(a) deferrable initially deferred;
Table altered.
SQL>
Testing: referential integrity is checked when you COMMIT:
SQL> insert into t1 (a, b) values (1, 2);
1 row created.
SQL> insert into t2 (c, d) values (1, 2);
1 row created.
SQL> commit;
Commit complete.
SQL>
If you enter invalid combination (values that violate referential integrity), you won't be stopped at the moment on insert but COMMIT (as I've already said):
SQL> insert into t1 (a, b) values (5, 6);
1 row created.
SQL> insert into t2 (c, d) values (9, 9);
1 row created.
SQL> commit;
commit
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02291: integrity constraint (SCOTT.FK12) violated - parent key not found
SQL>

Related

Convert foreign key constraint from SQL Server to Oracle

I want to convert the following script(SQL SERVER) to Oracle:
ALTER TABLE [dbo].[TDistribucion] WITH CHECK ADD CONSTRAINT [FK_TDistribucion_TDocumentos] FOREIGN KEY([Id_Documento])
REFERENCES [dbo].[TDocumentos] ([Id])
GO
ALTER TABLE [dbo].[TDistribucion] CHECK CONSTRAINT [FK_TDistribucion_TDocumentos]
GO
I have tried to run the same script in Oracle:
ALTER TABLE TDISTRIBUCION WITH CHECK ADD CONSTRAINT FK_TDistribucion_TDocumentos FOREIGN KEY(ID_DOCUMENTO)
REFERENCES TDOCUMENTOS (ID);
ALTER TABLE TDISTRIBUCION CHECK CONSTRAINT FK_TDistribucion_TDocumentos;
and I got this error:
Error starting at line : 3 in command -
ALTER TABLE TDISTRIBUCION WITH CHECK ADD CONSTRAINT FK_TDistribucion_TDocumentos FOREIGN KEY(ID_DOCUMENTO)
REFERENCES TDOCUMENTOS (ID)
Error report -
SQL Error: ORA-01735: invalid ALTER TABLE option
01735. 00000 - "invalid ALTER TABLE option"
*Cause:
*Action:
I believe that the "WITH CHECK ADD" is the problem!
See if this helps.
A master table - its primary key column will be referenced from the tdistribucion table.
SQL> create table tdocumentos (id number primary key);
Table created.
A detail - tdistribucion - table (with only one column, just to demonstrate the issue):
SQL> create table tdistribucion (id number);
Table created.
A foreign key constraint, using proper syntax. It will succeed if no records violate the constraint and fail if opposite. Oracle does it at once, you don't have to run another "check". As both tables are empty, it'll succeed:
SQL> alter table tdistribucion add constraint
2 fk_dis_doc foreign key (id)
3 references tdocumentos (id);
Table altered.
However, if there were some rows that violate the constraint, you wouldn't be able to create it:
SQL> alter table tdistribucion drop constraint fk_dis_doc;
Table altered.
SQL> insert all
2 into tdocumentos (id) values (1) --> 1 can't be referenced ...
3 into tdistribucion (id) values (2) --> ... by 2
4 select * from dual;
2 rows created.
SQL> alter table tdistribucion add constraint
2 fk_dis_doc foreign key (id)
3 references tdocumentos (id);
fk_dis_doc foreign key (id)
*
ERROR at line 2:
ORA-02298: cannot validate (SCOTT.FK_DIS_DOC) - parent keys not found
But, if you create it as enable novalidate, it'll "discard" rows that violate the constraint, but will check any subsequent inserts:
SQL> alter table tdistribucion add constraint
2 fk_dis_doc foreign key (id)
3 references tdocumentos (id)
4 enable novalidate;
Table altered.
Just to show that rows that violate the constraint really exist:
SQL> select * from tdocumentos;
ID
----------
1
SQL> select * from tdistribucion;
ID
----------
2
This is OK:
SQL> insert all
2 into tdocumentos (id) values (100)
3 into tdistribucion (id) values (100)
4 select * from dual;
2 rows created.
This isn't OK:
SQL> insert all
2 into tdocumentos (id) values (300)
3 into tdistribucion (id) values (400)
4 select * from dual;
insert all
*
ERROR at line 1:
ORA-02291: integrity constraint (SCOTT.FK_DIS_DOC) violated - parent key not
found
SQL>

Ensure combination of two columns existing in another table

How could one ensure the combination of two columns existing in another table?
CREATE TABLE a (
aid INTEGER PRIMARY KEY
);
CREATE TABLE b (
aid INTEGER REFERENCES a(aid),
bid INTEGER,
PRIMARY KEY (aid, bid)
);
CREATE TABLE c (
aid INTEGER REFERENCES a(aid),
cid INTEGER,
PRIMARY KEY (aid, cid)
);
-- combination of (aid, bid) must come from b
-- combination of (aid, cid) must come from c
CREATE TABLE d (
aid INTEGER REFERENCES a(aid),
bid INTEGER REFERENCES b(bid),
cid INTEGER REFERENCES c(bid),
PRIMARY KEY (aid, bid)
);
INSERT INTO a values(1);
INSERT INTO a values(2);
INSERT INTO b values(1, 1);
INSERT INTO b values(2, 2);
INSERT INTO c values(1, 1);
INSERT INTO c values(2, 2);
INSERT INTO d values(1, 2, 2);
Obviously the above "CREATE TABLE d" coding failed to ensure
combination of (aid, bid) must come from b
combination of (aid, cid) must come from c
Thanks.
In addition to Sticky bit and Vladimir Baranov's answers about using FOREIGN KEY and REFERENCES, for sqlite3 users:
"Foreign key constraints are disabled by default (for backwards compatibility), so must be enabled separately for each database connection." That means, the user has to open a database first, then run command "PRAGMA foreign_keys = ON;".
The pragma will not work if "the version of SQLite you are using does not support foreign keys (either because it is older than 3.6.19 or because it was compiled with SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined)".
You cannot define multicolumn foreign key constraints inline. Define them on their own.
CREATE TABLE d
(aid integer,
bid integer,
cid integer,
PRIMARY KEY (aid,
bid),
FOREIGN KEY (aid,
bid) REFERENCES b (aid,
bid),
FOREIGN KEY (aid,
cid) REFERENCES c (aid,
cid));
You didn't specify what RDBMS you are using. In SQL Server you can create a foreign key using more than one column. The key should point to columns that are in a unique or primary key and you do have the required primary keys in tables B and C.
The definitions of tables A, B and C can remain as they are in the question.
The definition of table D would look like this in SQL Server syntax. Here the foreign key constraints are created using separate ALTER TABLE statements. Different DBMS may use somewhat different syntax.
CREATE TABLE [dbo].[d](
[aid] [int] NULL,
[bid] [int] NULL,
[cid] [int] NULL
)
GO
ALTER TABLE [dbo].[d] WITH CHECK ADD CONSTRAINT [FK_d_b] FOREIGN KEY([aid], [bid])
REFERENCES [dbo].[b] ([aid], [bid])
GO
ALTER TABLE [dbo].[d] CHECK CONSTRAINT [FK_d_b]
GO
ALTER TABLE [dbo].[d] WITH CHECK ADD CONSTRAINT [FK_d_c] FOREIGN KEY([aid], [cid])
REFERENCES [dbo].[c] ([aid], [cid])
GO
ALTER TABLE [dbo].[d] CHECK CONSTRAINT [FK_d_c]
GO
It works as expected in my test:
INSERT INTO a values(1);
INSERT INTO a values(2);
INSERT INTO b values(1, 1);
INSERT INTO b values(2, 2);
INSERT INTO c values(1, 1);
INSERT INTO c values(2, 2);
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
Now let's try to insert into D:
INSERT INTO d values(1, 2, 2);
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_d_b".
The conflict occurred in database "TestDB", table "dbo.b".
The statement has been terminated.
These inserts go through, as expected:
INSERT INTO d values(1, 1, 1);
INSERT INTO d values(2, 2, 2);
(1 row affected)
(1 row affected)
OR you can use this syntax:
CREATE TABLE d2 (
aid INTEGER,
bid INTEGER,
cid INTEGER,
FOREIGN KEY (aid,bid) REFERENCES b (aid,bid),
FOREIGN KEY (aid,cid) REFERENCES c (aid,cid)
);
In this case the foreign keys would get some autogenerated names, but they will work the same:
INSERT INTO d2 values(1, 2, 2);
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__d2__351DDF8C".
The conflict occurred in database "TestDB", table "dbo.b".
The statement has been terminated.
INSERT INTO d2 values(1, 1, 2);
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__d2__361203C5".
The conflict occurred in database "TestDB", table "dbo.c".
The statement has been terminated.
These inserts work, as expected:
INSERT INTO d2 values(1, 1, 1);
INSERT INTO d2 values(2, 2, 2);
(1 row affected)
(1 row affected)
OR, you can use this syntax to give the constraints some meaningful names:
CREATE TABLE d3 (
aid INTEGER,
bid INTEGER,
cid INTEGER,
CONSTRAINT FK_d3_b FOREIGN KEY (aid,bid) REFERENCES b (aid,bid),
CONSTRAINT FK_d3_c FOREIGN KEY (aid,cid) REFERENCES c (aid,cid)
);

Even after dropping the unique constraint, I am getting ORA-00001: unique constraint violation

CREATE TABLE TEST (ID NUMBER(2) UNIQUE ,VAL VARCHAR2(100)
);
Table TEST created.
insert into test values (1,2);
1 row inserted.
I tried to insert the below data again.
insert into test values (1,2);
ORA-00001: unique constraint
So I altered the table and removed the unique constraint and tried
alter table test modify (id number(2))
Table TEST altered
insert into test values (1,2);
ORA-00001: unique constraint
The constraint is stored separately from the column definition -- even when defined using the shorthand you are using.
This db<>fiddle illustrates what is happening.
Use alter table drop constraint.
Giving constraints names is quite helpful. Otherwise, you have to search through system tables to find their name so they can be dropped.

Constraints interdependent tables [duplicate]

This question already has answers here:
Are circular references acceptable in database?
(8 answers)
Closed 5 years ago.
I created 2 tables which are dependent on each other like this.
CREATE TABLE A(NO1 NUMBER(2) PRIMARY KEY,NO2 NUMBER(2));
Table created.
CREATE TABLE B(NO1 NUMBER(2) PRIMARY KEY,NO2 NUMBER(2));
Table created.
ALTER TABLE A ADD CONSTRAINT AA FOREIGN KEY(NO2) REFERENCES B(NO1);
Table altered.
ALTER TABLE B ADD CONSTRAINT BB FOREIGN KEY(NO2) REFERENCES B(NO1);
Table altered.
INSERT INTO A VALUES(10,20);
INSERT INTO A VALUES(10,20);
ERROR at line 1:
ORA-02291: integrity constraint (SUBK.AA) violated - parent key not found
INSERT INTO B VALUES(10,20);
INSERT INTO B VALUES(10,20);
ERROR at line 1:
ORA-02291: integrity constraint (SUBK.BB) violated - parent key not found
How to insert data in table a and b
You are asking for troubles ;-), but You can do this in two steps:
insert into A values(10, null);
insert into B values(20, null);
update A set no2 = 20 where no1 = 10;
update B set no2 = 10 where no1 = 20;
You create an invalid constraints:
ALTER TABLE B ADD CONSTRAINT BB FOREIGN KEY(NO2) REFERENCES B(NO1);
Foreign key should be to different table, not to column in the same table.
If you want circular constraint A -> B and B ->A you can insert first data and then add constraints. your foreign key should direct to primary key, so new SQL will be :
CREATE TABLE A(NO1 NUMBER(2) PRIMARY KEY,NO2 NUMBER(2));
CREATE TABLE B(NO1 NUMBER(2) PRIMARY KEY,NO2 NUMBER(2));
INSERT INTO A VALUES(10,20);
INSERT INTO B VALUES(10,20);
ALTER TABLE A ADD CONSTRAINT AA FOREIGN KEY(NO1) REFERENCES B(NO1);
ALTER TABLE B ADD CONSTRAINT BB FOREIGN KEY(NO1) REFERENCES A(NO1);
Make your constraints deferred. Doing so will cause them to not be enforced until the transaction commits.
Under this setup, you can insert records into both tables without getting an error, as long as both inserts happen in the same transaction.
CREATE TABLE A(NO1 NUMBER(2) PRIMARY KEY,NO2 NUMBER(2));
CREATE TABLE B(NO1 NUMBER(2) PRIMARY KEY,NO2 NUMBER(2));
ALTER TABLE A ADD CONSTRAINT
AA FOREIGN KEY(NO2) REFERENCES B(NO1) INITIALLY DEFERRED DEFERRABLE;
ALTER TABLE B ADD CONSTRAINT
BB FOREIGN KEY(NO2) REFERENCES A(NO1) INITIALLY DEFERRED DEFERRABLE;
INSERT INTO A VALUES(10,20);
INSERT INTO B VALUES(20,10);
COMMIT;
NOTE: I assumed you wanted the BB constraint to refer to table A, so I changed it.

Oracle SQL, trigger inserting row into table X as FK for currently inserted row in table Y

So in Oracle 11g I have the following:
CREATE TABLE OBJECT(
ID NUMBER(8) NOT NULL,
CATEGORY_ENUM_ID NUMBER(8) NOT NULL
);
CREATE SEQUENCE OBJECT_SEQ
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
/
CREATE TABLE TREE(
ID NUMBER(8) NOT NULL,
OBJECT_ID NUMBER(8) NOT NULL,
NAME NVARCHAR2(128)
);
CREATE TABLE CATEGORY_ENUM(
ID NUMBER(8) NOT NULL,
NAME NVARCHAR2(64)
);
-- PK's
ALTER TABLE TREE
ADD CONSTRAINT TREE_PK PRIMARY KEY (ID);
ALTER TABLE OBJECT
ADD CONSTRAINT OBJECT_PK PRIMARY KEY (ID);
ALTER TABLE CATEGORY_ENUM
ADD CONSTRAINT CATEGORY_ENUM_PK PRIMARY KEY (ID)
--- FK's
ALTER TABLE TREE
ADD CONSTRAINT TREE_OBJECT_FK FOREIGN KEY (OBJECT_ID)
REFERENCES OBJECT (ID);
ALTER TABLE OBJECT
ADD CONSTRAINT OBJECT_CATEGORY_FK FOREIGN KEY (CATEGORY_ENUM_ID)
REFERENCES CATEGORY_ENUM (ID);
-- Closed dictionary sample data
INSERT INTO CATEGORY_ENUM (ID, NAME) VALUES (1, 'TREE');
INSERT INTO CATEGORY_ENUM (ID, NAME) VALUES (2, 'HERB');
INSERT INTO CATEGORY_ENUM (ID, NAME) VALUES (3, 'SHROOM');
-- Triggers
CREATE OR REPLACE TRIGGER TREE_before_insert
BEFORE INSERT
ON TREE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
CATEGORY_ID NUMBER;
BEGIN
SELECT ID INTO CATEGORY_ID FROM CATEGORY_ENUM WHERE NAME = 'TREE' AND ROWNUM <= 1;
if :NEW.OBJECT_ID is null then
:NEW.OBJECT_ID := OBJECT_SEQ.nextval;
INSERT INTO OBJECT (ID, CATEGORY_ENUM_ID) VALUES (:NEW.OBJECT_ID, CATEGORY_ID);
end if;
END;
/
If next I run:
INSERT INTO TREE (ID, NAME) VALUES (1, 'Tree1');
INSERT INTO TREE (ID, NAME) VALUES (2, 'Tree2');
I get an error:
...
TRIGGER TREE_BEFORE_INSERT compiled
Error starting at line 91 in command:
INSERT INTO TREE (ID, NAME) VALUES (1, 'Tree1')
Error report:
SQL Error: ORA-02291: integrity constraint (HR.TREE_OBJECT_FK) violated - parent key not found
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause: A foreign key value has no matching primary key value.
*Action: Delete the foreign key or add a matching primary key.
1 rows inserted.
But if before the above, I insert anything into FEATURES table (like below), it works fine.
INSERT INTO OBJECT (ID, CATEGORY_ENUM_ID) VALUES (0, 1);
INSERT INTO TREE (ID, NAME) VALUES (1, 'Tree1');
INSERT INTO TREE (ID, NAME) VALUES (2, 'Tree2');
So the problem occurs only for the very first insert, the others work fine, IDs assigned from OBJECT_SEQ.nextval are proper.
What am I doing wrong ?
Jah bless ya for help.
EDIT I have removed some unnecessary code, so now it's more clear and shorter.
The problem here is that you have a primary key constraint placed on the "TREE" table and a foreign key constraint placed on the "OBJECT" table. So any new record that you try inserting into the table with foreign key constraint, make sure it is already available in the table that has the primary key mapping.
Example shown below:
**Tables:**
create table tab1
(id number,
name varchar2(100)
)
create table tab2
(id number,
name varchar2(100)
)
**constraints added:**
alter table tab1 add constraint pk_tab1_id primary key (id)
alter table tab2 add constraint fk_tab2_id foreign key(id) references tab1(id)
**Insert statement on the second table:**
insert into tab2(values(1,'abc')
**Error:**
SQL Error: ORA-02291: integrity constraint (PRAVE.fk_tab2_id) violated - parent key not found
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause: A foreign key value has no matching primary key value.
*Action: Delete the foreign key or add a matching primary key.
**Solution:**
**Insert into the table with PK first as below:**
insert into tab1 values(1,'abc')
1 rows inserted.
insert into tab2 values(1,'abc')
1 rows inserted.