2012-09-21 64 views
19

有沒有人看到SQL Server的這段代碼有什麼問題?列創建後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「。

上的更新命令。

謝謝。

回答

33

在這種情況下,您可以通過將列添加爲NOT NULL並在一個語句as per my answer here中設置現有行的值來避免此問題。

更一般的問題是分析/編譯問題。在執行任何語句之前,SQL Server會嘗試編譯批處理中的所有語句。

當語句引用一個不存在的表時,所有語句都會被延遲編譯。當表已經存在時,如果引用不存在的列,則會引發錯誤。圍繞這個最好的方法是在與DML不同的批處理中執行DDL。

如果一個語句既引用現有表中的不存在的列,也引用不存在的表,則在編譯被延遲之前可能會或可能不會引發該錯誤。

您可以提交分批(例如,通過在客戶端工具使用批處理隔板GO)或由使用或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; 
+1

EXEC接近爲我工作。謝謝! – feradz

+0

這是我多年來一直使用的方法,每當我們想要添加一個新列並用數據填充時,我們都會被迫採取這種尷尬的動態sql路由,這讓我感到驚訝。 –

0

爲了您的信息,您可以替換IF NOT EXISTSCOL_LENGTH功能。它有兩個參數,

  1. 表名和

  2. 列您正在尋找

如果發現列則返回列防爆的數據類型的範圍: 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; 

使其變得更簡單。