为什么以下t-sql事务无法按预期工作?

为了测试事务如何工作,我编写了以下t-sql。由于第一个属性是主键,因此不应提交任何插入操作。 但是,第一次插入已提交吗?为什么?

begin transaction
   insert into instructor
   values ('99999','Yellow','Biology',700000)

   insert into instructor
   values ('99999','Blue','Statistics',85000)
commit;

select * from instructor where ID = '99999'

--delete from instructor where ID = '99999'
  

(受影响的1行)Msg 2627,级别14,状态1,第100行违反   主键约束'PK__instruct__3214EC278C8DA99F'。无法插入   对象“ dbo.instructor”中的重复键。重复的键值为   (99999)。该声明已终止。

完成时间:2019-11-06T14:02:27.3436411 + 02:00

fanyinfu 回答:为什么以下t-sql事务无法按预期工作?

因为XACT_ABORT处于关闭状态(默认设置):

  

当SET XACT_ABORT为OFF时,在某些情况下,仅Transact-SQL   引发错误的语句将回滚并进行事务处理   继续处理。

及其为ON时:

  

..如果Transact-SQL语句引发运行时错误,则整个   交易终止并回滚。

这就是我们将其ON所需要的,如果您尝试下面的代码,则可以进行以下检查:

DROP TABLE IF EXISTS [dbo].[StackOverflow];

CREATE TABLE [dbo].[StackOverflow]
(
    [StackID] TINYINT PRIMARY KEY
);

SET XACT_ABORT ON;

BEGIN TRANSACTION;

INSERT INTO [dbo].[StackOverflow] ([StackID])
VALUES (105);

INSERT INTO [dbo].[StackOverflow] ([StackID])
VALUES (105);

COMMIT TRANSACTION;

SET XACT_ABORT OFF;

SELECT [StackID]
FROM [dbo].[StackOverflow];

另外,请注意:

  

编译错误(例如语法错误)不受SET XACT_ABORT的影响。

上面的意思是,如果您想真正拥有自动交易功能,则需要使用以下代码块:

SET NOCOUNT,XACT_ABORT ON;

BEGIN TRY

    BEGIN TRANSACTION;
    -- CODE BLOCK GOES HERE
    COMMIT TRANSACTION;

END TRY
BEGIN CATCH 

   IF @@TRANCOUNT > 0
   BEGIN
      ROLLBACK TRANSACTION
   END;

   -- GET ERRORS DETAILS OR THROW ERROR

END CATCH;

SET NOCOUNT,XACT_ABORT OFF;

如果在特定情况下(例如下一个情况)不使用TRY-CATCH块,则将再次提交第一条语句:

DROP TABLE IF EXISTS [dbo].[StackOverflow];

CREATE TABLE [dbo].[StackOverflow]
(
    [StackID] TINYINT PRIMARY KEY
);

SET XACT_ABORT ON;

BEGIN TRANSACTION;

INSERT INTO [dbo].[StackOverflow] ([StackID])
VALUES (105);

EXEC 
(
    'INSERrrrrrT INTO [dbo].[StackOverflow] ([StackID]) VALUES (106);'
)

COMMIT TRANSACTION;

SET XACT_ABORT OFF;

SELECT [StackID]
FROM [dbo].[StackOverflow];
,

您需要添加SET XACT_ABORT ON;和/或使用TRY / CATCH,以使脚本在出现错误后不会继续到COMMIT

SET XACT_ABORT ON示例:

SET XACT_ABORT ON;
begin transaction
   insert into instructor
   values ('99999','Yellow','Biology',700000)

   insert into instructor
   values ('99999','Blue','Statistics',85000)
commit;

TRY / CATCH示例:

BEGIN TRY
    begin transaction
       insert into instructor
       values ('99999',700000)

       insert into instructor
       values ('99999',85000)
    commit;
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK;
    THROW;
END CATCH;
本文链接:https://www.f2er.com/3151972.html

大家都在问