Oracle Oracle hierarchical query to disable foreign keys - sql

I have some code (see below), which uses a hierarchical query that traverses down a table to find all the related Foriegn keys. This seems to be working fine.
Can this be modified not to display the top level table, in this case the TABLE_NAME='PARENT' as I want to wrap this code in PL/SQL in order to create the desired syntax to enable/disable Foriegn keys for all the descendants of a table.
In my example, I have 3 tables. A grandchild table, which REFERENCES a child table and a child table, which REFERENCES the parent table, which is the master table.
The reason for this is to clean up some massive tables and I am trying to figure out the most effective and efficient way to go about this exercise.
We don't have CASCADE DELETE setup as that is too dangerous and some people learned that the hard way unfortunately.
Below is my test case and expected results, which I plan to execute in a procedure.
create table parent (
id NUMBER(10),
value varchar2(30),
constraint parent_pk primary key (id)
);
CREATE TABLE child
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint child_pk primary key (id,value),
CONSTRAINT parent_child_fk
FOREIGN KEY (id)
REFERENCES parent(id));
CREATE TABLE grandchild
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint grandchild_pk primary key (id,value),
CONSTRAINT child_grandchild_fk
FOREIGN KEY (id,value)
REFERENCES child(id,value));
insert into parent values (1,'a');
insert into parent values (2,'b');
insert into parent values (3,'c');
insert into child values (1,1);
insert into child values (1,2);
insert into child values (1,3);
insert into child values (2,1);
insert into child values (2,2);
insert into child values (2,3);
insert into child values (3,1);
insert into child values (3,2);
insert into child values (3,3);
insert into grandchild values (1,1);
insert into grandchild values (1,2);
insert into grandchild values (1,3);
insert into grandchild values (2,1);
insert into grandchild values (2,2);
insert into grandchild values (2,3);
insert into grandchild values (3,1);
insert into grandchild values (3,2);
insert into grandchild values (3,3);
In the query I hard code the column name ID.
If possible, I would like to figure it out else I can live with the hard coded value.
select distinct table_name, constraint_name, column_name, r_table_name, position, constraint_type
from (
SELECT uc.table_name,
uc.constraint_name,
cols.column_name,
(select table_name from user_constraints where constraint_name = uc.r_constraint_name)
r_table_name,
(select column_name from user_cons_columns where constraint_name = uc.r_constraint_name and position = cols.position)
r_column_name,
cols.position,
uc.constraint_type
FROM user_constraints uc
inner join user_cons_columns cols on uc.constraint_name = cols.constraint_name
where constraint_type != 'C'
)
start with table_name = 'PARENT' and column_name = 'ID'
connect by nocycle
prior table_name = r_table_name
and prior column_name = r_column_name;
TABLE_NAME
CONSTRAINT_NAME
COLUMN_NAME
R_TABLE_NAME
POSITION
CONSTRAINT_TYPE
PARENT
PARENT_PK
ID
-
1
P
GRANDCHILD
CHILD_GRANDCHILD_FK
ID
CHILD
1
R
CHILD
PARENT_CHILD_FK
ID
PARENT
1
R
Expected results for my test CASE is to generate this syntax:
alter table CHILD disable constraint PARENT_CHILD_FK;
alter table GRANDCHILD disable constraint CHILD_GRANDCHILD_FK;

You can use:
SELECT 'ALTER TABLE "' || u.owner || '"."' || u.table_name || '" '
|| 'DISABLE CONSTRAINT "' || u.constraint_name || '"' AS statement
FROM user_constraints u
INNER JOIN user_constraints r
ON ( u.constraint_type = 'R'
AND r.constraint_type IN ('P', 'U')
AND u.r_owner = r.owner
AND u.r_constraint_name = r.constraint_name)
START WITH r.table_name = 'PARENT'
CONNECT BY PRIOR u.owner = r.owner
AND PRIOR u.table_name = r.table_name;
db<>fiddle here

It is not necessary to use hard code, in fact, it is more troublesome to display the top-level table
with tab1 as (
select t1.CONSTRAINT_NAME,
t1.CONSTRAINT_TYPE,
t1.TABLE_NAME,
t1.R_CONSTRAINT_NAME,
t2.CONSTRAINT_TYPE r_type,
t2.TABLE_NAME r_name
from user_constraints t1,
user_constraints t2
where t1.CONSTRAINT_TYPE = 'R'
and t1.R_CONSTRAINT_NAME = t2.CONSTRAINT_NAME
)
, tab2 as(
select t1.*
from tab1 t1
start with not exists(
select 1 from tab1 v1 where t1.r_name = v1.table_name
)
connect by prior t1.table_name = t1.r_name
)
select 'alter table ' || t1.table_name || ' disable constraint ' || t1.CONSTRAINT_NAME || ';'
from tab2 t1
;

