Create procedure that deletes data from several tables. SQL Server

早过忘川 提交于 2021-01-29 14:54:01

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!