开发者

T-SQL: control flow in case of errors

开发者 https://www.devze.com 2023-03-28 12:50 出处:网络
Sup guys, is it possible for INSERT or UPDATE to throw an exception that would stop the procedure? I\'m in a little bit of a pickle, because i\'ve hanging transactions in what seems to be a bullet pro

Sup guys, is it possible for INSERT or UPDATE to throw an exception that would stop the procedure? I'm in a little bit of a pickle, because i've hanging transactions in what seems to be a bullet proof code.

    BEGIN TRANSACTION;

SET @sSystemLogDataId  = CONVERT(NCHAR(36), NEWID());
INSERT INTO crddata.crd_systemlogdata (systemdataid,systemlogid,userid,
    actiondatetime,actionstate)
    VALUES(@sSystemLogDataId,@inSystemLogId,@sUserId,GETDATE(),@nActionState);
SET @nError = @@ERROR;

IF (1 = @nChangeMassprintTaskStatus) AND (0 = @nError)
BEGIN
    UPDATE crddata.crd_m开发者_JAVA百科assprinttasks SET massprinttaskstatus=@nMassprintTaskStatus
        WHERE massprinttaskid = @inMassprintTaskId;
    SET @nError = @@ERROR;
END

IF (@MassprintTaskType <> 1) AND (27 = @nActionState) AND (0 = @nError)
BEGIN
    UPDATE crddata.crd_massprinttasks SET massprinttasktype=1
        WHERE massprinttaskid = @inMassprintTaskId;
    SET @nError = @@ERROR;
END

IF 0 = @nError
BEGIN
    COMMIT TRANSACTION;
END
ELSE
BEGIN
    ROLLBACK TRANSACTION;
END 

Halp, anyone?


Without TRY/CATCH, this is not bullet proof.

Errors can be batch aborting (eg datatype conversions or errors thrown from triggers) which means ROLLBACK does not run.

You have to use TRY/CATCH and I always use SET XACT_ABORT ON too

SET XACT_ABORT, NOCOUNT ON;
BEGIN TRY

    BEGIN TRANSACTION;

    SET @sSystemLogDataId  = CONVERT(NCHAR(36), NEWID());
    INSERT INTO crddata.crd_systemlogdata (systemdataid,systemlogid,userid,
        actiondatetime,actionstate)
        VALUES(@sSystemLogDataId,@inSystemLogId,@sUserId,GETDATE(),@nActionState);

    IF (1 = @nChangeMassprintTaskStatus)
    BEGIN
        UPDATE crddata.crd_massprinttasks SET massprinttaskstatus=@nMassprintTaskStatus
            WHERE massprinttaskid = @inMassprintTaskId;
    END

    IF (@MassprintTaskType <> 1) AND (27 = @nActionState)
    BEGIN
        UPDATE crddata.crd_massprinttasks SET massprinttasktype=1
            WHERE massprinttaskid = @inMassprintTaskId;
    END

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 --may already be rolled back by SET XACT_ABORT or a trigger
         ROLLBACK TRANSACTION;
    RAISERROR [rethrow caught error using ERROR_NUMBER(), ERROR_MESSAGE(), etc]
END CATCH

Mandatory background reading is Erland Sommarskog's "Error Handling in SQL 2005 and Later": we'll test you on it later...


Create a trigger that will raise an exception if insert/update is not correct

example:

create table t (id int)

go

create trigger tr on t 
for insert 
as
if exists(select 1 from inserted where id = 0)
    raiserror('id is not valid', 16, 1)

go

insert t select 1

select @@error

insert t select 0

select @@error
0

精彩评论

暂无评论...
验证码 换一张
取 消