Related

How to delete from 3 tables with one query using where exists

I have four tables Monitoring, Participant, Participant validation group, Validation group,
I would like to delete all monitorings, and there particpants also each particpant possibly (not always) has participant validation group.
Blockquote
but i have the error sql command not properly ended.
NOTE: I am on oracle database and inner joins would not work here.
I would like to achieve an optimized query
that could take only the application number of monitoring and delete all monitorings, participants for each monitoring and participant validation group.
I am not sure if its actually possible in a single query if its not then what could be the optimized way to do this. and I cant use jpa for this at the moment.
Expected results, both monitorings are deleted, and there particpants as well as participant validation groups
You can define foreign keys on child tables to "ON DELETE CASCADE". So when you delete a parent table it will delete associated rows from child tables.
create table parent (
id NUMBER(10),
value varchar2(30),
constraint parent_pk primary key (id)
);
CREATE TABLE child
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint child_pk primary key (id,value),
CONSTRAINT parent_child_fk
FOREIGN KEY (id)
REFERENCES parent(id)
ON DELETE CASCADE
);
CREATE TABLE grandchild
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint grandchild_pk primary key (id,value),
CONSTRAINT child_grandchild_fk
FOREIGN KEY (id,value)
REFERENCES child(id,value)
ON DELETE CASCADE
);
insert into parent values (1,'a');
insert into parent values (2,'b');
insert into parent values (3,'c');
insert into child values (1,1);
insert into child values (1,2);
insert into child values (1,3);
insert into child values (2,1);
insert into child values (2,2);
insert into child values (2,3);
insert into child values (3,1);
insert into child values (3,2);
insert into child values (3,3);
insert into grandchild values (1,1);
insert into grandchild values (1,2);
insert into grandchild values (1,3);
insert into grandchild values (2,1);
insert into grandchild values (2,2);
insert into grandchild values (2,3);
insert into grandchild values (3,1);
insert into grandchild values (3,2);
insert into grandchild values (3,3);
SELECT (
SELECT COUNT(*)
FROM parent
) AS parent_cnt,
(
SELECT COUNT(*)
FROM child
) AS child_cnt,
(
SELECT COUNT(*)
FROM grandchild
) AS grandchild_cnt
FROM dual
DELETE from parent where value = 'a';
SELECT (
SELECT COUNT(*)
FROM parent
) AS parent_cnt,
(
SELECT COUNT(*)
FROM child
) AS child_cnt,
(
SELECT COUNT(*)
FROM grandchild
) AS grandchild_cnt
FROM dual
PARENT_CNT CHILD_CNT GRANDCHILD_CNT
2 6 6

How to remove/Delete the effect of UNIQUE KEY from TABLE

I have UNIQUE KEY attribute on my Table. For my project I deleted that UNIQUE KEY from table , but when try to enter data it still giving the error of UNIQUE KEY VIOLATION.
Already done
to check to commit the database .
to refreshed the entire database.
to find that CONSTRAINT on schema.
SELECT DISTINCT table_name
FROM all_indexes
WHERE index_name = 'CONSTRAINT_NAME';
The above query returns no data (Constraint not found).
I want my data duplicate for one employee without UNIQUE KEY VIOLATION ERROR
Below are some of the queries you can run and check if there is specified index, constraints exist on the table and once you find you can simply drop it. Maybe your unique index was created before the constraint was created:
SELECT * FROM user_cons_columns WHERE table_name = '<your table name>';
select column_name from user_ind_columns where index_name = '<index_name>';
select column_name from user_cons_columns where constraint_name = '<index_name>';
Use below command for dropping index:
DROP INDEX index_name;
Use below command for dropping constraints:
ALTER TABLE <table_name>
DROP CONSTRAINT <constraint_name>
[TL;DR] If you have a UNIQUE INDEX without a UNIQUE CONSTRAINT then you will get the same error message. You need to make sure you have dropped both the index and the constraint.
CREATE TABLE test_data ( id NUMBER );
CREATE UNIQUE INDEX test_data__id__u ON test_data ( id );
ALTER TABLE test_data ADD CONSTRAINT test_data__id__u UNIQUE ( id );
INSERT INTO test_data ( id ) VALUES ( 1 );
INSERT INTO test_data ( id ) VALUES ( 1 );
Will insert one row and will give ORA-00001: unique constraint (FIDDLE_ALGCPMTPWFJZCXIPXNLR.TEST_DATA__ID__U) violated for the second.
If you do:
SELECT * FROM user_constraints WHERE table_name = 'TEST_DATA';
SELECT * FROM user_indexes WHERE table_name = 'TEST_DATA';
Then it will show there is an index and a constraint on the table.
Then if you drop the constraint:
ALTER TABLE test_data DROP CONSTRAINT test_data__id__u;
and try to do:
INSERT INTO test_data ( id ) VALUES ( 1 );
Then you will get:
ORA-00001: unique constraint (FIDDLE_ALGCPMTPWFJZCXIPXNLR.TEST_DATA__ID__U) violated
If you look at the indexes and constraints again:
SELECT * FROM user_constraints WHERE table_name = 'TEST_DATA';
SELECT * FROM user_indexes WHERE table_name = 'TEST_DATA';
Then it will show no constraints but the index is still there. You need to make sure the unique index has been dropped too.
DROP INDEX test_data__id__u;
INSERT INTO test_data ( id ) VALUES ( 1 );
Will then insert the row.
db<>fiddle here

