mister.magoo (2/3/2011)
Hi, did you try this?
IF TRIGGER_NESTLEVEL()>1 RETURN
A bit less risky, but could still suffer from similar problems to @@NESTLEVEL if the trigger is ultimately fired as a result of updates from a trigger on another table in the same database.
I may be being a bit paranoid, but I'm speaking from experience of inheriting a system that suffered from exactly this kind of problem.
To add some more context to the trigger would help...
In your first database, use
DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
SET CONTEXT_INFO @ci;
And in the second, use:
IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
MM
select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);
How would the context setting be placed? For example, should it work if my first trigger (modify stmt) starts out like this:
======
ALTER TRIGGER [dbo].[UPDATE_EMAIL_IN_HEAT] ON [dbo].[CONTSUPP]
FOR DELETE
AS
BEGIN TRANSACTION
DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
SET CONTEXT_INFO @ci;
IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
--Scenario 1
begin
update heat_test.gmdev.Contacts set emailID = null
where custid in
(select accountno from deleted where
deleted.contact = 'E-mail Address'
and deleted.mergecodes = 'HEAT1'
and deleted.linkacct is null)
and contacttype='Primary Contact'
and the second trigger in the other db (modify) starts like this:
ALTER TRIGGER [gmdev].[DELETE_EMAIL_IN_GOLDMINE2] ON [gmdev].[Contacts]
FOR DELETE
AS
BEGIN TRANSACTION
DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
SET CONTEXT_INFO @ci;
IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
declare @custidexists varchar(100)
declare @contactidexists varchar(100)
set @contactidexists = null
set @contactidexists = (select top 1 contactid from deleted where custid is not null)
set @custidexists = null
set @custidexists = (select top 1 custid from deleted where custid is not null)
if @contactidexists is not null OR @custidexists is not null
BEGIN
???
Can I step back and ask why you need this? Not questioning you, but trying to help think a little outside the box about what might work.
My first thought is that you might want to add a column to the table that has a default value. If you are updating from another database, insert some marker in the column the trigger can read.
ae_from_pa (2/3/2011)
How would the context setting be placed? For example, should it work if my first trigger (modify stmt) starts out like this:======
ALTER TRIGGER [dbo].[UPDATE_EMAIL_IN_HEAT] ON [dbo].[CONTSUPP]
FOR DELETE
AS
BEGIN TRANSACTION
DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
SET CONTEXT_INFO @ci;
-- In this simple case you dont need this
-- if this trigger needs the functionality then it gets slightly more complex
-- let me know if two way checking is required...
--IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
--Scenario 1
begin
update heat_test.gmdev.Contacts set emailID = null
where custid in
(select accountno from deleted where
deleted.contact = 'E-mail Address'
and deleted.mergecodes = 'HEAT1'
and deleted.linkacct is null)
and contacttype='Primary Contact'
and the second trigger in the other db (modify) starts like this:
ALTER TRIGGER [gmdev].[DELETE_EMAIL_IN_GOLDMINE2] ON [gmdev].[Contacts]
FOR DELETE
AS
BEGIN TRANSACTION
-- No, if you set the CONTEXT_INFO here you wipe out the one set in the first trigger : commented out
-- DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
-- SET CONTEXT_INFO @ci;
IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
declare @custidexists varchar(100)
declare @contactidexists varchar(100)
set @contactidexists = null
set @contactidexists = (select top 1 contactid from deleted where custid is not null)
set @custidexists = null
set @custidexists = (select top 1 custid from deleted where custid is not null)
if @contactidexists is not null OR @custidexists is not null
BEGIN
???
I have amended your code (with a couple of comments). You just set CONTEXT_INFO in the primary trigger and read it in the secondary.
If you need two way checking i.e both triggers need to check whether to fire or not, then it becomes just a case of first checking if there is a value in CONTEXT_INFO() first.
Oh and get rid of those BEGIN TRANSACTION statements - they spell trouble...
MM
select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);
OF course, if those are the real triggers, then are you not showing us the delete from the "other" database table in the first trigger?
Just checking because it won't work if don't set the CONTEXT_INFO in the correct place to start with...
MM
select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);
Yes, two way checking is needed - deletes could start in either database, i want to have the second trigger not fire if the first one has already fired, otherwise it is trying to delete a record that was already deleted in the first database.
So...if I understand this right I need to reverse the statements...so the first trigger looks like
ALTER TRIGGER [dbo].[UPDATE_EMAIL_IN_HEAT] ON [dbo].[CONTSUPP]
FOR DELETE
AS
IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
ELSE
DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
SET CONTEXT_INFO @ci;
--Scenario 1
begin
update heat_test.gmdev.Contacts set emailID = null
where custid in
(select accountno from deleted where
deleted.contact = 'E-mail Address'
and deleted.mergecodes = 'HEAT1'
and deleted.linkacct is null)
and contacttype='Primary Contact'
and the second one goes like this...???
ALTER TRIGGER [gmdev].[DELETE_EMAIL_IN_GOLDMINE2] ON [gmdev].[Contacts]
FOR DELETE
AS
IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
SET CONTEXT_INFO @ci;
declare @custidexists varchar(100)
declare @contactidexists varchar(100)
set @contactidexists = null
set @contactidexists = (select top 1 contactid from deleted where custid is not null)
set @custidexists = null
set @custidexists = (select top 1 custid from deleted where custid is not null)
if @contactidexists is not null OR @custidexists is not null
BEGIN
Would this work?
I have also cut out the BEGIN TRANSACTION in both triggers.
Would it work? That all depends - if those were the only two triggers in use then yes - if you get rid of the ELSE - it is not needed.
Generally, if you want to prevent nested triggers from firing if the originating action( whether it be an insert, a delete or an update) was in another database then you need to check , set, and check again, like this :
CREATE TRIGGER db1_trigger1 ON db1.schema.table AFTER INSERT,DELETE,UPDATE
AS
DECLARE @ci VARBINARY(128) = CAST(DB_NAME() AS VARBINARY(128));
-- Check if anything has already set the CONTEXT_INFO and if not set it to my current database,
IF CONTEXT_INFO() IS NULL
SET CONTEXT_INFO @ci;
-- Check CONTEXT_INFO against my database and check the TRIGGER_NESTLEVEL
-- IF CONTEXT_INFO does not equal my database and TRIGGER_NESTLEVEL>1 just return
IF CONVERT(VARCHAR(50),CONTEXT_INFO()) <> DB_NAME() AND trigger_nestlevel () > 1 RETURN;
This code can be the same in all triggers that take part in these rules.
MM
select geometry::STGeomFromWKB(0x0106000000020000000103000000010000000B0000001000000000000840000000000000003DD8CCCCCCCCCC0840000000000000003DD8CCCCCCCCCC08408014AE47E17AFC3F040000000000104000CDCCCCCCCCEC3F9C999999999913408014AE47E17AFC3F9C99999999991340000000000000003D0000000000001440000000000000003D000000000000144000000000000000400400000000001040000000000000F03F100000000000084000000000000000401000000000000840000000000000003D0103000000010000000B000000000000000000143D000000000000003D009E99999999B93F000000000000003D009E99999999B93F8014AE47E17AFC3F400000000000F03F00CDCCCCCCCCEC3FA06666666666FE3F8014AE47E17AFC3FA06666666666FE3F000000000000003D1800000000000040000000000000003D18000000000000400000000000000040400000000000F03F000000000000F03F000000000000143D0000000000000040000000000000143D000000000000003D, 0);
Viewing 15 posts - 1 through 15 (of 27 total)
You must be logged in to reply to this topic. Login to reply