2009-08-03 58 views
2

我正在研究需要刪除列的數據庫升級腳本(該部分很簡單)。在我可以刪除該列之前,我想要將該值移到另一個已存在的列中。如何在條件爲真的情況下只執行更新命令?

我想acheive idempotence與我的劇本,這是我似乎是失敗的。我有這樣的代碼......

IF EXISTS (SELECT * 
     FROM sys.all_columns 
     WHERE sys.all_columns.object_id = OBJECT_ID(N'[dbo].[MyTable]') 
     AND sys.all_columns.name = 'Column1') 
BEGIN 
    UPDATE [dbo].[MyTable] 
    SET [Column2] = [Column1] 

    ALTER TABLE [dbo].[MyTable] 
    DROP COLUMN [Column1] 
END 

不管我做什麼,總是執行UPDATE查詢,即使條件是假的,這會導致錯誤。如果我的初始條件爲false,我需要做什麼來防止運行此查詢?如果條件爲真,它下面的ALTER TABLE語句纔會運行。

回答

11

我猜,當你說「更新查詢總是執行,這會導致錯誤的」,你的意思是,你得到的錯誤:因爲執行查詢時

Msg 207, Level 16, State 1 Line 6
Invalid column name 'Column1'.

這不是 - 這是一個解析錯誤。整個IF語句在執行之前被SQL Server解析,並且在UPDATE語句上失敗,因爲Column1不再存在。它也在ALTER TABLE語句上失敗,但SQL Server僅向您顯示第一個錯誤。順便說一句,這就是Shannon的例子的原因 - 因爲她的IF塊都被一次解析,第二個類似於你的解析就很好,因爲在解析腳本的時候,列仍然存在。我懷疑,如果香農再次運行腳本(減去創建表部件),則會出現相同的錯誤。

爲了解決這個問題,你只需要使用動態SQL - 直到實際運行該行纔會被解析。您使用EXEC命令運行動態SQL,並將其傳遞給您要執行的字符串,如下所示:

IF EXISTS (SELECT * 
     FROM sys.all_columns 
     WHERE sys.all_columns.object_id = OBJECT_ID(N'[dbo].[MyTable]') 
     AND sys.all_columns.name = 'Column1') 
BEGIN 
    EXEC('UPDATE [dbo].[MyTable] SET [Column2] = [Column1]') 

    EXEC('ALTER TABLE [dbo].[MyTable] DROP COLUMN [Column1]') 
END 
+0

+1我應該在條件更新的第一次和第二次運行之間放置一個批分隔符。 – 2009-08-03 22:13:00

相關問題