Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagesql
titleSample Scripts on how to use async trigger
collapsetrue
USE AdventureWorks2008R2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID('Purchasing.usp_AT_uPurchaseOrderDetail', 'P') IS NOT NULL
	DROP PROCEDURE Purchasing.usp_AT_uPurchaseOrderDetail;
GO
CREATE PROCEDURE Purchasing.usp_AT_uPurchaseOrderDetail
	@inserted	XML,
	@deleted	XML = NULL
AS
    SET NOCOUNT ON;

    BEGIN TRY
        IF EXISTS ( SELECT NULL FROM @inserted.nodes('inserted/row') AS T(X) )
        BEGIN
			-- Insert record into TransactionHistory 
            INSERT INTO [Production].[TransactionHistory]
                ([ProductID]
                ,[ReferenceOrderID]
                ,[ReferenceOrderLineID]
                ,[TransactionType]
                ,[TransactionDate]
                ,[Quantity]
                ,[ActualCost])
            SELECT 
                inserted.[ProductID]
                ,inserted.[PurchaseOrderID]
                ,inserted.[PurchaseOrderDetailID]
                ,'P'
                ,GETDATE()
                ,inserted.[OrderQty]
                ,inserted.[UnitPrice]
            FROM
            (
				SELECT
					  X.query('.').value('(row/PurchaseOrderID)[1]', 'int') AS PurchaseOrderID
					, X.query('.').value('(row/PurchaseOrderDetailID)[1]', 'int') AS PurchaseOrderDetailID
					, X.query('.').value('(row/ProductID)[1]', 'int') AS ProductID
					, X.query('.').value('(row/OrderQty)[1]', 'smallint') AS OrderQty
					, X.query('.').value('(row/UnitPrice)[1]', 'money') AS UnitPrice
				FROM @inserted.nodes('inserted/row') AS T(X)
			) AS inserted 
            INNER JOIN [Purchasing].[PurchaseOrderDetail] 
            ON inserted.[PurchaseOrderID] = [Purchasing].[PurchaseOrderDetail].[PurchaseOrderID];

            -- Update SubTotal in PurchaseOrderHeader record. Note that this causes the 
            -- PurchaseOrderHeader trigger to fire which will update the RevisionNumber.
            UPDATE [Purchasing].[PurchaseOrderHeader]
            SET [Purchasing].[PurchaseOrderHeader].[SubTotal] = 
                (SELECT SUM([Purchasing].[PurchaseOrderDetail].[LineTotal])
                    FROM [Purchasing].[PurchaseOrderDetail]
                    WHERE [Purchasing].[PurchaseOrderHeader].[PurchaseOrderID] 
                        = [Purchasing].[PurchaseOrderDetail].[PurchaseOrderID])
            WHERE [Purchasing].[PurchaseOrderHeader].[PurchaseOrderID] 
                IN (
					SELECT inserted.[PurchaseOrderID]
					FROM (
							SELECT
								  X.query('.').value('(row/PurchaseOrderID)[1]', 'int') AS PurchaseOrderID
							FROM @inserted.nodes('inserted/row') AS T(X)
						) AS inserted
					);

            UPDATE [Purchasing].[PurchaseOrderDetail]
            SET [Purchasing].[PurchaseOrderDetail].[ModifiedDate] = GETDATE()
            FROM (
					SELECT
						  X.query('.').value('(row/PurchaseOrderID)[1]', 'int') AS PurchaseOrderID
						, X.query('.').value('(row/PurchaseOrderDetailID)[1]', 'int') AS PurchaseOrderDetailID
					FROM @inserted.nodes('inserted/row') AS T(X)
				) AS inserted
            WHERE inserted.[PurchaseOrderID] = [Purchasing].[PurchaseOrderDetail].[PurchaseOrderID]
                AND inserted.[PurchaseOrderDetailID] = [Purchasing].[PurchaseOrderDetail].[PurchaseOrderDetailID];
        END;
    END TRY
    BEGIN CATCH
        -- Since we're in an Asynchronous Trigger, rolling back an update operation
        -- is a lot more complicated than in a regular trigger.
        -- For now, for this scenario we'll take the risk of having partial data.

        EXECUTE [dbo].[uspLogError];
    END CATCH;
