2015-09-10 48 views
3

我正在與一個以某種方式將小寫項目編號加載到一系列SQL表中的客戶合作。這在這個特定的應用程序中不應該是可能的,並且會導致各種問題。我着手將這些項目逐一更新爲大寫版本,但很快就意識到這將持續下去。所以我做了不可思議的事情,並試圖用光標來幫助我,但是我一直在困擾着一個讓我感到困惑的錯誤。這裏是我的代碼:用於更新幾個表中幾個列的T-SQL光標

declare @tablename varchar(10) 

declare upper_case cursor for 
    SELECT sys.objects.NAME 
    FROM sys.columns 
    INNER JOIN sys.objects ON sys.columns.object_id = sys.objects.object_id 
    WHERE sys.columns.NAME = 'item' 
     AND sys.objects.type = 'U' 

OPEN upper_case 
FETCH NEXT FROM upper_case into @tablename 

UPDATE @tablename 
SET item = upper(item) 

CLOSE upper_case 
DEALLOCATE upper_case 

而這裏的錯誤:

Msg 1087, Level 16, State 1, Line 13
Must declare the table variable "@tablename".

我不使用 @tablename作爲表變量

,我試圖把它作爲一個標量變量,但我想,是什麼哎呀,我會咬。所以我把它切換到一個表變量:

declare @tablename table (tablename varchar(10)) 

然後我得到這個錯誤:

Msg 137, Level 16, State 1, Line 5
Must declare the scalar variable "@tablename".

我缺少什麼?我不允許在UPDATE聲明中使用變量嗎?我知道每個UPDATE只能更新一個表,但我認爲通過使用遊標,我有效地發出多個更新,每個更新只更新一個表。我誤解了嗎?

這是有效的結果。我不能相信我是第一個想做到這一點,我懷疑我會是最後一個:

DECLARE @tablename varchar(10) 
DECLARE @sql nvarchar(max) 

declare upper_case cursor for 
    SELECT sys.objects.NAME 
    FROM sys.columns 
    INNER JOIN sys.objects ON sys.columns.object_id = sys.objects.object_id 
    WHERE sys.columns.NAME = 'item' 
     AND sys.objects.type = 'U' 

OPEN upper_case 
FETCH upper_case into @tablename 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SET @sql = 'UPDATE [' + @tablename + '] SET item = upper(item)' 
    EXEC(@sql) 

    FETCH upper_case into @tablename 
END 

CLOSE upper_case 
DEALLOCATE upper_case 
+1

您缺少Dynamic-SQL,快速解決方法'EXEC('UPDATE'+ @tablename + 'SET item = upper(item))'' – lad2025

回答

2

由於lad2025所指出的,你需要使用動態SQL技術來實現你想要做什麼。其他兩點:

首先,您只更新光標返回的第一個結果。你需要使用一個while循環通過遊標結果進行迭代,像這樣:

.... 
FETCH NEXT FROM upper_case into @tablename 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    <do dynamic update> 

    FETCH NEXT FROM upper_case into @tablename 
END 
<close & deallocate> 

其次,我真的會鼓勵使用的INFORMATION_SCHEMA意見,而不是直接查詢系統表。出於您的目的,它們提供的信息綽綽有餘,並且在SQL版本中更具可讀性和穩定性以便引導。

INFORMATION_SCHEMA中的系統元數據是SQL-92標準。它在MS-SQL版本和其他ANSI-SQL兼容引擎中穩定。另見:INFORMATION_SCHEMA vs sysobjects。編寫快速腳本的主要缺點是必須鍵入「information_schema」而不是「sys」。最終肌肉記憶踢在:)

+0

,謝謝Marc。我對遊標很陌生,因爲我被告知要避開它們,所以這也是一種學習體驗。爲什麼你推薦使用'INFORMATION_SCHEMA'而不是sys.objects?我已經對遊標提出了很多警告,但這是我第一次聽說過系統表。 – 3xStampA2xStamp

+0

編輯以充實迴應。你說得對,遊標一般都是要避免的,但對於動態SQL來說,它們是不可或缺的。 –

3

UPDATE你不能將表名作爲像您變量嘗試:

UPDATE @tablename 
SET item = upper(item); 

Msg 1087, Level 16, State 1, Line 13 Must declare the table variable "@tablename"

UPDATE可以使用表變量DECLARE @t TABLE = ...(不是你的情況)。

要使用它,你怎麼想,你需要動態SQL這樣的:

EXEC('UPDATE [' + @tablename + '] SET item = UPPER(item)'); 
+1

完美。非常感謝。我沒有意識到更新不允許變量名稱。我的光標也有問題,但我也修正了這個問題。我發佈了修改後的代碼 – 3xStampA2xStamp