Bagikan melalui


COBA... CATCH (Transact-SQL)

Berlaku untuk: Titik akhir analitik SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Platform System (PDW) SQL di Microsoft Fabric Warehouse di Microsoft Fabric

Menerapkan penanganan kesalahan untuk Transact-SQL yang mirip dengan penanganan pengecualian dalam bahasa C# dan Visual C++. Sekelompok pernyataan Transact-SQL dapat diapit dalam TRY blok. Jika terjadi kesalahan di blok, kontrol biasanya diteruskan TRY ke grup pernyataan lain yang diapit dalam CATCH blok.

Konvensi sintaks transact-SQL

Sintaks

BEGIN TRY
    { sql_statement | statement_block }
END TRY
BEGIN CATCH
    [ { sql_statement | statement_block } ]
END CATCH
[ ; ]

Argumen

sql_statement

Setiap pernyataan T-SQL.

statement_block

Setiap grup pernyataan Transact-SQL dalam batch atau diapit dalam BEGIN...END blok.

Keterangan

Konstruksi TRY...CATCH menangkap semua kesalahan eksekusi yang memiliki tingkat keparahan lebih tinggi dari 10 yang tidak menutup koneksi database.

Blok TRY harus segera diikuti oleh blok terkait CATCH . Menyertakan pernyataan lain antara END TRY pernyataan dan BEGIN CATCH menghasilkan kesalahan sintaks.

Konstruksi TRY...CATCH tidak dapat mencakup beberapa batch. Konstruksi TRY...CATCH tidak dapat mencakup beberapa blok pernyataan Transact-SQL. Misalnya, TRY...CATCH konstruksi tidak dapat mencakup dua BEGIN...END blok pernyataan Transact-SQL, dan tidak dapat menjangkau IF...ELSE konstruksi.

Jika tidak ada kesalahan dalam kode yang diapit dalam TRY blok, ketika pernyataan terakhir dalam TRY blok selesai, kontrol meneruskan ke pernyataan segera setelah pernyataan terkait END CATCH .

Jika ada kesalahan dalam kode yang diapit dalam TRY blok, kontrol akan meneruskan ke pernyataan pertama di blok terkait CATCH . Ketika kode di CATCH blok selesai, kontrol meneruskan ke pernyataan segera setelah END CATCH pernyataan.

Catatan

END CATCH Jika pernyataan adalah pernyataan terakhir dalam prosedur atau pemicu yang disimpan, kontrol diteruskan kembali ke pernyataan yang disebut prosedur tersimpan atau menembakkan pemicu.

Kesalahan yang CATCH terperangkap oleh blok tidak dikembalikan ke aplikasi panggilan. Jika ada bagian dari informasi kesalahan yang harus dikembalikan ke aplikasi, kode dalam CATCH blok harus melakukannya dengan menggunakan mekanisme seperti SELECT tataan hasil atau RAISERROR pernyataan dan PRINT .

TRY...CATCH konstruksi dapat ditumpuk. TRY Blok atau CATCH blok dapat berisi konstruksi berlapisTRY...CATCH. Misalnya, CATCH blok dapat berisi konstruksi yang disematkan TRY...CATCH untuk menangani kesalahan yang ditemui oleh CATCH kode.

Kesalahan yang ditemui dalam CATCH blok diperlakukan seperti kesalahan yang dihasilkan di tempat lain. CATCH Jika blok berisi konstruksi berlapisTRY...CATCH, kesalahan apa pun di blok berlapis meneruskan TRY kontrol ke blok berlapisCATCH. Jika tidak ada konstruksi berlapis TRY...CATCH , kesalahan akan diteruskan kembali ke pemanggil.

