26

有人看到 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; 

当我运行它时,我得到:

消息 207,级别 16,状态 1,第 3 行
无效的列名称“OPT_LOCK”。

在更新命令上。

谢谢。

4

3 回答 3

44

在这种情况下,您可以按照我在此处的回答NOT NULL添加列并在一个语句中设置现有行的值来避免该问题。

更一般地说,问题是解析/编译问题。SQL Server 在执行任何语句之前尝试编译批处理中的所有语句。

当一个语句引用一个根本不存在的表时,该语句将被延迟编译。当表已经存在时,如果您引用不存在的列,则会引发错误。解决此问题的最佳方法是在与 DML 不同的批次中执行 DDL。

如果语句同时引用现有表和不存在表中的不存在列,则在延迟编译之前可能会或可能不会抛出错误。

您可以分批提交它(例如,通过使用客户端工具中的批处理分隔符)或在使用orGO单独编译的子范围中执行它。EXECEXEC sp_executesql

第一种方法需要您将代码重构为IF ...不能跨批次。

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)

      EXEC('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; 
于 2012-09-21T17:40:22.123 回答
2

错误的根本原因是在重新启动 SQL Server Management Studio 之前,新添加的列名不会反映在 sys.syscolumns 和 sys.columns 表中。

于 2020-02-20T20:42:22.880 回答
0

为了您的信息,您可以将 替换IF NOT EXISTSCOL_LENGTH函数。它需要两个参数,

  1. 表名和

  2. 您正在搜索的列

如果找到 Column,则返回列 Ex: Int(4 字节)的数据类型范围,如果未找到,则返回 a 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;

使它更简单。

于 2012-09-21T19:12:42.600 回答