2013-09-25 78 views
0

請參閱下面的DDL:列標題包含在TSQL變量

CREATE TABLE TestTable (id int identity, name varchar(30)) 
INSERT INTO TestTable (Name) VALUES ('Ian') 

declare @Test As varchar(100) 
set @Test = 'Name' 
SELECT @Test FROM TestTable 

從選擇輸出爲「名」。我想要的輸出是:'伊恩'。怎麼樣?

+1

SQL Server是怎麼意思自動地知道你想要的不僅僅是'Test'中的每一行出現'Name'一次 - 在* name *和* string *之間有邏輯差別,你有什麼是一個字符串。 'SELECT'名稱'從TestTable'不同於'SELECT Name FROM TestTable'。 –

回答

0

您可以使用EXEC執行製作SQL字符串:

declare @Test As varchar(100) 
set @Test = 'Name' 
EXEC ('SELECT ' + @Test + ' FROM TestTable') 

對這些問題的答案的標準警告是一定的,你可以控制一下就把在SQL語句中獲取或使用限制的權利(如只讀只)執行它們,否則你可能會得到這樣的:

declare @Test As varchar(100) 
set @Test = '1 ; DROP TABLE TestTable; --' 
EXEC ('SELECT ' + @Test + ' FROM TestTable') 
+0

您可以通過首先構建命令並應用QUOTENAME()來避免注入漏洞,在這種情況下,您將獲得無效的列名稱錯誤而不是嘗試丟棄。你不能這樣做內聯。 –

0

動態生成的字符串,並使用exec

EXEC ('SELECT ' + @Test + ' FROM TestTable') 
+0

警告:SQL注入 –

3

您不能使用變量告訴SQL Server要使用的列,表,數據庫等。你需要在動態SQL中包含這種類型的代碼。

DECLARE @sql NVARCHAR(MAX); 
SET @sql = N'SELECT ' + QUOTENAME(@Test) + ' FROM dbo.TestTable;'; 
EXEC sp_executesql @sql; 

這也是爲什麼I prefer sp_executesql instead of EXEC()作爲一個標準的最佳實踐,並在這裏就是爲什麼you should always use the schema prefix (e.g. dbo.) when referencing objectsQUOTENAME()可以幫助保護您免受SQL injection在這種情況下,因爲我不知道@Test的價值最終來自何處。

+0

我非常喜歡這個答案。 :) – Sadique