【问题标题】:Create procedure that deletes data from several tables. SQL Server创建从多个表中删除数据的过程。 SQL 服务器
【发布时间】:2020-06-04 17:07:46
【问题描述】:

我需要创建一个过程,允许我一次从多个表中删除数据,搜索CUIT。这里显示了四个表:

我必须传入一个CUIT 值,如果它与数据库中保存的任何项目匹配,我需要将其删除。我找不到能够一次擦除两个以上表的语法,如果你能帮我一把,我将不胜感激。我怀疑该过程实际上要大得多,总共大约有 12 个表,但由于我只对传递此片段的语法感兴趣。

我在尝试使用 INNER JOIN 加入表格时遇到问题。

我使用的是 SQL Server 2016。谢谢

【问题讨论】:

  • “我找不到能够同时擦除两个以上表的语法”,因为没有这样的语法。 DML 语句一次只能影响一个表。考虑到您想从 4 个表中 DELETE,这意味着您将需要 4 个 DELETE 语句。
  • 那我该怎么做呢?什么用于执行这些类型的操作?因为我需要删除与该 CUIT 相关的所有信息,以及是否必须在表之间建立任何关系。谢谢

标签: sql-server stored-procedures sql-delete


【解决方案1】:

如果您不想更改数据库架构,可以选择INSTEAD OF TRIGGER

触发器允许您在执行特定操作时执行任何任务。在这种情况下,您可以在父/主表上编写INSTEAD OF DELETE 触发器,在触发器内部,您可以从子表中删除相关条目。看看下面的例子。

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;

以上代码仅适用于主表中的一个删除条目,如果删除操作影响父表中的多个条目,则您需要将JOINdeleted 表与您的子表一起删除。

【讨论】:

    【解决方案2】:

    考虑到您的设计,我会在您的外键上实现级联。这是一个示例,但应该让您走上正确的道路:

    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;
    

    【讨论】:

      猜你喜欢
      • 2019-07-02
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多