Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Menerapkan Penanganan Kesalahan dan Transaksi di SQL Server

Pengantar

Tidak peduli seberapa keras kita mencoba merancang dan mengembangkan aplikasi, kesalahan akan selalu terjadi. Ada dua kategori umum – sintaks atau kesalahan logis dapat berupa kesalahan program atau konsekuensi dari desain database yang salah. Jika tidak, Anda mungkin mendapatkan kesalahan karena input pengguna yang salah.

T-SQL (bahasa pemrograman SQL Server) memungkinkan penanganan kedua jenis kesalahan. Anda dapat men-debug aplikasi dan memutuskan apa yang perlu Anda lakukan untuk menghindari bug di masa mendatang.

Sebagian besar aplikasi mengharuskan Anda mencatat kesalahan, menerapkan pelaporan kesalahan yang mudah digunakan, dan, jika memungkinkan, menangani kesalahan dan melanjutkan eksekusi aplikasi.

Pengguna menangani kesalahan pada tingkat pernyataan. Ini berarti ketika Anda menjalankan sekumpulan perintah SQL, dan masalah terjadi di pernyataan terakhir, semua yang mendahului masalah itu akan dikomit ke database sebagai transaksi implisit. Ini mungkin bukan yang Anda inginkan.

Database relasional dioptimalkan untuk eksekusi pernyataan batch. Dengan demikian, Anda perlu menjalankan sekumpulan pernyataan sebagai satu unit dan gagalkan semua pernyataan jika satu pernyataan gagal. Anda dapat melakukannya dengan menggunakan transaksi. Artikel ini akan fokus pada penanganan kesalahan dan transaksi, karena topik ini sangat terkait.

Penanganan kesalahan SQL

Untuk mensimulasikan pengecualian, kita perlu memproduksinya dengan cara yang dapat diulang. Mari kita mulai dengan contoh paling sederhana – pembagian dengan nol:

SELECT 1/0

Keluaran menjelaskan kesalahan yang dilontarkan – Ditemukan kesalahan bagi dengan nol . Namun kesalahan ini tidak ditangani, dicatat, atau disesuaikan untuk menghasilkan pesan yang mudah digunakan.

Penanganan pengecualian dimulai dengan meletakkan pernyataan yang ingin Anda jalankan di blok BEGIN TRY…END TRY.

SQL Server menangani (menangkap) kesalahan di blok BEGIN CATCH…END CATCH, tempat Anda dapat memasukkan logika khusus untuk pencatatan atau pemrosesan kesalahan.

Pernyataan BEGIN CATCH harus segera diikuti setelah pernyataan END TRY. Eksekusi kemudian diteruskan dari blok TRY ke blok CATCH pada kejadian kesalahan pertama.

Di sini Anda dapat memutuskan cara menangani kesalahan, apakah Anda ingin mencatat data tentang pengecualian yang muncul atau membuat pesan yang mudah digunakan.

SQL Server memiliki fungsi bawaan yang dapat membantu Anda mengekstrak detail kesalahan:

  • ERROR_NUMBER():Mengembalikan jumlah kesalahan SQL.
  • ERROR_SEVERITY():Mengembalikan tingkat keparahan yang menunjukkan jenis masalah yang dihadapi dan tingkatnya. Level 11 hingga 16 dapat ditangani oleh pengguna.
  • ERROR_STATE():Mengembalikan nomor status kesalahan dan memberikan detail lebih lanjut tentang pengecualian yang dilemparkan. Anda menggunakan nomor kesalahan untuk mencari di basis pengetahuan Microsoft untuk detail kesalahan tertentu.
  • ERROR_PROCEDURE():Mengembalikan nama prosedur atau pemicu yang memunculkan kesalahan, atau NULL jika kesalahan tidak terjadi dalam prosedur atau pemicu.
  • ERROR_LINE():Mengembalikan nomor baris tempat kesalahan terjadi. Ini bisa berupa nomor baris prosedur atau pemicu atau nomor baris dalam batch.
  • ERROR_MESSAGE():Mengembalikan teks pesan kesalahan.

Contoh berikut menunjukkan cara menangani kesalahan. Contoh pertama berisi Pembagian dengan nol kesalahan, sedangkan pernyataan kedua benar.

BEGIN TRY
   PRINT 1/0  
   SELECT 'Correct text'
END TRY
BEGIN CATCH
   SELECT ERROR_NUMBER() AS ERR_NO
   ,      ERROR_SEVERITY() AS ERR_SEV
   ,      ERROR_STATE() AS ERR_STATE
   ,      ERROR_LINE() AS ERR_LINE
   ,      ERROR_MESSAGE() AS ERR_MESSAGE
