if else 代码块如何获取带有事务的存储过程来执行?

How to get stored procedure with transaction to execute if else code block?

我有带多个参数的存储过程。根据参数值,将执行插入或编辑过程。在每个进程中有多个 Update/Insert 语句(更新或插入多个 table)。这是我的例子:

CREATE PROCEDURE dbo.stpAddStatus (
    @record_id  NUMERIC(8),
    @new_type_id NUMERIC(2),
    @current_type_id NUMERIC(2),
    @renew SMALLINT,
    @start_date DATETIME,
    @end_date DATETIME
)
AS
BEGIN
    DECLARE @new_end_dt DATETIME
    DECLARE @approve_end_date DATETIME

    IF @current_type_id != 2 AND @current_type_id != 6 
        SET @new_end_dt = @end_date
    ELSE
        SET @new_end_dt = NULL

    SET @approve_end_date = CONVERT(CHAR(10), DATEADD(dd, -1, @start_date), 101)    

    CREATE TABLE #tmpTbl (
        rec_id NUMERIC(8,0) NULL,
        type_id NUMERIC(3,0) NULL,
        active_status NUMERIC(10,0) NULL
    )

    INSERT INTO #tmpTbl (
        rec_id, 
        type_id, 
        status_id
    )
    SELECT 
        a.rec_id, 
        a.type_id, 
        a.active_status 
    FROM profile a 
    WHERE a.related = @record_id  
        AND type_id IN (10,12,13)

    BEGIN TRANSACTION
        IF (@new_type_id = @current_type_id) AND @renew = 0
            SELECT 'New Type ID is the same as Current Type ID and Renew is 0' AS Message
            /* In this block few different tables should be updated. */
        ELSE
            /* In this block record should be inserted in few different tables. */
            SELECT 'New Type ID is not the same as Current Type ID and Renew is 1' AS Message
        IF @@error !=0
        BEGIN 
            SELECT 1 AS Status, 'Error!' AS Message     
            ROLLBACK TRANSACTION
            RETURN 1
        END
    COMMIT TRANSACTION

    DROP TABLE #tmpTbl 
END

上面的代码将同时执行 If 和 Else 语句中的代码。不知道为什么,连SP传的参数都是这样的:

EXECUTE stpAddStatus 45645, 4, 4, 0, '04/23/2018', '06/22/2019'

我不确定我的 if/else 块语句是否正确,或者我遗漏了其他内容。如果您明白为什么代码失败并执行这两个语句,无论在 SP 中传递什么参数,请告诉我。

如果您计划为 if and/or else 块执行多个命令,您必须将这组命令包装在 BEGIN/END 对中,例如:

if .... 
begin
    ... 'if' command #1
    ... 'if' command #2
    ...
    ... 'if' command #n
end
else
begin
    ... 'then' command #1
    ... 'then' command #2
    ...
    ... 'then' command #n
end

如果ifand/orelse块中只有一个命令,则BEGIN/END是可选的;如有疑问,请包含 BEGIN/END 包装器。

此外,@@error 变量在每个命令后(重新)设置;我猜你想在任何命令出错时回滚你的事务,这意味着你需要在 each 命令之后添加更多逻辑来测试 @@error;无论您是在第一个错误后中止,还是在 if/then 块结束时都由您决定。

另一项,如果您的过程在更高级别的事务中被调用(例如,您 运行 处于链接模式),那么您的 rollback transaction 实际上将回滚所有事务。 [嵌套事务管理完全是另一个话题。]