GO
ALTER TRIGGER [Purchasing].[uPurchaseOrderDetail] ON [Purchasing].[PurchaseOrderDetail] 
AFTER UPDATE AS 
BEGIN
    DECLARE @Count int;

    SET @Count = @@ROWCOUNT;
    IF @Count = 0 
        RETURN;

    SET NOCOUNT ON;

    BEGIN TRY
        IF UPDATE([ProductID]) OR UPDATE([OrderQty]) OR UPDATE([UnitPrice])
        BEGIN
			DECLARE
				@inserted	XML,
				@deleted	XML;
			
			SELECT @inserted =
				( SELECT * FROM inserted FOR XML PATH('row'), ROOT('inserted') );
			
			SELECT @deleted = 
				( SELECT * FROM deleted FOR XML PATH('row'), ROOT('deleted') );
			
			EXECUTE SB_AT_Fire_Trigger 'Purchasing.usp_AT_uPurchaseOrderDetail', @inserted, @deleted;
			
        END;
    END TRY
    BEGIN CATCH
        EXECUTE [dbo].[uspPrintError];

        -- Rollback any active or uncommittable transactions before
        -- inserting information in the ErrorLog
        IF @@TRANCOUNT > 0
        BEGIN
            ROLLBACK TRANSACTION;
        END

        EXECUTE [dbo].[uspLogError];
    END CATCH;
END;
GO
/*
====================================================

					Test script

====================================================
*/
-- See the data before the update
SELECT *
FROM Purchasing.PurchaseOrderDetail
WHERE PurchaseOrderID = 8

-- Update the data without actually performing any change
UPDATE
	Purchasing.PurchaseOrderDetail
SET ProductID = ProductID
WHERE PurchaseOrderID = 8

-- Wait 5 seconds
WAITFOR DELAY '00:00:05';

-- See the updated data (ModifiedDate should be updated)
SELECT *
FROM Purchasing.PurchaseOrderDetail
WHERE PurchaseOrderID = 8
GO

SELECT *
FROM SB_AT_ServiceBrokerLogs

SELECT *
FROM sys.conversation_endpoints

/* -- cleanup closed conversations (SQL Server eventually does this automatically)
declare @q uniqueidentifier;
select @q = conversation_handle from sys.conversation_endpoints where state='CD';
end conversation @q with cleanup
*/




Trouble shooting info:

Async trigger not working...

Code Block
languagesql
titleAsync triggers - debugging queries
collapsetrue
-- Message Types
SELECT * FROM sys.service_message_types;

-- Contracts
SELECT * FROM sys.service_contracts;

-- Queues
SELECT * FROM sys.service_queues;

-- Services
SELECT * FROM sys.services;

-- Endpoints
SELECT * FROM sys.endpoints;


-- Error messages in the queue --MOST IMPORTANT!
SELECT * FROM sys.transmission_queue order by enqueue_time desc;

Code Block
languagesql
titleSpecific Steel Division DB error.
collapsetrue
/*
An exception occurred while enqueueing a message in the target queue. Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.
*/
SELECT owner_sid, SUSER_SNAME(owner_sid) AS dbowner
FROM sys.databases
WHERE name = 'Steel Division (AS-DS-SS)';

SELECT name,sid, SUSER_SNAME(sid) AS dbo
FROM [Steel Division (AS-DS-SS)].sys.database_principals
WHERE name = 'dbo';
Code Block
languagesql
titleSQL - change DB owner
collapsetrue
--ALTER AUTHORIZATION ON DATABASE::[Steel Division (AS-DS-SS)] TO sa


Sample scripts - easy

Code Block

/*
--TESTING QUERIES:
insert into _as_AuditCrap(dDate, sText) values (GETDATE(), 'bla1');
select * from _as_AuditLog_Print order by ddate desc --7476
select * from SB_AT_ServiceBrokerLogs
*/

create table _as_AuditLog_Print (dDate datetime, query nvarchar(1000))

create trigger _as_TestAsync ON _as_AuditCrap
FOR UPDATE, INSERT
AS
BEGIN
	
	--EXECUTE SB_AT_Fire_Trigger 'dbo._as_InsertPayment 99,232,''blabla'',''2018-06-01''';
	EXECUTE SB_AT_Fire_Trigger '_as_spTestAsync'
END



create procedure _as_spTestAsync
	@Inserted XML,
	@Deleted XML
AS
begin
	--exec _as_InsertPayment 99,233,'adfsad','2018-06-01'
	insert into _as_AuditLog_Print (dDate, query) values (GETDATE(),'async test!');
end