更新失败,因为子查询返回的值超过1

时间:2016-02-07 12:11:27

标签: sql sql-server sql-update subquery inner-join

我尝试更新我的表时遇到以下错误,尽管没有任何子查询:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 

我的查询:

UPDATE  t1 
SET t1.modified = 2
FROM TransActions AS t1
INNER JOIN Ruser R
ON t1.USERID = r.USERID
WHERE  r.dep_code = 54 and r.dep_year =2014
and YEAR(t1.checktime) =2016 and MONTH(t1.checktime) =1 and  t1.modified   = 0

选择的数据如下:

USERID  empNum
3090    25
3090    25
2074    464

根据评论我的更新触发器:

after update 
as

declare @userid int , @date date 


if (select userid from inserted)<>(select userid from deleted )
raiserror ('YOU ARE NOT ALLOWED TO PERFORME THIS ACTION',10 , 1)
ELSE
begin 
    set nocount on;

    set @userid = (select userid from inserted)
    set @date = (select convert(date , checktime) from inserted)


    exec calc_atten @date , @userid 
end

4 个答案:

答案 0 :(得分:3)

触发器按语句执行,而不是按执行,这是您的错误来源。 你的触发器假设插入和删除的表只有一行,但这是完全错误的 插入/删除表中的行数是受DML语句影响的行数(更新/插入/删除)。

我不知道程序calc_atten的作用,但你需要找到一种方法来在设定的级别上执行它的逻辑,而不是现在的标量变量。< / p>

应该更改触发开始时的条件以适应多行更新。 一种方法是:(如果我知道表的结构,我可能会写得更短更好)

IF EXISTS (
    SELECT 1
    FROM deleted d 
    INNER JOIN inserted i
    ON d.[unique row identifier] = i.[unique row identifier]
    WHERE i.userId <> d.UserId
)

* [唯一行标识符]表示该表中每行唯一的列或列组合。如果唯一行标识符包含UserId列,那么这将无法正常工作。

答案 1 :(得分:2)

您的查询没问题。问题是触发器。 inserteddeleted是表格(嗯,实际上是视图但不相关),因此它们可以包含多行。

假设transactions有主键,您可以通过执行

来检查更新
declare @userid int , @date date ;

if (exists (select 1
            from inserted i
            where not exists (select 1
                              from deleted d
                              where d.transactionid = i.transactionid and
                                    d.userid <> i.userid
                             )
           )
   )
begin
    raiserror ('Changing user ids is not permitted', 10 , 1);
end;
else begin 
    set nocount on;

    declare icursor cursor for select userid, checktime from inserted;
    open icursor;

    fetch next from icursor into @userid, @date;

    while not @@FETCH_STATUS = 0
    begin
        exec calc_atten @date, @userid 
        fetch next from icursor into @userid, @date;
    end;

   close icursor; deallocate icursor;
end;

游标不是我最喜欢的SQL构造。但是,如果您需要遍历表并调用存储过程,那么它们是合适的。如果你可以重写基于集合的代码,那么你可以摆脱光标。

答案 2 :(得分:0)

尝试使用不同的方式:

UPDATE  t1 
SET t1.modified = 2
FROM TransActions AS t1
INNER JOIN (select distinct userid from Ruser
            where r.dep_code = 54 and r.dep_year = 2014 ) R
ON t1.USERID = r.USERID
WHERE YEAR(t1.checktime) =2016 and MONTH(t1.checktime) =1 and  t1.modified   = 0

顺便说一句 - 我在这里看不到任何子查询,所以很奇怪你得到的错误,我感觉错误不会因为代码的那部分而发生。

答案 3 :(得分:0)

您可以使用distinct返回唯一的用户ID:

UPDATE TransActions 
SET modified = 2
WHERE YEAR(checktime) = 2016
AND   MONTH(checktime = 1
AND   modified = 0
AND   userid IN ( SELECT DISTINCT userid FROM Ruser r WHERE  r.dep_code = 54 and r.dep_year =2014 );