Khi BACKUP DATABASE
tạo ra một lỗi, nó thực sự tạo ra hai. Thật không may TRY/CATCH
là không có khả năng bắt lỗi đầu tiên; nó chỉ bắt lỗi thứ hai.
Tôi nghi ngờ đặt cược tốt nhất của bạn để nắm bắt được lý do thực sự đằng sau một bản sao lưu thất bại là để tự động sao lưu của bạn thông qua SQLCMD (với -o
để gửi đầu ra vào một tập tin), SSIS, C #, PowerShell vv Tất cả trong số đó sẽ cung cấp cho bạn kiểm soát tốt hơn nhiều so với chụp tất cả của các lỗi.
Câu trả lời SO trong bình luận gợi ý sử dụng DBCC OUTPUTBUFFER
- trong khi có thể, điều này dường như không giống như trò chơi trẻ con. Hãy vui vẻ với thủ tục này từ trang web của Erland Sommarskog , nhưng điều này dường như vẫn không hoạt động tốt khi kết hợp với TRY/CATCH
.
Cách duy nhất tôi dường như có thể nắm bắt được thông báo lỗi spGET_LastErrorMessage
là nếu lỗi thực tế bị ném. Nếu bạn bọc nó trong một TRY/CATCH
lỗi sẽ bị nuốt và quy trình được lưu trữ không làm gì:
BEGIN TRY
EXEC sp_executesql N'backup that fails...';
END TRY
BEGIN CATCH
EXEC dbo.spGet_LastErrorMessage;
END CATCH
Trong SQL Server <2012, bạn không thể tự khắc phục lỗi, nhưng bạn có thể trong SQL Server 2012 trở lên. Vì vậy, hai biến thể này hoạt động:
CREATE PROCEDURE dbo.dothebackup
AS
BEGIN
SET NOCOUNT ON;
EXEC sp_executesql N'backup that fails...';
END
GO
EXEC dbo.dothebackup;
EXEC dbo.spGET_LastErrorMessage;
Hoặc trong năm 2012 trở lên, điều này hoạt động, nhưng ở một mức độ lớn đánh bại mục đích TRY/CATCH
, vì lỗi ban đầu vẫn bị ném:
CREATE PROCEDURE dbo.dothebackup2
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
EXEC sp_executesql N'backup that fails...';
END TRY
BEGIN CATCH
THROW;
END CATCH
END
GO
EXEC dbo.dothebackup2;
EXEC dbo.spGET_LastErrorMessage;
Trong cả hai trường hợp này, lỗi vẫn được ném cho khách hàng, tất nhiên. Vì vậy, nếu bạn đang sử dụng TRY/CATCH
để tránh điều đó, trừ khi có một kẽ hở nào đó tôi không nghĩ tới, tôi sợ bạn sẽ phải đưa ra lựa chọn ... hoặc cung cấp cho người dùng lỗi và có thể nắm bắt chi tiết về nó, hoặc ngăn chặn cả lỗi và lý do thực tế.