END CATCH

Jika pernyataan kedua dijalankan tanpa penanganan kesalahan (PILIH 'Teks yang benar'), itu akan berhasil.

Karena kami menerapkan penanganan kesalahan khusus di blok TRY-CATCH, eksekusi program diteruskan ke blok CATCH setelah kesalahan dalam pernyataan pertama, dan pernyataan kedua tidak pernah dieksekusi.

Dengan cara ini, Anda dapat memodifikasi teks yang diberikan kepada pengguna dan mengontrol apa yang terjadi jika kesalahan terjadi dengan lebih baik. Misalnya, kami mencatat kesalahan ke tabel log untuk analisis lebih lanjut.

Menggunakan transaksi

Logika bisnis mungkin menentukan bahwa penyisipan pernyataan pertama gagal saat pernyataan kedua gagal, atau bahwa Anda mungkin perlu mengulangi perubahan pernyataan pertama pada kegagalan pernyataan kedua. Menggunakan transaksi memungkinkan Anda mengeksekusi sekumpulan pernyataan sebagai satu unit yang gagal atau berhasil.

Contoh berikut menunjukkan penggunaan transaksi.

Pertama, kami membuat tabel untuk menguji data yang disimpan. Kemudian kami menggunakan dua transaksi di dalam blok TRY-CATCH untuk mensimulasikan hal-hal yang terjadi jika bagian dari transaksi gagal.

Kami akan menggunakan pernyataan CATCH dengan pernyataan XACT_STATE(). Fungsi XACT_STATE() digunakan untuk memeriksa apakah transaksi masih ada. Jika transaksi dibatalkan secara otomatis, TRANSAKSI ROLLBACK akan menghasilkan pengecualian baru.

Dapatkan looting pada kode di bawah ini:

-- CREATE TABLE TEST_TRAN(VALS INT)

BEGIN TRY
   BEGIN TRANSACTION
       INSERT INTO TEST_TRAN(VALS) VALUES(1);
   COMMIT TRANSACTION  

   BEGIN TRANSACTION
       INSERT INTO TEST_TRAN(VALS) VALUES(2);
       INSERT INTO TEST_TRAN(VALS) VALUES('A'); 
       INSERT INTO TEST_TRAN(VALS) VALUES(3);
   COMMIT TRANSACTION
END TRY
BEGIN CATCH  
   IF XACT_STATE() > 0 ROLLBACK TRANSACTION

   SELECT ERROR_NUMBER() AS ERR_NO
   ,      ERROR_SEVERITY() AS ERR_SEV
   ,      ERROR_STATE() AS ERR_STATE
   ,      ERROR_LINE() AS ERR_LINE
   ,      ERROR_MESSAGE() AS ERR_MESSAGE

END CATCH

SELECT * FROM TEST_TRAN

-- DROP TABLE TEST_TRAN

Gambar menunjukkan nilai dalam tabel TEST_TRAN dan pesan kesalahan:

Seperti yang Anda lihat, hanya nilai pertama yang dilakukan. Pada transaksi kedua, kami memiliki kesalahan konversi jenis di baris kedua. Dengan demikian, seluruh batch dibatalkan.

Dengan cara ini, Anda dapat mengontrol data apa yang masuk ke database dan bagaimana batch diproses.

Membuat pesan kesalahan khusus dalam SQL

Terkadang, kami ingin membuat pesan kesalahan khusus. Biasanya, mereka dimaksudkan untuk skenario ketika kita tahu bahwa masalah mungkin terjadi. Kami dapat membuat pesan kustom kami sendiri yang mengatakan bahwa sesuatu yang salah telah terjadi tanpa menunjukkan detail teknis. Untuk itu, kami menggunakan kata kunci THROW.

BEGIN TRY
   IF ( SELECT COUNT(sys.all_objects) > 1 )
	THROW ‘More than one object is ALL_OBJECTS system table’
END TRY
BEGIN CATCH
   SELECT ERROR_NUMBER() AS ERR_NO
   ,      ERROR_SEVERITY() AS ERR_SEV
   ,      ERROR_STATE() AS ERR_STATE
   ,      ERROR_LINE() AS ERR_LINE
   ,      ERROR_MESSAGE() AS ERR_MESSAGE
END CATCH

Atau, kami ingin memiliki katalog pesan kesalahan khusus untuk kategorisasi dan konsistensi pemantauan dan pelaporan kesalahan. SQL Server memungkinkan kita untuk menentukan kode pesan kesalahan, tingkat keparahan, dan status.

Prosedur tersimpan yang disebut "sys.sp_addmessage" digunakan untuk menambahkan pesan kesalahan khusus. Kita dapat menggunakannya untuk memanggil pesan kesalahan di banyak tempat.

