问题
I Get the following error when i try to update my table although there's n't any sub query :
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
MY QUERY :
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
The data selected like this :
USERID empNum
3090 25
3090 25
2074 464
According to the comments my update trigger :
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
回答1:
Triggers are executed per statement, not per row, that's the source of your error.
Your trigger assumes that the inserted and deleted tables will only ever have one row, however that is simply wrong.
The number of rows in the inserted / deleted tables is the number of rows effected by the DML statement (update/insert/delete).
I don't know what the procedure calc_atten
does, but you need to find a way to execute it's logic on a set level and not on scalar variables as it does now.
Your condition at the beginning of the trigger should be changed to fit a multi-row update. One way to do it is this: (I could probably write it shorter and better if I would have known the table's structure)
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
)
*[unique row identifier] stands for any column or column combination that is unique per row in that table. If the unique row identifier contains the UserId column then this will not work properly.
回答2:
Your query is ok. The problem is the trigger. inserted
and deleted
are tables (well, really views but that is irrelevant), so they can contain multiple rows.
Assuming that transactions
has a primary key, you can check the update by doing
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;
Cursors are not my favorite SQL construct. But, if you need to loop through a table and call a stored procedure, then they are appropriate. If you can rewrite the code to be set-based, then you can get rid of the cursor.
回答3:
Try using distinct like this:
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
BTW - I don't see any subquery here, so its weird thats the error you get, I have a feeling the error doesn't occurs because of that part of the code.
回答4:
You can use distinct to return unique userid's:
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 );
来源:https://stackoverflow.com/questions/35253299/update-fails-because-subquery-returned-more-than-1-value