问题
I need to create a procedure that allows me to delete data from several tables at once, searching through the CUIT
. There are four tables shown here:
I must pass a CUIT
value in, and if it matches any item saved in the database, I need it to be deleted. I could not find the syntax to be able to erase more than two tables at once, if you could give me a hand I would greatly appreciate it. I clarify by the doubts that the procedure is actually much larger, in total it would be about 12 tables, but as I am interested only the syntax I pass this fragment.
I have problems trying to join the tables using INNER JOIN
.
I am using SQL Server 2016. Thank you
回答1:
Considering your design, i would implement Cascading on your Foreign Key. This is a sample, but should get you on the right path:
USE Sandbox;
GO
CREATE TABLE dbo.ParentTable (PK int IDENTITY PRIMARY KEY,
I int);
CREATE TABLE dbo.ChildTable1 (PK int IDENTITY PRIMARY KEY,
FK int,
S varchar(10));
CREATE TABLE dbo.ChildTable2 (PK int IDENTITY PRIMARY KEY,
FK int,
S varchar(10));
CREATE TABLE dbo.ChildTable3 (PK int IDENTITY PRIMARY KEY,
FK int,
S varchar(10));
GO
--Create keys with CASCADE ON DELETE
ALTER TABLE dbo.ChildTable1 ADD CONSTRAINT FK1 FOREIGN KEY (FK) REFERENCES dbo.ParentTable(PK) ON DELETE CASCADE;
GO
ALTER TABLE dbo.ChildTable2 ADD CONSTRAINT FK2 FOREIGN KEY (FK) REFERENCES dbo.ParentTable(PK) ON DELETE CASCADE;
GO
ALTER TABLE dbo.ChildTable3 ADD CONSTRAINT FK3 FOREIGN KEY (FK) REFERENCES dbo.ParentTable(PK) ON DELETE CASCADE;
GO
INSERT INTO dbo.ParentTable (I)
VALUES(1),(7),(9);
INSERT INTO dbo.ChildTable1 (FK,
S)
VALUES(1,'abc'),(3,'def');
INSERT INTO dbo.ChildTable2 (FK,
S)
VALUES(1,'xyz'),(2,'qwe');
INSERT INTO dbo.ChildTable3 (FK,
S)
VALUES(1,'123');
GO
SELECT *
FROM dbo.ParentTable PT
LEFT JOIN dbo.ChildTable1 CT1 ON PT.PK = CT1.PK
LEFT JOIN dbo.ChildTable2 CT2 ON PT.PK = CT2.PK
LEFT JOIN dbo.ChildTable3 CT3 ON PT.PK = CT3.PK;
--1, as we're going to DELETE that
SELECT *
FROM dbo.ChildTable1 CT1
WHERE CT1.FK = 1;
SELECT *
FROM dbo.ChildTable1 CT2
WHERE CT2.FK = 1;
SELECT *
FROM dbo.ChildTable1 CT3
WHERE CT3.FK = 1;
GO
--Perform the DELETE, which will CASCADE to the child tables.
DELETE FROM dbo.ParentTable
WHERE PK = 1;
GO
--no rows
SELECT *
FROM dbo.ParentTable PT
LEFT JOIN dbo.ChildTable1 CT1 ON PT.PK = CT1.PK
LEFT JOIN dbo.ChildTable2 CT2 ON PT.PK = CT2.PK
LEFT JOIN dbo.ChildTable3 CT3 ON PT.PK = CT3.PK;
SELECT *
FROM dbo.ChildTable1 CT1
WHERE CT1.FK = 1;
SELECT *
FROM dbo.ChildTable1 CT2
WHERE CT2.FK = 1;
SELECT *
FROM dbo.ChildTable1 CT3
WHERE CT3.FK = 1;
GO
DROP TABLE dbo.ChildTable3;
DROP TABLE dbo.ChildTable2;
DROP TABLE dbo.ChildTable1;
DROP TABLE dbo.ParentTable;
回答2:
In case if you do not want to alter your database schema, you could go for INSTEAD OF TRIGGER
.
Trigger allows you to perform any tasks when a particular action is performed. In this case, you can write INSTEAD OF DELETE
trigger on your parent/master table and inside trigger you can delete related entries from child tables. Have a look at below example.
CREATE TABLE dbo.Gestiones
(
id_gestione int IDENTITY (1, 1) PRIMARY KEY,
CUIT INT
);
CREATE TABLE dbo.ChildGestione1
(
ID INT IDENTITY PRIMARY KEY,
id_gestioneFK int REFERENCES Gestiones(id_gestione),
Description VARCHAR(100)
);
CREATE TABLE dbo.ChildGestione2
(
ID INT IDENTITY PRIMARY KEY,
id_gestioneFK int REFERENCES Gestiones(id_gestione),
Description VARCHAR(100)
);
CREATE TABLE dbo.ChildGestione3
(
ID INT IDENTITY PRIMARY KEY,
id_gestioneFK int REFERENCES Gestiones(id_gestione),
Description VARCHAR(100)
);
INSERT INTO dbo.Gestiones (CUIT)
VALUES (10), (20), (30), (40);
INSERT INTO dbo.ChildGestione1 (id_gestioneFK, Description)
VALUES (1,'abc'), (2,'efg');
INSERT INTO dbo.ChildGestione2 (id_gestioneFK, Description)
VALUES (1,'abc'), (3,'pqr');
INSERT INTO dbo.ChildGestione3 (id_gestioneFK, Description)
VALUES (1,'abc'), (3,'pqr'), (4,'stu');
GO
SELECT * FROM dbo.Gestiones
SELECT * FROM dbo.ChildGestione1
SELECT * FROM dbo.ChildGestione2
SELECT * FROM dbo.ChildGestione3
DELETE FROM Gestiones where CUIT = 10
SELECT * FROM dbo.Gestiones
SELECT * FROM dbo.ChildGestione1
SELECT * FROM dbo.ChildGestione2
SELECT * FROM dbo.ChildGestione3
CREATE TRIGGER InsteadOfDELETETriggerExample ON [Gestiones]
INSTEAD OF DELETE
AS
BEGIN
DECLARE @id_gestione INT
SELECT @id_gestione = id_gestione FROM deleted
IF @id_gestione IS NOT NULL
BEGIN
DELETE FROM ChildGestione1 WHERE id_gestioneFK = @id_gestione
DELETE FROM ChildGestione2 WHERE id_gestioneFK = @id_gestione
DELETE FROM ChildGestione3 WHERE id_gestioneFK = @id_gestione
/*...
and so on...you can right as many child tables as you have
*/
-- At the last, delete the entry from parent table
DELETE FROM Gestiones WHERE id_gestione = @id_gestione
END
PRINT 'Successfully deleted references of CUIT column from all the child tables.'
END
GO
DROP TRIGGER InsteadOfDELETETriggerExample
GO
DROP TABLE dbo.ChildGestione3;
DROP TABLE dbo.ChildGestione2;
DROP TABLE dbo.ChildGestione1;
DROP TABLE dbo.Gestiones;
Above code will work only for one delete entry on master table, if the delete operation is affecting more than one entry in parent table then you need to JOIN
the deleted
table with your child tables for deleting.
来源:https://stackoverflow.com/questions/60318835/create-procedure-that-deletes-data-from-several-tables-sql-server