【问题标题】:SQL Server for delete trigger to delete records in other table with procedureSQL Server 用于删除触发器以使用过程删除其他表中的记录
【发布时间】:2015-11-01 18:27:01
【问题描述】:

我有一张像 table1 (table1_id, col1, some_ID) 和另一张 table2 (table2_id, col1, table1_id) 这样的桌子

我有一个程序

PROC deleteTable2(@id int)
AS
BEGIN 
    DELETE table2 
    WHERE table1_id = @id
END

我正在尝试为table1 表创建删除触发器,因此当我尝试从table1 中删除时,触发器将删除table2 中的所有记录。

我是这样写触发器的:

CREATE TRIGGER deleteTable1 on table1
FOR DELETE
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @id int = 0

    SELECT @id = del.table1_ID from deleted as del

    EXECUTE dbo.deleteTable2 @id

如果some_ID 只有一条记录,它可以工作,但如果有更多记录,它就不起作用。例如:

delete table1 
where some_ID='some value'

此 SQL 查询将删除 table1 中的所有记录,并且只删除 table2 中的第一个记录。

有道理,所以我用 CURSOR 做了一个触发器,类似于

CREATE TRIGGER deleteTable1 ON table1
FOR DELETE
AS
BEGIN
    DECLARE @id int = 0, @CURSOR cursor

    SET @CURSOR = CURSOR scroll FOR 
       SELECT deleted.table1_id 
       FROM deleted

    OPEN @CURSOR
    FETCH NEXT FROM @CURSOR into @id

    WHILE @@FETCH_STATUS = 0
    BEGIN
          EXECUTE dbo.deleteTable2 @id
          FETCH NEXT FROM @CURSOR into @id
    END
    CLOSE @CURSOR
END

但它根本不起作用......也许我只是错过了一些东西或者我没有得到一些细微差别。谢谢。

更新

事实上,这 2 个表在一个 db 中,但我有第 3 个表 table3 (table3_id, col1, table2_id)。而这个table3 在其他数据库中,它们通过链接服务器连接。因此,当我尝试调用存储过程时,此存储过程会调用存储过程(带有游标)来删除table3 中的记录。这就是我尝试使用存储过程删除 table2 中记录的确切原因。

【问题讨论】:

  • PLEASE .... 触发器应该快速、小巧、灵活 - 一切都是光标 绝对不是!请不要在触发器中使用 CURSOR(所有事物)来杀死您的系统!这太糟糕了......使用@M.Ali 在他的回复中显示的基于集合的方法 - 总是。触发器中的游标是任何 SQL Server 数据库的最糟糕的噩梦!在任何情况下都不要这样做!

标签: sql-server triggers cursors


【解决方案1】:

避免使用所有这些不必要的游标和存储过程。只需遵循基于集合的方法并在触发器中执行以下操作。

CREATE TRIGGER deleteTable1 on table1
FOR DELETE
AS
BEGIN
SET NOCOUNT ON

Delete FROM Table2 
WHERE Exists (SELECT 1 
              FROM deleted del
              WHERE del.table1_ID = table2.Table1_ID)             

END

更新

既然您提到您也想从第三个表中删除记录,该表位于链接服务器上的某个位置。

我建议您使用相同的方法,只需在链接服务器上的第三个表的过程中添加另一个删除语句。

CREATE TRIGGER deleteTable1 on table1
FOR DELETE
AS
BEGIN
SET NOCOUNT ON

Delete FROM Table2 
WHERE Exists (SELECT 1 
              FROM deleted del
              WHERE del.table1_ID = table2.Table1_ID)             

DELETE FROM t3
FROM [LinkedServerName].[DBName].[SchemaName].Table3 t3 
WHERE Exists (SELECT 1 
              FROM deleted del
              WHERE del.table1_ID = t3.Table1_ID)             


END

【讨论】:

  • table3 与 table2 连接,而不是 table1。此外,我很确定触发器不起作用,因为“另一个会话正在使用事务上下文”问题。因为我们不能像在 MS Sql 中那样从其他数据库中删除。
【解决方案2】:
CREATE TRIGGER deleteTable1 on table1
FOR DELETE
AS
BEGIN
    SET NOCOUNT ON
    DELETE FROM table2 WHERE table1_id IN (SELECT table1_id FROM deleted)
END

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    相关资源
    最近更新 更多