Solved

Updating multiple rows with my trigger gives me a subquery error

Posted on 2010-11-25
12
320 Views
Last Modified: 2012-05-10
I have created the following SQL trigger which always returns an error when I run it on multiple rows, so if have more than 1 row and I execute "UPDATE TSDETAIL SET TSD_SUN=120" I get the error below.  When I execute with the KEY such as "UPDATE TSDETAIL SET TSD_SUN=120 WHERE TSD_KEY=1" , I do not get any errors.

My question is how do I write the trigger to work in both cases.

Msg 512, Level 16, State 1, Procedure UPDATE_TSD_RATES, Line 11
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.

ALTER TRIGGER [dbo].[UPDATE_TSD_RATES] ON [dbo].[TSDETAIL]
AFTER UPDATE
AS
DECLARE @v_rate1 NUMERIC(15,4)
DECLARE @v_rate2 NUMERIC(15,4)
DECLARE @v_min   NUMERIC(11)
DECLARE @tsd_key NUMERIC(11)
DECLARE @tsd_rat NUMERIC(11)

BEGIN
    SET @tsd_key=(SELECT TSD_KEY FROM inserted)
    SET @tsd_rat=(SELECT TSD_RAT FROM inserted)
    SET @v_rate1=(SELECT RAT_RATE1 FROM RATE WHERE RAT_KEY=@tsd_rat)
    SET @v_rate2=(SELECT RAT_RATE2 FROM RATE WHERE RAT_KEY=@tsd_rat)
    SET @v_min = (SELECT TSD_MON+TSD_TUE+TSD_WED+TSD_THU+TSD_FRI+TSD_SAT+TSD_SUN FROM inserted)

    UPDATE [dbo].[TSDETAIL] SET TSD_RATE1=@v_rate1, TSD_RATE2=@v_rate2, TSD_MIN=@v_min
      WHERE [dbo].[TSDETAIL].TSD_KEY = @TSD_KEY
END
0
Comment
Question by:hmstechsupport
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 5
  • 2
12 Comments
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 34213208
Hi,

As you also know that

when you run below query

UPDATE TSDETAIL SET TSD_SUN=120

This will update multiple rows.

so  SET @tsd_key=(SELECT TSD_KEY FROM inserted) will failed.

You can put (SELECT TOP 1 TSD_KEY FROM inserted) but this is not right way.

Best thing is update query with parameter.

or why you wanted to update multiple at a time????
0
 

Author Comment

by:hmstechsupport
ID: 34213225
The trigger works fine 1 row at a time, but I need to retroactively update the rows that are already in the table and the easiest way is an update statment.  I could write some PLSQL in a stored procedure to update 1 line at a time, but that seems like a long workaround.
Is there no way to write the TRIGGER in SQL to accomplish this?
0
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 34213227
or what you can do is....

You can remove trigger and update directly..

UPDATE TSDETAIL
SET TSD_SUN=120,
 TSD_RATE1=RAT_RATE1,
         TSD_RATE2=RAT_RATE2,
 TSD_MIN = TSD_MON+TSD_TUE+TSD_WED+TSD_THU+TSD_FRI+TSD_SAT+TSD_SUN
from TSDETAIL A INNER JOIN RATE B
ON A.TSD_RAT = B.RAT_KEY
WHERE TSD_KEY=1
0
More Than Just A Video Library

Train for your certification. Learn the latest DevOps tools. Grow your skillset to do better work.

At Linux Academy, we release new training modules every week so you'll always be up to date on the latest tech.

 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 34213244
Hi,

It might not be accomplish with trigger, if you can update in single query then that will more beneficial, in terms of performance and debugging view.

As you said I  could write some PLSQL in a stored procedure to update 1 line at a time, but that seems like a long workaround.

- It wont be....i dont think so

0
 

Author Comment

