Click here to monitor SSC
SQLServerCentral is supported by Redgate
 
Log in  ::  Register  ::  Not logged in
 
 
 


Selectively delete items in a delete trigger


Selectively delete items in a delete trigger

Author
Message
AnnA-607068
AnnA-607068
SSC Rookie
SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)

Group: General Forum Members
Points: 45 Visits: 72
I am rewriting a FOR DELETE trigger. The current trigger, written in 2004 when we were still on SQL Server 2000, assumes only one row will be deleted at a time; it checks tables on another server to see if the item has history in those tables. If it does, an error is raised and the record is not deleted. If not, then a row in a table on another server in another database is deleted and the record in the deleted table is processed.

This is the old trigger:

CREATE TRIGGER [dbo].[del_Test$Vendor] ON [dbo].[Test$Vendor]
FOR DELETE
AS
SET NOCOUNT ON
SET XACT_ABORT ON
DECLARE @TRUE BIT,
@FALSE BIT
SET @TRUE = 1
SET @FALSE = 0
DECLARE @cDbName VARCHAR(50),
@cServer VARCHAR(50),
@cCommand NVARCHAR(1000),
@cStatement NVARCHAR(1500)
CREATE TABLE #cur_delete (can_delete bit)
SET @cDbName = DB_NAME()
SET @cServer = interface.dbo.cf_db_id(@cDbName)
SET @cStatement = ''
DECLARE @cVendorId VARCHAR(20)
DECLARE cur_vendor CURSOR LOCAL FOR
SELECT [No_]
FROM deleted
OPEN cur_vendor
FETCH NEXT FROM cur_vendor
INTO @cVendorId
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cStatement = 'Select SQL2000.dbo.cf_ven_delete(''''' + @cVendorId + ''''') as can_delete'
SET @cCommand = 'SELECT can_delete FROM OPENQUERY(' + @cServer + ', ''' + @cStatement + ''')'
Insert into #cur_delete
EXEC sp_executesql @cCommand
IF (SELECT can_delete FROM #cur_delete) = @TRUE
BEGIN
SET @cStatement =
'DELETE FROM ' + interface.dbo.cf_db_id(@cDbName)COLLATE Latin1_General_100_CS_AS + '.taxsystem.dbo.vendor
WHERE vendor_id = ''' + @cVendorId + ''''
Print @cStatement
EXEC sp_executesql @cStatement
END
ELSE
BEGIN
--- Raise an error, do not continue processing
RAISERROR ('Vendor Has History in In-House Systems. Cannot Delete.', 16, 1) WITH NOWAIT
END
FETCH NEXT FROM cur_vendor
INTO @cVendorId
END
CLOSE cur_vendor
DEALLOCATE cur_vendor


When multiple records are deleted, the old trigger fails.

I can't seem to wrap my mind around how to process the records so that the items in the deleted table will only be deleted if there is no history in the other tables. I know how to delete only the records in the related table, but not how to selectively process the records in the deleted table based on the presence/absence of history. Does anyone have any suggestions? The code I've written so far follows. The deleted records are coming from a third party application, so I have no control over the records coming in. Any help would be greatly appreciated!



ALTER TRIGGER [dbo].[del_Test$Vendor] ON [dbo].[Test$Vendor]
FOR DELETE
AS
SET NOCOUNT ON
SET XACT_ABORT ON
IF EXISTS (SELECT 'x'
FROM deleted d
JOIN LTQASQL1.shared.dbo.VendorHistory h
ON d.No_ = h.VendorId COLLATE SQL_Latin1_General_CP1_CI_AS
WHERE h.HasHistory = 1)
BEGIN
--This obviously will prevent all the records in the deleted table from being processed
--not just those that have history
RAISERROR ('Vendor Has History in In-House Systems. Cannot Delete.', 16, 1) WITH NOWAIT
RETURN
END
ELSE
BEGIN
DELETE tcv
FROM LTQASQL1.TaxSystem.dbo.Vendor tcv
JOIN deleted d
ON tcv.vendor_id = d.No_ COLLATE Latin1_General_100_CS_AS
JOIN LTQASQL1.shared.dbo.VendorHistory h
ON d.No_ = h.VendorId COLLATE SQL_Latin1_General_CP1_CI_AS
WHERE h.HasHistory = 0
END


AnnA-607068
AnnA-607068
SSC Rookie
SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)

Group: General Forum Members
Points: 45 Visits: 72
Sorry, forgot to mention we are on SQL Server 2008 SP 3
Lynn Pettis
Lynn Pettis
SSC-Insane
SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)

Group: General Forum Members
Points: 24206 Visits: 37967
AnnA-607068 (5/10/2013)
I am rewriting a FOR DELETE trigger. The current trigger, written in 2004 when we were still on SQL Server 2000, assumes only one row will be deleted at a time; it checks tables on another server to see if the item has history in those tables. If it does, an error is raised and the record is not deleted. If not, then a row in a table on another server in another database is deleted and the record in the deleted table is processed.

This is the old trigger:

CREATE TRIGGER [dbo].[del_Test$Vendor] ON [dbo].[Test$Vendor]
FOR DELETE
AS
SET NOCOUNT ON
SET XACT_ABORT ON
DECLARE @TRUE BIT,
@FALSE BIT
SET @TRUE = 1
SET @FALSE = 0
DECLARE @cDbName VARCHAR(50),
@cServer VARCHAR(50),
@cCommand NVARCHAR(1000),
@cStatement NVARCHAR(1500)
CREATE TABLE #cur_delete (can_delete bit)
SET @cDbName = DB_NAME()
SET @cServer = interface.dbo.cf_db_id(@cDbName)
SET @cStatement = ''
DECLARE @cVendorId VARCHAR(20)
DECLARE cur_vendor CURSOR LOCAL FOR
SELECT [No_]
FROM deleted
OPEN cur_vendor
FETCH NEXT FROM cur_vendor
INTO @cVendorId
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cStatement = 'Select SQL2000.dbo.cf_ven_delete(''''' + @cVendorId + ''''') as can_delete'
SET @cCommand = 'SELECT can_delete FROM OPENQUERY(' + @cServer + ', ''' + @cStatement + ''')'
Insert into #cur_delete
EXEC sp_executesql @cCommand
IF (SELECT can_delete FROM #cur_delete) = @TRUE
BEGIN
SET @cStatement =
'DELETE FROM ' + interface.dbo.cf_db_id(@cDbName)COLLATE Latin1_General_100_CS_AS + '.taxsystem.dbo.vendor
WHERE vendor_id = ''' + @cVendorId + ''''
Print @cStatement
EXEC sp_executesql @cStatement
END
ELSE
BEGIN
--- Raise an error, do not continue processing
RAISERROR ('Vendor Has History in In-House Systems. Cannot Delete.', 16, 1) WITH NOWAIT
END
FETCH NEXT FROM cur_vendor
INTO @cVendorId
END
CLOSE cur_vendor
DEALLOCATE cur_vendor


When multiple records are deleted, the old trigger fails.

I can't seem to wrap my mind around how to process the records so that the items in the deleted table will only be deleted if there is no history in the other tables. I know how to delete only the records in the related table, but not how to selectively process the records in the deleted table based on the presence/absence of history. Does anyone have any suggestions? The code I've written so far follows. The deleted records are coming from a third party application, so I have no control over the records coming in. Any help would be greatly appreciated!



ALTER TRIGGER [dbo].[del_Test$Vendor] ON [dbo].[Test$Vendor]
FOR DELETE
AS
SET NOCOUNT ON
SET XACT_ABORT ON
IF EXISTS (SELECT 'x'
FROM deleted d
JOIN LTQASQL1.shared.dbo.VendorHistory h
ON d.No_ = h.VendorId COLLATE SQL_Latin1_General_CP1_CI_AS
WHERE h.HasHistory = 1)
BEGIN
--This obviously will prevent all the records in the deleted table from being processed
--not just those that have history
RAISERROR ('Vendor Has History in In-House Systems. Cannot Delete.', 16, 1) WITH NOWAIT
RETURN
END
ELSE
BEGIN
DELETE tcv
FROM LTQASQL1.TaxSystem.dbo.Vendor tcv
JOIN deleted d
ON tcv.vendor_id = d.No_ COLLATE Latin1_General_100_CS_AS
JOIN LTQASQL1.shared.dbo.VendorHistory h
ON d.No_ = h.VendorId COLLATE SQL_Latin1_General_CP1_CI_AS
WHERE h.HasHistory = 0
END






You may want to look at INSTEAD OF triggers instead of AFTER triggers.

Cool
Lynn Pettis

For better assistance in answering your questions, click here
For tips to get better help with Performance Problems, click here
For Running Totals and its variations, click here or when working with partitioned tables
For more about Tally Tables, click here
For more about Cross Tabs and Pivots, click here and here
Managing Transaction Logs

SQL Musings from the Desert Fountain Valley SQL (My Mirror Blog)
AnnA-607068
AnnA-607068
SSC Rookie
SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)SSC Rookie (45 reputation)

Group: General Forum Members
Points: 45 Visits: 72
If I used an instead of trigger, and deleted records on the table that has an instead of trigger from the instead of trigger, then the instead of trigger would be fired from inside itself. I think that might be a problem.
Lynn Pettis
Lynn Pettis
SSC-Insane
SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)SSC-Insane (24K reputation)

Group: General Forum Members
Points: 24206 Visits: 37967
AnnA-607068 (5/10/2013)
If I used an instead of trigger, and deleted records on the table that has an instead of trigger from the instead of trigger, then the instead of trigger would be fired from inside itself. I think that might be a problem.


Read about INSTEAD OF triggers. They are not recursive. If you do a DELETE inside of a DELETE INSTEAD OF trigger, the DELETE INSTEAD OF trigger does NOT fire again.

Cool
Lynn Pettis

For better assistance in answering your questions, click here
For tips to get better help with Performance Problems, click here
For Running Totals and its variations, click here or when working with partitioned tables
For more about Tally Tables, click here
For more about Cross Tabs and Pivots, click here and here
Managing Transaction Logs

SQL Musings from the Desert Fountain Valley SQL (My Mirror Blog)
GilaMonster
GilaMonster
SSC-Forever
SSC-Forever (47K reputation)SSC-Forever (47K reputation)SSC-Forever (47K reputation)SSC-Forever (47K reputation)SSC-Forever (47K reputation)SSC-Forever (47K reputation)SSC-Forever (47K reputation)SSC-Forever (47K reputation)

Group: General Forum Members
Points: 47259 Visits: 44389
Triggers (any triggers) aren't recursive. AFTER triggers can be made recursive by turning the database option on (though I haven't seen many cases where that's a good idea)


Gail Shaw
Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

We walk in the dark places no others will enter
We stand on the bridge and no one may pass


Go


Permissions

You can't post new topics.
You can't post topic replies.
You can't post new polls.
You can't post replies to polls.
You can't edit your own topics.
You can't delete your own topics.
You can't edit other topics.
You can't delete other topics.
You can't edit your own posts.
You can't edit other posts.
You can't delete your own posts.
You can't delete other posts.
You can't post events.
You can't edit your own events.
You can't edit other events.
You can't delete your own events.
You can't delete other events.
You can't send private messages.
You can't send emails.
You can read topics.
You can't vote in polls.
You can't upload attachments.
You can download attachments.
You can't post HTML code.
You can't edit HTML code.
You can't post IFCode.
You can't post JavaScript.
You can post emoticons.
You can't post or upload images.

Select a forum

































































































































































SQLServerCentral


Search