This question already has answers here:
Dropping a table in Oracle SQL
(5 answers)
Closed 2 years ago.
DROP TABLE Errors
results in
ORA-02449: unique/primary keys in table referenced by foreign keys
How to drop the table?
Handle referential integrity first.
What will you do with data that references values in a table you'd want to drop?
if you don't care, then drop foreign key constraint(s), then drop the errors table
if you do care, then - obviously - you can't drop it
If you don't know how to find foreign keys, have a look here.
ALTER TABLE tablename
DROP PRIMARY KEY CASCADE;
it drops your foreign key or any dependencies in other tables. Only use it if you know you don't need this relation. Once committed it won't rollback.
If you don't want to drop them you can disable them.
ALTER TABLE tablename
DISABLE CONSTRAINT constraintname CASCADE;
You can find the names of constraints by:
SELECT constraint_name, constraint_type, search_condition
FROM user_constraints
WHERE table_name = 'tablename';
Find out the table where the table you are dropping(Let's say XYZ) is referenced.
You can use the following query to find such tables and constraint name.
select * from user_constraints u
where u.constraint_type = 'R'
and u.constraint_name = (select p.constraint_name from user_constraints p
where p.table_name = 'XYZ' and p.constraint_type = 'P')
Related
I have created two tables:
Create Table Dept
(Department_id number Constraint Depart_id_pk Primary Key
,Department_name varchar2(20));
Create table Emp
(Emp_id number Constraint Empl_id_pk Primary Key
,First_name varchar2(10)
,salary number
,Department_id number
,Constraint depart_id_fk Foreign Key (department_id)
References Dept (Department_id) on delete set null);
Then I have inserted some records in dept and Emp table. But when I try to drop dept table, instead of setting null in Emp.department_id column it shows error like this:
SQL> Drop Table Dept;
Drop Table Dept
*
ERROR at line 1:
ORA-02449: unique/primary keys in table referenced by foreign keys
The foreign key's clause say "on delete set null". Delete is a DML operation, and had you attempted to delete rows from the dept table, the corresponding emp rows would have been updated with a null dept_id.
But this isn't the case - you tried to drop the entire table, a DDL operation. This isn't allowed, because you'd be leaving behind constraints on the emp table that reference a table that no longer exists. If you want to drop these constraints too, you can use a cascade constraints clause:
DROP TABLE dept CASCADE CONSTRAINTS
I am trying to add UNIQUE KEY on a previously existing table with duplicate records by setting ENABLE NOVALIDATE.
But I am getting ORA-02299: cannot validate (my_owner.my_key_UK ) - duplicate keys found
ALTER TABLE my_owner.my_table
ADD CONSTRAINT my_key_UK UNIQUE (ID1,ID2)
ENABLE NOVALIDATE;
A unique constraint uses an index to enforce the noduplicates rule. By default it will create a unique index (makes sense right?). It is this index creation which is hurling ORA-02299.
However, if this is an existing index on the constrained columns the constraint will use that. The good news is, the index doesn't need to be unique for the constraint to use it.
So what you need to do is build a non-unique index first:
create index whatever_idx on my_table (ID1,ID2);
Then you will be able to create your constraint:
ALTER TABLE my_owner.my_table
ADD CONSTRAINT my_key_UK UNIQUE (ID1,ID2)
ENABLE NOVALIDATE;
You can check this by querying the data dictionary:
select uc.constraint_name
, uc.constraint_type
, uc.index_name
, ui.uniqueness as idx_uniqueness
from user_constraints uc
join user_indexes ui
on ui.index_name = uc.index_name
where uc.table_name = 'MY_TABLE'
Oracle ensure unique values using indexes. And if you create unique constrains db automatic creates unique index. Workaround is add DEFERRABLE options. In this case oracle creates normal index. Check example.
create table table_abc (a number,b number);
insert into table_abc values(1,1);
insert into table_abc values(1,2);
ALTER TABLE table_abc ADD CONSTRAINT my_key_a UNIQUE (a) DEFERRABLE enable novalidate; -- no error but in table nonunique values
ALTER TABLE table_abc ADD CONSTRAINT my_key_b UNIQUE (b) ENABLE NOVALIDATE; --no error
select * from user_indexes where table_name ='TABLE_ABC';
I have the following tables:
create table emp_test_lucian as select employee_id,last_name,first_name,department_id from employees;
ALTER TABLE emp_test_lucian
ADD PRIMARY KEY (employee_id);
create table dept_test_lucian as select department_id,department_name from departments_copy;
ALTER TABLE dept_test_lucian
ADD PRIMARY KEY (department_id);
On this tables I want to perform different operations for example: If a department gets deleted (from dept_test_lucian) I will delete all the rows in emp_test_lucian that have that department id with a trigger. This works fine when no fk between the 2 is declared with the following code :
CREATE OR REPLACE TRIGGER triger5
BEFORE UPDATE or DELETE on dept_test_lucian
FOR EACH ROW
BEGIN
IF DELETING then
delete
from emp_test_lucian
where department_id = :OLD.department_id;
else if UPDATING('department_id') then
UPDATE emp_test_lucian
set department_id = :NEW.department_id
where department_id = :OLD.department_id;
END IF;
END IF;
END;
/
What can I add to the code above to work even if I have a fk between the 2 tables like so:
ALTER TABLE emp_test_lucian
ADD CONSTRAINT fk_dep_id FOREIGN KEY(department_id) REFERENCES dept_test_lucian(department_id);
the current code returns :
Error report:
ORA-00001: unique constraint (C##LABORATOR.SYS_C009994) violated
ORA-06512: at line 2
00001. 00000 - "unique constraint (%s.%s) violated"
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
For Trusted Oracle configured in DBMS MAC mode, you may see
this message if a duplicate entry exists at a different level.
*Action: Either remove the unique restriction or do not insert the key.
You need to make clear what table is the 'parent' and what table is the 'child'.
In your example:
- Parent: dept_test_lucian
- Child: emp_test_lucian
Lets call 'dept_test_lucian': TableA
Lets call 'emp_test_lucian': TableB
I come to this conclusion since there is a CONSTRAINT on TableB.department_id" that can only have a value that exists
in "TableA.department_id"
The error message tells you that there is a 'primary key being vialated'.
Primary keys on you tables are:
- "TableA.employee_id"
- "TableB.department_id"
Apparently you are trying to insert a value in one of these columns where that value already exists in.
If '1' is already existing in "TableA.employee_id" you would get such an error.
What I also see in your trigger is:
You have a BEFORE UPDATE Trigger.
So the Trigger looks if there is an UPDATE comming on "TableA" (Parent).
Then you try to UPDATE "TableB" (child) first.
This could be tricky, since "TableB.department_id" can only have values that exist in "TableA.department_id".
If the new UPDATE value doesn't exist in "TableA.department_id", you can not UPDATE that value in "TableB.department_id"
I want to check if film.language_id refers to language.language_id.
I used the code:
SELECT *
FROM all_tab_columns
WHERE column_name = 'film.language';
Result:
no rows selected
Does this mean there are no references/referential constraints?
If you want to find out if a column refers to another column by foreign key constraint you can do the following:
Find out if the column is in a constraint:
select constraint_name from user_cons_columns
where table_name='<Your_table>'
and column_name='<Your_column>';
If it is this will give you the name of that constraint.
Next you can find out if that constraint is a foreign key constraint and where the foreign key points to:
select constraint_type
,r_constraint_name
from user_constraints
where constraint_name='<your constraint name>';
If the constraint is a foreign key constraint it is of type 'R'. This will also give you the name of the primary key constraint the foreign key relates to.
Given the name of the primary key constraint you can find the table and column(s) as follows:
select table_name
,column_name
from user_cons_columns
where constraint_name = 'Your PK constraint'
To make life easier you can join all these queries together. But I leave that to you.
Is there some equivalent to the Mysql specific instruction that disable the check of the foreign keys constraints ?
SET FOREIGN_KEY_CHECKS = 0;
There is no command in Oracle that will disable all constraints at once.
However it seems you want to disable constraints in the context of dropping tables. In that case you can use the CASCADE CONSTRAINTS clause to drop the referencing constraints from other tables along with the table being dropped.
Here's an example:
SQL> CREATE TABLE t1 (ID NUMBER PRIMARY KEY);
Table created
SQL> CREATE TABLE t2 (ID NUMBER REFERENCES t1);
Table created
SQL> INSERT INTO t1 VALUES (1);
1 row inserted
SQL> INSERT INTO t2 VALUES (1);
1 row inserted
SQL> -- this fails because of the foreign key
SQL> DROP TABLE t1;
ORA-02449: unique/primary keys in table referenced by foreign keys
SQL> DROP TABLE t1 CASCADE CONSTRAINTS;
Table dropped
SET FOREIGN_KEY_CHECKS = 0; is session based. In an Oracle context I can only imagine you needing to do this when you have circular references.
You've commented that this is what you want to do:
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE table1;
DROP TABLE table2;
SET FOREIGN_KEY_CHECKS = 1;
I'm assuming that this means that TABLE1 has a foreign key referencing TABLE2 and TABLE2 has a foreign key referencing TABLE1.
If this is the case then Moudiz's answer is correct. You want to disable the foreign keys before dropping the table:
alter table table1 disable constraint <constraint_name>;
alter table table2 disable constraint <constraint_name>;
drop table table1;
drop table table2;
There's no point disabling all foreign keys for the length of the session, you're only interested in two of them, both of which will be dropped with the table.
You don't want to ever disable all foreign keys.
The only other context I can think of this in is if you want to insert something into your circular reference, in which case you would declare the constraint as DEFERRABLE. This means that the constraint check is done at the end of the transaction rather than on DML being performed, see the documentation.
If your references aren't circular then simply drop the tables in the other order.
IF Your asking for a query to disable a foreign key then try this :
ALTER TABLE mytable
disable CONSTRAINT fk_mytable;