【问题标题】:How to prevent a trigger from firing so that duplicate data is not entered into a table如何防止触发器触发,以免重复数据输入到表中
【发布时间】:2020-11-05 17:37:37
【问题描述】:

假设我有 3 个这样的表:

authorGenres (authorGenreId, authorId, isPublished)

bookLibrarys (bookLibraryId, authorGenreId, bookId)

bookList (bookId, authorId)

我创建了一个触发器,当authorGenres 中的行更新并且isPublished 列设置为1 时触发。

发生这种情况时,触发器会在bookLibrarys 表中插入一行,其中authorGenreId 列设置为在authorGenres 中更新的行

这是我的工作触发器:

ALTER TRIGGER [dbo].[setCorrectGenreAfterUpdate]
   ON  [dbo].[authorGenres]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;
    DECLARE @bookID AS NVARCHAR(50);
    DECLARE @bookLibraryId AS UNIQUEIDENTIFIER;
    DECLARE @author IDUNIQUEIDENTIFIER;
    SELECT @authorID = Inserted.authorID FROM inserted;

    SET @bookLibraryId = NEWID(); 
    SET @bookID = ( SELECT bookId 
                    FROM booklist nl 
                    WHERE nl.authorID = @authorID)

    INSERT INTO booklibrarys(bookLibraryID, parentBookID, genreID)
    SELECT @bookLibraryId, @bookID, genreID FROM Inserted

END

当我像UPDATE dbo.authorGenres SET isPublished = 1 WHERE genreID = 'C325061D-4274-487B-93F9-03BEB8B7D4D5' 这样进行测试更新时,它会工作并将新行插入bookLibrarys

问题是,如果我再次进行该更新,我会在 bookLibrarys 中获得另一个新行,具有相同的 authorGenreId 和 bookId,但是一个新的 bookLibraryId 因为它是在触发器中生成的。

有没有办法让触发器仅在 bookLibrarys 中不存在具有该 bookId 和 authorGenreId 的行时运行?

谢谢!

【问题讨论】:

  • 小心,您的触发器假定UPDATE 只影响一行;这根本不是真的。
  • @Larnu 对不起,我对触发器完全陌生。我在哪里犯这个错误?我需要解决这个问题。谢谢
  • @Larnu 谢谢我读了那个网站。您认为存储过程对于这种行为会更好吗?我选择触发器的原因是因为我可以让它自动运行。
  • @Larnu 感谢您的学习服务,这是一个很好的读者网站。尽管它说 2009 我认为它是好的。再次感谢

标签: sql-server sql-server-2012


【解决方案1】:

尝试使用 LEFT JOIN 来检查是否已经存在相同的记录,并确保有一个适用于多行的代码,正如 @Lamu 在 cmets 中向您建议的那样。

类似这样的:

ALTER TRIGGER [dbo].[setCorrectGenreAfterUpdate]
   ON  [dbo].[authorGenres]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO booklibrarys(bookLibraryID, parentBookID, genreID)
    SELECT NEWID(), bl.bookId, ins.genreID FROM Inserted ins
    INNER JOIN booklist bl ON bl.authorID = ins.authorID -- this is to get  bookId for each row, not for one like in variable
    LEFT JOIN booklibrarys blib ON blib.genreID = ins.genreID AND bl.bookId = 
blib.parentBookID
    WHERE blib.bookLibraryID is NULL
END

【讨论】:

  • 您的意思是在底部的INSERT 中处理多行?
  • 是的,不要在变量中存储任何东西,只需像使用表一样使用 Inserted :) 和 LEFT join 检查是否存在不会导致重复
  • 谢谢!我需要 bookList 中的 @bookID 怎么样?它也被插入到 bookLibrarys 的新行中。再次感谢您的学习。
  • 不,INSERT 语句插入的行数与更新后的行数一样多(并且还没有重复)。如果您更新一行 - 它将插入一行
  • 它不会单独出现,而是使用 WHERE rightTable.Id IS NULL。这就是通常的做法:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 2012-09-23
  • 1970-01-01
相关资源
最近更新 更多