Get list of rows without any references in other tables in postgresql

I have a table that holds translations in an entire system and other tables reference to it, for example something like this:
Table "translations"
id | title
----------------------------
1 | First Translation
2 | Second Translation
And second table with foreign key pointing to translations:
Table "article"
id | translation_id | ...
1 | 1 | ...
I would like to get a list of rows that are not referenced by any other table (in this example row with id=2).
Number of tables might change and I would like to have a general solution that will operate on native relations mechanism in psql.
I've made the function you need. Bellow is the sample data I created to test it. In my data sample the return should be the ID 4 from the table t1. To your case the t1 table would be the translations table.
You have to change it to your tables. It shouldn't be difficult.
create table t1 (
id integer primary key not null,
lang varchar(10)
);
create table t2 (
id integer primary key not null,
id_t1 integer,
constraint fk_t2 foreign key (id_t1) references t1(id)
);
create table t3 (
id integer primary key not null,
id_t1 integer,
constraint fk_t3 foreign key (id_t1) references t1(id)
);
insert into t1 values (1, 'pt'), (2, 'us'), (3,'cn'), (4,'uk');
insert into t2 values (1, 1), (2,2);
insert into t3 values (1, 1), (2,3);
CREATE OR REPLACE FUNCTION listAllReferences()
RETURNS setof integer AS
$$
declare
fullSQL text;
rs RECORD;
begin
fullSQL := '';
for rs in
SELECT 'select t1.id from t1 inner join ' || tc.table_name || ' ON ('||tc.table_name||'.'||kcu.column_name||' = t1.id)' as sel
FROM information_schema.table_constraints AS tc
JOIN information_schema.key_column_usage AS kcu
ON tc.constraint_name = kcu.constraint_name
JOIN information_schema.constraint_column_usage AS ccu
ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY'
AND ccu.table_name='t1' loop
if fullSQL != '' then
fullSQL := fullSQL || ' union ';
end if;
fullSQL := fullSQL || rs.sel;
end loop;
return query
execute 'select t1.id
from t1 left join ('||fullSQL||') alltb on (t1.id = alltb.id)
where alltb.id is null';
return;
end;
$$
LANGUAGE plpgsql;
And to use it just do:
select * from listAllReferences();
It will return:
listallreferences
4
Future tables with reference to your language table will also get covered because I'm getting the data from the INFORMATION_SCHEMA of PostgreSQL
Also you may have to add another filter () to the query on the implicit cursor which is AND tc.table_schema = 'yourSchemaName'

Merging two parent > child table sets

