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

Update fails because Subquery returned more than 1 value

虽然没有任何子查询,但当我尝试更新 table 时出现以下错误:

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

尝试像这样使用 distinct:

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

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

您可以使用不同的 return 唯一用户 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 );

触发器是按 语句 执行的,而不是按 执行的,这就是错误的来源。 您的触发器假定插入和删除的 table 只会有一行,但这是完全错误的。
inserted/deleted tables中的行数是DML语句影响的行数(update/insert/delete).

我不知道过程 calc_atten 做了什么,但你需要找到一种方法来在集合级别而不是像现在这样在标量变量上执行它的逻辑。

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

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
)

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

您的查询没问题。问题是触发器。 inserteddeleted 是 table(好吧,确实是视图,但这无关紧要),因此它们可以包含多行。

假设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 结构。但是,如果您需要遍历 table 并调用存储过程,那么它们是合适的。如果您可以将代码重写为基于集合,那么您就可以摆脱游标。