SQL 服务器存储过程:等待删除触发器完成,然后再继续该过程
SQL Server stored procedure: wait for a delete's trigger to finish before continuing in the procedure
我的存储过程执行了一条删除语句,该语句触发了一个触发器,该触发器无法记录谁删除了该行,但为 changed_by
记录了一个空白。
然后存储过程使用给定的用户名更新 changed_by
。
一半时间,下面存储过程的第 2 部分找到触发器的结果,另一半时间,它没有找到触发器的结果,所以没有什么可以更新。
我如何"yield"控制并确保更新的触发器在继续存储过程之前完成?
(在评论中您会看到一些我迄今为止尝试过但没有奏效的方法)
DROP PROCEDURE IF EXISTS dbo.deleteAndUpdateChangedByInAuditTrail
GO
CREATE PROCEDURE dbo.deleteAndUpdateChangedByInAuditTrail
(@tableName VARCHAR(100),
@pkIDColName VARCHAR(100),
@pkIDValue NUMERIC,
@delUser VARCHAR(100) )
AS
BEGIN TRANSACTION;
-- PART 1: DO THE DELETE:
DECLARE @JUST_BEFORE_DELETION_TIMESTAMP AS DATETIME2;
SET @JUST_BEFORE_DELETION_TIMESTAMP = CONVERT(varchar, SYSDATETIME(), 121);
DECLARE @DELETION_TEMPLATE AS VARCHAR(MAX);
SET @DELETION_TEMPLATE = 'delete from {THE_TABLE_NAME} WHERE {PK_ID_COL_NAME} = {PK_ID_VALUE}';
SET @DELETION_TEMPLATE = REPLACE(@DELETION_TEMPLATE, '{THE_TABLE_NAME}', @tableName);
SET @DELETION_TEMPLATE = REPLACE(@DELETION_TEMPLATE, '{PK_ID_COL_NAME}', @pkIDColName);
SET @DELETION_TEMPLATE = REPLACE(@DELETION_TEMPLATE, '{PK_ID_VALUE}', @pkIDValue);
--PRINT @DELETION_TEMPLATE
EXEC (@DELETION_TEMPLATE);
COMMIT TRANSACTION;
BEGIN TRANSACTION;
-- PART 2: UPDATE THE AUDIT_TRAIL:
DECLARE @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME AS NUMERIC;
SET @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME = 0;
--DECLARE @TOTAL_TRIES_SO_FAR AS NUMERIC;
--SET @TOTAL_TRIES_SO_FAR = 0;
--WHILE @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME < 1 AND @TOTAL_TRIES_SO_FAR < 5
--BEGIN
--SET @TOTAL_TRIES_SO_FAR = @TOTAL_TRIES_SO_FAR + 1;
--WAITFOR DELAY '00:00:01.000' -- SEEN IT FAIL FOR 4 SECONDS :(
DECLARE @UPDATE_AUDIT_TRAIL_TEMPLATE AS VARCHAR(MAX);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = 'update AUDIT_TRAIL set changed_by = ''{CHANGED_BY}'' WHERE upper(table_name) = upper(''{THE_TABLE_NAME}'') and table_pk_value = {PK_ID_VALUE} and CONVERT(varchar, changed_at, 121) >= ''{CHANGED_AT}'' ';
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{CHANGED_BY}', @delUser);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{THE_TABLE_NAME}', @tableName);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{PK_ID_VALUE}', @pkIDValue);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{CHANGED_AT}', @JUST_BEFORE_DELETION_TIMESTAMP);
--PRINT @UPDATE_AUDIT_TRAIL_TEMPLATE
EXEC (@UPDATE_AUDIT_TRAIL_TEMPLATE);
SELECT @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME = @@ROWCOUNT;
--END
COMMIT TRANSACTION;
RETURN @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME;
GO
触发器不会异步执行。 DELETE 之后的下一步要等到触发器完成后才会发生。
如果您看到的东西让您有不同的想法,那么还有其他原因。不是因为触发器 "didn't finish".
我的存储过程执行了一条删除语句,该语句触发了一个触发器,该触发器无法记录谁删除了该行,但为 changed_by
记录了一个空白。
然后存储过程使用给定的用户名更新 changed_by
。
一半时间,下面存储过程的第 2 部分找到触发器的结果,另一半时间,它没有找到触发器的结果,所以没有什么可以更新。
我如何"yield"控制并确保更新的触发器在继续存储过程之前完成?
(在评论中您会看到一些我迄今为止尝试过但没有奏效的方法)
DROP PROCEDURE IF EXISTS dbo.deleteAndUpdateChangedByInAuditTrail
GO
CREATE PROCEDURE dbo.deleteAndUpdateChangedByInAuditTrail
(@tableName VARCHAR(100),
@pkIDColName VARCHAR(100),
@pkIDValue NUMERIC,
@delUser VARCHAR(100) )
AS
BEGIN TRANSACTION;
-- PART 1: DO THE DELETE:
DECLARE @JUST_BEFORE_DELETION_TIMESTAMP AS DATETIME2;
SET @JUST_BEFORE_DELETION_TIMESTAMP = CONVERT(varchar, SYSDATETIME(), 121);
DECLARE @DELETION_TEMPLATE AS VARCHAR(MAX);
SET @DELETION_TEMPLATE = 'delete from {THE_TABLE_NAME} WHERE {PK_ID_COL_NAME} = {PK_ID_VALUE}';
SET @DELETION_TEMPLATE = REPLACE(@DELETION_TEMPLATE, '{THE_TABLE_NAME}', @tableName);
SET @DELETION_TEMPLATE = REPLACE(@DELETION_TEMPLATE, '{PK_ID_COL_NAME}', @pkIDColName);
SET @DELETION_TEMPLATE = REPLACE(@DELETION_TEMPLATE, '{PK_ID_VALUE}', @pkIDValue);
--PRINT @DELETION_TEMPLATE
EXEC (@DELETION_TEMPLATE);
COMMIT TRANSACTION;
BEGIN TRANSACTION;
-- PART 2: UPDATE THE AUDIT_TRAIL:
DECLARE @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME AS NUMERIC;
SET @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME = 0;
--DECLARE @TOTAL_TRIES_SO_FAR AS NUMERIC;
--SET @TOTAL_TRIES_SO_FAR = 0;
--WHILE @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME < 1 AND @TOTAL_TRIES_SO_FAR < 5
--BEGIN
--SET @TOTAL_TRIES_SO_FAR = @TOTAL_TRIES_SO_FAR + 1;
--WAITFOR DELAY '00:00:01.000' -- SEEN IT FAIL FOR 4 SECONDS :(
DECLARE @UPDATE_AUDIT_TRAIL_TEMPLATE AS VARCHAR(MAX);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = 'update AUDIT_TRAIL set changed_by = ''{CHANGED_BY}'' WHERE upper(table_name) = upper(''{THE_TABLE_NAME}'') and table_pk_value = {PK_ID_VALUE} and CONVERT(varchar, changed_at, 121) >= ''{CHANGED_AT}'' ';
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{CHANGED_BY}', @delUser);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{THE_TABLE_NAME}', @tableName);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{PK_ID_VALUE}', @pkIDValue);
SET @UPDATE_AUDIT_TRAIL_TEMPLATE = REPLACE(@UPDATE_AUDIT_TRAIL_TEMPLATE, '{CHANGED_AT}', @JUST_BEFORE_DELETION_TIMESTAMP);
--PRINT @UPDATE_AUDIT_TRAIL_TEMPLATE
EXEC (@UPDATE_AUDIT_TRAIL_TEMPLATE);
SELECT @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME = @@ROWCOUNT;
--END
COMMIT TRANSACTION;
RETURN @TOTAL_NUM_ROWS_UPDATED_WITH_USERNAME;
GO
触发器不会异步执行。 DELETE 之后的下一步要等到触发器完成后才会发生。
如果您看到的东西让您有不同的想法,那么还有其他原因。不是因为触发器 "didn't finish".