I need to get the data in two parent > child table sets merged/combined into a third parent > child table.
The tables look like this:
The only difference in the three sets of tables is that TableC has a TableType column to help discern the difference between a TableA record and a TableB record.
My first thought was to use a cursor.. Here's code to create the table structure, insert some records, and then merge the data together. It works very well, sooooo....
--Create the tables
CREATE TABLE TableA
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableAChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_A FOREIGN KEY (Parent) REFERENCES TableA(ID)
);
CREATE TABLE TableB
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableBChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_B FOREIGN KEY (Parent) REFERENCES TableB(ID)
);
CREATE TABLE TableC
(
ID int not null identity primary key,
TableType VARCHAR(1),
Name VARCHAR(30)
);
CREATE TABLE TableCChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_C FOREIGN KEY (Parent) REFERENCES TableC(ID)
);
-- Insert some test records..
INSERT INTO TableA (Name) Values ('A1')
INSERT INTO TableAChild (Name, Parent) VALUES ('A1Child', SCOPE_IDENTITY())
INSERT INTO TableB (Name) Values ('B1')
INSERT INTO TableBChild (Name, Parent) VALUES ('B1Child', SCOPE_IDENTITY())
-- Needed throughout..
DECLARE #ID INT
-- Merge TableA and TableAChild into TableC and TableCChild
DECLARE TableACursor CURSOR
-- Get the primary key from TableA
FOR SELECT ID FROM TableA
OPEN TableACursor
FETCH NEXT FROM TableACursor INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
-- INSERT INTO SELECT the parent record into TableC, being sure to specify a TableType
INSERT INTO TableC (Name, TableType) SELECT Name, 'A' FROM TableA WHERE ID = #ID
-- INSERT INTO SELECT the child record into TableCChild using the parent ID of the last row inserted (SCOPE_IDENTITY())
-- and the current record from the cursor (#ID).
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableAChild WHERE Parent = #ID
FETCH NEXT FROM TableACursor INTO #ID
END;
CLOSE TableACursor
DEALLOCATE TableACursor
-- Repeat for TableB
DECLARE TableBCursor CURSOR
FOR SELECT ID FROM TableB
OPEN TableBCursor
FETCH NEXT FROM TableBCursor INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO TableC (Name, TableType) SELECT Name, 'B' FROM TableB WHERE ID = #ID
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableBChild WHERE Parent = #ID
FETCH NEXT FROM TableBCursor INTO #ID
END;
CLOSE TableBCursor
DEALLOCATE TableBCursor
Now, my question(s):
I've always been told that cursors are bad. But I couldn't find another way of doing it. I'm wondering if there's some way to do that with a CTE?
If the cursor is appropriate in this situation, how did I do? Is there a better way of doing what I did? It doesn't look very DRY to me, but I'm no SQL expert.
Lastly, if you want to re-run the query above, here's a small script to delete the tables that were created.
DROP TABLE TableAChild
DROP TABLE TableBChild
DROP TABLE TableCChild
DROP TABLE TableA
DROP TABLE TableB
DROP TABLE TableC
The correct result should look like:
You can use merge as described by Adam Machanic in Dr. OUTPUT or: How I Learned to Stop Worrying and Love the MERGE and in this question to get a mapping between the new identity value and the old primary key value in a table variable and the use that when you insert to your child tables.
declare #T table(ID int, IDC int);
merge dbo.TableC as C
using dbo.TableA as A
on 0 = 1
when not matched by target then
insert (TableType, Name) values('A', A.Name)
output A.ID, inserted.ID into #T(ID, IDC);
insert into dbo.TableCChild(Parent, Name)
select T.IDC, AC.Name
from dbo.TableAChild as AC
inner join #T as T
on AC.Parent = T.ID;
delete from #T;
merge dbo.TableC as C
using dbo.TableB as B
on 0 = 1
when not matched by target then
insert (TableType, Name) values('B', B.Name)
output B.ID, inserted.ID into #T(ID, IDC);
insert into dbo.TableCChild(Parent, Name)
select T.IDC, BC.Name
from dbo.TableBChild as BC
inner join #T as T
on BC.Parent = T.ID;
SQL Fiddle
Here is one way to do this without a cursor or other RBAR type stuff.
ALTER TABLE TableC ADD LegacyID INT
GO
INSERT INTO TableC (TableType, Name, LegacyID)
SELECT 'A', Name, ID
FROM TableA
INSERT TableCChild
SELECT C.ID, AC.Name
FROM TableAChild AC
JOIN TableA A ON A.Id = AC.ID
JOIN TableC C ON C.LegacyID = A.ID AND C.TableType = 'A'
INSERT INTO TableC (TableType, Name, LegacyID)
SELECT 'B', Name, ID
FROM TableB
INSERT TableCChild
SELECT C.ID, AC.Name
FROM TableBChild AC
JOIN TableB A ON A.Id = AC.ID
JOIN TableC C ON C.LegacyID = A.ID AND C.TableType = 'B'
ALTER TABLE TableC DROP COLUMN LegacyID
GO
You can use a map table to link the old and new ids together based on some key.
In my example, I am using the order of insertion into TableC.
Create a map table with an identity column.
Add data in TableC table based on order of ID of TableA and get the inserted ids in the map
Use the same order of TableA.id to get a ROWNUMBER() and match it with the identity column of the map table and update the old_id in map to match TableA.id with TableC.id .
Use the map to insert into the TableCChild table
Truncate the map and rinse and repeat for other tables.
Sample Query
CREATE TABLE #map(id int identity,new_id int,old_id int);
INSERT INTO TableC
(
TableType,
Name
)output inserted.id into #map(new_id)
SELECT 'A',Name
FROM TableA
ORDER BY ID
update m
set m.old_id = ta.id
FROM #map m
inner join
(
select row_number()OVER(order by id asc) rn,id
from tableA
)ta on ta.rn = m.id
INSERT INTO TableCChild (Name, Parent)
SELECT Name,M.new_ID
FROM #Map M
INNER JOIN TableAChild TA ON M.old_id = TA.Parent
TRUNCATE TABLE #map
INSERT INTO TableC
(
TableType,
Name
)output inserted.id into #map(new_id)
SELECT 'B',Name
FROM TableB
ORDER BY ID
update m
set m.old_id = tb.id
FROM #map m
inner join
(
select row_number()OVER(order by id asc) rn,id
from tableB
)tb on tb.rn = m.id
INSERT INTO TableCChild (Name, Parent)
SELECT Name,M.new_ID
FROM #Map M
INNER JOIN TableBChild TB ON M.old_id = TB.Parent
DROP TABLE #Map
I just wrote the following SQL to do it if the Name is unique in TableA and unique in TableB
INSERT INTO TableCChild
(
Parent,
NAME
)
SELECT tc.ID,
ta.Name
FROM TableAChild AS ta
JOIN TableA a
ON a.ID = ta.Parent
JOIN TableC AS tc
ON tc.Name = a.Name
AND tc.TableType = 'A'
UNION
SELECT tc.ID,
tb.Name
FROM TableBChild AS tb
JOIN TableB b
ON b.ID = tb.Parent
JOIN TableC AS tc
ON tc.Name = b.Name
AND tc.TableType = 'B'
If Name is not unique and only the ID is the Unique Identifier then I would add the LegacyId as suggested and the code would then be as follows
/* Change Table C to Have LegacyId as well and this is used to find the New Key for Inserts
CREATE TABLE TableC
(
ID INT NOT NULL IDENTITY PRIMARY KEY,
TableType VARCHAR(1),
LegacyId INT,
NAME VARCHAR(30)
);
*/
INSERT INTO TableC (Name, TableType, LegacyId)
SELECT DISTINCT NAME,
'A',
Id
FROM TableA
UNION
SELECT DISTINCT NAME,
'B',
Id
FROM TableB
INSERT INTO TableCChild
(
Parent,
NAME
)
SELECT tc.ID,
ta.Name
FROM TableAChild AS ta
JOIN TableA a
ON a.ID = ta.Parent
JOIN TableC AS tc
ON tc.LegacyId = a.Id
AND tc.TableType = 'A'
UNION
SELECT tc.ID,
tb.Name
FROM TableBChild AS tb
JOIN TableB b
ON b.ID = tb.Parent
JOIN TableC AS tc
ON tc.LegacyId = b.Id
AND tc.TableType = 'B'
We can reach this by turning the Identity column off till we finish the insertion like the following example.
--Create the tables
CREATE TABLE TableA
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableAChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_A FOREIGN KEY (Parent) REFERENCES TableA(ID)
);
CREATE TABLE TableB
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableBChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_B FOREIGN KEY (Parent) REFERENCES TableB(ID)
);
CREATE TABLE TableC
(
ID int not null identity primary key,
TableType VARCHAR(1),
Name VARCHAR(30)
);
CREATE TABLE TableCChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_C FOREIGN KEY (Parent) REFERENCES TableC(ID)
);
-- Insert some test records..
INSERT INTO TableA (Name) Values ('A1')
INSERT INTO TableAChild (Name, Parent) VALUES ('A1Child', SCOPE_IDENTITY())
INSERT INTO TableB (Name) Values ('B1')
INSERT INTO TableBChild (Name, Parent) VALUES ('B1Child', SCOPE_IDENTITY())
SET IDENTITY_INSERT TableC ON
INSERT INTO TableC(ID, TableType, Name)
SELECT ID, 'A', Name FROM TableA
INSERT INTO TableCChild(Parent, Name)
SELECT Parent, Name FROM TableAChild
DECLARE #MAXID INT
SELECT #MAXID = MAX(ID) FROM TableC
PRINT #MAXID
SET IDENTITY_INSERT TableC ON
INSERT INTO TableC(ID, TableType, Name)
SELECT ID + #MAXID, 'B', Name FROM TableB
SET IDENTITY_INSERT TableC OFF
INSERT INTO TableCChild(Parent, Name)
SELECT Parent + #MAXID, Name FROM TableBChild
SET IDENTITY_INSERT TableC OFF
SELECT * FROM TableC
SELECT * FROM TableCChild
DROP TABLE TableAChild
DROP TABLE TableBChild
DROP TABLE TableCChild
DROP TABLE TableA
DROP TABLE TableB
DROP TABLE TableC
If you need to insert records in third table TableC and TableCChild for later use then it's fine to insert data in these tables but if you only need this table data to use it in your stored procedure for the time being then you can also just work with first two tables to get the desired result.
select * from (
select a.ID,'A' as TableType,a.Name from TableA a inner join TableAChild b on a.ID=b.ID
union
select a.ID,'B' as TableType,a.Name from TableB a inner join TableBChild b on a.ID=b.ID) TableC
Similarly get TableCChild
select * from
(
select b.ID,b.Parent,b.Name from TableA a inner join TableAChild b on a.ID=b.ID
union
select b.ID,b.Parent,b.Name from TableB a inner join TableBChild b on a.ID=b.ID) TableCChild
And if you have to insert in TableC and TableCChild then you have to recreate TableC with primary key on ID and TableType, and turn off the identity for ID column.

