创建列后,sql server update上的列名无效

时间:2012-09-21 17:35:04

标签: sql sql-server tsql ddl

有没有人看到这个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”无效。

更新命令。

感谢。

4 个答案:

答案 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。它需要两个参数,

  1. 表名和

  2. 您要搜索的专栏

  3. 如果找到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;
    

    使其更简单。