9

我有一个 T-Sql 脚本,该脚本的一部分检查表中是否存在某个列。如果是这样,我希望它执行一个例程……如果不是,我希望它绕过这个例程。我的代码如下所示:

IF COL_LENGTH('Database_Name.dbo.Table_Name', 'Column_Name1') IS NOT NULL
    BEGIN
        UPDATE Table_Name
            SET Column_Name2 = (SELECT Column_Name3 FROM Table_Name2
                WHERE Column_Name4 = 'Some Value')
            WHERE Column_Name5 IS NULL;

        UPDATE Table_Name
            SET Column_Name6 = Column_Name1
            WHERE Column_Name6 IS NULL;
    END

我的问题是,即使 Column_Name1 的 COL_LENGTH 为空(意味着它不存在),我仍然收到一条错误消息,告诉我来自 IF 语句中的第二个 UPDATE 语句的“无效的列名 'Column_Name1'”。由于某种原因,即使条件为 FALSE 并且我不知道为什么,仍在评估此 IF 条件。

4

2 回答 2

20

SQL Server 解析语句并对其进行验证,忽略任何 if 条件。这就是为什么以下也失败的原因:

IF 1 = 1
BEGIN
  CREATE TABLE #foo(id INT);
END
ELSE
BEGIN
  CREATE TABLE #foo(id INT);
END

无论您点击 Execute 还是 Parse,这都会导致:

消息 2714,级别 16,状态 1
数据库中已经有一个名为“#foo”的对象。

SQL Server 不知道也不关心将输入条件的哪个分支;无论如何,它会验证批处理中的所有语句。您可以执行以下操作(由于延迟名称解析):

IF <something>
BEGIN
  SELECT foo FROM dbo.Table_That_Does_Not_Exist;
END

但你不能这样做:

IF <something>
BEGIN
  SELECT column_that_does_not_exist FROM dbo.Table_That_Does;
END

解决方法通常是使用动态 SQL:

IF <something>
BEGIN
  DECLARE @sql NVARCHAR(MAX);
  SET @sql = N'SELECT column_that_does_not_exist FROM dbo.Table_That_Does;';
  EXEC sp_executesql @sql;
END
于 2013-11-06T21:28:44.663 回答
3

让你的陈述成为一个字符串。如果列存在,则执行它

IF COL_LENGTH('Database_Name.dbo.Table_Name', 'Column_Name1') IS NOT NULL
BEGIN
    DECLARE @sql VARCHAR(MAX)
    SET @sql = 'UPDATE Table_Name
            SET Column_Name2 = (SELECT Column_Name3 FROM Table_Name2
                WHERE Column_Name4 = ''Some Value'')
            WHERE Column_Name5 IS NULL;

        UPDATE Table_Name
            SET Column_Name6 = Column_Name1
            WHERE Column_Name6 IS NULL;'
     EXEC(@sql)
END
于 2013-11-06T21:31:45.590 回答