Constraints interdependent tables [duplicate] - sql

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.

Related

Even with complete and readable statements, an error occurs: SQL Error [900] [42000]: ORA-00900: invalid SQL statement

I have two tables created in my Oracle database: the table 'responsible' (which has the id and description of the responsible) and the table 'ident' (which has id's of three types of expenses).
Below, I am trying to create a script in which:
Add values to the columns of the 'responsible';
create a 'type_responsible' table, and insert values into it;
create a relationship table called 'responsible_by_type', which, using the data from the table 'responsible', 'ident' and 'responsible_type' establishes one relationship between them.
These changes in data type to primary key or foreign key are attempts to get the bank to recognize the fields as relatable.
I get the error: 'SQL Error [900] [42000]: ORA-00900: invalid SQL statement'. Even if I execute one instruction at a time, which makes no sense.
I really don't know where my mistake is. Since I can't run the script, I can't know if the script allows me to reach my goal. Could someone help me?
<--Table RESPONSIBLE-->
INSERT INTO RESPONSIBLE(RESPONSIBLE_ID, RESPONSIBLE_DESC) VALUES (1, 'payer1');
INSERT INTO RESPONSIBLE(RESPONSIBLE_ID, RESPONSIBLE_DESC) VALUES (2, 'payer2');
ALTER TABLE RESPONSIBLE ADD CONSTRAINT PK_RESPONSIBLE_ID PRIMARY KEY (RESPONSIBLE_ID);
ALTER TABLE RESPONSIBLE ADD CONSTRAINT UNIQUE_RESPONSIBLE_DESC UNIQUE (RESPONSIBLE_DESC);
<--Table IDENT-->
<--OPTION ONE-->
ALTER TABLE IDENT ADD CONSTRAINT pk_RESPONSIBLES_TYPE_IDS primary key(RESPONSIBLE_DEBTS_ID, RESPONSIBLE_ASSETS_ID, RESPONSIBLE_EXPENSES_ID);
<--OPTION TWO-->
ALTER TABLE IDENT ADD CONSTRAINT FK_RESPONSIBLE_DEBTS_ID FOREIGN KEY (RESPONSIBLE_DEBTS_ID);
ALTER TABLE IDENT ADD CONSTRAINT FK_RESPONSIBLE_ASSETS_ID FOREIGN KEY (RESPONSIBLE_ASSETS_ID);
ALTER TABLE IDENT ADD CONSTRAINT FK_RESPONSIBLE_EXPENSES_ID FOREIGN KEY (RESPONSIBLE_EXPENSES_ID);
<--Table RESPONSIBLE_TYPE-->
CREATE TABLE RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID NUMBER(10), RESPONSIBLE_TYPE_DESC VARCHAR(100));
INSERT INTO RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC) VALUES (1, 'Assets');
INSERT INTO RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC) VALUES (2, 'Expenses');
INSERT INTO RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC) VALUES (3, 'Debts');
ALTER TABLE RESPONSIBLE_TYPE ADD CONSTRAINT PK_RESPONSIBLE_TYPE_ID PRIMARY KEY (RESPONSIBLE_TYPE_ID);
<--Table RESPONSIBLE_BY_TYPE-->
CREATE TABLE RESPONSIBLE_BY_TYPE(RESPONSIBLE_ID NUMBER(10) NOT NULL, RESPONSIBLE_EXPENSES_ID NUMBER(10) NOT NULL,
RESPONSIBLE_ASSETS_ID NUMBER(10) NOT NULL, RESPONSIBLE_DEBTS_ID NUMBER(10) NOT NULL, RESPONSIBLE_DESC VARCHAR(100), RESPONSIBLE_TYPE VARCHAR(100),
CONSTRAINT FK_RESPONSIBLE_BY_TYPE FOREIGN KEY(RESPONSIBLE_ID) REFERENCES RESPONSIBLE(RESPONSIBLE_ID),
CONSTRAINT FK_RESPONSIBLE_BY_TYPE FOREIGN KEY(RESPONSIBLE_EXPENSES_ID) REFERENCES IDENT(RESPONSIBLE_EXPENSES_ID),
CONSTRAINT FK_RESPONSIBLE_BY_TYPE FOREIGN KEY(RESPONSIBLE_ASSETS_ID) REFERENCES IDENT(RESPONSIBLE_ASSETS_ID),
CONSTRAINT FK_RESPONSIBLE_BY_TYPE FOREIGN KEY(RESPONSIBLE_DEBTS_ID) REFERENCES IDENT(RESPONSIBLE_DEBTS_ID),
CONSTRAINT FK_RESPONSIBLE_BY_TYPE FOREIGN KEY(RESPONSIBLE_TYPE) REFERENCES RESPONSIBLE_TYPE(RESPONSIBLE_TYPE),
CONSTRAINT FK_RESPONSIBLE_BY_TYPE FOREIGN KEY(RESPONSIBLE_DESC) REFERENCES RESPONSIBLE(RESPONSIBLE_DESC);
In the first steps it was running. From the moment I created the table 'responsible_by_type' and started changing the data types of the other tables, I couldn't do anything anymore.
Now, even when I execute a simple insert instruction, I get the error I mentioned above.
This works from Oracle SQL Developer
-- ******************* Existing Table RESPONSIBLE - you don't need to create it ***************************
--CREATE TABLE RESPONSIBLE
-- (
-- RESPONSIBLE_ID NUMBER(10),
-- RESPONSIBLE_DESC VARCHAR2(100)
-- );
-- -------------- Alter table --------------------
ALTER TABLE RESPONSIBLE ADD CONSTRAINT pk_responsible_id PRIMARY KEY (RESPONSIBLE_ID);
ALTER TABLE RESPONSIBLE ADD CONSTRAINT unique_responsible_desc UNIQUE (RESPONSIBLE_DESC);
-- ---------- I n s e r t s ----------------
INSERT INTO RESPONSIBLE(RESPONSIBLE_ID, RESPONSIBLE_DESC) VALUES (1, 'payer1');
INSERT INTO RESPONSIBLE(RESPONSIBLE_ID, RESPONSIBLE_DESC) VALUES (2, 'payer2');
-- ******************* Existing Table IDENT - you don't need to create it ***************************
-- CREATE TABLE IDENT
-- (
-- RESPONSIBLE_DEBTS_ID NUMBER,
-- RESPONSIBLE_ASSETS_ID NUMBER,
-- RESPONSIBLE_EXPENSES_ID NUMBER
-- );
-- -------------- Alter table --------------------
ALTER TABLE IDENT ADD CONSTRAINT pk_responsibles_type_ids
PRIMARY KEY(RESPONSIBLE_DEBTS_ID, RESPONSIBLE_ASSETS_ID, RESPONSIBLE_EXPENSES_ID);
-- *************** New Table RESPONSIBLE_TYPE ***************************
CREATE TABLE RESPONSIBLE_TYPE
(
RESPONSIBLE_TYPE_ID NUMBER(10),
RESPONSIBLE_TYPE_DESC VARCHAR(100),
CONSTRAINT pk_responsible_type_id PRIMARY KEY (RESPONSIBLE_TYPE_ID)
-- option 2 -- PK(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC)
);
-- ---------- I n s e r t s ----------------
INSERT INTO RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC) VALUES (1, 'Assets');
INSERT INTO RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC) VALUES (2, 'Expenses');
INSERT INTO RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC) VALUES (3, 'Debts');
-- *************** New Table RESPONSIBLE_BY_TYPE ***************************
CREATE TABLE RESPONSIBLE_BY_TYPE
(
RESPONSIBLE_ID NUMBER(10) NOT NULL,
RESPONSIBLE_EXPENSES_ID NUMBER(10) NOT NULL,
RESPONSIBLE_ASSETS_ID NUMBER(10) NOT NULL,
RESPONSIBLE_DEBTS_ID NUMBER(10) NOT NULL,
RESPONSIBLE_DESC VARCHAR(100),
RESPONSIBLE_TYPE_ID NUMBER(10),
-- NOTE *** FK Constraints References PKs in referenced tables *** ----------
CONSTRAINT fk_resp_by_type_resp
FOREIGN KEY(RESPONSIBLE_ID) REFERENCES RESPONSIBLE(RESPONSIBLE_ID),
CONSTRAINT fk_resp_by_type_idnt
FOREIGN KEY(RESPONSIBLE_EXPENSES_ID, RESPONSIBLE_ASSETS_ID, RESPONSIBLE_DEBTS_ID)
REFERENCES IDENT(RESPONSIBLE_EXPENSES_ID, RESPONSIBLE_ASSETS_ID, RESPONSIBLE_DEBTS_ID),
CONSTRAINT fk_resp_by_type_resptype
FOREIGN KEY(RESPONSIBLE_TYPE_ID) REFERENCES RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID)
-- option 2 -- FK(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC) references RESPONSIBLE_TYPE(RESPONSIBLE_TYPE_ID, RESPONSIBLE_TYPE_DESC)
);
-- R e s u l t
table RESPONSIBLE created.
table RESPONSIBLE altered.
table RESPONSIBLE altered.
1 rows inserted.
1 rows inserted.
table IDENT created.
table IDENT altered.
table RESPONSIBLE_TYPE created.
1 rows inserted.
1 rows inserted.
1 rows inserted.
table RESPONSIBLE_BY_TYPE created

