Bisakah saya mengubah struktur tabel dalam transaksi dan kemudian mengembalikannya jika ada kesalahan?

15

Saya memiliki beberapa ALTER TABLEpernyataan yang sedang saya jalankan. Tidak semua dari mereka bekerja (mereka adalah hasil dari menjalankan Bandingkan Data SQL) dan saya ingin mengelompokkan mereka dalam beberapa transaksi dan memutar kembali pernyataan jika ada yang salah.

Apakah ini mungkin, atau hanya data yang dapat diputar kembali?

Piers Karsenbarg
sumber
Apakah Anda berbicara tentang Redgate SQL Compare? Salah satu opsi sinkronisasi di sana adalah menggunakan transaksi IIRC sehingga Anda bisa melihat skrip yang dibuat di sana untuk melihat beberapa kode pelat ketel untuk ini.
Martin Smith
Ya, benar. Saya akan melihatnya.
Piers Karsenbarg

Jawaban:

10
   BEGIN TRANSACTION
      BEGIN TRY
        ALTER TABLE1...
        ALTER TABLE2...
        -- Additional data/structural changes
        COMMIT
      END TRY
      BEGIN CATCH
         ROLLBACK;
         THROW; -- Only if you want reraise an exception (to determine the reason of the exception)
      END CATCH
Pete Carter
sumber
3
Akankah SET XACT_ABORT ONdan final COMMIT TRANmeniadakan perlunya TRYblok?
Luke Puplett
13

Ya, ini mungkin.

Sebagian besar pernyataan DDL dapat diputar kembali di SQL Server (Ada beberapa pengecualian seperti CREATE DATABASE)

Martin Smith
sumber
6

Banyak perubahan dalam satu transaksi dengan rollbackdan commit- itu bukan mimpi. Itu mungkin.

Berikut adalah scaffold untuk skrip Anda (mengikuti pedoman MS dengan peningkatan):

BEGIN TRANSACTION

BEGIN TRY
    -- place your script in this TRY block

    -- your DDL instructions:
    ALTER TABLE1...
    ALTER TABLE2...
    -- data modifications:
    EXEC('
        UPDATE A
        SET    c1 = 23,
               c2 = ''ZZXX'';
    ');
    -- another DDL instruction:
    ALTER TABLE2...

    -- end of your script
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;


    -- If you want reraise an exception (to determine the reason of the exception)
    -- just uncomment block with appropriate version:

    -- SQL SERVER > 2012
    /*
    THROW;
    */

    -- SQL SERVER < 2012 (tested against 2008 R2)
    /*
    DECLARE @ErrorMessage VARCHAR(MAX);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT
        @ErrorMessage = ERROR_MESSAGE(),
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE();

    RAISERROR (
        @ErrorMessage, -- Message text.
        @ErrorSeverity, -- Severity.
        @ErrorState -- State.
    );
    */
END CATCH;

IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO

Hati-hati, THROWhanya berfungsi untuk versi SQL SERVER> 2012. Di sini Anda dapat mengkonversi versi dari notasi semver ke tahun : http://sqlserverbuilds.blogspot.ru (tidak mengetahui .rudomain, ada versi bahasa Inggris)

maxkoryukov
sumber