Click here to monitor SSC
SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
 
 
 
        
Home       Members    Calendar    Who's On


Add to briefcase

Selectively delete items in a delete trigger Expand / Collapse
Author
Message
Posted Friday, May 10, 2013 12:56 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Monday, June 24, 2013 6:55 AM
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


Post #1451719
Posted Friday, May 10, 2013 12:59 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Monday, June 24, 2013 6:55 AM
Points: 45, Visits: 72
Sorry, forgot to mention we are on SQL Server 2008 SP 3
Post #1451720
Posted Friday, May 10, 2013 1:38 PM


SSC-Insane

SSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-Insane

Group: General Forum Members
Last Login: Today @ 2:48 PM
Points: 23,397, Visits: 32,244
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.



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)
Post #1451731
Posted Friday, May 10, 2013 1:41 PM
SSC Rookie

SSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC RookieSSC Rookie

Group: General Forum Members
Last Login: Monday, June 24, 2013 6:55 AM
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.
Post #1451732
Posted Friday, May 10, 2013 2:57 PM


SSC-Insane

SSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-InsaneSSC-Insane

Group: General Forum Members
Last Login: Today @ 2:48 PM
Points: 23,397, Visits: 32,244
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.



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)
Post #1451744
Posted Friday, May 10, 2013 3:14 PM


SSC-Forever

SSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-ForeverSSC-Forever

Group: General Forum Members
Last Login: Today @ 10:19 AM
Points: 43,026, Visits: 36,192
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 2008, MVP
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

Post #1451746
« Prev Topic | Next Topic »

Add to briefcase

Permissions Expand / Collapse