Penggunaan transaksi yang benar dalam SQL Server

236

Saya punya 2 perintah dan perlu keduanya dieksekusi dengan benar atau tidak ada yang dieksekusi. Jadi saya pikir saya perlu transaksi, tetapi saya tidak tahu bagaimana menggunakannya dengan benar.

Apa masalah dengan skrip berikut?

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

The INSERTperintah dijalankan, tetapi UPDATEperintah memiliki masalah.

Bagaimana saya bisa menerapkan ini untuk mengembalikan kedua perintah jika salah satu dari mereka memiliki kesalahan dalam eksekusi?

Saeid
sumber

Jawaban:

513

Tambahkan blok coba / tangkap, jika transaksi berhasil maka akan melakukan perubahan, jika transaksi gagal transaksi dibatalkan:

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  
Darren
sumber
1
Bukankah BEGIN TRANSACTION [Tran1]seharusnya ditempatkan di dalam TRY? Pokoknya - sepotong kode yang sangat sederhana dan elegan.
Piotr Nawrot
4
@PiotrNawrot Tidak, jika kreasi transaksi gagal, tidak perlu mengembalikannya.
Monsinyur
114

Pada awal prosedur tersimpan, seseorang harus menempatkan SET XACT_ABORT ON untuk menginstruksikan Sql Server untuk secara otomatis mengembalikan transaksi jika terjadi kesalahan. Jika ommited atau diatur ke OFF, seseorang perlu menguji @@ ERROR setelah setiap pernyataan atau menggunakan ... COCH blok rollback .

Nikola Markovinović
sumber
2
Dengan kata lain, transaksi Anda tidak bersifat atomik kecuali Anda SET XACT_ABORT AKTIF dulu.
4AM
Sulit untuk melihat dengan url yang digarisbawahi, tetapi ada garis bawah diXACT_ABORT
BurnsBA
32

Pendekatan mudah:

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;
Bohdan
sumber