testing列存在,添加列和更新列
我正在尝试编写一个SQL Server数据库更新脚本。 我想testing表中是否存在列,如果不存在,则添加具有默认值的列,最后根据同一表中不同列的当前值更新该列。 我希望这个脚本可以多次运行,第一次更新表,并在随后的运行脚本应该被忽略。 我的脚本目前看起来如下所示:
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable') BEGIN ALTER TABLE [dbo].[PurchaseOrder] ADD [IsDownloadable] bit NOT NULL DEFAULT 0 UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref] IS NOT NULL END
SQL Server返回错误“无效的列名”IsDownloadable'“,即我需要提交DDL才能更新列。 我尝试了各种排列,但是我无法快速完成。
除非列已经存在,否则这个脚本将不能成功运行,这正是您不需要它的时候。
SQL脚本必须先parsing才能被执行。 如果在parsing脚本时该列不存在,则parsing将失败。 您的脚本稍后创build列并不重要; parsing器无法知道这一点。
如果要访问刚刚添加的列,则需要inputGO
语句(批分隔符)。 但是,一旦这样做,就不能再维护上一批中的任何控制stream或variables – 就像运行两个单独的脚本一样。 这使得有条件地同时执行DDL和DML是非常棘手的。
最简单的解决方法,我可能会推荐给你,因为你的DML不是很复杂,是使用dynamicSQL,parsing器直到“运行时”才会尝试parsing:
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable') BEGIN ALTER TABLE [dbo].[PurchaseOrder] ADD [IsDownloadable] bit NOT NULL DEFAULT 0 EXEC sp_executesql N'UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref] IS NOT NULL' END
尝试在ALTER TABLE之后添加一个“GO”语句。
这对我来说是新闻,但是它在这里说批处理中的所有语句(GO之前的语句)被编译成一个查询计划。)在SQL中没有GO,整个计划实际上是一个查询。
编辑:由于GO给出了一个语法错误(这对我来说似乎很奇怪),我创build了类似的东西,发现这个工作
declare @doUpdate bit; SELECT @doUpdate = 0; IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PurchaseOrder' AND COLUMN_NAME = 'IsDownloadable') BEGIN SELECT @doUpdate=1 END IF @doUpdate<>0 ALTER TABLE [dbo].[PurchaseOrder] ADD [IsDownloadable] bit NOT NULL DEFAULT 0 IF @doUpdate<>0 UPDATE [dbo].[PurchaseOrder] SET [IsDownloadable] = 1 WHERE [Ref]=0 COMMIT TRAN