TRY...CATCH konstruksi menangkap kesalahan yang tidak tertangani dari prosedur tersimpan atau pemicu yang dijalankan oleh kode di TRY blok. Atau, prosedur atau pemicu yang disimpan dapat berisi konstruksi mereka sendiri TRY...CATCH untuk menangani kesalahan yang dihasilkan oleh kode mereka. Misalnya, ketika TRY blok menjalankan prosedur tersimpan dan kesalahan terjadi dalam prosedur tersimpan, kesalahan dapat ditangani dengan cara berikut:

  • Jika prosedur tersimpan tidak berisi konstruksinya sendiri TRY...CATCH , kesalahan mengembalikan kontrol ke CATCH blok yang terkait dengan TRY blok yang berisi EXECUTE pernyataan.

  • Jika prosedur tersimpan berisi TRY...CATCH konstruksi, kesalahan mentransfer kontrol ke CATCH blok dalam prosedur tersimpan. CATCH Ketika kode blok selesai, kontrol diteruskan kembali ke pernyataan segera setelah EXECUTE pernyataan yang memanggil prosedur tersimpan.

GOTO pernyataan tidak dapat digunakan untuk memasukkan TRY atau CATCH memblokir. GOTOpernyataan dapat digunakan untuk melompat ke label di dalam blok atau CATCH yang sama TRY atau untuk meninggalkan atau TRY CATCH memblokir.

Konstruksi TRY...CATCH tidak dapat digunakan dalam fungsi yang ditentukan pengguna.

Mengambil informasi kesalahan

Dalam cakupan CATCH blok, fungsi sistem berikut dapat digunakan untuk mendapatkan informasi tentang kesalahan yang menyebabkan CATCH blok dijalankan:

Fungsi Deskripsi
ERROR_NUMBER Mengembalikan jumlah kesalahan.
ERROR_SEVERITY Mengembalikan tingkat keparahan.
ERROR_STATE Mengembalikan nomor status kesalahan.
ERROR_PROCEDURE Mengembalikan nama prosedur tersimpan atau pemicu tempat kesalahan terjadi.
ERROR_LINE Mengembalikan nomor baris di dalam rutinitas yang menyebabkan kesalahan.
ERROR_MESSAGE Mengembalikan teks lengkap pesan kesalahan. Teks mencakup nilai yang disediakan untuk parameter yang dapat diganti, seperti panjang, nama objek, atau waktu.

Fungsi-fungsi ini kembali NULL jika dipanggil di luar cakupan CATCH blok. Informasi kesalahan dapat diambil dengan menggunakan fungsi-fungsi ini dari mana saja dalam cakupan CATCH blok. Misalnya, skrip berikut menunjukkan prosedur tersimpan yang berisi fungsi penanganan kesalahan. CATCH Di blok TRY...CATCH konstruksi, prosedur tersimpan dipanggil dan informasi tentang kesalahan dikembalikan.

-- Verify that the stored procedure does not already exist.
IF OBJECT_ID('usp_GetErrorInfo', 'P') IS NOT NULL
    DROP PROCEDURE usp_GetErrorInfo;
GO

-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT ERROR_NUMBER() AS ErrorNumber,
    ERROR_SEVERITY() AS ErrorSeverity,
    ERROR_STATE() AS ErrorState,
    ERROR_PROCEDURE() AS ErrorProcedure,
    ERROR_LINE() AS ErrorLine,
    ERROR_MESSAGE() AS ErrorMessage;
GO

BEGIN TRY
    -- Generate divide-by-zero error.
    SELECT 1 / 0;
END TRY

BEGIN CATCH
    -- Execute error retrieval routine.
    EXECUTE usp_GetErrorInfo;
END CATCH;

Fungsi ini ERROR_* juga berfungsi di CATCH blok di dalam prosedur tersimpan yang dikompilasi secara asli.

Kesalahan tidak terpengaruh oleh TRY... Konstruksi CATCH

