是否编译包含不存在列的sql server脚本?

fhg3lkii  于 2021-07-27  发布在  Java
关注(0)|答案(1)|浏览(271)

我有一个sql脚本,它在删除列之前作为迁移在数据库上运行。因为源列存在,所以它第一次工作正常,但是如果您再次尝试运行迁移,它将失败,因为现在该列不存在。我将它 Package 在if中,因此该语句仅在列确实存在时运行,但它仍然需要能够编译该位,即使我知道它不会运行它。
以下是简化版本:

IF COL_LENGTH('TableA', 'SourceColumn') IS NOT NULL
BEGIN
    UPDATE TableB
    SET DestColumn = TableA.SourceColumn
    FROM TableB
    JOIN TableA AS ON TableB.AId = TableA.Id
    WHERE TableB.DestColumn != TableA.SourceColumn;
END

ALTER TABLE TableA 
DROP COLUMN SourceColumn;
flvlnr44

flvlnr441#

一种方法是动态sql:

IF COL_LENGTH('TableA', 'SourceColumn') IS NOT NULL
BEGIN
    DECLARE @sql NVARCHAR(MAX);

    SET @sql = '
UPDATE TableB
    SET DestColumn = TableA.SourceColumn
FROM TableB JOIN
     TableA 
     ON TableB.AId = TableA.Id
WHERE TableB.DestColumn <> TableA.SourceColumn';

    EXEC sp_executesql @sql;
END;

你也可以使用一个有趣的黑客来解决这个问题,而不是使用动态sql。假设 id 是主键:

IF COL_LENGTH('TableA', 'SourceColumn') IS NOT NULL
BEGIN
    UPDATE TableB
    SET DestColumn = a.SourceColumn
    FROM TableB JOIN
         (SELECT a.id,
                 (SELECT SourceColumn   -- NO ALIAS!!
                  FROM TableA a2
                  WHERE a2.id = a.id
                 ) as SourceColumn
          FROM TableA a CROSS JOIN
               (VALUES (NULL)) v(SourceColumn)
         ) a
         ON TableB.AId = a.Id
    WHERE TableB.DestColumn <> TableA.SourceColumn;
END;

这是怎么回事?它使用作用域规则来分配 SourceColumn 在子查询中。如果列在 TableA ,然后填写。如果不是,则用中的值填充 v . 但是,这并不重要,因为在这种情况下代码不会运行。唯一的目的是避免标识符错误。

相关问题