有微妙的差别,如下所示。
首先设置以下内容:
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
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
的好处取决于您如何管理事务边界。
- 如果在任何错误上回滚,则更改将被撤消。但这并不能消除附加处理等副作用。注意:如果不同的会话同时使用
WITH(NOLOCK)
查询
TMP
,它甚至可能能够观察到临时更改。
- 但是,如果您不打算回滚事务,则可能会发现该技术非常重要,可以防止早期错误导致应用某些数据更改。
CATCH
抛出新异常,行号信息和错误号信息会更准确,因此在我看来实际上似乎会减少价值... - Martin Smith