TRY...CATCH konstruksi tidak menjebak kondisi berikut:

  • Peringatan atau pesan informasi yang memiliki tingkat keparahan 10 atau lebih rendah.

  • Kesalahan yang memiliki tingkat keparahan 20 atau lebih tinggi yang menghentikan pemrosesan tugas Mesin Database SQL Server untuk sesi tersebut. Jika terjadi kesalahan yang memiliki tingkat keparahan 20 atau lebih tinggi dan koneksi database tidak terganggu, TRY...CATCH menangani kesalahan.

  • Perhatian, seperti permintaan yang mengganggu klien atau koneksi klien yang rusak.

  • Ketika administrator sistem menggunakan KILL pernyataan untuk mengakhiri sesi.

Jenis kesalahan berikut tidak ditangani oleh CATCH blok ketika terjadi pada tingkat eksekusi yang sama dengan TRY...CATCH konstruksi:

  • Kompilasi kesalahan, seperti kesalahan sintaksis, yang mencegah batch berjalan.

  • Kesalahan yang terjadi selama kompilasi ulang tingkat pernyataan, seperti kesalahan resolusi nama objek yang terjadi setelah kompilasi karena resolusi nama yang ditangguhkan.

  • Kesalahan resolusi nama objek

Kesalahan ini dikembalikan ke tingkat yang menjalankan batch, prosedur tersimpan, atau pemicu.

Jika terjadi kesalahan selama kompilasi atau kompilasi ulang tingkat pernyataan pada tingkat eksekusi yang lebih rendah (misalnya, saat mengeksekusi sp_executesql atau prosedur tersimpan yang ditentukan pengguna) di dalam TRY blok, kesalahan terjadi pada tingkat yang lebih rendah dari TRY...CATCH konstruksi dan akan ditangani oleh blok terkait CATCH .

Contoh berikut menunjukkan bagaimana kesalahan resolusi nama objek yang SELECT dihasilkan oleh pernyataan tidak ditangkap oleh TRY...CATCH konstruksi, tetapi ditangkap oleh CATCH blok ketika pernyataan yang sama dijalankan di dalam prosedur tersimpan SELECT .

BEGIN TRY
    -- Table does not exist; object name resolution
    -- error not caught.
    SELECT *
    FROM NonexistentTable;
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH

Kesalahan tidak tertangkap dan kontrol keluar dari TRY...CATCH konstruksi ke tingkat yang lebih tinggi berikutnya.

Menjalankan pernyataan di SELECT dalam prosedur tersimpan menyebabkan kesalahan terjadi pada tingkat yang lebih rendah dari TRY blok. Kesalahan ditangani oleh TRY...CATCH konstruksi.

-- Verify that the stored procedure does not exist.
IF OBJECT_ID(N'usp_ExampleProc', N'P') IS NOT NULL
    DROP PROCEDURE usp_ExampleProc;
GO

-- Create a stored procedure that will cause an
-- object resolution error.
CREATE PROCEDURE usp_ExampleProc
AS
SELECT *
FROM NonexistentTable;
GO

BEGIN TRY
    EXECUTE usp_ExampleProc;
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH;

Transaksi dan XACT_STATE yang tidak dapat diterapkan

Jika kesalahan yang dihasilkan dalam TRY blok menyebabkan status transaksi saat ini tidak valid, transaksi diklasifikasikan sebagai transaksi yang tidak dapat diterapkan. Kesalahan yang biasanya mengakhiri transaksi di luar TRY blok menyebabkan transaksi memasuki status tidak dapat diterapkan ketika kesalahan terjadi di dalam TRY blok. Transaksi yang tidak dapat diterapkan hanya dapat melakukan operasi baca atau ROLLBACK TRANSACTION. Transaksi tidak dapat menjalankan pernyataan Transact-SQL apa pun yang akan menghasilkan operasi tulis atau COMMIT TRANSACTION. Fungsi XACT_STATE mengembalikan nilai -1 jika transaksi telah diklasifikasikan sebagai transaksi yang tidak dapat diterapkan. Ketika batch selesai, Mesin Database mengembalikan transaksi aktif yang tidak dapat diterapkan. Jika tidak ada pesan kesalahan yang dikirim ketika transaksi memasuki status yang tidak dapat diterapkan, ketika batch selesai, pesan kesalahan dikirim ke aplikasi klien. Ini menunjukkan bahwa transaksi yang tidak dapat diterapkan terdeteksi dan digulung balik.

