【问题标题】:Update on a table using inner join in a trigger在触发器中使用内部联接更新表
【发布时间】:2022-10-01 12:36:08
【问题描述】:

我在数据库中有两个表,它们具有一对多的关系(例如:表dbo树[tree_id, tree_code] 有很多dbo.Fruits[id,姓名,father_tree_id,father_tree_code])。

我试图创建一个触发器,当 dbo.Frutos 的列 codigo_arvore_pai 被更新或插入到其中时,dbo.Frutos 的列father_tree_code 被更新为与 dbo.Tree 表的 tree_id 对应的值。条件是 dbo.Tree 的 code_tree 等于 code_tree_father ofdbo.Fruits.

CREATE TRIGGER [dbo].[tr_updateFruit] on [dbo].[Fruits]
AFTER INSERT, UPDATE
AS
    IF (UPDATE(father_tree_code))
    BEGIN
        UPDATE dbo.Fruits
        SET         id_arvore_pai = A.id_arvore 
        FROM        dbo.Fruits as obj
        INNER JOIN dbo.Tree A  ON  obj.father_tree_code  = A.tree_code
        WHERE obj.Id IN (SELECT DISTINCT obj.Id FROM dbo.Fruits) 
    END;

怎么了?

  • 不使用inserteddeleted 伪表的触发器是可疑的。您的IN 查询也没有意义,因为DISTINCT obj.Id 指的是外部表。因此,您实际上是在询问表中的 id 是否存在于同一个表中。
  • 那么如何进行这个更新过程呢?
  • Fruits 应该只保存father_tree_id,而不是father_tree_code。

标签: sql sql-server triggers


【解决方案1】:

实际上,当执行更新 SQL 服务器的命令时,首先删除记录,然后再次插入带有新更改的新记录,给用户一种错觉,即已对所需字段进行了编辑。但实际上,更新命令是一个由删除和插入组成的两步​​命令。首先,您必须指定执行的操作或命令的类型。出于这个原因,您可以在触发器内部使用以下代码:

DECLARE @WhatActionHappened as char(1);
    SET @WhatActionHappened = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
                         AND EXISTS(SELECT * FROM DELETED)
                        THEN 'U'  -- Set to Updated.
                        WHEN EXISTS(SELECT * FROM INSERTED)
                        THEN 'I'  -- Set to Insert.
                        WHEN EXISTS(SELECT * FROM DELETED)
                        THEN 'D'  -- Set to Deleted.
                        ELSE NULL -- Skip. It may have been a "failed delete".   
                    END)

之后,您可以按如下方式使用触发器进行插入和编辑。

CREATE TRIGGER [dbo].[tr_updateFruit] on [dbo].[Fruits]
AFTER INSERT, UPDATE
AS
    BEGIN
    DECLARE @WhatActionHappened as char(1);
        SET @WhatActionHappened = (CASE WHEN EXISTS(SELECT * FROM INSERTED)
                             AND EXISTS(SELECT * FROM DELETED)
                            THEN 'U'  -- Set to Updated.
                            WHEN EXISTS(SELECT * FROM INSERTED)
                            THEN 'I'  -- Set to Insert.
                            --WHEN EXISTS(SELECT * FROM DELETED)
                            --THEN 'D'  -- Set to Deleted.
                            ELSE NULL -- Skip. It may have been a "failed delete".   
                        END)
IF(@WhatActionHappened = 'U' OR @WhatActionHappened = 'I')
BEGIN
   UPDATE dbo.Fruits
        SET         id_arvore_pai = A.id_arvore 
        FROM        dbo.Fruits as obj
        INNER JOIN dbo.Tree A  ON  obj.father_tree_code  = A.tree_code
        WHERE obj.Id IN (SELECT DISTINCT i.Id FROM Inserted i) 
    END
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 2014-01-21
    相关资源
    最近更新 更多