Xử lý ngoại lệ trong T-SQL

Xử lý ngoại lệ

Trong một vài trường hợp, logic của câu truy vấn sẽ bị sai lệch, ảnh hưởng đến toàn bộ hệ thống. T-SQL cung cấp cho chúng ta một số câu lệnh để xử lý những ngoại lệ đó. Nhằm đảo bảo tính logic tổng thể cho hệ thống.

Với những bạn lập trình viên, những câu lệnh xử lý ngoại lệ này không có gì mới lạ. Tuy nhiên, chúng ta hãy cùng xem qua, cách mà T-SQL hiện thực chúng.

TRY – CATCH

Cú pháp TRY – CATCH cho phép chúng ta xử lý ngoại lệ một cách chủ động. Nhờ vậy, chúng ta có thể kiểm soát logic cũng như những lỗi phát sinh một cách tốt hơn. Ý tưởng của phương pháp này rất đơn giản. Yêu cầu hệ thống thực hiện một công việc nào đó. Nếu một lỗi phát sinh, xử lý lỗi đó theo một phương pháp đã định trước.

Cấu trúc của TRY – CATCH như sau:

Hệ thống sẽ thử thực hiện các câu lệnh SQL trong block lệnh TRY. Nếu phát sinh lỗi, nó sẽ tự động thực hiện các câu lệnh SQL trong block lệnh CATCH.

Để hiểu rõ hơn, chúng ta cùng xem qua một ví dụ bên dưới.

Tranh thủ ôn tập lại một chút kiến thức cũ. Trong ví dụ này mình có tạo một stored procedure cơ bản với chức năng thực hiện phép chia.

Bây giờ, chúng ta sẽ cùng sử dụng procedure này.

Lần 1: Mình thử chia 10 cho 2.

Câu truy vấn
Kết quả trả về = 5.

Lần 2: Mình thử lại, đổi số chia = 0. Tất cả chúng ta đều biết, phép tính này không hợp lệ.

Phép tính không hợp lệ
Phép tính không hợp lệ

Phép tính này không hợp lệ, các lệnh SQL trong block CATCH được thực thi, cho chúng ta biết các thông tin về lỗi.

RAISERROR

Vì một số lý do, Microsoft khuyến cáo chúng ta sử dụng cú pháp THROW thay cho RAISERROR. Tuy nhiên, mình cũng giới thiệu sơ qua về cú pháp RAISERROR cho các bạn.

Ở ví dụ trên, các bạn để ý thuộc tính cuối cùng trong kết quả trả về ‘Divide by zero…’ hay trong Tiếng Việt là ‘lỗi chia cho số 0’. Đây là một lỗi khá phổ thông trong toán học, nên nó được T-SQL định nghĩa sẵn. Vậy, các lỗi riêng biệt cho một CSDL cụ thể thì như thế nào? SQL Server cũng cho phép chúng ta định nghĩa thêm các lỗi mới cho từng trường hợp cụ thể với cú pháp RAISERROR.

Với cấu trúc trên, phương thức RAISERROR sẽ có 2 tham số bắt buộc:

  • tham số đầu tiên: nội dung thông báo lỗi. Có thể sử dụng 1 trong 3 cách:
    • msg_id: Là một ‘error mesage’ được người dùng khai báo. Nó được lưu trữ trong sys.message.
    • msg_str: Là một chuỗi lỗi, được đặt trong dấu nháy đơn.
    • @local_variable: Một biến cục bộ, chứa thông báo lỗi.
  • tham số thứ hai: mức độ của lỗi:
    • serverity: là một số nằm trong đoạn [0, 25]. Với mỗi giá trị thể hiện một mức độ nghiêm trọng.
      • 0-10: Informational messages
      • 11-18: Errors
      • 19-25: Fatal errors
    • state: là một số nằm trong đoạn [0-255]. Mỗi giá trị sẽ mang một ý nghĩa được quy ước bởi quản trị viên. Ví dụ một số lỗi phát sinh cùng một lý do (như không tìm thấy id của nhân viên, do nhân viên đó đã nghỉ việc và bị xóa khỏi hệ thống…vv), có thể set 1 giá trị chung, để có phương án xử lý.

THROW

Tương tự TRY – CATCH, THROW cũng là một câu lệnh khá quen thuộc trong xử lý ngoại lệ đối với những bạn lập trình viên. Trong T-SQL, cú pháp của phương thức THROW như sau:

Ý nghĩa của các tham số như sau:

  • error_number: là một số nguyên, có giá trị >= 50 000 và nhỏ hơn 2 147 483 647.
  • message: là một chuỗi mô tả lỗi, message là một biến NVARCHAR(2048)
  • state: là một hằng số nằm trong đoạn [0-255]. Chức năng tương tự state trong RAISERROR. State là một biến TINYINT

Ví dụ sử dụng THROW

Khi thực thi các câu lệnh SQL trong block TRY, chúng ta insert trùng giá trị primary key. Hệ thống sẽ chuyển qua block CATCH. Với câu lệnh THROW (không có tham số), hệ thống sẽ xuất ra các lỗi mặc định (nếu có). Ngược lại, chúng ta cũng có thể điền các tham số khác cho phương thức THROW, nếu chúng ta muốn hiển thị các thông báo lỗi đặc biệt.