更新触发器触发后,有一个EXISTS子句阻止更新

时间:2017-01-05 13:07:35

标签: sql sql-server triggers

当对包含另一个用户已存在的电子邮件地址的记录运行以下查询时,我的应用程序在数据库中的“更新后”触发器上抛出异常。换句话说,记录尚未更新,但由于EXISTS条款应该被忽略。

有人知道为什么可能会解雇这个事件吗?或者触发器是否应该测试一些标志以确保它是真正的更新?

我在禁用触发器后测试了我的代码,它完全符合预期,所以我假设我的查询是正确的。

电子邮件地址可以为空,但在数据库中必须是唯一的。

导致此问题的查询如下:

UPDATE users

SET EmailAddress = @emailaddress

WHERE

(

  RecID = @recid AND fk_Sites_RecID = @fk_sites_recid

  AND

  (

    /* Allow an update when address is being updated with a blank */

    ( @emailaddress = '' )

    /* Address isn't blank, so test it doesn't exist elsewhere */

    OR NOT EXISTS

    (

      SELECT * FROM users

      WHERE

      NOT ( RecID = @recid AND fk_Sites_RecID = @fk_sites_recid )

      AND RTRIM(LTRIM(COALESCE(EmailAddress,''))) = @emailaddress

    )

  )

)

1 个答案:

答案 0 :(得分:2)

在sql server中,只要update语句成功完成,就会触发更新后触发器,即使没有实际更新记录

来自CREATE TRIGGER MSDN page

  

仅在触发SQL语句后才执行AFTER触发器   已成功执行。

因此,您必须通过比较inserteddeleted表之间的数据来检查相关数据是否确实发生了变化。

这是一个简单的例子:

创建样本表并触发:

CREATE TABLE [dbo].[t] (
    [id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [text] [char](1) NOT NULL
);


CREATE TABLE [dbo].[t2](
    [id] [int] NOT NULL,
    [t] [char](1) NOT NULL
);


CREATE TRIGGER [dbo].[t_forupdate]
   ON  [dbo].[t]
   AFTER UPDATE
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    INSERT INTO t2 
    SELECT id, [text]
    FROM t 

END

插入样本数据:

INSERT INTO T VALUES ('a');

运行更新语句,不会更改表中的任何内容

UPDATE T 
SET [text] = 'b'
WHERE 1 = 0;

从样本表中选择:

SELECT *
FROM T2 

SELECT *
FROM T

结果:

t
id          t
----------- ----
1           a


t2
id          text
----------- ----
1           a