SQL Server:每次触发触发

时间:2018-01-07 16:32:39

标签: sql sql-server database triggers constraints

对于我的学校项目,我需要为我的SQL Server数据库添加一个触发器。我决定在Users表上使用“无双用户名”触发器是相关的。

问题是,每次执行INSERT查询时都会触发此触发器。我无法弄清楚为什么每次都会发生这种情况。我甚至试过不同的方法来编写触发器。

我现在拥有的触发器:

CREATE TRIGGER [Trigger_NoDuplicates]
ON [dbo].[Users]
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON

    IF(EXISTS(SELECT Username FROM Users 
              WHERE Username = (SELECT Username FROM inserted)))
    BEGIN;
        RAISERROR('This username already exists!',15, 0)
        ROLLBACK
    END
END

提前致谢!

1 个答案:

答案 0 :(得分:2)

触发器每次都会触发,你的意思是“每次都会引发错误”吗?

您目前拥有以下(扩展为多行以使其更清晰)...

IF (
  EXISTS (
    SELECT Username
      FROM users
     WHERE Username = (SELECT Username FROM inserted)
  )
)

这里的关键点是表inserted的名称。过去式。它已经发生了。

inserted表格中的任何内容已将 插入目标表格中。

那么,您需要检查的是用户名在目标表中 more 而不是一次。

但是 ,可以一次将多个记录插入到表中。这意味着Username = (SELECT Username FROM inserted)会导致自己的错误。 (您无法将单个值与一组值进行比较,inserted可以包含多个行=>多个用户名...)

这就是我接近你的触发器的方式......

IF EXISTS (
  SELECT
    users.Username
  FROM
    users
  INNER JOIN
    inserted
      ON  inserted.Username = users.Username
  GROUP BY
    users.Username
  HAVING
    COUNT(*) > 1
)

这将获取(已插入到)用户表,并使用inserted表中的任何记录选取所有mach用户名的记录。

然后GROUPusername字段显示它们。

然后它将结果过滤到包含多于1条记录的组。

这些(用户名)组具有重复的条目,应该会导致触发器引发错误。


替代方案与您的方法更相似,但很多人不会认出来,所以我一般不会推荐它...

IF EXISTS (
  SELECT
    users.Username
  FROM
    users
  WHERE
    users.Username = ANY (SELECT username FROM inserted)
  GROUP BY
    users.Username
  HAVING
    COUNT(*) > 1
)

ANY关键字很少使用,但听起来像是听起来像。它允许将单个值与一组值进行比较。


最后,如果您的表格中有IDENTITY列,则可以通过明确声明您不想将某行与自身进行比较来避免GROUP BY ...

IF EXISTS (
  SELECT
    users.Username
  FROM
    users
  INNER JOIN
    inserted
      ON  inserted.Username  = users.Username
      AND inserted.id       <> users.id
)