Database contains foreign key that doesn exist even though there is a foreign key constraint?

I am working with a database where there is a foreign key ID that doesn't exist even though there is a foreign key constraint.
There is a table called "Workplace" with a foreign key column called "AddressID" pointing to another table called "Address"
The foreign key is as follows:
ALTER TABLE [dbo].[Workplace] WITH NOCHECK ADD CONSTRAINT [FK_Workplace_Address] FOREIGN KEY([AddressID])
REFERENCES [dbo].[Address] ([ID])
GO
ALTER TABLE [dbo].[Workplace] CHECK CONSTRAINT [FK_Workplace_Address]
GO
For one particular row in the Workplace table, the AddressID has a value of "1".
When I run select * from Address where ID = 1 there is no result.
Then I ran update Workplace set AddressID = 3 where Workplace.ID = 20 the value changed to 3 and I have verified that an Address with ID 3 exists.
Then I ran update Workplace set AddressID = 1 where Workplace.ID = 20 again and I get the error
The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_Workplace_Address". The conflict occurred in database db_name, table "dbo.Address", column 'ID'.
I don't understand how the value 1 could have been put there in the first place. The Address with ID=1 couldn't have been deleted after the constraint was put in place. The constraint creation would also fail if the record was deleted in the first place. Does anyone know how this could be possible?
This is a database on Windows Server 2016, SQL Server 12.0.4237.0
You create your FOREIGN KEY with NOCHECK, as a result the values that already exist in the table are not checked. This can be replicated with the following:
CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
AddressID int)
GO
INSERT INTO dbo.Workplace
VALUES(1,3); --Works
GO
ALTER TABLE dbo.WorkPlace WITH NOCHECK ADD CONSTRAINT FK_Workplace_Address FOREIGN KEY (AddressID) REFERENCES dbo.Address(ID);
GO
ALTER TABLE dbo.Workplace CHECK CONSTRAINT FK_Workplace_Address;
GO
INSERT INTO dbo.Workplace
VALUES(2,3); --Fails
GO
UPDATE dbo.Workplace
SET AddressID = 2
WHERE ID = 1; --Fails
GO
DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;
As you can see, only rows that are INSERTed or UPDATEd after the constraint was created (with NOCHECK) are validated; the first row INSERTed is left as it was, with a reference to a row that does not exist.
Instead, create the key without NOCHECK defined, or with CHECK, and the statement will fail when you try to create it:
CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
AddressID int)
GO
INSERT INTO dbo.Workplace
VALUES(1,3); --Works
GO
ALTER TABLE dbo.WorkPlace WITH CHECK ADD CONSTRAINT FK_Workplace_Address FOREIGN KEY (AddressID) REFERENCES dbo.Address(ID); --Fails
GO
DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;
This generates the error below:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Workplace_Address". The conflict occurred in database "Sandbox", table "dbo.Address", column 'ID'.
Alternatively, create the key when you create the tables; though it's likely too late for that now.
CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
AddressID int CONSTRAINT FK_Workplace_Address FOREIGN KEY REFERENCES dbo.Address(ID));
GO
INSERT INTO dbo.Workplace
VALUES(1,3); --Fails
GO
DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;

