Từ tài liệu RAISERROR (nhấn mạnh của tôi):
Mức độ nghiêm trọng từ 0 đến 18 có thể được chỉ định bởi bất kỳ người dùng nào. Mức độ nghiêm trọng từ 19 đến 25 chỉ có thể được chỉ định bởi các thành viên của vai trò máy chủ cố định sysadmin hoặc người dùng có quyền ALTER TRACE. Đối với các mức độ nghiêm trọng từ 19 đến 25, tùy chọn VỚI LOG là bắt buộc.
Rất có khả năng hiệu trưởng bạn đang thực thi tập lệnh vì không đáp ứng các tiêu chí này.
Không có gì sai khi sử dụng RAISERROR
; bạn chỉ đang sử dụng một mức độ nghiêm trọng quá mức. Tôi sử dụng cấp 16 làm mặc định cho một lỗi được nêu ra và chuỗi sẽ bị chấm dứt. Nếu bạn muốn chính xác hơn, bạn có thể làm theo các mức do chính Microsoft đưa ra:
Bây giờ, đã nói tất cả những điều đó, tùy thuộc vào ngữ cảnh của tập lệnh, sử dụng RAISERROR
có thể là không đủ, vì nó không tự "thoát" tập lệnh (sử dụng mức độ nghiêm trọng thông thường).
Ví dụ:
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Executed! */
Điều này sẽ vừa nâng cao một lỗi và trả về một tập kết quả.
Để chấm dứt tập lệnh ngay lập tức, tôi thích sử dụng RETURN
(sử dụng các GOTO
cấu trúc -type thường không được khuyến khích trong hầu hết các vòng lập trình nơi có các lựa chọn thay thế):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
Hoặc xử lý lỗi bằng cách sử dụng TRY/CATCH
, điều này sẽ khiến việc thực thi nhảy sang CATCH
khối nếu mức độ nghiêm trọng là 11 hoặc cao hơn:
BEGIN TRY
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Not executed */
END TRY
BEGIN CATCH
SELECT 2; /* Executed */
END CATCH
BEGIN TRY
RAISERROR(N'Test', 10, 1);
SELECT 1; /* Executed */
END TRY
BEGIN CATCH
SELECT 2; /* Not executed */
END CATCH
Một vấn đề khác là nếu tập lệnh kéo dài nhiều đợt - RETURN
sẽ chỉ thoát khỏi lô :
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
SELECT 2; /* Executed! */
Để khắc phục điều này, bạn có thể kiểm tra @@ERROR
tại đầu mỗi đợt:
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
RETURN;
SELECT 2; /* Not executed */
Chỉnh sửa: Như Martin Smith đã chỉ ra chính xác trong các bình luận, điều này chỉ hoạt động trong 2 đợt. Để mở rộng lên 3 đợt trở lên, bạn có thể xếp tầng tăng các lỗi như vậy (lưu ý: GOTO
phương pháp không giải quyết được vấn đề này vì nhãn đích phải được xác định trong lô):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 2; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 3; /* Not executed */
Hoặc, như ông cũng chỉ ra, bạn có thể sử dụng SQLCMD
phương pháp nếu phù hợp với môi trường của bạn.