我遇到了一个存储过程,它在更新尝试后立即出现以下错误处理块。以下是SP的最后几行。
这样做有什么好处吗?在我看来好像这个代码只是重新抛出它没有添加任何值时捕获的相同错误,并且如果Try Block完全被忽略,代码可能会表现为100%相同。
如果省略TRY块,生成的SP的行为会有什么不同吗?
BEGIN CATCH
SELECT @ErrMsg = ERROR_MESSAGE(), @ErrSev = ERROR_SEVERITY(), @ErrState = ERROR_STATE()
RAISERROR (@ErrMsg, @ErrSev, @ErrState)
END CATCH
答案 0 :(得分:2)
我们通常在存储过程中执行的操作是像这样编写catch块
BEGIN CATCH
DECLARE @i_intErrorNo int
DECLARE @i_strErrorMsg nvarchar(1000)
DECLARE @i_strErrorProc nvarchar(1000)
DECLARE @i_intErrorLine int
SELECT @i_intErrorNo=Error_Number()
SELECT @i_strErrorMsg=Error_Message()
SELECT @i_strErrorProc=Error_Procedure()
SELECT @i_intErrorLine=Error_Line()
INSERT INTO error table ////// Insert statement.
END CATCH
这是我们用来存储错误的方法。为了向用户提供正确的消息,我总是将输出参数用于存储过程以显示错误的详细/必需原因。
答案 1 :(得分:2)
除非返回的任何消息部分出现“行错误”,否则将引用RAISERROR行而不是错误实际发生的行,这将没有区别。执行此操作的主要原因是@Chris说,允许您以编程方式使用/操作错误数据。
答案 2 :(得分:1)
如果您查看msdn page for RAISERROR,则可以看到此一般说明:
生成错误消息 启动错误处理 会话。 RAISERROR可以 引用用户定义的消息 存储在sys.messages目录中 动态查看或构建消息。 该消息作为服务器返回 呼叫错误消息 应用程序或相关的CATCH TRY ... CATCH构造的块。
似乎“调用应用程序”将收到错误消息。可能是存储过程的创建者只想要报告错误消息,严重性和状态,而不能添加其他选项。这可能是出于安全问题或仅仅是调用应用程序不需要知道额外信息(可能是冗长或过于详细的信息)。
答案 3 :(得分:0)
存在细微差别,如下所示。
首先设置以下内容:
CREATE TABLE TMP
( ROW_ID int NOT NULL,
ALTER TABLE TMP ADD CONSTRAINT PK_TMP PRIMARY KEY CLUSTERED (ROW_ID)
)
GO
CREATE PROC pTMP1
AS
BEGIN TRY
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(2)
END TRY
BEGIN CATCH
DECLARE @ErrMsg varchar(max)= ERROR_MESSAGE(),
@ErrSev int = ERROR_SEVERITY(),
@ErrState int = ERROR_STATE()
RAISERROR (@ErrMsg, @ErrSev, @ErrState)
END CATCH
GO
CREATE PROC pTMP2
AS
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(2)
GO
现在运行以下命令:
SET NOCOUNT ON
DELETE TMP
exec pTMP1
SELECT * FROM TMP
DELETE TMP
exec pTMP2
SELECT * FROM TMP
SET NOCOUNT OFF
--Cleanup
DROP PROCEDURE pTMP1
DROP PROCEDURE pTMP2
DROP TABLE TMP
您应该得到以下结果:
Msg 50000, Level 14, State 1, Procedure pTMP1, Line 12
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1).
ROW_ID
-----------
1
Msg 2627, Level 14, State 1, Procedure pTMP2, Line 4
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1).
The statement has been terminated.
ROW_ID
-----------
1
2
请注意TRY..CATCH
版本没有执行第三个INSERT
语句,而pTMP2
个版本没有执行。这是因为一旦发生错误,控制就会跳转到CATCH
。
注意:pTMP2
设置会影响XACT_ABORT
的行为。
使用TRY..CATCH
的好处取决于您管理交易边界的方式。
TMP
查询WITH(NOLOCK)
,则甚至可以观察到临时更改。