2013-12-19 64 views
16

我想在動態SQL查詢中設置表名。我成功地嘗試了參數如下:如何在動態SQL查詢中設置表名?

/* Using sp_executesql */ 
/* Build and Execute a Transact-SQL String with a single parameter 
value Using sp_executesql Command */ 

/* Variable Declaration */ 
DECLARE @EmpID AS SMALLINT 
DECLARE @SQLQuery AS NVARCHAR(500) 
DECLARE @ParameterDefinition AS NVARCHAR(100) 
/* set the parameter value */ 
SET @EmpID = 1001 
/* Build Transact-SQL String by including the parameter */ 
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeID = @EmpID' 
/* Specify Parameter Format */ 
SET @ParameterDefinition = '@EmpID SMALLINT' 
/* Execute Transact-SQL String */ 
EXECUTE sp_executesql @SQLQuery, @ParameterDefinition, @EmpID 

現在我要動態地使用參數採取TABLE NAME但我沒能做到這一點。請指導我。

+0

你不能參數化表名。您只需在SET @ SQLQuery步驟手動執行。 – MatBailie

+1

@MatBailie @MatBailie實際上你可以使用它作爲字符串並使用字符串名稱的exec(它的行爲完全像一個過程) – HellBaby

+1

@hellbaby - 仍然不能提供表名作爲*參數* 'sp_executesql',這隻能通過替換字符串來完成。這些非常不同。參數化允許進行類型檢查,防止SQL注入攻擊,執行計劃重用等等。將字符串替換爲其他字符串並不會造成任何影響,因此是* not * parameterisation。 – MatBailie

回答

22

表名不能提供作爲參數,所以你必須手動構造SQL字符串是這樣的:

SET @SQLQuery = 'SELECT * FROM ' + @TableName + ' WHERE EmployeeID = @EmpID' 

但是,請確保您的應用程序不允許用戶直接輸入值@TableName,因爲這會使您的查詢容易受到SQL注入的影響。有關這方面的一個可能的解決方案,請參閱this answer

+0

謝謝,但無論如何,我真的不想要這一個。 無法將表名稱傳遞給sp_executesql :( – Neo

+0

@Neo)因爲在設置SQL字符串時應該已經插入了正確的表名,所以您應該能夠使用'sp_executesql'這是SQL字符串的主要原因首先手動構建 –

+1

另一個考慮是也要在變量周圍應用'QuoteName',這將正確地包裝表格名稱和對象包裝器,默認爲方括號'[...]'' – GoldBishop

3

試試這個:

/* Variable Declaration */ 
DECLARE @EmpID AS SMALLINT 
DECLARE @SQLQuery AS NVARCHAR(500) 
DECLARE @ParameterDefinition AS NVARCHAR(100) 
DECLARE @TableName AS NVARCHAR(100) 
/* set the parameter value */ 
SET @EmpID = 1001 
SET @TableName = 'tblEmployees' 
/* Build Transact-SQL String by including the parameter */ 
SET @SQLQuery = 'SELECT * FROM ' + @TableName + ' WHERE EmployeeID = @EmpID' 
/* Specify Parameter Format */ 
SET @ParameterDefinition = '@EmpID SMALLINT' 
/* Execute Transact-SQL String */ 
EXECUTE sp_executesql @SQLQuery, @ParameterDefinition, @EmpID 
+0

絕對是我正在尋找的完整答案。 –

+0

太棒了!完美解決了我的問題。 – Dan

+4

打開SQL注入。所有你需要做的就是傳遞一個糟糕的@TableName參數,比如'sys.databaeses;更改服務器角色sysadmin添加成員[BadGuy]; - '那裏有你的系統。 –

21

爲了防止SQL注入,我通常儘量使用函數。在這種情況下,你可以這樣做:

... 
SET @TableName = '<[db].><[schema].>tblEmployees' 
SET @TableID = OBJECT_ID(TableName) --won't resolve if malformed/injected. 
... 
SET @SQLQuery = 'SELECT * FROM ' + OBJECT_NAME(@TableID) + ' WHERE EmployeeID = @EmpID'