Parent table A with some records.
Child table B with 0 records.
I have a cursor to do truncation on these tables in reverse tree order (i.e. truncate child first, then parent)
But I'm still getting this error when I truncate the parent table 'ORA-02266: unique/primary keys in table referenced by enabled foreign keys' error, despite the fact that the child table has no records at all.
However, when I do 'Delete from ' in the same order, all constraint related errors were avoided. And 'Delete from' takes really long time to run.
I don't want to disable or drop any constraints.
However, when I do 'Delete from ' in the same order, all constraint related errors were avoided.
That's the only way if you have constraints enabled. You cannot truncate. If you still want to truncate the table, then you could find the constraint name from user_constraints, and then DISABLE them:
ALTER TABLE table_name DISABLE CONSTRAINT constraint_name;
Then you could TRUNCATE the table, and re-enable the constraint:
ALTER TABLE table_name ENABLE CONSTRAINT constraint_name;
If your table has ON DELETE CASCADE option, then from Oracle 12.1 onward, you could use:
TRUNCATE TABLE table_name CASCADE;
Note, both the DELETE CASCADE and the TRUNCATE CASCADE will fail if any of the relationships in the hierarchy are not defined with the ON DELETE CASCADE clause.
There are three ways to delete from parent/child tables:
CREATE TABLE par (i NUMBER CONSTRAINT par_pk PRIMARY KEY);
CREATE TABLE chi (i NUMBER CONSTRAINT chi_fk REFERENCES par(i) ON DELETE CASCADE);
INSERT INTO par VALUES(1);
INSERT INTO chi VALUES(1);
1) If you have Oracle 12 or later, and you have foreign keys with ON DELETE CASCADE, you can use TRUNCATE CASCADE, which I expect to be the fastest option:
TRUNCATE TABLE par CASCADE;
Table PAR truncated.
SELECT count(*) FROM par;
0
SELECT count(*) FROM chi;
0
2) If your foreign keys are defined with ON DELETE CASCADE, you can use DELETE, which I expect to be the slowest option:
DELETE FROM par;
1 row deleted.
SELECT count(*) FROM par;
0
SELECT count(*) FROM chi;
0
3) Otherwise, you can disable the foreign keys, truncate the tables and reenable the foreign keys. This is fast, but is a little bit more risky than the other options (please check that the constraints are all valid afterwards):
ALTER TABLE chi DISABLE CONSTRAINT chi_fk;
TRUNCATE TABLE chi;
TRUNCATE TABLE par;
ALTER TABLE chi ENABLE CONSTRAINT chi_fk;
AFAIK, it is not possible to alter a foreign key from normal to ON DELETE CASCADE. I guess you have to drop and recreate them:
ALTER TABLE chi DROP CONSTRAINT chi_fk;
ALTER TABLE chi ADD CONSTRAINT chi_fk REFERENCES par(i) ON DELETE CASCADE;
Related
Here's the scenario.
- Parent Table: TEAMMEMBERS, with a primary key RecID
- Child Table: TEAMMEMBERTASKS
I have two columns in the TEAMMEMBERTASKS table, ReportedBy and AssignedTo.
Both of these columns use the RecID to store which team member reported a task and which team member the task is assigned to. The RecID could be the same for both columns, but that is not always the case.
I need to add in a FK for both child columns that check the relationship to the parent, and I would like to add ON UPDATE CASCADE to both of the foreign keys.
Whenever I try to do this, my second foreign key throws a 'may cause cycles or multiple cascade paths' error.
Here's my code:
ALTER TABLE [dbo].[TEAMMEMBERTASKS] WITH CHECK ADD CONSTRAINT
[FK_AssignedTo_TeamMemberRecID] FOREIGN KEY([AssignedTo])
REFERENCES [dbo].[TEAMMEMBERS] ([RecID])
GO
ALTER TABLE [dbo].[TEAMMEMBERTASKS] CHECK CONSTRAINT
[FK_AssignedTo_TeamMemberRecID]
GO
ALTER TABLE [dbo].[TEAMMEMBERTASKS] WITH CHECK ADD CONSTRAINT
[FK_ReportedBy_TeamMemberRecID] FOREIGN KEY([ReportedBy])
REFERENCES [dbo].[TEAMMEMBERS] ([RecID])
ON UPDATE CASCADE
GO
ALTER TABLE [dbo].[TEAMMEMBERTASKS] CHECK CONSTRAINT
[FK_ReportedBy_TeamMemberRecID]
GO
With the current code, will this cause the RecID to be updated in both child columns or will it cause the update command to be restricted?
Should I just go ahead and write up a trigger that deals with this instead?
DELETE tbemp.emp_id,
tbadd.emp_id
FROM TBEMPLOYEE tbemp
JOIN TBADDRESS tbadd ON (tbemp.emp_id=tbadd.emp_id)
Oracle 11g not compile it
This delete statement is not valid in Oracle. There are other statements for deletion, one could be
DELETE FROM TBEMPLOYEE tbemp
WHERE EXISTS (select 'x'
from TBADDRESS
where tbemp.emp_id=tbadd.emp_id);
You can't delete directly from multiple tables with a join.
But you can enforce a foreign key constraint with ON DELETE CASCADE.
ALTER TABLE tbaddress ADD CONSTRAINT fk_emp FOREIGN KEY (emp_id) REFERENCES tbemployee (emp_id) ON DELETE CASCADE;
DELETE FROM tbemployee; -- This also deletes referencing keys from tbaddress
I have one question about DELETE query in SQL. I have 3 child tables say B,C,D and one parent Table A. Priamry key of A is shared in all its child tables. If I have to delete a record from the child tables and then from the parent in a single SQL then is it possible? If yes can you guide me for an SQL query contruct? If not is it at least possible to delete record from the child tables in a single query?
If you don't have a foreign keys with ON DELETE CASCADE then you should do it with transaction:
BEGIN;
DELETE FROM B WHERE ...
DELETE FROM C WHERE ...
DELETE FROM D WHERE ...
COMMIT;
ADDED:
If you use mysql read DELETE doc and discussion here stackoverflow delete-from-two-tables-in-one-query
Nahue's comment and sufleR's answer are right. If you have an ON DELETE CASCADE specified on the foreign key relationships, you will be able to delete from all these tables using a single DELETE statement.
If you do not have this constraint enforced, you can enforce it with ALTER TABLE statement. I would take your schema as
A (a_pk, ...) -- PRIMARY KEY specified on a_pk
B (b_pk, a_fk, ...)
C (c_pk, a_fk, ...)
D (d_pk, a_fk, ...)
Then,
ALTER TABLE b
ADD CONSTRAINT b_a_fk
a_fk REFERENCES a(a_pk) ON DELETE CASCADE;
ALTER TABLE c
ADD CONSTRAINT c_a_fk
a_fk REFERENCES a(a_pk) ON DELETE CASCADE;
ALTER TABLE d
ADD CONSTRAINT d_a_fk
a_fk REFERENCES a(a_pk) ON DELETE CASCADE;
All the tables will enforce a FOREIGN KEY with ON DELETE CASCADE referential constraint on all these tables.
Now, if you issue
DELETE FROM a WHERE a_pk = <some value>
then this would delete records from B, C and D where each of their a_fk = <some value>.
Note that I have used Oracle syntax in my queries. You will have to convert these to suit your DBMS syntax but I don't think that is necessary as this is the standard syntax.
I'm currently reading through this Yii application eBook: http://www.packtpub.com/agile-web-application-development-yii11-and-php5/book - and I'm having a problem inputting the tutorials DDL / SQL statements into PHPMyAdmin without it throwing up errors.
Would someone be kind enough to shed some light on why the following syntax is invalid? It might be something simple but I can't see it:
SQL statement:
ALTER TABLE tbl_issue
ADD CONSTRAINT FK_issue_project FOREIGN KEY (`project_id`)
REFERENCES tbl_project(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE tbl_issue
ADD CONSTRAINT `FK_issue_owner` FOREIGN KEY (`owner_id`)
REFERENCES tbl_user(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE tbl_issue
ADD CONSTRAINT `FK_issue_requester` FOREIGN KEY (`requester_id`)
REFERENCES tbl_user(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE tbl_project_user_assignment
ADD CONSTRAINT `FK_project_user` FOREIGN KEY (`project_id`)
REFERENCES tbl_project(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
ALTER TABLE tbl_project_user_assignment
ADD CONSTRAINT `FK_user_project` FOREIGN KEY (`user_id`)
REFERENCES tbl_user(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
INSERT INTO tbl_user (`email`, `username`, `password`)
VALUES
(`test1#notanaddress.com`,`Test_User_One`, MD5(`test1`)),
(`test2#notanaddress.com`,`Test_User_Two`, MD5(`test2`));
Error Message
Error
SQL query:
ALTER TABLE tbl_issue
ADD CONSTRAINT FK_issue_project FOREIGN KEY ( `project_id` )
REFERENCES tbl_project( `id` ) ON DELETE CASCADE ON UPDATE RESTRICT ;
MySQL said:
#1005 - Can't create table 'trackstar_test.#sql-c78_127' (errno: 121) (<a
href="server_engines.php?engine=InnoDB&page=Status&
token=252c0553975923580ca430b6e98c4243">Details...</a>)
Note:
All the tables in the database are set to innodb as their storage engine.
I've tried using different foreign key names for each FK, still get the same error.
Update:
After finding no solution to the problem, I deleted by DB, uninstalled Xampp and then redid everything again. Seems to work now. Sorry to not be able to tell future readers exactly what the cause was, but it was most probably to do with my Database config or the information I added to it.
Actual Problem is :
AS you are Following the book, there are a few insert/ update statements are executed on
tbl_proect,
tbl_issue
than you are trying to add Foreign Key Constraint. that checks the table data before applying. So, Here is the actual mistake, may be your tables contain a few records that violate the foreign key constraints. hence phpmyadmin doesnot allow you to alter table and generates error message.
Solution :
TRUNCATE TABLE `tbl_project`
TRUNCATE TABLE `tbl_issue`
Do Only one thing, clear all the tables . Empty tables. . And here's your problm resolved now phpmyadmin allows you to run commands.
Suppose there is a main table containing a primary key and there is another table which contains a foreign key to this main table. So if we delete the row of main table it will delete the child table also.
How do I write this query?
First, as a one-time data-scrubbing exercise, delete the orphaned rows e.g.
DELETE
FROM ReferencingTable
WHERE NOT EXISTS (
SELECT *
FROM MainTable AS T1
WHERE T1.pk_col_1 = ReferencingTable.pk_col_1
);
Second, as a one-time schema-alteration exercise, add the ON DELETE CASCADE referential action to the foreign key on the referencing table e.g.
ALTER TABLE ReferencingTable DROP
CONSTRAINT fk__ReferencingTable__MainTable;
ALTER TABLE ReferencingTable ADD
CONSTRAINT fk__ReferencingTable__MainTable
FOREIGN KEY (pk_col_1)
REFERENCES MainTable (pk_col_1)
ON DELETE CASCADE;
Then, forevermore, rows in the referencing tables will automatically be deleted when their referenced row is deleted.
From your question, I think it is safe to assume you have CASCADING DELETES turned on.
All that is needed in that case is
DELETE FROM MainTable
WHERE PrimaryKey = ???
You database engine will take care of deleting the corresponding referencing records.
You can alter a foreign key constraint with delete cascade option as shown below. This will delete chind table rows related to master table rows when deleted.
ALTER TABLE MasterTable
ADD CONSTRAINT fk_xyz
FOREIGN KEY (xyz)
REFERENCES ChildTable (xyz) ON DELETE CASCADE
If you have multiply rows to delete and you don't want to alter the structure of your tables
you can use cursor.
1-You first need to select rows to delete(in a cursor)
2-Then for each row in the cursor you delete the referencing rows and after that delete the row him self.
Ex:
--id is primary key of MainTable
declare #id int
set #id = 1
declare theMain cursor for select FK from MainTable where MainID = #id
declare #fk_Id int
open theMain
fetch next from theMain into #fk_Id
while ##fetch_status=0
begin
--fkid is the foreign key
--Must delete from Main Table first then child.
delete from MainTable where fkid = #fk_Id
delete from ReferencingTable where fkid = #fk_Id
fetch next from theMain into #fk_Id
end
close theMain
deallocate theMain
hope is useful
If you want to delete all the rows, you can use truncate with cascade:
TRUNCATE TABLE products CASCADE;
Need to set the foreign key option as on delete cascade...
in tables which contains foreign key columns.... It need to set at the time of table creation or add later using ALTER table