Untuk informasi selengkapnya tentang transaksi dan fungsi yang XACT_STATE tidak dapat diterapkan, lihat XACT_STATE.

Contoh

J. Gunakan TRY... MENANGKAP

Contoh berikut menunjukkan SELECT pernyataan yang menghasilkan kesalahan dibagi berdasarkan nol. Kesalahan menyebabkan eksekusi melompat ke blok terkait CATCH .

BEGIN TRY
    -- Generate a divide-by-zero error.
    SELECT 1 / 0;
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO

B. Gunakan TRY... CATCH dalam transaksi

Contoh berikut menunjukkan cara TRY...CATCH kerja blok di dalam transaksi. Pernyataan di TRY dalam blok menghasilkan kesalahan pelanggaran batasan.

BEGIN TRANSACTION;

BEGIN TRY
    -- Generate a constraint violation error.
    DELETE
    FROM Production.Product
    WHERE ProductID = 980;
END TRY

BEGIN CATCH
    SELECT ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_STATE() AS ErrorState,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage;

    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
END CATCH;

IF @@TRANCOUNT > 0
    COMMIT TRANSACTION;
GO

C. Gunakan TRY... CATCH dengan XACT_STATE

Contoh berikut menunjukkan cara menggunakan TRY...CATCH konstruksi untuk menangani kesalahan yang terjadi di dalam transaksi. Fungsi menentukan XACT_STATE apakah transaksi harus dilakukan atau digulung balik. Dalam contoh ini, SET XACT_ABORT adalah ON. Ini membuat transaksi tidak dapat diterapkan ketika kesalahan pelanggaran batasan terjadi.

-- Check to see whether this stored procedure exists.
IF OBJECT_ID(N'usp_GetErrorInfo', N'P') IS NOT NULL
    DROP PROCEDURE usp_GetErrorInfo;
GO

-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT ERROR_NUMBER() AS ErrorNumber,
    ERROR_SEVERITY() AS ErrorSeverity,
    ERROR_STATE() AS ErrorState,
    ERROR_LINE() AS ErrorLine,
    ERROR_PROCEDURE() AS ErrorProcedure,
    ERROR_MESSAGE() AS ErrorMessage;
GO

-- SET XACT_ABORT ON will cause the transaction to be uncommittable
-- when the constraint violation occurs.
SET XACT_ABORT ON;

BEGIN TRY
    BEGIN TRANSACTION;

    -- A FOREIGN KEY constraint exists on this table. This
    -- statement will generate a constraint violation error.
    DELETE
    FROM Production.Product
    WHERE ProductID = 980;

    -- If the DELETE statement succeeds, commit the transaction.
    COMMIT TRANSACTION;
END TRY

BEGIN CATCH
    -- Execute error retrieval routine.
    EXECUTE usp_GetErrorInfo;

    -- Test XACT_STATE:
    -- If 1, the transaction is committable.
    -- If -1, the transaction is uncommittable and should
    --     be rolled back.
    -- XACT_STATE = 0 means that there is no transaction and
    --     a commit or rollback operation would generate an error.
    -- Test whether the transaction is uncommittable.
    IF (XACT_STATE()) = -1
    BEGIN
        PRINT N'The transaction is in an uncommittable state. Rolling back transaction.'

        ROLLBACK TRANSACTION;
    END;

    -- Test whether the transaction is committable.
    -- You may want to commit a transaction in a catch block if you want to commit changes to statements that ran prior to the error.
    IF (XACT_STATE()) = 1
    BEGIN
        PRINT N'The transaction is committable. Committing transaction.'

        COMMIT TRANSACTION;
    END;
END CATCH;
GO