[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

SQL Trigger with multiple insert statements not working

Posted on 2013-01-23
12
Medium Priority
?
519 Views
Last Modified: 2013-02-07
I have a trigger on one of my table that has multiple insert statements in it.  When the trigger kicks off it is only executing the first insert statement.  What do I need to do to get all of the insert statements to run.  Code attached.

ALTER TRIGGER [dbo].[UpdateForecastBreakdown]
   ON  [dbo].[Forecasts] 
   FOR Insert
AS 
Begin
INSERT INTO dbo.Forecasts_Breakdown(Forecast_KeyID, BreakdownType, lineorder, margin)
VALUES(@@IDENTITY, 'Labor', 1, 0)

INSERT INTO dbo.Forecasts_Breakdown(Forecast_KeyID, BreakdownType, lineorder, margin)
VALUES(@@IDENTITY, 'Subs/POs', 2, 0)


INSERT INTO dbo.Forecasts_Breakdown(Forecast_KeyID, BreakdownType, lineorder)
VALUES(@@IDENTITY, 'Materials', 3)

INSERT INTO dbo.Forecasts_Breakdown(Forecast_KeyID, BreakdownType, lineorder, margin)
VALUES(@@IDENTITY, 'Retainage', 4, 0)
end

Open in new window

0
Comment
Question by:imstac73
[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 40

Expert Comment

by:lcohan
ID: 38810743
You need to get a list of ALL the records identifier from INSERTED which is a internal SQL table and process them ALL one by one in a LOOP OR in a batch depending what you need to do.

So it would be something like:

DECLARE @rct int
SET @rct =      (select count(*) from INSERTED)

IF @rct = 1
BEGIN
      -- statements for single row to process here
END
ELSE IF @rct > 1
BEGIN

      DECLARE @id int
      DECLARE id_list CURSOR FOR (SELECT ID  FROM INSERTED)
      OPEN id_list
      FETCH next FROM id_list INTO @id
      WHILE @@fetch_status=0
            BEGIN

                  --statements to process one row from the batch
                  FETCH next FROM id_list INTO @id
            END

CLOSE id_list
DEALLOCATE id_list

END
0
 

Author Comment

by:imstac73
ID: 38810816
So would I put all my insert statements in both locations where you have '-statements'?  

I"m not sure how the code above helps as there will only be one record added to the triggered table at a time.  

The problem I"m having is that I need to insert 4 records in my breakdown table for every one record that is added to the triggered 'Forecasts' table. And currently the trigger runs the first insert line and then dies.
0
 
LVL 70

Accepted Solution

by:
Scott Pletcher earned 1000 total points
ID: 38810996
ALTER TRIGGER [dbo].[UpdateForecastBreakdown]
   ON  [dbo].[Forecasts]
   AFTER Insert
AS
INSERT INTO dbo.Forecasts_Breakdown (
    Forecast_KeyID, BreakdownType, lineorder, margin
)
SELECT
    $IDENTITY, BreakdownType, lineorder, 0
FROM inserted
CROSS JOIN (
    SELECT 'Labor' AS BreakdownType, 1 AS lineorder UNION ALL
    SELECT 'Subs/POs', 2 UNION ALL
    SELECT 'Materials', 3 UNION ALL
    SELECT 'Retainage', 4
) AS hardcoded_data
0
Get your Conversational Ransomware Defense e‑book

This e-book gives you an insight into the ransomware threat and reviews the fundamentals of top-notch ransomware preparedness and recovery. To help you protect yourself and your organization. The initial infection may be inevitable, so the best protection is to be fully prepared.

 

Author Comment

by:imstac73
ID: 38810997
I think I figured it out.  From your code I figured out that I need to assign the @@identity to a variable as the trigger maybe couldn't find the identity id after the first insert statement.  I did this and tested it and it worked with me manually inserting a record into the triggered table. I'm going to watch it and see if the next record added automatically also works.
0
 
LVL 70

Expert Comment

by:Scott Pletcher
ID: 38811000
That's not the best method.

Please refresh this q and look at my suggested code.
0
 
LVL 40

Expert Comment

by:lcohan
ID: 38811166
lets understand this correctly...you said that "...trigger runs the first insert line and then dies. "
so my understanding was that you do a batch operation (insert or a batch delete/update where the result would be the same) in the table therefor the trigger dies because of that.
Is this what is happening? Whet is the error when the "trigger runs the first insert line and then dies. '?
0
 

Author Comment

by:imstac73
ID: 38816683
I don't get an error..it just only adds the first insert record in my trigger code.  It is now working since I added the code to store the @@identity value in a variable and then call the variable within all the insert statements.
0
 
LVL 70

Expert Comment

by:Scott Pletcher
ID: 38816703
That is not an accurate method in any sense.  Good luck with that any time you insert more than one row at once, or a different trigger fires ahead of the current trigger, or any of a dozen other things.
0
 

Author Comment

by:imstac73
ID: 38852839
This trigger fires in response to another trigger. What is the correct method to do it then?
0
 

Author Comment

by:imstac73
ID: 38852867
Scott,
I am looking at your code posted: by: ScottPletcherPosted on 2013-01-23 at 11:27:41ID: 38810996 and I don't understand how this inserts 4 separate records.  To me it only looks like it inserts one record.

My process is as follows:
User enters record into Projects table
Trigger on Projects table inserts one record into Forecasts table
Trigger on Forecasts table  inserts four records into Forecasts_Breakdown table.
0
 
LVL 70

Expert Comment

by:Scott Pletcher
ID: 38852923
The CROSS JOIN generates the extra rows.

For example, run this SQL and you'll see that every input row gets joined to all 4 rows from the CROSS JOINed table:


SELECT
    ident, BreakdownType, lineorder
FROM (
    SELECT 1 AS ident UNION ALL
    SELECT 2
) AS inserted --simulate two "inserted" col values
CROSS JOIN (
    SELECT 'Labor' AS BreakdownType, 1 AS lineorder UNION ALL
    SELECT 'Subs/POs', 2 UNION ALL
    SELECT 'Materials', 3 UNION ALL
    SELECT 'Retainage', 4
) AS hardcoded_data
0
 
LVL 70

Expert Comment

by:Scott Pletcher
ID: 38864759
Just to clarify, a CROSS JOIN joins every row in the first table to every row in the second table.

So, if the first table had 10 rows, and the second table had 8 rows, a CROSS JOIN would produce 80 rows.
0

Featured Post

Learn Veeam advantages over legacy backup

Every day, more and more legacy backup customers switch to Veeam. Technologies designed for the client-server era cannot restore any IT service running in the hybrid cloud within seconds. Learn top Veeam advantages over legacy backup and get Veeam for the price of your renewal

Question has a verified solution.

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

Long way back, we had to take help from third party tools in order to encrypt and decrypt data.  Gradually Microsoft understood the need for this feature and started to implement it by building functionality into SQL Server. Finally, with SQL 2008, …
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.
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
This lesson discusses how to use a Mainform + Subforms in Microsoft Access to find and enter data for payments on orders. The sample data comes from a custom shop that builds and sells movable storage structures that are delivered to your property. …

649 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