存在一个细微的差异,如下所示。
首次设置如下:
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
proc没有。这是因为一旦发生错误,控制就跳转到CATCH
。
注意:pTMP2
的行为受XACT_ABORT
设置的影响。
结论
使用TRY..CATCH
所证实的好处取决于你如何管理自己的事务边界。
- 如果您回滚任何错误,则更改将被撤消。但是这并不能消除附加处理等副作用。注意:如果不同的会话使用
WITH(NOLOCK)
同时查询TMP
,它甚至可能会观察到临时更改。
- 但是,如果您不打算回滚事务,则可能会发现该技术对于防止应用某些数据更改(尽管存在较早的错误)非常重要。
我能想到的唯一区别是,行号信息和错误号码信息会更准确,因为没有`CATCH`抛出一个新的异常,所以它实际上似乎减去了值,据我所知。 .. – 2011-02-14 14:44:41
我总是喜欢在前端有一个自定义的错误消息,而不是sql生成的错误消息。这种方式会给你你理解和提到的逻辑和技术错误。 – Chris 2011-02-14 15:08:48