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>
Related
I am writing below command to make my column pname of table programs a foreign key, but the it gives me an error saying
ORA-00905: missing keyword
SQL> alter table programs alter column pname varchar2(20) foreign key references programmer(pname);
Test case:
SQL> create table programmer (pname varchar2(20) primary key);
Table created.
SQL> create table programs (pname varchar2(10));
Table created.
Altering the table:
SQL> alter table programs modify pname varchar2(20);
Table altered.
SQL> alter table programs add constraint fk_prog_ammer
2 foreign key (pname) references programmer (pname);
Table altered.
SQL>
You want to use ADD CONSTRAINT:
ALTER TABLE programs -- table name
ADD CONSTRAINT programs__pname__fk -- constraint name
FOREIGN KEY (pname) -- column to apply the constraint to
REFERENCES programmer(pname) -- table and column to reference
db<>fiddle here
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>
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>
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.
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.