MENCOBA... CATCH (Transact-SQL)

Berlaku untuk: SQL Server (semua versi yang didukung) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW)

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

Ikon tautan topikKonvensi Sintaks Transact-SQL

Sintaks

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

Catatan

Untuk melihat sintaks Transact-SQL untuk SQL Server 2014 dan yang lebih lama, lihat Dokumentasi versi sebelumnya.

Argumen

sql_statement
Adalah pernyataan Transact-SQL apa pun.

statement_block
Setiap grup pernyataan Transact-SQL dalam batch atau diapit dalam BEGIN... Blok AKHIR.

Keterangan

SEBUAH COBA... Konstruksi 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 CATCH terkait. Menyertakan pernyataan lain antara pernyataan END TRY dan BEGIN CATCH menghasilkan kesalahan sintaks.

SEBUAH COBA... Konstruksi CATCH tidak dapat menjangkau beberapa batch. SEBUAH COBA... Konstruksi CATCH tidak dapat menjangkau beberapa blok pernyataan Transact-SQL. Misalnya, TRY... Konstruksi CATCH tidak dapat menjangkau dua BEGIN... Blok AKHIR dari pernyataan Transact-SQL dan tidak dapat menjangkau IF... Konstruksi ELSE.

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

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

Catatan

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

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

MENCOBA... Konstruksi CATCH dapat disarangkan. Baik blok TRY atau blok CATCH dapat berisi TRY berlapis... Konstruksi CATCH. Misalnya, blok CATCH dapat berisi TRY yang disematkan... KONSTRUKSI CATCH untuk menangani kesalahan yang ditemui oleh kode CATCH.

Kesalahan yang ditemui di blok CATCH diperlakukan seperti kesalahan yang dihasilkan di tempat lain. Jika blok CATCH berisi TRY berlapis... Konstruksi CATCH, setiap kesalahan dalam blok TRY berlapis akan meneruskan kontrol ke blok CATCH berlapis. Jika tidak ada TRY berlapis... KONSTRUKSI CATCH, kesalahan diteruskan kembali ke pemanggil.

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

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

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

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

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

Mengambil Informasi Kesalahan

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

  • 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 menyertakan nilai yang disediakan untuk parameter yang dapat diganti, seperti panjang, nama objek, atau waktu.

Fungsi-fungsi ini mengembalikan NULL jika dipanggil di luar cakupan blok CATCH. Informasi kesalahan dapat diambil dengan menggunakan fungsi-fungsi ini dari mana saja dalam cakupan blok CATCH. 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 ERROR_* juga berfungsi di blok di CATCH dalam prosedur tersimpan yang dikompilasi secara asli.

Kesalahan Tidak Terpengaruh oleh TRY... Konstruksi CATCH

MENCOBA... Konstruksi CATCH 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 akan menangani kesalahan.

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

  • Ketika sesi berakhir oleh administrator sistem dengan menggunakan pernyataan KILL.

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

  • 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 menjalankan sp_executesql atau prosedur tersimpan yang ditentukan pengguna) di dalam blok TRY, kesalahan terjadi pada tingkat yang lebih rendah daripada TRY... Konstruksi CATCH dan akan ditangani oleh blok CATCH terkait.

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

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.

SELECT Menjalankan pernyataan di dalam prosedur tersimpan akan menyebabkan kesalahan terjadi pada tingkat yang lebih rendah dari TRY blok. Kesalahan akan 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 tidak dapat dijalankan

Jika kesalahan yang dihasilkan dalam blok TRY menyebabkan status transaksi saat ini tidak valid, transaksi diklasifikasikan sebagai transaksi yang tidak dapat diterapkan. Kesalahan yang biasanya mengakhiri transaksi di luar blok TRY menyebabkan transaksi memasuki status tidak dapat diterapkan ketika kesalahan terjadi di dalam blok TRY. Transaksi yang tidak dapat dilakukan 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 tidak dapat diterapkan, ketika batch selesai, pesan kesalahan akan dikirim ke aplikasi klien. Ini menunjukkan bahwa transaksi yang tidak dapat dilakukan terdeteksi dan digulung balik.

Untuk informasi selengkapnya tentang transaksi yang tidak dapat diterapkan dan fungsi XACT_STATE, lihat XACT_STATE (Transact-SQL).

Contoh

A. Menggunakan TRY... MENANGKAP

Contoh berikut menunjukkan SELECT pernyataan yang akan menghasilkan kesalahan bagi-demi-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. Menggunakan TRY... CATCH dalam transaksi

Contoh berikut menunjukkan cara TRY...CATCH kerja blok di dalam transaksi. Pernyataan di dalam TRY 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. Menggunakan 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 dikomit 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  

D. Menggunakan TRY... MENANGKAP

Contoh berikut menunjukkan SELECT pernyataan yang akan menghasilkan kesalahan bagi-demi-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_MESSAGE() AS ErrorMessage;  
END CATCH;  
GO  

Lihat juga

THROW (Transact-SQL)
Tingkat Keparahan Kesalahan Mesin Database
ERROR_LINE (T-SQL)
ERROR_MESSAGE (Transact-SQL)
ERROR_NUMBER (T-SQL)
ERROR_PROCEDURE (T-SQL)
ERROR_SEVERITY (T-SQL)
ERROR_STATE (T-SQL)
RAISERROR (Transact-SQL)
@@ERROR (T-SQL)
GOTO (Transact-SQL)
MULAI... END (Transact-SQL)
XACT_STATE (T-SQL)
SET XACT_ABORT (Transact-SQL)