SQL Server Forums
Profile | Register | Active Topics | Members | Search | Forum FAQ
 
Register Now and get your question answered!
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Trigger failing from Multiple Inserts
 New Topic  Reply to Topic
 Printer Friendly
Author Previous Topic Topic Next Topic  

Ted75
Starting Member

Australia
4 Posts

Posted - 07/13/2012 :  02:54:23  Show Profile  Reply with Quote
Hi all, I know exactly what my problem is from research on this forum but I am not sure how to fix it. Any attempts made have not been successful. I have a trigger that fails when multiple records are inserted at once. Some say I need a cursor, some say NEVER use a cursor. I was hoping someone could re-write the following to make it fire for each inserted row. (I think it is just the variables declarations that need to be addressed and then the rest can be ignored)

Many thanks in advance.
ALTER TRIGGER [dbo].[TG_UPDATE_MBR_DEMOGRAPHICS] ON [dbo].[ER100_ACCT_ORDER]
AFTER UPDATE
AS
BEGIN
DECLARE	@ORG_CODE varchar(2)
SET		@ORG_CODE = (SELECT i.ER100_ORG_CODE FROM inserted i WITH (NOLOCK))

DECLARE	@EXT_ACCT_CODE varchar(10)
SET		@EXT_ACCT_CODE = (SELECT i.ER100_ORD_ACCT FROM inserted i WITH (NOLOCK))

DECLARE @ORD_TYPE varchar(2)
SET		@ORD_TYPE = (SELECT i.ER100_ORD_TYPE FROM inserted i WITH (NOLOCK))

DECLARE @ORD_NBR int
SET		@ORD_NBR = (SELECT i.ER100_ORD_NBR FROM inserted i WITH (NOLOCK))

DECLARE @ORD_DUE numeric(11,2)
SET		@ORD_DUE = (SELECT i.ER100_ACT_DUE FROM inserted i WITH (NOLOCK))
								 
DECLARE	@ORD_STS varchar(1)
SET		@ORD_STS = (SELECT i.ER100_NEW_STS FROM inserted i WITH (NOLOCK))

DECLARE	@RES_CODE varchar(12)
SET		@RES_CODE = (SELECT MAX(ER101_RES_CODE) FROM	ER101_ACCT_ORDER_DTL WITH (NOLOCK) 
												WHERE	ER101_ORG_CODE = @ORG_CODE AND ER101_ORD_NBR = @ORD_NBR AND 
														ER101_PHASE = '5' AND ER101_RES_CODE in ('AMABSENT', 'SDABSENT'))
														
DECLARE @NEW_MBR_CATEGORY varchar(6)
SET		@NEW_MBR_CATEGORY = (SELECT MRC02_MBR_CATEGORY FROM MRC02_CARD_NBR_MSTR WITH (NOLOCK) WHERE MRC02_RES_CODE = @RES_CODE)
	
DECLARE @NEW_MBR_TYPE varchar(6)
SET		@NEW_MBR_TYPE = (SELECT MRC02_MEMBER_TYPE FROM MRC02_CARD_NBR_MSTR WITH (NOLOCK) WHERE MRC02_RES_CODE = @RES_CODE)

