Solved

SQL Server Trigger for INSERT, UPDATE is not working

Posted on 2016-10-27
9
73 Views
Last Modified: 2016-11-14
Hi Experts,

I have created a trigger on my table (FOR INSERT, UPDATE), when I tried to update one record only using below query, the trigger is working fine and give me the correct message:

Update y table
set id = 1 WHERE name = Jhon

Open in new window




But, When I tried to update that table based on another table "it will update more than 1 record using join" using below query it doesn't work.
update y
set y.column= x.column
from Y
    inner join x on
        x.id = y.id

Open in new window


So, how can I fix this issue.
Thanks a lot in advance.
0
Comment
Question by:Harreni
  • 2
  • 2
  • 2
  • +2
9 Comments
 
LVL 47

Expert Comment

by:Vitor Montalvão
ID: 41862021
So, how can I fix this issue.
That depends on how you built your trigger. Without the trigger code we can't help you.
0
 
LVL 28

Expert Comment

by:Pawan Kumar
ID: 41862034
Trigger code pls?
0
 
LVL 12

Assisted Solution

by:Dimitris
Dimitris earned 125 total points
ID: 41862120
your trigger code should use the INSERTED and DELETED tables
So I assume that in your Trigger you are just reading the values from these tables in local variables (@)
If you are updating a table in batch you should use something like this

CREATE TRIGGER MyTrigger ON MyTable
FOR INSERT
AS
--for example insert into a secondary table
INSERT INTO SECONDTABLE (FIELD1,FIELD1)
SELECT FIELDx1, FIELDx2
FROM INSERTED
-------------------
If the trigger is insert  trigger you only have INSERTED (new values)
if is an Update trigger you have INSERTED (new values) and DELETED (Old Values)
and in case of a delete trigger you only have Deleted

Nevertheless, the trigger code would help even more :)
0
Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

 

Author Comment

by:Harreni
ID: 41862292
ALTER TRIGGER [dbo].[TRG_ForInsertAndUpdate]  ON MyTable
FOR INSERT, UPDATE
 
AS

DECLARE @SID nvarchar(20)
DECLARE @CID nvarchar(10)
DECLARE @DID nvarchar(10)

SELECT @SID = SID from inserted
SELECT @CID = CID from inserted


BEGIN TRANSACTION
BEGIN TRY
	
		if (SELECT 
				  PID 
				  FROM tb_Dataset CMD
				  WHERE CMD.DID= @DID)= @CID
		 
		BEGIN
	
					RAISERROR(N'CID are Same As PID ', 11, 1);
					INSERT INTO [dbo].[tb_Log](SID,CID)
					Values (@SID, @CID)
			
		END

END TRY

BEGIN CATCH  
    SELECT   
        ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_SEVERITY() AS ErrorSeverity  
        ,ERROR_STATE() AS ErrorState  
        ,ERROR_PROCEDURE() AS ErrorProcedure  
        ,ERROR_LINE() AS ErrorLine  
        ,ERROR_MESSAGE() AS ErrorMessage;  
  
      IF @@TRANCOUNT > 0  
        ROLLBACK TRANSACTION;  
		PRINT ERROR_MESSAGE();
END CATCH;  

IF @@TRANCOUNT > 0  
    COMMIT TRANSACTION;  

Open in new window

0
 
LVL 47

Assisted Solution

by:Vitor Montalvão
Vitor Montalvão earned 125 total points
ID: 41862311
In that case try to work with a cursor:
ALTER TRIGGER [dbo].[TRG_ForInsertAndUpdate]  ON MyTable
FOR INSERT, UPDATE
 
AS

DECLARE @SID nvarchar(20)
DECLARE @CID nvarchar(10)
DECLARE @DID nvarchar(10)

BEGIN TRANSACTION

DECLARE @inserted CURSOR FOR   
SELECT SID, CID
FROM inserted

OPEN @inserted  
  
FETCH NEXT FROM @inserted   
INTO @SID, @CID  

WHILE @@FETCH_STATUS = 0  
BEGIN  
	BEGIN TRY

		if (SELECT PID 
			FROM tb_Dataset CMD
			WHERE CMD.DID= @DID)= @CID
		 
		BEGIN
			RAISERROR(N'CID are Same As PID ', 11, 1);
			INSERT INTO [dbo].[tb_Log](SID,CID)
			Values (@SID, @CID)
		END

	END TRY
	FETCH NEXT FROM @inserted   
	INTO @SID, @CID  
END   
CLOSE @inserted;  
DEALLOCATE @inserted;  

BEGIN CATCH  
    SELECT   
        ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_SEVERITY() AS ErrorSeverity  
        ,ERROR_STATE() AS ErrorState  
        ,ERROR_PROCEDURE() AS ErrorProcedure  
        ,ERROR_LINE() AS ErrorLine  
        ,ERROR_MESSAGE() AS ErrorMessage;  
  
      IF @@TRANCOUNT > 0  
        ROLLBACK TRANSACTION;  
		PRINT ERROR_MESSAGE();
END CATCH;  

IF @@TRANCOUNT > 0  
    COMMIT TRANSACTION;

Open in new window

0
 
LVL 12

Assisted Solution

by:Dimitris
Dimitris earned 125 total points
ID: 41862343
First of all your variable @DID is always null
you never assign  a value

For this I assume that @DID is actualy the @CID

ALTER TRIGGER [dbo].[TRG_ForInsertAndUpdate]  ON MyTable
FOR INSERT, UPDATE
 
AS

DECLARE @SID nvarchar(20)
DECLARE @CID nvarchar(10)
DECLARE @DID nvarchar(10) -- Where this is set???

SELECT @SID = SID from inserted
SELECT @CID = CID from inserted


BEGIN TRANSACTION 
-- In most cases the transaction should be initiated externally and not within the trigger 
-- because if you rollback here the data will be written to toyr main table
BEGIN TRY
		IF EXISTS (	SELECT	1
					FROM	tb_Dataset CMD
							INNER JOIN INSERTED InsCIDs
								ON CMD.DID = InsCIDs.CID
							INNER JOIN INSERTED InsSID
								ON CMD.PID = InsSID.SID
					)
		BEGIN
			RAISERROR(N'CID are Same As PID ', 11, 1);
			--The log statement is never executed because the code goes directly to CATCH
			INSERT INTO [dbo].[tb_Log](SID,CID)
			SELECT	DISTINCT InsSID.SID , InsCIDs.CID
			FROM	tb_Dataset CMD
					INNER JOIN INSERTED InsCIDs
						ON CMD.DID = InsCIDs.CID
					INNER JOIN INSERTED InsSID
						ON CMD.PID = InsSID.SID
		END
END TRY

BEGIN CATCH  
    SELECT   
        ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_SEVERITY() AS ErrorSeverity  
        ,ERROR_STATE() AS ErrorState  
        ,ERROR_PROCEDURE() AS ErrorProcedure  
        ,ERROR_LINE() AS ErrorLine  
        ,ERROR_MESSAGE() AS ErrorMessage;  
  
      IF @@TRANCOUNT > 0  
        ROLLBACK TRANSACTION;  
		PRINT ERROR_MESSAGE();
END CATCH;  

IF @@TRANCOUNT > 0  
    COMMIT TRANSACTION;  

Open in new window

0
 
LVL 69

Assisted Solution

by:Scott Pletcher
Scott Pletcher earned 250 total points
ID: 41862641
SQL Server only fires a trigger once per statement, not per row.  So triggers must be written to handle multiple updates at once.

You're never supposed to attempt to return data from a trigger, so the SELECT ERROR... and the PRINT statement need to be removed.

A trigger is already within a transaction, so any rollback would affect the entire statement and not just what the trigger did (SQL Server doesn't support truly nested transactions.)  So I've removed any references to TRANSACTION in the trigger.

[Final minor point: The "FOR INSERT, UPDATE" is older syntax, so I've replaced it with the more current "AFTER INSERT, UPDATE".]


SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
GO
ALTER TRIGGER [dbo].[TRG_ForInsertAndUpdate]  
ON MyTable
AFTER INSERT, UPDATE

AS
SET NOCOUNT ON;

IF EXISTS(
    SELECT 1
    FROM inserted i
    INNER JOIN tb_Dataset CMD ON i.DID = CMD.DID AND i.CID = CMD.PID
)
BEGIN
          RAISERROR(N'CID(s) are Same As PID(s). ', 11, 1);
          INSERT INTO [dbo].[tb_Log](SID,CID)
          SELECT i.SID, i.CID
          FROM inserted i
          INNER JOIN tb_Dataset CMD ON i.DID = CMD.DID AND i.CID = CMD.PID
END /*IF*/
GO
0
 
LVL 69

Accepted Solution

by:
Scott Pletcher earned 250 total points
ID: 41882639
I propose the last comment, my comment:

https://www.experts-exchange.com/questions/28979260/SQL-Server-Trigger-for-INSERT-UPDATE-is-not-working.html#a41862641

as the best, and only, solution, because all other solutions use variables in the trigger, and thus can't handle multiple rows being modified at once, but SQL Server always fires a trigger only once, no matter how many rows have been modified, so any solution that assumes that only a single row is being modified is not accurate.  Other solutions also attempt to return data and/or output from a trigger, which is also not allowed.
0
 

Author Closing Comment

by:Harreni
ID: 41887345
Thanks a lot Experts.
0

Featured Post

U.S. Department of Agriculture and Acronis Access

With the new era of mobile computing, smartphones and tablets, wireless communications and cloud services, the USDA sought to take advantage of a mobilized workforce and the blurring lines between personal and corporate computing resources.

Question has a verified solution.

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

Let's review the features of new SQL Server 2012 (Denali CTP3). It listed as below: PERCENT_RANK(): PERCENT_RANK() function will returns the percentage value of rank of the values among its group. PERCENT_RANK() function value always in be…
Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
Familiarize people with the process of utilizing SQL Server functions from within Microsoft Access. Microsoft Access is a very powerful client/server development tool. One of the SQL Server objects that you can interact with from within Microsoft Ac…
Using examples as well as descriptions, and references to Books Online, show the documentation available for date manipulation functions and by using a select few of these functions, show how date based data can be manipulated with these functions.

831 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