如果SQL Server中存在列,如何更新表?

问题描述 投票:5回答:2

我有一个表MyTable创建者

CREATE TABLE MyTable
(
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [Type] [int] NOT NULL,
    [CreatedDate] [datetime] NOT NULL,
    [ModifiedDate] [datetime] NOT NULL,
)

我想检查表中是否存在一列,如果存在,我想将数据复制到另一个列,然后删除旧列,如下所示:

IF (SELECT COLUMNPROPERTY(OBJECT_ID('MyTable'), 'Timestamp', 'Precision')) IS NOT NULL
BEGIN
    UPDATE [dbo].[MyTable]
    SET [CreatedDate] = [Timestamp]

    ALTER TABLE [dbo].[MyTable]
    DROP COLUMN [Timestamp]
END
GO

但是,当我尝试运行此程序时,出现错误:

Invalid column name 'Timestamp'

我该如何完成我想做的事情?

sql-server tsql
2个回答
8
投票

这是一个编译问题。

如果编译批处理时该表不存在,则所有工作都很好,因为引用该表的语句可以延迟编译。但是,对于预先存在的表,您将遇到此问题,因为它会尝试编译所有语句并在不存在的列中出错。

您可以将代码推送到子批处理中,以便仅在该分支被命中时才进行编译。

IF (SELECT COLUMNPROPERTY(OBJECT_ID('MyTable'), 'Timestamp', 'Precision')) IS NOT NULL
BEGIN
EXEC('
    UPDATE [dbo].[MyTable]
    SET [CreatedDate] = [Timestamp]

    ALTER TABLE [dbo].[MyTable]
    DROP COLUMN [Timestamp]
    ')
END
GO

如果您只是想重命名列

EXEC sys.sp_rename 'dbo.MyTable.[TimeStamp]' , 'CreatedDate', 'COLUMN'

但是(从CreatedDate列不存在的位置会更容易。


0
投票

您必须首先使用ALTER TABLE语句创建[Timestamp]列。

然后其余的应该运行。

基于评论的编辑(我知道此信息在SO的其他地方重复,但我找不到它):

好吧,不幸的是,SQL Server中的IF条件不允许您忽略未解析的代码。发生的情况是,SQL Server正在查看您的命令,并分析每个语句以确保其有效。

[这样做时,SQL Server不够聪明,无法确定如果没有UPDATE,将无法到达无效的语句(需要[TimeStamp][TimeStamp])。

换句话说,您不能编写一个期望不存在该列的SQL命令,即使您将该命令嵌套在不会达到的IF条件中也是如此。 SQL Server将分析整个语句,并且不允许它在测试IF条件之前运行。

一个常用的解决方法是动态SQL,SQL Server无法预先准备动态SQL,因此不会尝试。

© www.soinside.com 2019 - 2024. All rights reserved.