DECLARE @MBR_STS varchar(4)
SET		@MBR_STS = (SELECT EV870_SALES_REGION	FROM	EV870_ACCT_MASTER WITH (NOLOCK)
												WHERE	EV870_ORG_CODE = @ORG_CODE AND EV870_ACCT_CODE = @EXT_ACCT_CODE)													

	-- FOR CLOSED, FULLY PAID ABSENTEE MEMBERSHIP ORDERS
	IF @ORD_STS = 'C' AND @ORD_DUE <= 0 AND @ORD_TYPE = 'MB' AND (@RES_CODE in ('AMABSENT', 'SDABSENT'))
	BEGIN
		-- UPDATE DESIGNATION
			UPDATE	EV870_ACCT_MASTER
			SET		EV870_MEMBER_DESIG =  '1'
			WHERE	EV870_MEMBER_DESIG <> '1' AND EV870_ORG_CODE = @ORG_CODE AND EV870_ACCT_CODE = @EXT_ACCT_CODE
			
		-- UPDATE DESIGNATION STATUS
			UPDATE	EV870_ACCT_MASTER
			SET		EV870_MEMBER_STS =  'A'
			WHERE	EV870_MEMBER_STS <> 'A' AND EV870_ORG_CODE = @ORG_CODE AND EV870_ACCT_CODE = @EXT_ACCT_CODE	
			
		-- UPDATE AR SECURITY CODE
			UPDATE	EV870_ACCT_MASTER
			SET		EV870_ACCT_SECURITY =  'MBR'
			WHERE	EV870_ACCT_SECURITY <> 'MBR' AND EV870_ORG_CODE = @ORG_CODE AND EV870_ACCT_CODE = @EXT_ACCT_CODE
			
		-- UPDATE MARKET SEGMENT
			UPDATE	EV870_ACCT_MASTER
			SET		EV870_MKT_SEG_1 = 'M', EV870_MKT_SEG_2 = 'MEM'
			WHERE	EV870_MKT_SEG_2 <> 'MEM' AND EV870_ORG_CODE = @ORG_CODE AND EV870_ACCT_CODE = @EXT_ACCT_CODE
			
		-- UPDATE MEMBERSHIP STATUS
			UPDATE	EV885_MEMBER_INFO
			SET		EV885_MEMBER_STS =  'A'
			WHERE	EV885_MEMBER_STS <> 'A' AND EV885_ORG_CODE = @ORG_CODE AND EV885_EXT_ACCT_CODE = @EXT_ACCT_CODE
						
		-- UPDATE MEMBER TYPE
			UPDATE	EV885_MEMBER_INFO
			SET		EV885_MEMBER_TYPE = @NEW_MBR_TYPE, EV885_MBR_TYPE_DATE = GETDATE()
			WHERE	EV885_MEMBER_TYPE <> @NEW_MBR_TYPE AND  
					EV885_ORG_CODE = @ORG_CODE AND EV885_EXT_ACCT_CODE = @EXT_ACCT_CODE
			
		-- UPDATE MEMBER CATEGORY
			UPDATE	EV885_MEMBER_INFO
			SET		EV885_MBR_CATEGORY = @NEW_MBR_CATEGORY, EV885_MBR_CAT_DATE = GETDATE()
			WHERE	EV885_MBR_CATEGORY <> @NEW_MBR_CATEGORY AND 
					EV885_ORG_CODE = @ORG_CODE AND EV885_EXT_ACCT_CODE = @EXT_ACCT_CODE
	
		-- UPDATE STATUS TYPE (SALES REGION)
			IF @MBR_STS IN ('NF', 'OF', 'LP', 'WT')
			BEGIN
				UPDATE	EV870_ACCT_MASTER
				SET		EV870_SALES_REGION = (CASE	WHEN @MBR_STS = 'OF' THEN 'NW'
													WHEN @MBR_STS = 'WT' THEN 'NW'
													WHEN @MBR_STS = 'NF' THEN 'RW'
													WHEN @MBR_STS = 'LP' THEN 'RW' 
												END)
				WHERE	EV870_ORG_CODE = @ORG_CODE AND EV870_ACCT_CODE = @EXT_ACCT_CODE
			END	
	END
END

sunitabeck
Flowing Fount of Yak Knowledge

5152 Posts

Posted - 07/13/2012 :  06:47:13  Show Profile  Reply with Quote
It is a lot of code to rewrite, so rather than do it all, I am going to demonstrate what needs to be done. In your code, you have a section where you are setting the value of two variables from data in the INSERTED table.:
DECLARE	@ORG_CODE varchar(2)
SET		@ORG_CODE = (SELECT i.ER100_ORG_CODE FROM inserted i WITH (NOLOCK))

DECLARE	@EXT_ACCT_CODE varchar(10)
SET		@EXT_ACCT_CODE = (SELECT i.ER100_ORD_ACCT FROM inserted i WITH (NOLOCK))
Then, further down, you use those two variables to update a column in a table.
-- UPDATE DESIGNATION
UPDATE	EV870_ACCT_MASTER
SET		EV870_MEMBER_DESIG =  '1'
WHERE	EV870_MEMBER_DESIG <> '1' 
	AND EV870_ORG_CODE = @ORG_CODE 
	AND EV870_ACCT_CODE = @EXT_ACCT_CODE

Instead of using those intermediate variables, which can hold only a scalar value, you should think of the INSERTED table as having more than one row and so join on the INSERTED table. So you would do something like this:
UPDATE	e
SET		EV870_MEMBER_DESIG =  '1'
FROM	EV870_ACCT_MASTER e
		INNER JOIN INSERTED i ON 
			e.EV870_ORG_CODE = i.ER100_ORG_CODE 
			AND e.EV870_ACCT_CODE = i.ER100_ORD_ACCT
WHERE	
	e.EV870_MEMBER_DESIG <> '1';
Go to Top of Page

Ted75
Starting Member

Australia
4 Posts

Posted - 07/16/2012 :  18:58:54  Show Profile  Reply with Quote
Many thanks. I understand what you have done. This is fine for the update statements but how do I incorporate this logic into the IF BEGIN statements? I only need the trigger to run for particular records.
Go to Top of Page

Ted75
Starting Member

Australia
4 Posts

Posted - 07/16/2012 :  19:32:19  Show Profile  Reply with Quote
Also, I am using a trigger with similar variable declarations to pass these to a stored procedure. I need to be able to pass values from each record in the INSERTED table to the SP. How do I do that? Sample code below. (Help really appreciated)

ALTER TRIGGER [dbo].[TG_ASSIGN_CARDS_ISSUE_UPDATE] ON [dbo].[CR073_ISSUES]
AFTER UPDATE
AS
BEGIN
DECLARE @ORG_CODE varchar(2)
SET @ORG_CODE = (SELECT CR073_ORG_CODE FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_CLASS char(1)
SET @ISSUE_CLASS = (SELECT CR073_ISSUE_CLASS FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_STS varchar(1)
SET @ISSUE_STS = (SELECT CR073_ISSUE_STS FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_TYPE varchar(2)
SET @ISSUE_TYPE = (SELECT CR073_ISSUE_TYPE FROM inserted WITH (NOLOCK))

DECLARE @ORD_NBR int
SET @ORD_NBR = (SELECT CR073_ORD_NBR FROM inserted WITH (NOLOCK))

DECLARE @UPDATE_FLAG varchar(3)
SET @UPDATE_FLAG = (SELECT CR073_TXT_02 FROM inserted WITH (NOLOCK))

-- ONLY FOR MEMBERSHIP CARD ISSUE TYPES
IF @ISSUE_CLASS = 'M' AND @ISSUE_TYPE IN (SELECT MRC02_ISSUE_TYPE
FROM MRC02_CARD_NBR_MSTR WITH (NOLOCK))
AND @UPDATE_FLAG = '002'
BEGIN

DECLARE @ISSUE_DESC varchar(255)
SET @ISSUE_DESC = (SELECT CR073_ISSUE_DESC FROM inserted WITH (NOLOCK))

DECLARE @EXT_ACCT_CODE varchar(10)
SET @EXT_ACCT_CODE = (SELECT CR073_EXT_ACCT_CODE FROM inserted WITH (NOLOCK))

DECLARE @OCCURENCE int
SET @OCCURENCE = (SELECT CR073_OCCURENCE FROM inserted WITH (NOLOCK))

DECLARE @USER_ID varchar(10)
SET @USER_ID = (SELECT CR073_UPD_USER_ID FROM inserted WITH (NOLOCK))

DECLARE @CURRENT_CARD_NUM varchar(10)
SET @CURRENT_CARD_NUM = (SELECT CR073_ISSUE_LOG_ID FROM inserted WITH (NOLOCK))

DECLARE @ORD_TOT numeric(11,2)
SET @ORD_TOT = (SELECT ER100_ACT_TOTAL FROM ER100_ACCT_ORDER WITH (NOLOCK) WHERE ER100_ORD_NBR = @ORD_NBR)

DECLARE @ORD_TAX numeric(11,2)
SET @ORD_TAX = (SELECT ER100_ACT_TAX FROM ER100_ACCT_ORDER WITH (NOLOCK) WHERE ER100_ORD_NBR = @ORD_NBR)

DECLARE @RES_TYPE varchar(6)
SET @RES_TYPE = (SELECT CR073_TXT_04 FROM inserted WITH (NOLOCK))

DECLARE @RES_CODE varchar(12)
SET @RES_CODE = (SELECT CR073_TXT_05 FROM inserted WITH (NOLOCK))

EXEC sp_Assign_Cards_Update
@ORG_CODE, @EXT_ACCT_CODE, @OCCURENCE, @ISSUE_CLASS, @ISSUE_STS,
@ISSUE_TYPE, @USER_ID, @UPDATE_FLAG, @CURRENT_CARD_NUM, @ISSUE_DESC,
@ORD_NBR, @ORD_TOT, @ORD_TAX, @RES_TYPE, @RES_CODE
END
END
Go to Top of Page

Deepak S
Starting Member

India
4 Posts

Posted - 07/17/2012 :  06:29:26  Show Profile  Reply with Quote
At any point of time, INSERTED will have only one record at a time. So, your current trigger should take care of it.

quote:
Originally posted by Ted75

Also, I am using a trigger with similar variable declarations to pass these to a stored procedure. I need to be able to pass values from each record in the INSERTED table to the SP. How do I do that? Sample code below. (Help really appreciated)

ALTER TRIGGER [dbo].[TG_ASSIGN_CARDS_ISSUE_UPDATE] ON [dbo].[CR073_ISSUES]
AFTER UPDATE
AS
BEGIN
DECLARE @ORG_CODE varchar(2)
SET @ORG_CODE = (SELECT CR073_ORG_CODE FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_CLASS char(1)
SET @ISSUE_CLASS = (SELECT CR073_ISSUE_CLASS FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_STS varchar(1)
SET @ISSUE_STS = (SELECT CR073_ISSUE_STS FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_TYPE varchar(2)
SET @ISSUE_TYPE = (SELECT CR073_ISSUE_TYPE FROM inserted WITH (NOLOCK))

DECLARE @ORD_NBR int
SET @ORD_NBR = (SELECT CR073_ORD_NBR FROM inserted WITH (NOLOCK))

DECLARE @UPDATE_FLAG varchar(3)
SET @UPDATE_FLAG = (SELECT CR073_TXT_02 FROM inserted WITH (NOLOCK))

-- ONLY FOR MEMBERSHIP CARD ISSUE TYPES
IF @ISSUE_CLASS = 'M' AND @ISSUE_TYPE IN (SELECT MRC02_ISSUE_TYPE
FROM MRC02_CARD_NBR_MSTR WITH (NOLOCK))
AND @UPDATE_FLAG = '002'
BEGIN

DECLARE @ISSUE_DESC varchar(255)
SET @ISSUE_DESC = (SELECT CR073_ISSUE_DESC FROM inserted WITH (NOLOCK))

DECLARE @EXT_ACCT_CODE varchar(10)
SET @EXT_ACCT_CODE = (SELECT CR073_EXT_ACCT_CODE FROM inserted WITH (NOLOCK))

DECLARE @OCCURENCE int
SET @OCCURENCE = (SELECT CR073_OCCURENCE FROM inserted WITH (NOLOCK))

DECLARE @USER_ID varchar(10)
SET @USER_ID = (SELECT CR073_UPD_USER_ID FROM inserted WITH (NOLOCK))

DECLARE @CURRENT_CARD_NUM varchar(10)
SET @CURRENT_CARD_NUM = (SELECT CR073_ISSUE_LOG_ID FROM inserted WITH (NOLOCK))

DECLARE @ORD_TOT numeric(11,2)
SET @ORD_TOT = (SELECT ER100_ACT_TOTAL FROM ER100_ACCT_ORDER WITH (NOLOCK) WHERE ER100_ORD_NBR = @ORD_NBR)

DECLARE @ORD_TAX numeric(11,2)
SET @ORD_TAX = (SELECT ER100_ACT_TAX FROM ER100_ACCT_ORDER WITH (NOLOCK) WHERE ER100_ORD_NBR = @ORD_NBR)

DECLARE @RES_TYPE varchar(6)
SET @RES_TYPE = (SELECT CR073_TXT_04 FROM inserted WITH (NOLOCK))

DECLARE @RES_CODE varchar(12)
SET @RES_CODE = (SELECT CR073_TXT_05 FROM inserted WITH (NOLOCK))

EXEC sp_Assign_Cards_Update
@ORG_CODE, @EXT_ACCT_CODE, @OCCURENCE, @ISSUE_CLASS, @ISSUE_STS,
@ISSUE_TYPE, @USER_ID, @UPDATE_FLAG, @CURRENT_CARD_NUM, @ISSUE_DESC,
@ORD_NBR, @ORD_TOT, @ORD_TAX, @RES_TYPE, @RES_CODE
END
END




Deepak S
Go to Top of Page

DonAtWork
Flowing Fount of Yak Knowledge

2113 Posts

Posted - 07/17/2012 :  07:52:30  Show Profile  Reply with Quote
quote:
Originally posted by Deepak S

At any point of time, INSERTED will have only one record at a time. So, your current trigger should take care of it.

Deepak S


Since when?

create table #foo (ar int, gb char(1))
create table #bar (ar int, gb char(1))

insert into #foo
output inserted.ar,inserted.gb
	into #bar
values (1,'3'),(2,'f'),(6,'p')

select * from #bar

looks like 3 rows to me...









How to ask: http://weblogs.sqlteam.com/brettk/archive/2005/05/25/5276.aspx

Go to Top of Page

sunitabeck
Flowing Fount of Yak Knowledge

5152 Posts

Posted - 07/17/2012 :  08:11:13  Show Profile  Reply with Quote
quote:
Originally posted by Ted75

Many thanks. I understand what you have done. This is fine for the update statements but how do I incorporate this logic into the IF BEGIN statements? I only need the trigger to run for particular records.

You can incorporate those also into the WHERE clause like this:
UPDATE	e
SET		EV870_MEMBER_DESIG =  '1'
FROM	EV870_ACCT_MASTER e
		INNER JOIN INSERTED i ON 
			e.EV870_ORG_CODE = i.ER100_ORG_CODE 
			AND e.EV870_ACCT_CODE = i.ER100_ORD_ACCT
WHERE	
	e.EV870_MEMBER_DESIG <> '1'
	AND i.ER100_NEW_STS = 'C'
	AND i.ER100_ACT_DUE <= 0
	AND i.ER100_ORD_TYPE = 'MB'
The @RES_CODE appears to be a MAX value with some additional conditions. You may need to first select those into a temp table (rather than a scalar variable as you have) or a subquery and join with that. I couldn't understand enough about the logic to suggest what needs to be done, but if you get stuck, reply and we will figure it out.
Go to Top of Page

sunitabeck
Flowing Fount of Yak Knowledge

5152 Posts

Posted - 07/17/2012 :  08:19:14  Show Profile  Reply with Quote
quote:
Originally posted by Ted75

Also, I am using a trigger with similar variable declarations to pass these to a stored procedure. I need to be able to pass values from each record in the INSERTED table to the SP. How do I do that? Sample code below. (Help really appreciated)

ALTER TRIGGER [dbo].[TG_ASSIGN_CARDS_ISSUE_UPDATE] ON [dbo].[CR073_ISSUES]
AFTER UPDATE
AS
BEGIN
DECLARE @ORG_CODE varchar(2)
SET @ORG_CODE = (SELECT CR073_ORG_CODE FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_CLASS char(1)
SET @ISSUE_CLASS = (SELECT CR073_ISSUE_CLASS FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_STS varchar(1)
SET @ISSUE_STS = (SELECT CR073_ISSUE_STS FROM inserted WITH (NOLOCK))

DECLARE @ISSUE_TYPE varchar(2)
SET @ISSUE_TYPE = (SELECT CR073_ISSUE_TYPE FROM inserted WITH (NOLOCK))

DECLARE @ORD_NBR int
SET @ORD_NBR = (SELECT CR073_ORD_NBR FROM inserted WITH (NOLOCK))

DECLARE @UPDATE_FLAG varchar(3)
SET @UPDATE_FLAG = (SELECT CR073_TXT_02 FROM inserted WITH (NOLOCK))

-- ONLY FOR MEMBERSHIP CARD ISSUE TYPES
IF @ISSUE_CLASS = 'M' AND @ISSUE_TYPE IN (SELECT MRC02_ISSUE_TYPE
FROM MRC02_CARD_NBR_MSTR WITH (NOLOCK))
AND @UPDATE_FLAG = '002'
BEGIN

DECLARE @ISSUE_DESC varchar(255)
SET @ISSUE_DESC = (SELECT CR073_ISSUE_DESC FROM inserted WITH (NOLOCK))

DECLARE @EXT_ACCT_CODE varchar(10)
SET @EXT_ACCT_CODE = (SELECT CR073_EXT_ACCT_CODE FROM inserted WITH (NOLOCK))

DECLARE @OCCURENCE int
SET @OCCURENCE = (SELECT CR073_OCCURENCE FROM inserted WITH (NOLOCK))

DECLARE @USER_ID varchar(10)
SET @USER_ID = (SELECT CR073_UPD_USER_ID FROM inserted WITH (NOLOCK))

DECLARE @CURRENT_CARD_NUM varchar(10)
SET @CURRENT_CARD_NUM = (SELECT CR073_ISSUE_LOG_ID FROM inserted WITH (NOLOCK))

DECLARE @ORD_TOT numeric(11,2)
SET @ORD_TOT = (SELECT ER100_ACT_TOTAL FROM ER100_ACCT_ORDER WITH (NOLOCK) WHERE ER100_ORD_NBR = @ORD_NBR)

DECLARE @ORD_TAX numeric(11,2)
SET @ORD_TAX = (SELECT ER100_ACT_TAX FROM ER100_ACCT_ORDER WITH (NOLOCK) WHERE ER100_ORD_NBR = @ORD_NBR)

DECLARE @RES_TYPE varchar(6)
SET @RES_TYPE = (SELECT CR073_TXT_04 FROM inserted WITH (NOLOCK))

DECLARE @RES_CODE varchar(12)
SET @RES_CODE = (SELECT CR073_TXT_05 FROM inserted WITH (NOLOCK))

EXEC sp_Assign_Cards_Update
@ORG_CODE, @EXT_ACCT_CODE, @OCCURENCE, @ISSUE_CLASS, @ISSUE_STS,
@ISSUE_TYPE, @USER_ID, @UPDATE_FLAG, @CURRENT_CARD_NUM, @ISSUE_DESC,
@ORD_NBR, @ORD_TOT, @ORD_TAX, @RES_TYPE, @RES_CODE
END
END


To begin with, my comment (which I hope you don't find condescending or offensive) is that doing a whole lot of things in a trigger is not a good thing.

If you find that you need to call additional stored procedures and pass the variables etc., there is something not quite right with the design - there is room for improvement and such complexities can probably be avoided.

If you must do those, the way to do it would be to pass in the data in a table variable or temp table. Take a look at Sommarskog's article here on how to do that: http://www.sommarskog.se/share_data.html

I have never tried to send data in a table or temp table from a trigger into another stored proc, so this is theoretical for me as well.

Edited by - sunitabeck on 07/17/2012 08:19:44
Go to Top of Page

Ted75
Starting Member

Australia
4 Posts

Posted - 07/17/2012 :  23:39:38  Show Profile  Reply with Quote
Not at all Sunitabeck. I very much appreciate your help. The need for these triggers to to make up for a lack in critical functionality in our ERP system. I'll research your link and see how I go.

Thanks!
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
 Printer Friendly
Jump To:
SQL Server Forums © 2000-2009 SQLTeam Publishing, LLC Go To Top Of Page
This page was generated in 0.11 seconds. Powered By: Snitz Forums 2000