【问题标题】:SQL ELSE block still throws error when IF condition is true当 IF 条件为真时,SQL ELSE 块仍然抛出错误
【发布时间】:2021-08-22 22:37:27
【问题描述】:

我有以下 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
;

第一步运行正确,但即使UserColumn1 列不存在,第二步仍会在ELSE 块中引发错误:


(注意:这里的代码实际上在第 24 行抛出。我的 SSMS 中的代码没有“步骤 1”等的 cmets)

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

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

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

我得到了同样的结果。

【问题讨论】:

    标签: sql-server tsql if-statement exists


    【解决方案1】:

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

    您可以通过使用动态 sql 在其自己的进程中执行更新语句来解决此问题 - 尽管在此用法中没有任何 动态,但它只是推迟了 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;'
    
    ...
    ...
    

    【讨论】:

    • 我最终将它用于ELSE 块的全部内容,现在效果很好。感谢您的澄清。
    猜你喜欢
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多