June 27, 2007 at 12:31 pm
I'm trying to create an update table script that will run on two different clients (A & B) databases. If it is Client A, I need to drop a specific trigger (or temporarily disable the trigger), update the table, and then recreate the trigger. For Client B, I just need to update the table (as the trigger does not exist on the table). The following script below is what I'm trying to accomplish, but it does not work. Trying to figure out how to script this:
DECLARE @AIsOwner bit
set @AIsOwner=0
/** Only delete if client A **/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[NonUniqueITIN]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
BEGIN
drop trigger [dbo].[NonUniqueITIN]
set @AOwner=1
END
/** Update a table for both clients **/
UPDATE PersonTable SET personType=1
GO
if (@AOwner=1)
BEGIN
/**** Create the Trigger for Client A ***/
CREATE TRIGGER [dbo].[NonUniqueITIN]
ON [dbo].[PersonTable]
FOR UPDATE, INSERT
As
IF
EXISTS
(
SELECT DISTINCT
i.*
FROM
Inserted i
INNER JOIN [PersonTable] tbl
on i.id = tbl.id
WHERE
i.id <> tbl.id
)
BEGIN
RAISERROR('Non-unique ITIN', 16, 1)
ROLLBACK TRAN
END
GO
END
In addition to B not having the trigger, I can also differentiate between client A and B by a specific value in a database table both clients have (ProgramOwner table SELECT owner FROM TblProgramOwner (where a return value of A is clioent A and B is client B).
Any help is greatly appreciated.
June 27, 2007 at 12:38 pm
The variable @AOwner is no longer exists after the UPDATE statement, as you terminate the batch with a GO statement. If you can determine the client by querying the database, that is a better way to go.
June 27, 2007 at 1:12 pm
The trouble is that it always wants the CREATE Trigger statement immediately after a GO statement. I'm not sure how I could do a conditional check and then run the CREATE TRIGGER statement (is there some way to break out of the entire TSQL if the Owner is B?)
June 27, 2007 at 1:48 pm
Not the prettiest thing I have ever seen, but how about creating the trigger, then checking if you have to keep it depending on the client and dropping it again accordingly?
Or have 2 separate install scripts for the 2 clients.
June 27, 2007 at 2:05 pm
I could separately the install scripts, but future requirements dictate I'll have to do many similar items and the tracking becomes quite cumbersome. Your first idea sounds quite plausible - shall give it a shot.
June 28, 2007 at 7:36 am
Why don't you DISABLE/ENABLE the trigger instead of dropping it:
The trigger still exists but will not fire!
/** Only disable if client A **/
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[NonUniqueITIN]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
BEGIN
DISABLE TRIGGER NonUniqueITIN on PersonTable
set @AOwner=1
END
/** Update a table for both clients **/
UPDATE PersonTable SET personType=1
GO
if (@AOwner=1)
BEGIN
ENABLE TRIGGER NonUniqueITIN on PersonTable
END
Alternatively, we have a situation where we only want to bypass the trigger in a certain context. For this case we wrote a bypass trigger function:
CREATE
FUNCTION [dbo].[BypassTrigger] (@strTrigger varchar(128))
RETURNS
int AS
BEGIN
--Determines whether a given trigger is to be bypassed in this session
DECLARE @nBypass int
DECLARE @vTrigger varbinary(128)
SELECT @vTrigger = context_info FROM master.dbo.sysprocesses
WHERE spid = @@spid
if @vTrigger = cast(@strTrigger as varbinary(128))
SELECT @nBypass = 1
else
SELECT @nBypass = 0
RETURN(@nBypass)
END
Then in the trigger we add:
ALTER
TRIGGER [dbo].[NonUniqueITIN ] on [dbo].[PersonTable]
for
INSERT, UPDATE
NOT
FOR REPLICATION
as
-- if the trigger is currently bypassed for this process, exit
IF
dbo.BypassTrigger(OBJECT_NAME(@@procid)) = 1 RETURN
-- trigger code goes here
Then
The trigger still exists but will be bypassed in this session, but will fire in other sessions
DECLARE
@vTrigger varbinary(128)
SET @vTrigger = CAST('NonUniqueITIN' as varbinary(128))
SET CONTEXT_INFO @vTrigger
/** Update a table for both clients **/
UPDATE PersonTable SET personType=1
SET @vTrigger = CAST('' as varbinary(128))
SET CONTEXT_INFO @vTrigger
Terri
To speak algebraically, Mr. M. is execrable, but Mr. C. is
(x+1)-ecrable.
Edgar Allan Poe
[Discussing fellow writers Cornelius Mathews and William Ellery Channing.]
June 28, 2007 at 8:38 am
Here is the solution I developed with everyones recommendations.
1) The Disable works great (slight format change - I'm not sure if it is because I'm using SQL 2000). I had to disable several triggers before performing an update.
2) I also dynamically created a new Trigger (wanted to revise the original Trigger and did it all in the same script). Here is the script:
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[NonUniqueITIN]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
BEGIN
/*** Rebuilding trigger in a new methodology ***/
drop trigger [dbo].[NonUniqueITIN]
END
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[BizEntityAdminChange]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
BEGIN
ALTER TABLE [PersonTable] DISABLE TRIGGER [BizEntityAdminChange]
END
GO
/** Update a table for both clients **/
UPDATE PersonTable SET personType=1
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[BizEntityAdminChange]') and OBJECTPROPERTY(id, N'IsTrigger') = 1)
BEGIN
ALTER TABLE [] ENABLE TRIGGER [BizEntityAdminChange]
END
GO
if (exists (select * from [dbo].TblProgramOwner WHERE owner='A'))
BEGIN
DECLARE @sSetTrigger varchar(2000),
@sCRLF char(2),
@STAB char(1)
SET @sCRLF = char(13) + char(10)
SET @STAB = char(9)
SET @sSetTrigger = ''
SET @sSetTrigger = @sSetTrigger + 'CREATE TRIGGER [dbo].[NonUniqueITIN] ' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + 'ON [dbo].[PersonTable] ' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + 'FOR UPDATE, INSERT' + @sCRLF
SET @sSetTrigger = @sSetTrigger + 'As ' + @sCRLF
SET @sSetTrigger = @sSetTrigger + 'IF EXISTS' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + '(' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB +'SELECT DISTINCT' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + @STAB +'i.*' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + 'FROM' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + @STAB + 'Inserted i' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + @STAB + 'INNER JOIN [2006_TblPartner] tbl' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + @STAB + @STAB + 'on i.F030 = tbl.F030' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + 'WHERE' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + @STAB + 'i.Id tbl.Id ' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + ')' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB +'BEGIN' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + @STAB + 'RAISERROR(' + '''' + 'Non-unique ITIN' + '''' + ', 16, 1) ' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB + @STAB + 'ROLLBACK TRAN ' + @sCRLF
SET @sSetTrigger = @sSetTrigger + @STAB + @STAB +'END'
PRINT @sSetTrigger
EXEC (@sSetTrigger)
END
June 28, 2007 at 11:29 am
I just have one question.
Do you disable tables and columns you don't use in an application or do you drop them, or even better, don't install them at all in production?
June 28, 2007 at 11:39 am
We conditionally bypass triggers for some batch processes on the production database. We don't bypass triggers in the application.
Terri
To speak algebraically, Mr. M. is execrable, but Mr. C. is
(x+1)-ecrable.
Edgar Allan Poe
[Discussing fellow writers Cornelius Mathews and William Ellery Channing.]
June 28, 2007 at 4:06 pm
I was reffering to the create / disable version. If you're going to write that logic, you might as well DROP IT. That way there can't be any confusion later on as to know that trigger is not enabled.
June 28, 2007 at 4:13 pm
Not the best approach I've ever seen.
Actually, one of the worst.
Why not just include the check into the trigger itself?
Create Trigger .. blah-blah-blah
AS
BEGIN
IF dbo.IsOwner(suser_sname()) = 0
RETURN
[Trigger body]
END
Of course, users must connect to the server using proper accounts, not as "sa".
But if you insist on parameter from application then move the code out of trigger. It does not belong there.
Trigger must depend only on data in "inserted" and "deleted" tables and data in static tables in database.
_____________
Code for TallyGenerator
June 29, 2007 at 6:18 am
Why keep a do nothing trigger in the database?
Interesting how opinions can be made without knowing the business rules and logic of the triggers, users, etc.
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply