【问题标题】:MS SQL 2005 AFTER UPDATE trigger updating other row than updatedMS SQL 2005 AFTER UPDATE 触发器更新其他行而不是更新
【发布时间】:2010-10-19 16:11:20
【问题描述】:

作为一个经验很少或没有经验的用户,我必须在表上创建触发器(或寻找其他解决方案)。需要完成的是,当表中另一行的 ESB 列的值更改为“1”时,该列必须设置为“0”。

我的意图是使用 AFTER UPDATE 触发器来执行此操作。

ALTER TRIGGER [TR_PHOTO_UPD]
   ON    [SOA].[dbo].[photos_TEST]
   AFTER  UPDATE
AS 

DECLARE @ID  VARCHAR(10)
DECLARE @ESB  VARCHAR(1)

SELECT @ID  = (SELECT TOP(1) ID 
      FROM SOA.dbo.photos_TEST 
               WHERE esb = 'Q' 
               ORDER BY ARRIVALDATETIME ASC)
SELECT @ESB (SELECT esb FROM INSERTED)


IF @ESB = '1'
UPDATE SOA.dbo.photos_TEST SET esb = '0' WHERE ID = @I

你可能明白,这行不通,下一个触发器定义也行不通。

ALTER TRIGGER [TR_PHOTO_UPD]
   ON    [SOA].[dbo].[photos_TEST]
   AFTER  UPDATE
AS 

DECLARE @ID  VARCHAR(10)
DECLARE @ESB  VARCHAR(1)

SELECT @ID  = (SELECT TOP(1) ID 
      FROM SOA.dbo.photos_TEST 
               WHERE esb = 'Q' 
               ORDER BY ARRIVALDATETIME ASC)
SELECT @ESB (SELECT esb FROM INSERTED)


    IF @ESB = '1'
    BEGIN
  UPDATE SOA.dbo.photos_TEST 
  SET esb = '0'
  WHERE id = (SELECT TOP(1) ID 
       FROM SOA.dbo.photos_TEST 
       WHERE esb = 'Q' 
       ORDER BY ARRIVALDATETIME ASC)
    END

经过几个小时的谷歌搜索和尝试,我还没有发现为什么该行没有更新为“0”。我怀疑 AFTER UPDATE 触发器中的 UPDATE 是它不起作用的原因。有人有任何提示或更好的解决方案吗?

干杯,

彼得

【问题讨论】:

  • 看起来您希望在将值 1 插入 ESB 列时更新具有最近添加的 ID 的行,对吗?
  • 是的,完全正确。如果添加一行,则 ESB 的值为“Q”。触发器应将一行的值设置为“0”。在此之后,数据库适配器处理数据并将值从 0->R(eserved)->1(processed) 更改。如果存在 ESB='Q' 的行,则必须将一行(到达日期最早的)设置为 0 以启动处理。

标签: sql-server-2005 triggers


【解决方案1】:

在处理多个更新时,这两种方法都不起作用。

为什么您甚至需要逐案进行。还是不能在整个表中运行更新。

也许是这样的:

If Update(ESB)
    begin

       Update a
       Set AnotherColumn = 0
       From YourTable a
       Join inserted ins on a.Id = ins.Id
       Where ins.ESB = 1

    end

这会检查是否是更新的 ESB 列。如果是,则运行更新语句将 AnotherColumn 设置为零,其中 ESB 值为 1

我认为这应该适合你

【讨论】:

  • 嗨,巴里,不,它不起作用;从 SOA.dbo.photos_TEST 更新集合 a.esb = 0 a.Id = ins.Id 上插入的连接 其中 ins.ESB = 1 上面的更新触发器导致“行值更新或删除不要使该行唯一,否则它们会更改多行(2 行)。
  • @pcvnes - 你的表photos_TEST 有主键吗?或者你那里有重复的行?
  • @pcvnes - 还将SET NOCOUNT ON 添加到触发器定义的开头。
  • 存在重复行,不存在主键。重新创建表后,按照建议在触发器中重新填充并进行更改,触发器会更改更新的行。
  • 这似乎有效; SET NOCOUNT ON If (Update(ESB)) BEGIN IF ((SELECT esb FROM INSERTED) = '1') BEGIN UPDATE TOP(1) p SET p.esb = '0' FROM SOA.dbo.photos p WHERE p.esb = 'Q' END END 我明天再验证一下
【解决方案2】:

感谢巴里的帮助,如果最终确定了触发器;

    CREATE TRIGGER TR_PHOTO_AU
   ON          SOA.dbo.photos
   AFTER     UPDATE
AS 

DECLARE @MAXCONC INT  -- Maximum concurrent processes
DECLARE @CONC INT     -- Actual concurrent processes

SET @MAXCONC = 1      -- 1 concurrent process

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON

-- If column esb is involved in the update, does not necessarily mean
-- that the column itself is updated
If ( Update(ESB) )
BEGIN
    -- If column esb has been changed to 1
    IF ((SELECT esb FROM INSERTED) = '1')
    BEGIN
        -- count the number of (imminent) active processes
        SET @CONC = (SELECT COUNT(*) 
                  FROM SOA.dbo.photos pc
                  WHERE pc.esb in ('0','R'))

        -- if maximum has not been reached
        IF NOT ( @CONC >= @MAXCONC )
        BEGIN
            -- set additional rows esb to '0' to match @MAXCONC
               UPDATE TOP(@MAXCONC-@CONC) p2
               SET p2.esb = '0'
            FROM ( SELECT TOP(@MAXCONC-@CONC) p1.esb 
                   FROM SOA.dbo.photos  p1
                   WHERE  p1.esb = 'Q'
                   ORDER BY p1.arrivaldatetime ASC 

            ) p2

        END
    END
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多