繁体   English   中英

SQL Server无效的列名

[英]SQL Server invalid column name

如果我尝试执行以下代码,我会收到错误

消息207,级别16,状态1,行3无效的列名称“另一个”。 消息207,级别16,状态1,行4无效的列名称“另一个”。

即使两个IF语句的谓词总是评估为false。

CREATE TABLE #Foo (Bar INT)
GO
IF (1=0)
BEGIN
    SELECT Another FROM #Foo
END
GO
IF (1=0)
BEGIN
    ALTER TABLE #Foo ADD Another INT
    SELECT Another FROM #Foo 
END
GO
DROP TABLE #Foo

为了这个例子,这可能过于简化了; 实际上我需要做的是从列中选择值,但仅在列存在时才选择。 如果它不存在,我不关心它。 在驱使我提出这个问题的问题中,我的谓词是EXISTS (SELECT * FROM sys.columns WHERE object_id = @ID AND name = @Name) 有没有办法实现这一点,而不诉诸我的敌人动态SQL? 我知道我的SQL必须始终是格式良好的(即符合语法) - 即使是在一个从未执行过的块中 - 但我也大惊小怪,我也被迫在语义上也正确!

编辑:虽然我不确定下面的代码增加了上面的代码,但它是问题的另一个例子。 在这种情况下,我只想设置绝对值(绝对存在作为列)的值,其值为Maybe(可能存在为列)如果Maybe存在。

IF EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('dbo.TableName', 'U') AND name = 'Maybe')
BEGIN
    UPDATE dbo.TableName SET Definitely = Maybe
END

SQL Server不会逐行执行。 它不是像程序 .NET或Java代码。 所以没有“非执行块”

批处理一次编译。 此时,该列不存在,但它知道该表将是。 表没有名为“Another”的列。 失败。

完全符合预期。

现在,你想要解决的真正问题是什么?

一些选择:

  • 2个表或一个包含两列的表
  • 使用存储过程来解除范围
  • 不使用临时表(可能不需要;它可能是你的程序性思考......)
  • 动态SQL(来自Mitch删除的答案)

评论后编辑;

为什么不隐藏视图后面的架构更改,而不是更改所有代码以使用可能/可能不存在的列?

您可以使用EXEC来处理它。 如果代码永远不会真正改变,那它就不是真正的动态SQL。

例如:

CREATE TABLE dbo.Test (definitely INT NOT NULL)
INSERT INTO dbo.Test (definitely) VALUES (1), (2), (3)

IF EXISTS (SELECT *
           FROM sys.columns
           WHERE object_id = OBJECT_ID('dbo.Test', 'U') AND
                 name = 'Maybe')
BEGIN
    EXEC('UPDATE dbo.Test SET definitely = maybe')
END

SELECT * FROM dbo.Test

ALTER TABLE dbo.Test ADD maybe INT NOT NULL DEFAULT 999

IF EXISTS (SELECT *
           FROM sys.columns
           WHERE object_id = OBJECT_ID('dbo.Test', 'U') AND
                 name = 'Maybe')
BEGIN
    EXEC('UPDATE dbo.Test SET definitely = maybe')
END

SELECT * FROM dbo.Test

DROP TABLE dbo.Test

您还可以使用不存在的表来尝试使用Martin Smith的 “替代方法”来获取列的“延迟名称解析”。

我遇到过同样的问题。 我们多年来为所有更改创建了一个脚本,这是我们第一次遇到此问题。 我已经尝试了你所有的答案,但没有找到问题。

在我的情况下,这是因为脚本中的临时表我也在存储过程中使用,尽管每个句子都已经去了。 我发现,如果我在脚本使用临时表后添加if存在并删除临时表,则表明它正常工作。

最诚挚的问候,陈

源自@gbn的答案。 我解决这个问题的方法是在ALTER查询和使用ALTER添加的列的查询之间使用“GO”。 这将使2个查询作为单独的批处理运行,从而确保在SELECT查询之前存在“Another”列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM