Reputation: 4399
There's a database table that has an update trigger. Whenever a column is updated, one of its columns is automatically calculated.
I have tweaked the trigger and I'd like to run it on all of the rows again. In SQL Server Management Studio, if I choose "Edit Top 200 Rows" on my table and edit one of the rows, the update trigger works. But when I write a query like:
UPDATE MyTable
SET SomeIrrelevantColumn = 0
the trigger doesn't work, the column that is supposed to be calculated by the trigger stays the same.
How can I run the trigger manually on all the rows?
Edit: Here's the trigger:
USE [MY_DATABASE]
GO
/****** Object: Trigger [dbo].[MY_TABLE_AUER] Script Date: 04/24/2013 00:05:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[MY_TABLE_AUER]
ON [dbo].[MY_TABLE]
AFTER UPDATE
AS
DECLARE @UPD_COLUMN_A int,
@INS_COLUMN_A int,
@UPD_COLUMN_B int,
@UPD_COLUMN_C varchar(255),
@UPD_COLUMN_D varchar(255),
@UPD_COLUMN_E int,
@UPD_COLUMN_F datetime
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT @UPD_COLUMN_A = _Column_A,
@UPD_COLUMN_B =_Column_B,
@UPD_COLUMN_C = COLUMN_C,
@UPD_COLUMN_D = [Column_D]
FROM DELETED;
IF @UPD_COLUMN_D not like '%SomeString%'
BEGIN
SELECT @INS_COLUMN_A = _Column_A
FROM INSERTED;
IF @UPD_COLUMN_A != @INS_COLUMN_A
BEGIN
SELECT @UPD_COLUMN_E = MAX([_Column_B]),
@UPD_COLUMN_F = MAX([_Column_G])
FROM MY_TABLE
WHERE COLUMN_C = @UPD_COLUMN_C
AND [Column_D] LIKE '%SomeString%';
UPDATE MY_TABLE
SET COLUMN_E = @UPD_COLUMN_E,
COLUMN_F = @UPD_COLUMN_F
WHERE [_Column_B] = @UPD_COLUMN_B;
UPDATE MY_TABLE
SET COLUMN_H = @UPD_COLUMN_B
WHERE [_Column_B] = @UPD_COLUMN_E;
END
END
END
Upvotes: 1
Views: 25595
Reputation: 1
Please try using the below code..in trigger..!
//Check if the column is getting updated
if (Update(column1) or Update(Column2)...etc)
Begin
Write the entire logic inside this loop..!
End
Hope this works..!!!
Upvotes: -2
Reputation: 50241
Your trigger makes a very common but false assumption that it will execute once per row. It doesn't, it executes once per action--so when you update the entire table, I bet if you look closer, you'll see that one row was updated. * with thanks to Aaron Bertrand's comment for this intro paragraph.
You'll need to look into how to perform an update based on a JOIN (with the inserted
or deleted
meta-tables). For example:
CREATE TRIGGER TR_Sample_U ON dbo.Sample FOR UPDATE -- AFTER is default so not needed
AS
IF EXISTS ( --check for disallowed modifications
SELECT *
FROM
Inserted I
INNER JOIN Deleted D
ON I.SampleID = D.SampleID
WHERE
I.Something <> D.Something
AND I.UpdateDate = D.UpdateDate
)
ROLLBACK TRAN;
These resources may also help you:
Upvotes: 8
Reputation: 4399
I have found out that one way to do it is something like the following:
UPDATE A
SET A.SOME_COLUMN = D.ANOTHER_COLUMN
FROM MY_TABLE AS A
JOIN inserted AS B ON A.ID = B.ID -- Point 1.
JOIN deleted AS C ON A.ID = C.ID
JOIN (SELECT MAX(ID) AS OTHER_ID, GROUP_ID AS OTHER_GROUP_ID -- Point 2.
FROM MY_TABLE AS E
WHERE E.SOME_STRING_COLUMN LIKE '%SomeString%'
GROUP BY E.GROUP_ID) AS D ON A.GROUP_ID = D.OTHER_GROUP_ID
WHERE C.SOME_BOOL_COLUMN != B.SOME_BOOL_COLUMN -- Point 3.
AND C.SOME_STRING_COLUMN NOT LIKE '%SomeString%'
UPDATE
statement, I go ahead and join the table to 'inserted' and 'deleted' special tables (more info about those at http://www.mssqltips.com/sqlservertip/2342/understanding-sql-server-inserted-and-deleted-tables-for-dml-triggers/). This way, I'll only go through the rows that have been updated, and I won't mess with the other ones. You can only join with one of them, but I needed to see a difference in one column between the values before and after the update operation. So that's why I used them both. 'deleted' has the row in the state before the update operation, and 'inserted' has the row in the state after the update operation.GROUP_ID
, and I made a string test to make sure that the new row I get is qualified as a parent, you can define any kind of filter there. Basically, you write another query to find the row based on your updated row, and then you make another JOIN
to that returned table.WHERE
clause to make sure that I only update the rows that has changed state by looking at the SOME_BOOL_COLUMN
column. You can put any kind of criterion here. As you can see I check the difference between the state of the column before and after the update.Take whatever written here with a grain of salt though, as it's coming from someone that has virtually no experience with SQL.
Upvotes: 0