您需要分批执行更新。否则,SQL Server 会在尝试运行创建它的ALTER 之前尝试解析并验证该列是否存在。您在解析时得到无效的列名,而不是在运行时。
一种解决方法是在两个批次之间使用GO:
ALTER TABLE dbo.myTable ADD myNewColumn VARCHAR(50) NULL;
GO
UPDATE dbo.myTable SET myNewColumn = 'test';
(Always use schema prefixes to reference objects 和 always terminate statements with semi-colons.)
但这仅适用于 Management Studio 和其他某些客户端应用程序,因为它实际上不是 T-SQL 语言的一部分;这些客户端工具将其视为批次分隔符,并告诉他们分别提交和评估这两个批次。它不适用于以其他方式提交给 SQL Server 的代码块和作为单个批次,例如在存储过程的主体中:
CREATE PROCEDURE dbo.foo
AS
BEGIN
SET NOCOUNT ON;
SELECT 1;
GO
SELECT 2;
END
GO
这会产生以下错误,因为它实际上将存储过程拆分为两个单独的批次:
消息 102,级别 15,状态 1,过程 foo,第 8 行
';' 附近的语法不正确。
消息 102,第 15 级,状态 1,第 11 行
“END”附近的语法不正确。
作为一种不同的解决方法,您可以通过在动态 SQL 中执行更新来强制更新到自己的批处理中。
DECLARE @sql NVARCHAR(MAX), @value VARCHAR(50) = 'test';
ALTER TABLE dbo.myTable ADD myNewColumn VARCHAR(50) NULL;
SET @sql = N'UPDATE dbo.myTable SET myNewColumn = @value;';
EXEC sp_executesql @sql, N'@value VARCHAR(50)', @value;
(Why you should use EXEC sp_executesql vs. EXEC(@sql).)
另一种解决方法;一步完成添加和更新:
ALTER TABLE dbo.myTable ADD myNewColumn VARCHAR(50) DEFAULT 'test' WITH VALUES;
(如果您实际上不希望任何未来的行在可能导致该行为的情况下继承该值,则可以稍后删除默认约束。)