by:hmstechsupport
ID: 34213345
Ok.  I have written the stored procedure to accomplish the update and it works fine and accomplished the immediate solution to the problem, but my question about how to do this in a trigger remains unanswered.  Is there no answer to this?
0
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 34213493
0
 

Author Comment

by:hmstechsupport
ID: 34213599
Ok.  Thanks Brichsoft.  Unfortunate, but I guess that is the way it works.
0
 
LVL 70

Accepted Solution

by:
Qlemo earned 500 total points
ID: 34213764
Of course that is possible. You do not want to insert records, just update, and that is absolutely feasible. And here we go: The "secret" is to consider INSERTED and DELETED as temporary tables you need to join to. DELETED contains the old record, INSERTED the new one. As you do not need the old values here, we can ignore that one.
ALTER TRIGGER [dbo].[UPDATE_TSD_RATES] ON [dbo].[TSDETAIL] 
AFTER UPDATE 
AS
BEGIN
  UPDATE tbl
     SET TSD_RATE1 = RAT_RATE1 
         TSD_RATE2 = RAT_RATE2
         TSD_MIN   = TSD_MON+TSD_TUE+TSD_WED+TSD_THU+TSD_FRI+TSD_SAT+TSD_SUN
    FROM dbo.TSDETAIL tbl
    JOIN inserted i ON tbl.TSD_KEY = i.TSD_KEY
    JOIN RATE     r ON   i.TSD_RAT = r.RAT_KEY
END

Open in new window

0
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 34213834
I didnt said,its not possible.but does it require?

Wen u can do it without trigger then why trigger require?



0
 
LVL 70

Expert Comment

by:Qlemo
ID: 34213854
There are many reasons you want to have a trigger acting on the records you have updated:
* updating a secondary table
* no influence to the programming
* expansions which would else require to have the change done on many code lines
* supporting accumulated columns (like the TSD_MIN here).

The danger with such attempt is that is not directly derivable when seeing the query which tables are involved in a transaction. The RATE table would be part of the transaction, hence locked, though the query does not refer to it.
0
 

Author Comment

by:hmstechsupport
ID: 34213927
Ok.  I had to modify this a little as I do want it to work for Insert and Update so I added the INSERT clause and I had to make a few other minor changes adding commas and adding aliases to avoid ambiguity but this is EXACTLY what I hoped for.  Works like a charm in both inserting new rows and also running a big update statement.
Thank you Qlemo.
I also agree that the reason I do this is to avoid adding code to the application that ther clients do not require.  This trigger suits this client perfectly.

ALTER TRIGGER [dbo].[UPDATE_TSD_RATES] ON [dbo].[TSDETAIL]
AFTER INSERT,UPDATE
AS
BEGIN
  UPDATE tbl
     SET TSD_RATE1 = r.RAT_RATE1,
         TSD_RATE2 = r.RAT_RATE2,
         TSD_MIN   = tbl.TSD_MON+tbl.TSD_TUE+tbl.TSD_WED+tbl.TSD_THU+tbl.TSD_FRI+tbl.TSD_SAT+tbl.TSD_SUN
    FROM dbo.TSDETAIL tbl
    JOIN inserted i ON tbl.TSD_KEY = i.TSD_KEY
    JOIN RATE     r ON   i.TSD_RAT = r.RAT_KEY
END
0
 

Author Closing Comment

by:hmstechsupport
ID: 34213931
Fabulous and exactly what I was looking for.
0

Featured Post

SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article I will describe the Copy Database Wizard method as one possible migration process and I will add the extra tasks needed for an upgrade when and where is applied so it will cover all.
This post looks at MongoDB and MySQL, and covers high-level MongoDB strengths, weaknesses, features, and uses from the perspective of an SQL user.
In this video, viewers are given an introduction to using the Windows 10 Snipping Tool, how to quickly locate it when it's needed and also how make it always available with a single click of a mouse button, by pinning it to the Desktop Task Bar. Int…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question