SQL 当 IF 条件为真时,ELSE 块仍然抛出错误

SQL ELSE block still throws error when IF condition is true

我有以下 T-SQL 脚本,它将旧列的值复制到新列中,然后删除旧列。看这里:

--step 1: create new column
IF NOT EXISTS(SELECT 1 from sys.columns
                WHERE Name = N'UserColumn2'
                AND Object_ID = Object_ID(N'Account'))
    BEGIN
        ALTER TABLE Account
        ADD UserColumn2 int null
        ;
    END
GO
;

--step 2: copy and drop
IF NOT EXISTS(SELECT 1 from sys.columns
        WHERE Name = N'UserColumn1'
        AND Object_ID = Object_ID(N'Account'))
    BEGIN 
        PRINT 'Column ''UserColumn1'' does not exist.';
    END
ELSE
    BEGIN
        UPDATE Account
        SET UserColumn2 = UserColumn1
        WHERE UserColumn1 is not null
        ;

        BEGIN TRY
            Declare @count int;
            SELECT @count = Count(AccountID)
            FROM Account
            WHERE UserColumn2 <> UserColumn1
            ;
            IF @count > 0
                BEGIN 
                    --PRINT 'Not all records were properly updated. UserColumn1 has not been dropped.';
                    THROW 50000,'Not all records were properly updated. UserColumn1 has not been dropped.',1
                    ;
                END
            ELSE
                BEGIN
                    ALTER TABLE Account
                    DROP Column UserColumn1
                    ;
                END
        END TRY
        BEGIN CATCH THROW; END CATCH
    END
GO
;

第一步运行正确,但第二步仍然在 ELSE 块中抛出错误,即使 UserColumn1 列不存在也是如此:


(注意:这里的代码实际上在第 24 行抛出。我的 SSMS 中的代码没有 'step 1' 等的注释)

为什么会发生这种情况,我该如何预防?

我尝试删除 NOT 并将指令移出 ELSE 块,但行为没有改变。我也试过这样写第二步的开头:

IF (SELECT 1 from sys.columns
        WHERE Name = N'UserColumn1'
        AND Object_ID = Object_ID(N'Account')) <> null

我得到了相同的结果。

问题是整个 sql 文本在执行之前被解析和编译,在编译时抛出错误。

您可以通过使用动态 sql 在其自己的进程中执行更新语句来解决它 - 尽管此用法中没有任何 dynamic,它只是推迟了编译并执行 update 语句,它只在您的 else 条件下发生:

IF NOT EXISTS(SELECT 1 from sys.columns
        WHERE Name = N'UserColumn1'
        AND Object_ID = Object_ID(N'Account'))
    BEGIN 
        PRINT 'Column ''UserColumn1'' does not exist.';
    END
ELSE
    BEGIN
        EXEC sp_executesql N'
          UPDATE Account
          SET UserColumn2 = UserColumn1
          WHERE UserColumn1 is not null;'

...
...