Constructing single query for cascading deletes - sql

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.

Related

Oracle Truncate Parent table constraint error

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;

Deleting row on Foreign key relation

I have table on which I have a foreign key constraint like below
ALTER TABLE [dbo].[Element] WITH CHECK
ADD CONSTRAINT [FK_Element_Band]
FOREIGN KEY([BandID]) REFERENCES [dbo].[Band] ([BandID])
GO
ALTER TABLE [dbo].[Element] CHECK CONSTRAINT [FK_Element_Band]
GO
Now I am trying to delete a row from the band table like this
DELETE FROM Band
WHERE TypeID = 21 AND BandUpperLimit = 10000 AND PID = 61
But I am getting a reference constraint error:
The DELETE statement conflicted with the REFERENCE constraint "FK_Element_Band". The conflict occurred in database "pricingModified", table "dbo.Element", column 'BandID'.
So this should happen if I have anything in the Elements table which is referencing Band table with the ID 21 but that's not the case since the SQL
SELECT *
FROM Element
WHERE BandID = 21
returns nothing.
Can someone please tell me why I am not able to delete row data from the parent table even though there is no reference present in the child table?
Thanks
Just specify ON DELETE CASCADE in your foreign key constraint. Then when you delete a row from the Band table it will automatically delete any child records in the Element table.
ALTER TABLE [dbo].[Element] WITH CHECK
ADD CONSTRAINT [FK_Element_Band]
FOREIGN KEY([BandID]) REFERENCES [dbo].[Band] ([BandID]) ON DELETE CASCADE
GO
Check with this query instead:
select b.*
from Element e
inner join Band b
on e.BandId = b.BandId
where b.TypeId = 21
and b.BandUpperLimit = 10000
and b.PID = 61
while creating child table
create table <child_table_name>
(
_______,
_______,
([FOREIGN KEY column_name]) [size of FOREIGN KEY column] references [parent table(primary key column_name)] on delete cascade
)
Using this you can easily delete record of fk using delete operation..
Try this, if it is successful then mark it positive...

Delete data from two tables by using join condition in Oracle 11g

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

multiple cascade paths, on update cascade

I have a problem with sql server, when I want to have 3 table and make relationship between them, and change the "On Update" property to "cascade".
this problem happend when I want to save the diagram:
Introducing FOREIGN KEY constraint 'FK_Company_Slave' on table 'Company' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.
in this picture, I define my data base, FK and ....
thanks.
First:
A FOREIGN KEY in one table points to a PRIMARY KEY in another table. if you don't want to use PRIMARY KEY on other table in order to foreign key, you must be create unique index on the table.
Second:
you can create after trigger on Master table in order to develop on update cascade manually. In other word your foreign key between Company table and Master table created without on update cascade and then create following trigger on master to update company table after changed row in Master table.
create trigger triggername on dbo.[Master]
After Insert
AS Begin
Update Company
Set MasterKey = I.MasterKey
From Inserted I
Inner join Deleted D on D.Code = I.Code
Where Company.MasterKey = D.MasterKey
End

How to update 2 columns in 2 tables that have foreign key

I know the question of how to update multiple tables in SQL has been asked before and the common answer seems to be do them separately in a transaction.
However, the 2 columns I need to update have a foreign key so cannot be updated separately.
e.g.
Table1.a is a foreign key to Table2.a
One of the entries in the tables is wrong, e.g. both columns are 'xxx' and should be 'yyy'
How do I update Table1.a and Table2.a to be 'yyy'?
I know I could temp remove the key and replace but surely there's another way.
Thanks
You can't do the update simultaneously, however you can force SQL to do the update. You need to make sure your foreign keys have the referential triggered action ON UPDATE CASCADE
e.g.
ALTER TABLE YourTable
ADD CONSTRAINT FK_YourForeignKey
FOREIGN KEY (YourForeignKeyColumn)
REFERENCES YourPrimaryTable (YourPrimaryKeyColumn) ON UPDATE CASCADE
Not being a fan of on update cascade, I would suggest a different route.
First you do not update the Parent table, you add a new record with the value you want (and the same data as the other record for all other fields). Then you have no difficulty updating the child tables to use this value instead of that value. Further you now have the ability to to do the work in batches to avoid locking the system up while the change promulgates through it. Once all the child tables have been updated, you can delete the original bad record.
my answer is based on the following link: http://msdn.microsoft.com/en-us/library/ms174123%28v=SQL.90%29.aspx
You need to make sure that your table_constraint will be defined as ON UPDATE CASCADE
CREATE TABLE works_on1
(emp_no INTEGER NOT NULL,
project_no CHAR(4) NOT NULL,
job CHAR (15) NULL,
enter_date DATETIME NULL,
CONSTRAINT prim_works1 PRIMARY KEY(emp_no, project_no),
CONSTRAINT foreign1_works1 FOREIGN KEY(emp_no) REFERENCES employee(emp_no) ON DELETE CASCADE,
CONSTRAINT foreign2_works1 FOREIGN KEY(project_no) REFERENCES project(project_no) ON UPDATE CASCADE)
and then when you will change the value of your primary key
see the following quote:
For ON DELETE or ON UPDATE, if the CASCADE option is specified, the
row is updated in the referencing table if the corresponding
referenced row is updated in the parent table. If NO ACTION is
specified, SQL Server Compact Edition returns an error, and the update
action on the referenced row in the parent table is rolled back.
For example, you might have two tables, A and B, in a database. Table
A has a referential relationship with table B: the A.ItemID foreign
key references the B.ItemID primary key.
If an UPDATE statement is executed on a row in table B and an ON
UPDATE CASCADE action is specified for A.ItemID, SQL Server Compact
Edition checks for one or more dependent rows in table A. If any
exist, the dependent rows in table A are updated, as is the row
referenced in table B.
Alternatively, if NO ACTION is specified, SQL Server Compact Edition
returns an error and rolls back the update action on the referenced
row in table B when there is at least one row in table A that
references it.