การใช้ธุรกรรมที่ถูกต้องใน SQL Server


236

ฉันมี 2 คำสั่งและต้องการทั้งสองอย่างดำเนินการอย่างถูกต้องหรือไม่มีพวกเขาดำเนินการ ดังนั้นฉันคิดว่าฉันต้องการธุรกรรม แต่ฉันไม่รู้วิธีใช้อย่างถูกต้อง

ปัญหาของสคริปต์ต่อไปนี้คืออะไร

BEGIN TRANSACTION [Tran1]

INSERT INTO [Test].[dbo].[T1]
    ([Title], [AVG])
VALUES ('Tidd130', 130), ('Tidd230', 230)

UPDATE [Test].[dbo].[T1]
  SET [Title] = N'az2' ,[AVG] = 1
  WHERE [dbo].[T1].[Title] = N'az'

COMMIT TRANSACTION [Tran1]
GO

INSERTคำสั่งจะถูกดำเนินการ แต่UPDATEคำสั่งที่มีปัญหา

ฉันจะใช้สิ่งนี้เพื่อย้อนกลับทั้งสองคำสั่งหากมีข้อผิดพลาดในการดำเนินการ?

คำตอบ:


513

เพิ่มบล็อกลอง / catch หากธุรกรรมสำเร็จจะส่งมอบการเปลี่ยนแปลงหากธุรกรรมล้มเหลวธุรกรรมจะถูกย้อนกลับ:

BEGIN TRANSACTION [Tran1]

  BEGIN TRY

      INSERT INTO [Test].[dbo].[T1] ([Title], [AVG])
      VALUES ('Tidd130', 130), ('Tidd230', 230)

      UPDATE [Test].[dbo].[T1]
      SET [Title] = N'az2' ,[AVG] = 1
      WHERE [dbo].[T1].[Title] = N'az'

      COMMIT TRANSACTION [Tran1]

  END TRY

  BEGIN CATCH

      ROLLBACK TRANSACTION [Tran1]

  END CATCH  

1
ไม่ควรBEGIN TRANSACTION [Tran1]วางไว้ข้างในTRY? อย่างไรก็ตาม - โค้ดที่เรียบง่ายและสง่างาม
Piotr Nawrot

4
@PiotrNawrot ไม่หากการสร้างธุรกรรมล้มเหลวไม่จำเป็นต้องย้อนกลับในการตรวจจับ
พระคุณเจ้า

114

ที่จุดเริ่มต้นของขั้นตอนการจัดเก็บหนึ่งควรใส่SET XACT_ABORT ONเพื่อสั่ง SQL Server ที่จะย้อนกลับการทำธุรกรรมโดยอัตโนมัติในกรณีที่เกิดข้อผิดพลาด หาก ommited หรือตั้งเป็นปิดจำเป็นต้องทดสอบ@@ ข้อผิดพลาดหลังจากแต่ละคำสั่งหรือใช้TRY ... CATCH rollback block


2
กล่าวอีกนัยหนึ่งธุรกรรมของคุณไม่ได้เป็นแบบอะตอมมิเช่นนั้นเว้นแต่ว่าคุณจะตั้ง XACT_ABORT เป็นอันดับแรก
4AM

เป็นเรื่องยากที่จะเห็นด้วยการขีดเส้นใต้ URL แต่มีขีดล่างในXACT_ABORT
BurnsBA

32

วิธีการง่าย ๆ :

CREATE TABLE T
(
    C [nvarchar](100) NOT NULL UNIQUE,
);

SET XACT_ABORT ON -- Turns on rollback if T-SQL statement raises a run-time error.
SELECT * FROM T; -- Check before.
BEGIN TRAN
    INSERT INTO T VALUES ('A');
    INSERT INTO T VALUES ('B');
    INSERT INTO T VALUES ('B');
    INSERT INTO T VALUES ('C');
COMMIT TRAN
SELECT * FROM T; -- Check after.
DELETE T;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.