Sample Header Ad - 728x90

Catching QUOTED_IDENTIFIER Errors in Trigger without aborting transaction

2 votes
0 answers
327 views
Is there a way to catch a QUOTED_IDENTIFIER error without failing the transaction? I have assembled a minimal test case here. The trigger must have SET QUOTED_IDENTIFIER ON because it uses XML data processing to concatenate the message it builds. In my particular case, the database where it was installed - the script did not SET QUOTED_IDENTIFIER ON because the trigger was not installed by my normal installation process. I'd like to know if there is a way to trap this without failing the transaction. In normal operations, I don't want any errors in the trigger to fail transactions, because it is solely designed to construct a message and send it to the service broker for later processing, and should not interfere with operations on the table otherwise. SET NOCOUNT ON; GO IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TestTable') BEGIN DROP TABLE dbo.TestTable ; END GO CREATE TABLE dbo.TestTable ( ID int IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED ,Name varchar(50) NOT NULL ); GO INSERT INTO dbo.TestTable (Name) VALUES ('Test 1'), ('Test 2'); GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER dbo.QuoteTest ON dbo.TestTable AFTER INSERT, UPDATE, DELETE AS BEGIN SET NOCOUNT ON; SET XACT_ABORT OFF; BEGIN TRY DECLARE @ChangeTemplate nvarchar(max) = N'{Type}{Name}{Value}'; DECLARE @ChangeMsg XML; WITH ChangeRows AS ( SELECT [Type] = CASE WHEN inserted.ID IS NULL THEN 'D' WHEN deleted.ID IS NULL THEN 'I' ELSE 'U' END ,[Name] = 'ID' ,[ID] = COALESCE(inserted.[ID], deleted.[ID]) FROM inserted FULL OUTER JOIN deleted ON inserted.[ID] = deleted.[ID] ) SELECT @ChangeMsg = (SELECT REPLACE(REPLACE(REPLACE(@ChangeTemplate , '{Type}', [Type]) , '{Name}', [Name]) , '{Value}', [ID]) FROM ChangeRows ORDER BY ID FOR XML PATH(''), TYPE).value('.', 'varchar(max)') ; PRINT 'Message Built'; PRINT CAST(@ChangeMsg AS varchar(max)); END TRY BEGIN CATCH PRINT 'Catch Error in Trigger'; PRINT ERROR_MESSAGE(); END CATCH END GO UPDATE TestTable SET Name = Name; GO IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TestTable') BEGIN DROP TABLE dbo.TestTable ; END GO CREATE TABLE dbo.TestTable ( ID int IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED ,Name varchar(50) NOT NULL ); GO INSERT INTO dbo.TestTable (Name) VALUES ('Test 1'), ('Test 2'); GO SET QUOTED_IDENTIFIER OFF GO CREATE TRIGGER dbo.QuoteTest ON dbo.TestTable AFTER INSERT, UPDATE, DELETE AS BEGIN SET NOCOUNT ON; SET XACT_ABORT OFF; BEGIN TRY DECLARE @ChangeTemplate nvarchar(max) = N'{Type}{Name}{Value}'; DECLARE @ChangeMsg XML; WITH ChangeRows AS ( SELECT [Type] = CASE WHEN inserted.ID IS NULL THEN 'D' WHEN deleted.ID IS NULL THEN 'I' ELSE 'U' END ,[Name] = 'ID' ,[ID] = COALESCE(inserted.[ID], deleted.[ID]) FROM inserted FULL OUTER JOIN deleted ON inserted.[ID] = deleted.[ID] ) SELECT @ChangeMsg = (SELECT REPLACE(REPLACE(REPLACE(@ChangeTemplate , '{Type}', [Type]) , '{Name}', [Name]) , '{Value}', [ID]) FROM ChangeRows ORDER BY ID FOR XML PATH(''), TYPE).value('.', 'varchar(max)') ; PRINT 'Message Built'; PRINT CAST(@ChangeMsg AS varchar(max)); END TRY BEGIN CATCH PRINT 'Catch Error in Trigger'; PRINT ERROR_MESSAGE(); END CATCH END GO UPDATE TestTable SET Name = Name; GO Gives the following output: Message Built UID1UID2 Catch Error in Trigger SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations. Reviewed this, but not sure where QUOTED_IDENTIFIER fits in the possible error modes: http://www.sommarskog.se/error_handling/Part2.html
Asked by Cade Roux (6684 rep)
Aug 1, 2019, 06:08 PM