2016-02-13 51 views
0

我使用SQL服务器2012年我写了这样一个触发器:触发器(UPDATE后)导致错误?

ALTER TRIGGER [dbo].[ModValue] 
    ON [dbo].[Table1] 
    AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 
    declare @ocid bigint 
    declare @ncid bigint,@pid bigint 

    set @ocid=(select CategoryId from deleted) 
    select @ncid=CategoryId,@pid=Id from inserted 

    if(@ocid<>@ncid) 
    begin 
    delete from [Table2] where [email protected] 
    delete from [Table3] where [email protected] 
    delete from [Table4] where [email protected] 
    end 
END 

当我想更新我的表(表1)我得到这个错误:

Msg 512, Level 16, State 1, Procedure ModValue, Line 15
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. The statement has been terminated.

更新查询:

update Table1 
set sizing = 0 
where categoryid = 238 

这个脚本有什么问题?

+5

你的触发器有** MAJOR **缺陷,因为你认为它会被称为每行**一次** - 这是**不是**的情况。它会在每个语句**中触发一次**。如果你的'UPDATE'语句更新了25行,你将会触发**触发**一次**,但是'Deleted'和'Inserted'伪表每个将包含25行。您的代码在这25行中选择哪一个? 'set @ ocid =(从删除中选择CategoryId)' - 这是非确定性的,你将得到**一个任意的行**,你将**忽略所有其他行**。你需要重写你的触发器来考虑这个问题! –

+0

谢谢@marc_s。那是我的答案。 – Mashtani

回答

1

我认为有以下线的问题是:

set @ocid=(select CategoryId from deleted) 

SET命令期望从SELECT声明至多1行。 deleted表可能包含多于1行,因为触发器会在batch级触发,而不是record级。

3

DELETEDINSERTED表可能包含多行。

  • DELETED - 包含了之前存在的修改(旧)
  • INSERTED数据 - 修改数据(新)。

所以,你必须找出CategoryID改为:

... 
from 
    Inserted new 
inner join 
    Deleted old on old.id = new.id 
where 
    new.CategoryID <> old.CategoryID 

做的东西,同时牢记可能有很多行,例如:

delete from [Table2] t2 
where exists (select 1 
       from Inserted new 
       inner join Deleted old on old.id = new.id 
       where new.CategoryID <> old.CategoryID 
       and t2.ProductId = d.ProductID) 

请注意,ProductID也可以通过UPDATE声明进行更改。