Kami dapat memanggil RAISERROR dan mengirim nomor pesan sebagai parameter alih-alih mengkodekan detail kesalahan yang sama di beberapa tempat dalam kode.

Dengan mengeksekusi kode yang dipilih dari bawah, kami menambahkan kesalahan khusus ke SQL Server, meningkatkannya, dan kemudian menggunakan sys.sp_dropmessage untuk menghapus pesan kesalahan yang ditentukan pengguna yang ditentukan:

exec sys.sp_addmessage @msgnum=55000, @severity = 11, 
                                          @msgtext = 'My custom error message'
GO

RAISERROR(55000,11,1)
GO

exec sys.sp_dropmessage @msgnum=55000
GO

Juga, kita dapat melihat semua pesan di SQL Server dengan menjalankan formulir kueri di bawah ini. Pesan kesalahan khusus kami terlihat sebagai item pertama di hasil:

SELECT * FROM master.dbo.sysmessages

Buat sistem untuk mencatat kesalahan

Itu selalu berguna untuk mencatat kesalahan untuk debugging dan pemrosesan nanti. Anda juga dapat menempatkan pemicu pada tabel yang dicatat ini dan bahkan menyiapkan akun email dan sedikit kreatif dalam cara memberi tahu orang-orang ketika terjadi kesalahan.

Untuk mencatat kesalahan, kami membuat tabel bernama DBError_Log , yang dapat digunakan untuk menyimpan data detail log:

CREATE TABLE DBError_Log
(
    DBError_Log_ID    INT IDENTITY(1, 1) PRIMARY KEY,
    UserName              VARCHAR(100),
    ErrorNumber    INT,
    ErrorState     INT,
    ErrorSeverity  INT,
    ErrorLine      INT,
    ErrorProcedure VARCHAR(MAX),
    ErrorMessage   VARCHAR(MAX),
    ErrorDateTime  DATETIME
);

Untuk mensimulasikan mekanisme logging, kami membuat GenError prosedur tersimpan yang menghasilkan Pembagian dengan nol kesalahan dan mencatat kesalahan ke DBError_Log tabel:

CREATE PROCEDURE dbo.GenError
AS
  BEGIN TRY
    SELECT 1/0
  END TRY
  BEGIN CATCH
    INSERT INTO dbo.DBError_Log
    VALUES
    (SUSER_SNAME(),
     ERROR_NUMBER(),
     ERROR_STATE(),
     ERROR_SEVERITY(),
     ERROR_LINE(),
     ERROR_PROCEDURE(),
     ERROR_MESSAGE(),
     GETDATE()
	);
  END CATCH
GO

EXEC dbo.GenError
SELECT * FROM  dbo.DBError_Log

DBError_Log tabel berisi semua informasi yang kita butuhkan untuk men-debug kesalahan. Juga, ini memberikan informasi tambahan tentang prosedur yang menyebabkan kesalahan. Meskipun ini mungkin tampak seperti contoh sepele, Anda dapat memperluas tabel ini dengan bidang tambahan atau menggunakannya untuk mengisinya dengan pengecualian yang dibuat khusus.

Kesimpulan

Jika kami ingin memelihara dan men-debug aplikasi, kami setidaknya ingin melaporkan bahwa ada yang tidak beres dan juga mencatatnya di bawah tenda. Saat kami memiliki aplikasi tingkat produksi yang digunakan oleh jutaan pengguna, penanganan kesalahan yang konsisten dan dapat dilaporkan adalah kunci untuk men-debug masalah dalam waktu proses.

Meskipun kami dapat mencatat kesalahan asli ke log kesalahan basis data, pengguna akan melihat pesan yang lebih ramah. Oleh karena itu, sebaiknya terapkan pesan kesalahan khusus yang ditampilkan ke aplikasi pemanggil.

Apa pun desain yang Anda terapkan, Anda perlu mencatat dan menangani pengecualian pengguna dan sistem. Tugas ini tidak sulit dengan SQL Server, tetapi Anda perlu merencanakannya dari awal.

Menambahkan operasi penanganan kesalahan pada database yang sudah berjalan dalam produksi mungkin melibatkan pemfaktoran ulang kode yang serius dan masalah kinerja yang sulit ditemukan.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara menggunakan penghapusan kaskade dengan SQL Server?

  2. Baris SQL ke Kolom

  3. Bagaimana cara mengubah nilai kolom identitas secara terprogram?

  4. Bagaimana saya bisa terhubung ke Sql Server dari Mac dengan PHP PDO?

  5. bagaimana cara memisahkan string menjadi kolom yang berbeda?