Add multiple foreign keys to existing table in Oracle

I want to add multiple foreign keys to existing table in Oracle database. Following sql query gives me an error. One by one I can add foreign key constraint. But I want to do this within one statement like below.
ALTER TABLE address
ADD CONSTRAINT fk_customer_id FOREIGN KEY (customer_id)
REFERENCES customer (id) ON DELETE CASCADE ,
ADD CONSTRAINT fk_city_id FOREIGN KEY (city_id)
REFERENCES city (id) ON DELETE CASCADE;
Any idea how to do this?
That's not entirely true (what #Thorsten has said). You can add two constraints at a time.
SQL> create table test (empno number, deptno number);
Table created.
SQL>
SQL> alter table test add
2 ( constraint fk_test_emp foreign key (empno) references emp (empno),
3 constraint fk_test_dept foreign key (deptno) references dept (deptno)
4 );
Table altered.
SQL>

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.

deferrable initially deferred in postgresql

I have a cyclic foreign keys on 2 tables, so i use deferrable initially deferred as below:
uni=# create table vorlesungen (vnr integer primary key, gelesenvon integer);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "vorlesungen_pkey" for table "vorlesungen"
CREATE TABLE
uni=# create table professoren (pnr integer primary key, lieblingsvo integer);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "professoren_pkey" for table "professoren"
CREATE TABLE
uni=# alter table professoren add constraint vfk foreign key (lieblingsvo) references vorlesungen (vnr) deferrable initially deferred;
ALTER TABLE
uni=# alter table vorlesungen add constraint pfk foreign key (gelesenvon) references professoren (pnr) deferrable initially deferred;
ALTER TABLE
so far so good.
but now when i want to insert into the tables, i get foreign key violations, although i specified deferrable initially deferred:
uni=# insert into vorlesungen values (1, 1);
ERROR: insert or update on table "vorlesungen" violates foreign key constraint "pfk"
DETAIL: Key (gelesenvon)=(1) is not present in table "professoren".
uni=# insert into professoren values (1, 1);
ERROR: insert or update on table "professoren" violates foreign key constraint "vfk"
DETAIL: Key (lieblingsvo)=(1) is not present in table "vorlesungen".
whats the problem?
Are you explicitly opening a transaction before the
INSERTs? If you do not use BEGIN, each insert is an independent transaction, therefore enforcing the foreign keys at the end of each command.