Các bạn có thể xem tài liệu chính thức về câu lệnh RAISERROR
của Microsoft tại đây.
Giới thiệu
Câu lệnh RAISERROR
được dùng để tạo một nội dung (thường là lỗi, nhưng cũng có thể là nội dung khác như debug) để trả về cho ứng dụng. Nội dung này có thể được bắt bởi câu lệnh TRY...CATCH
hoặc trả về trực tiếp cho ứng dụng đang kết nối vào SQL Server.
Nếu ứng dụng là SSMS thì nội dung này sẽ nằm trong tab Messages.
Cú pháp
Như có thể thấy trong cú pháp này, RAISERROR
nhận 1 trong 3 loại đầu vào cho tham số đầu tiên:
msg_id
- là số định danh của mẫu câu có sẵn được lưu trong SQL Servermsg_str
- là nội dung tự chọn mà bạn mong muốn được xuất ra bởiRAISERROR
@local_variable
- là biến của ngôn ngữ T-SQL, có thể là số (tương ứng vớimsg_id
) hoặc chuỗi (tương ứng vớimsg_str
)
Sử dụng định danh của mẫu có sẵn trong SQL Server
Nếu tham số đầu tiên là số dưới dạng INT
, SQL Server sẽ sử dụng con số này để lấy mẫu câu có sẵn được lưu trong bảng sys.messages
để làm nội dung xuất ra cho RAISERROR
.
Các bạn có thể đọc thêm tài liệu chính thức của Microsoft về bảng sys.messages
tại đây.
Sử dụng mẫu của hệ thống
Mẫu có sẵn của hệ thống mà RAISERROR
có thể dùng được có định danh nằm trong khoảng 13000
đến 49999
. Cụ thể, các bạn có thể sử dụng câu lệnh ở dưới để liệt kê các mẫu có sẵn của hệ thống.
Ví dụ, nếu bạn muốn lấy mẫu có định danh 14138
với tham số cho mẫu là Aha
, bạn có thể sử dụng câu lệnh sau:
Sử dụng mẫu tự tạo
Ngoài mẫu có sẵn của hệ thống, SQL Server cũng cho phép người dùng tự tạo mẫu cho riêng mình bằng cách sử dụng SP (stored procedure) sys.sp_addmessage
(xem thêm).
Mẫu tự tạo mới bắt buộc phải sử dụng định danh từ 50001
trở lên và không trùng định danh với mẫu đã tạo trước đó.
Sau khi tạo mẫu thì chúng ta có thể sử dụng nó giống như là mẫu của hệ thống.
Sử dụng nội dung tự chọn
Nếu tham số đầu tiên là chuỗi dưới dạng CHAR
, NCHAR
, VARCHAR
hoặc NVARCHAR
, SQL Server sẽ sử dụng chuỗi này để làm nội dung xuất ra cho RAISERROR
.
RAISERROR
chỉ hỗ trợ chuỗi với nội dung không quá 2047 ký tự. Nếu nội dung có số lượng ký tự từ 2048 trở lên,RAISERROR
sẽ chỉ in ra 2044 ký tự và kết thúc bằng dấu ba chấm...
Khi sử dụng cách này, RAISERROR
sẽ sử dụng định danh 50000
cho nội dung trả về.
Sử dụng biến làm đầu vào
Nếu tham số đầu tiên là biến của T-SQL, thì tùy theo kiểu dữ liệu của biến là INT
hay CHAR
/NCHAR
/VARCHAR
/NVARCHAR
mà RAISERROR
sẽ xử lý tương ứng như đã trình bày ở trên.
Ví dụ nếu biến là định danh của mẫu:
Và ví dụ nếu biến là nội dung tự chọn:
Độ nghiêm trọng severity
và tình trạng state
của thông báo lỗi
Mục tiêu của bài này là giới thiệu sơ bộ nên mình sẽ không đi sâu vào giải thích 2 thuộc tính này. Nếu có dịp mình sẽ trình bày trong một bài khác.
Tuy nhiên để có thể sử dụng RAISERROR
theo ý muốn thì các bạn cũng nên có một cái nhìn sơ về 2 thuộc tính này.
Độ nghiêm trọng severity
Mỗi thông báo lỗi đều được gắn với một mức độ nghiêm trọng để SQL Server và ứng dụng có thể biết được để xử lý tương xứng. Cụ thể về severity
các bạn có thể xem thêm tại đây.
Cơ bản thì mình quan tâm đến các giá trị sau của severity
:
severity |
Cách sử dụng |
---|---|
0 | 10 |
Nội dung bình thường (không phải lỗi), và chỉ in nội dung. Sử dụng cho nội dung thông báo bình thường (information). |
1 ~ 9 |
Nội dung bình thường (không phải lỗi), và in đầy đủ thông tin. Sử dụng cho nội dung debug. |
16 |
Sử dụng cho lỗi tự tạo |
-1 |
Sử dụng giá trị mặc định của mẫu |
Khi các bạn sử dụng SSMS thì toàn bộ nội dung mà RAISERROR
tạo ra đều nằm trong tab Messages. Nội dung bình thường sẽ có màu đen còn nội dung lỗi sẽ có màu đỏ.
Tình trạng state
Gọi là tình trạng vậy thôi, chứ trên thực tế giá trị này được tạo ra để có thể xác định vị trí của lỗi một cách dễ dàng hơn bằng cách sử dụng các giá trị state
khác nhau ở những đoạn code khác nhau.
state
nhận giá trị từ 0
đến 255
, và mình cũng khuyến khích các bạn sử dụng giá trị trong khoảng này.
Ví dụ
Định nghĩa và sử dụng tham số nhúng
Ở một vài ví dụ ở trên, các bạn có thể thấy mình sử dụng tham số cho mẫu hoặc nội dung bằng cách truyền giá trị tham số vào vị trí thứ 4 trong câu lệnh. Giá trị này thay thế cờ %s
trong nội dung được in ra.
Bạn có thể định nghĩa nhiều hơn một cờ trong nội dung, khi đó RAISERROR
sẽ sử dụng các tham số ở vị trí tiếp theo để thay thế cho các cờ này.
Cấu trúc hoàn chỉnh của cờ khá là phức tạp, nên mình để dành nội dung này cho một bài khác. Trong bài này mình chỉ liệt kê ra các cờ thông dụng mà mình hay sử dụng và kiểu dữ liệu tương ứng có thể sử dụng cho cờ đó.
Cờ | Kiểu dữ liệu có thể dùng |
---|---|
%s |
CHAR NCHAR VARCHAR NVARCHAR |
%d |
INT |
%I64d |
BIGINT |
%#x |
BINARY VARBINARY |
%% |
In ra ký tự % |
Điểm trừ lớn nhất của tham số nhúng là không hỗ trợ các kiểu dữ liệu thập phân như DECIMAL
, FLOAT
hay MONEY
/SMALLMONEY
. Tuy nhiên các bạn vẫn có thể dùng CAST
hoặc CONVERT
để chuyển dữ liệu thập phân về dạng chuỗi, sau đó sử dụng cờ %s
để làm tham số nhúng.
Tùy chọn bổ sung WITH NOWAIT
RAISERROR
cho phép người dùng bổ sung thêm tùy chọn để thay đổi cách SQL Server xử lý câu lệnh. Trong bài này, mình chỉ đề cập đến tùy chọn được sử dụng nhiều nhất, cũng như là lý do chính mà mình sử dụng RAISERROR
, đó là tùy chọn WITH NOWAIT
.
Hãy lấy ví dụ sau làm minh họa cho tình huống thực tế (ví dụ như theo dõi tiến độ chạy của script):
Trong đoạn code trên, mình đang muốn in ra nội dung First message
và Second message
, sau đó chờ 5 giây rồi mới in ra Final message after 5 seconds
. Nhưng khi chạy đoạn code trên thì hoàn toàn không giống mong đợi:
SSMS đợi hết 5 giây rồi mới in ra cả 3 nội dung. Sở dĩ có hành vi này là do SSMS sử dụng buffer cho nội dung trả về từ SQL Server. Cho đến khi truy vấn kết thúc hoặc buffer đầy (khoảng 8KB
- xem thêm) thì SSMS mới in kết quả ra cho chúng ta. Điều này cũng áp dụng cho nội dung in ra từ câu lệnh PRINT
.
May thay, RAISERROR
cho phép chúng ta bật tùy chọn WITH NOWAIT
để ngay lập tức in ra nội dung mà không cần phải đợi truy vấn kết thúc hay buffer đầy nữa. Hãy xem thử script của chúng ta có hành xử đúng như mong muốn sau khi thêm tùy chọn này hay không:
Tada. Ngay lập tức chúng ta nhận ra sự khác biệt. First message
và Second message
đều được in ra như mong đợi. Ngoài ra chúng ta cũng có thể thấy ---
của câu lệnh PRINT
đầu tiên được in ra theo đúng thứ tự, nhưng ---
tiếp theo lại không được in ra. Điều này là do như đã nói ở trên, PRINT
phải đợi truy vấn kết thúc hoặc khi buffer được giải phóng do đầy hoặc RAISERROR ... WITH NOWAIT
thì mới được in ra.
Chính vì cách hành xử của RAISERROR ... WITH NOWAIT
giống với mong đợi của mình nên mình luôn sử dụng tùy chọn này mỗi khi dùng RAISERROR
.
Lời kết
Trên đây là toàn bộ những kiến thức cơ bản về câu lệnh RAISERROR
mà mình tổng hợp lại. Hy vọng bài này có thể giúp các bạn biết và hiểu thêm về câu lệnh này, cũng như có thể áp dụng được RAISERROR
(hay nói cách khác, RAISERROR ... WITH NOWAIT
) vào công việc của các bạn.
Nếu có vấn đề gì thắc mắc liên quan đến chủ đề này, các bạn có thể liên hệ mình thông qua Facebook Messenger. Chúc các bạn một ngày làm việc vui vẻ ./.