ORA-02291:INTEGRITY CONSTRAINT (SYSTEM.SYS_C007150) VIOLATED - PARENT KEY NOT FOUND

When I create the table EMPLOYEE, I made ESSN as a primary key and the SUPERSSN a foreign key from the same table with DNO as a foreign key from the dep table, when I want to insert values that show up and now I am confused.
The table contains the following:
Name Null? Type
----------------------------------------- -------- --------------
ENAME NOT NULL VARCHAR2(30)
ESSN NOT NULL CHAR(14)
BDATE DATE
DNO NUMBER(38)
SUPERSSN CHAR(14)
in first time I used the following command line:
INSERT INTO EMPLOYEE ('JOSEPH','789456','14-DEC-1986','3','123');
then I try without DNO as that:
SQL> INSERT INTO EMPLOYEE (ENAME,ESSN,BDATE)
2 VALUES('JOSEPH','9861050560','14-DEC-1986');
-------------------------------
INSERT INTO EMPLOYEE (ENAME,ESSN,BDATE)
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.SYS_C007150) violated - parent key not
found
----------------------------
Most likely parent_key record which is SUPERSSN(assuming) must be missing in parent table. You can find that out by
SELECT *
FROM user_constraints
WHERE table_name = 'EMPLOYEE'
So you need to first insert values in parent table of employees table and then insert values in child table.
To find out parent_table do as
SELECT uc.constraint_name
|| CHR (10)
|| '('
|| ucc1.TABLE_NAME
|| '.'
|| ucc1.column_name
|| ')'
constraint_source,
'REFERENCES'
|| CHR (10)
|| '('
|| ucc2.TABLE_NAME
|| '.'
|| ucc2.column_name
|| ')'
references_column
FROM user_constraints uc, user_cons_columns ucc1, user_cons_columns ucc2
WHERE uc.constraint_name = ucc1.constraint_name
AND uc.r_constraint_name = ucc2.constraint_name
AND ucc1.POSITION = ucc2.POSITION
AND UC.TABLE_NAME = 'EMPLOYEE'
AND uc.constraint_type = 'R'
For more details please have a look at this.
And go through this and this as well.
I think the new entry(having foreign key constraint) you are entering is referring to an entry which doesnt exist
Here is a query you could use to check to see if the values in your foreign key table exist or not, and of course if they do not exist then they would have to be inserted to resolve the parent key violation:
SELECT E.* FROM EMPLOYEE E
LEFT JOIN SUPER_TABLE S
ON E.SUPERSSN = S.SUPERSSN
WHERE S.SUPERSSN IS NULL AND E.SUPERSSN IS NOT NULL;
Of course, that is assuming the problem is with the SUPERSSN key. If you have other foreign keys, then you may have to check those as well.