BEGIN的意外,非直观行为 - COMMIT TRANSACTION

时间:2017-11-06 06:35:58

标签: sql sql-server sql-update commit

我在几天前提到我的this question时写过。

符合我需要的答案是:

UPDATE ProcActivity SET IsActive = 1 WHERE ProcedureName = 'proc_name'
BEGIN TRANSACTION
EXEC proc_name
COMMIT TRANSACTION
UPDATE ProcActivity SET IsActive = 0 WHERE ProcedureName = 'proc_name'

现在又来了另一个问题:

直觉上,我想如果我在UPDATE中包装BEGIN....COMMIT TRANSACTION语句,它会在到达COMMIT...后立即生效,但我错了。实际上,如上所述,当它达到BEGIN...时,就会发生更新。

总结一下:

像这样做更新:

UPDATE ProcActivity SET IsActive = 1 WHERE ProcedureName = 'proc_name'
BEGIN TRANSACTION
EXEC proc_name
COMMIT TRANSACTION
UPDATE ProcActivity SET IsActive = 0 WHERE ProcedureName = 'proc_name'

假设在执行过程IsActive期间proc_name的值设置为1(更新在过程开始之前生效)。

像这样做更新:

BEGIN TRANSACTION
UPDATE ProcActivity SET IsActive = 1 WHERE ProcedureName = 'proc_name'
COMMIT TRANSACTION
EXEC proc_name
UPDATE ProcActivity SET IsActive = 0 WHERE ProcedureName = 'proc_name'
执行proc_name

无效。在执行过程期间,IsActive的值设置为0.

为什么这样工作?它背后的机制是什么?

1 个答案:

答案 0 :(得分:0)

我无法重现您的问题 - 在这两种情况下,我都会0 - 1 - 0

IF OBJECT_ID('[dbo].[StackOoverFlow]') IS NOT NULL
BEGIN
    DROP TABLE [dbo].[StackOoverFlow];
END;

IF OBJECT_ID('[dbo].[usp_StackOoverFlow]') IS NOT NULL
BEGIN
    DROP PROCEDURE [dbo].[usp_StackOoverFlow];
END;

GO

CREATE TABLE [dbo].[StackOoverFlow]
(
    [ProcedureName] SYSNAME
   ,[IsActive] BIT
); 

GO

CREATE PROCEDURE [dbo].[usp_StackOoverFlow] AS
BEGIN
    SELECT [IsActive]
    FROM [dbo].[StackOoverFlow]
    WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]';
END;

GO

INSERT INTO [dbo].[StackOoverFlow] ([ProcedureName], [IsActive])
VALUES ('[dbo].[usp_StackOoverFlow]', 0);

GO

SELECT [IsActive]
FROM [dbo].[StackOoverFlow]
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]';

BEGIN TRANSACTION

UPDATE [dbo].[StackOoverFlow]
SET [IsActive] = 1
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]'; 

COMMIT TRANSACTION

EXEC [dbo].[usp_StackOoverFlow];

UPDATE [dbo].[StackOoverFlow]
SET [IsActive] = 0
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]'; 

SELECT [IsActive]
FROM [dbo].[StackOoverFlow]
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]';


GO

SELECT [IsActive]
FROM [dbo].[StackOoverFlow]
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]';

UPDATE [dbo].[StackOoverFlow]
SET [IsActive] = 1
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]'; 

BEGIN TRANSACTION
EXEC [dbo].[usp_StackOoverFlow];
COMMIT TRANSACTION

UPDATE [dbo].[StackOoverFlow]
SET [IsActive] = 0
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]'; 

SELECT [IsActive]
FROM [dbo].[StackOoverFlow]
WHERE [ProcedureName] = '[dbo].[usp_StackOoverFlow]';