有没有人看到这个SQL Server代码出了什么问题?
IF NOT EXISTS(SELECT *
FROM sys.columns
WHERE Name = 'OPT_LOCK'
AND object_ID = Object_id('REP_DSGN_SEC_GRP_LNK'))
BEGIN
ALTER TABLE REP_DSGN_SEC_GRP_LNK
ADD OPT_LOCK NUMERIC(10, 0)
UPDATE REP_DSGN_SEC_GRP_LNK
SET OPT_LOCK = 0
ALTER TABLE REP_DSGN_SEC_GRP_LNK
ALTER COLUMN OPT_LOCK NUMERIC(10, 0) NOT NULL
END;
当我跑步时,我得到:
Msg 207,Level 16,State 1,Line 3
列名称“OPT_LOCK”无效。
更新命令。
感谢。
答案 0 :(得分:37)
在这种情况下,您可以通过将列添加为NOT NULL
并在一个语句as per my answer here中设置现有行的值来避免此问题。
更一般地说,问题是解析/编译问题。 SQL Server尝试在执行任何语句之前编译批处理中的所有语句。
当一个语句引用一个根本不存在的表时,该语句将被延迟编译。当表已存在时,如果引用非现有列,则会引发错误。解决此问题的最佳方法是在DML的不同批次中执行DDL。
如果一个语句都引用了现有表中的非现有列和不存在的表,则在推迟编译之前可能会抛出错误,也可能不会抛出错误。
您可以在不同的批次中提交它(例如,通过在客户端工具中使用批处理分隔符GO
),也可以在使用EXEC
或{{1}单独编译的子范围中执行它}}。
第一种方法要求您重构代码,因为EXEC sp_executesql
无法跨越批次。
IF ...
答案 1 :(得分:3)
该错误的根本原因是,除非重新启动SQL Server Management Studio,否则sys.syscolumns和sys.columns表中不会反映新添加的列名。
答案 2 :(得分:2)
使用Go命令和默认0来解决此问题。
--Add all columns, if they don't exist
ALTER TABLE REP_DSGN_SEC_GRP_LNK
ADD OPT_LOCK NUMERIC(10, 0) NOT NULL DEFAULT 0
ALTER TABLE REP_DSGN_SEC_GRP_LNK
ALTER COLUMN OPT_LOCK NUMERIC(10, 0) NOT NULL
GO
--Consume new columns
UPDATE REP_DSGN_SEC_GRP_LNK SET OPT_LOCK = 1 WHERE SOMETHING = 'ELSE'
GO
答案 3 :(得分:0)
有关您的信息,可以使用IF NOT EXISTS
功能替换COL_LENGTH
。它需要两个参数,
表名和
您要搜索的专栏
如果找到Column,则返回Ex:Int(4字节)列的数据类型范围,如果未找到,则返回NULL
。
因此,你可以按如下方式使用它,并将3个语句合并为一个。
IF (SELECT COL_LENGTH('REP_DSGN_SEC_GRP_LNK','OPT_LOCK')) IS NULL
BEGIN
ALTER TABLE REP_DSGN_SEC_GRP_LNK
ADD OPT_LOCK NUMERIC(10, 0) NOT NULL DEFAULT 0
END;
使其更简单。