2013-08-21 31 views
3

我需要一些與我的SQL邏輯有關的幫助,而且我一直在爲此工作(並研究)這個爲期兩天的工作,並取得了零成功。SQL變量作爲Where子句中的列名稱

我的目標是嘗試將一個變量從一個ASP頁傳遞給一個存儲過程,該存儲過程利用該變量作爲where子句中列名稱的條件。

因此,例如,(我的查詢的簡化版本):

@strDept nvarchar(10), @strUser nvarchar(30) 
-- The asp page will pass f18 to @strDept & Ted Lee to strUser 
-- f18 is the column name in my database that I need in the where. 

select x, y, z from table1 where @strDept in (@strUser) 
-- and this is the select statement, notice the where clause. 

的存儲過程中沒有執行,但是它會返回值,我知道它的治療@strDept作爲文字nvarchar的,而不是列名稱。

所以我想我的問題是,我如何讓SQL Server 2005將我的@sqlDept變量當作列名稱對待?

+0

所以'@ strUser'是逗號分隔的整數列表? –

+0

不,@struser正在引用一個帶有字符串的文本框,並將其傳遞給存儲的生成的文本框。 – SyD

回答

5

如果這是一個內部公司的應用程序,爲什麼每個人都在重複迭代並擊敗SQL注入死亡...使用動態SQL非常簡單。 如果你很自在,這些只是內部用戶使用它,那麼它很簡單。這是概念。您基本上編寫了一條SQL語句,它寫入了一個真正爲SQL語句的字符串,然後執行它。

CREATE Procedure myDynamicProcedure 
@strDept nvarchar(10), 
@strUser nvarchar(30) 

as 

BEGIN 

1.聲明一個變量來存儲SQL語句。

DECLARE @SQL varchar(max) 

2.設置@SQL變量是SELECT語句。基本上你正在構建它,所以它返回你想寫的東西。就像這樣:

SET @SQL = 'select x, y, z from table1 where' + @strDept + 
' in ' + @strUser 

3.執行@SQL聲明,這將是完全像你跑: SELECT X,Y,從表1 z,其中F18 ='泰德李

EXEC (@SQL) 
END 
+1

用戶只需點擊一個鏈接,頁面就會顯示他們需要的內容。注入部分由我的代碼完成,爲什麼我要考慮他的動態過程順便說一句 - 謝謝,這看起來完全像wh在我試圖寫。 – SyD

+0

@SyD - 沒問題,先生...一些答案有些混亂。當然,你需要一個面向公衆的網站,我會同意所有注射安全功能100%。祝你好運! – logixologist

1

你可以使用一些動態的sql例如

DECLARE @sqlDept VARCHAR(100)='CURRENT_TIMESTAMP'; 

EXEC('SELECT '[email protected]) 

在你的情況,這將是

DECLARE @strDept nvarchar(10)='dept1' 
,@strUser nvarchar(30)='user1'; 

DECLARE @DynamicSql nvarchar(1000); 

SET @DynamicSql='select x, y, z from table where '[email protected]+' in ('''[email protected]+''')'; 

然後

SELECT @DynamicSql; 

會給你:

選擇X,Y,Z從表所在DEPT1在( 'user1')

要執行這個語句,你這樣做,因爲

EXEC(@DynamicSql); 
+0

我不確定我是否理解上面的代碼在做什麼 - 您能解釋一下嗎? – SyD

+0

我同意關於注射的其他評論,但我已經更新了答案,以便更清楚一點。 – HotblackDesiato

3

爲什麼你想使列名的動態?你打算實現什麼?您可以使用類似上面的答案的動態查詢,但可能會開始注入攻擊

如果你解釋你想要做什麼,也許我們可以推薦另一種解決方案。

+0

基本上,我的公司需要一個報告儀表板。儀表板將具有經理視圖和個人視圖。基本上管道,但問題是數據庫有不同的部門領域,這些領域有個別僱員的名字。最簡單的解決方案是將一個數字傳遞給過程,並複製並粘貼一堆帶有正確字段的IF語句,但這很耗時且很麻煩。我想根據部門的asp頁面動態輸入列引用。 – SyD

7

你無法找到如何做到這一點的指導的原因是它是一個真的壞主意

遲早有人會通過1 ;drop database badidea的「列名」。這將是所有有關方面的祝福。

閱讀SQL注入,並重新考慮您的設計。

+0

是的,關於動態SQL的每條途徑都讓我失望了一個單向SQL注入式街道。但是事情就是這樣,用戶不能明確地將任何事情傳遞給存儲過程 - 即使頁面單獨傳遞變量,它是否仍然對注入攻擊開放? – SyD

+0

如果參數嚴格控制,則不。 但是這裏發生了什麼。你部署它。然後遲早有人說:「我們可以選擇我們喜歡的任何領域嗎?」,而你不在,有人說:「哦,這看起來像是一個簡單的改變,我只是調整了這一點.. – podiluska

+0

@SyD此外,你說'不,@struser引用了一個帶有字符串的文本框' – podiluska

0

我認爲最好的方法是構建一個動態SQL並添加一個查找來查看該列是否存在,並防止列名中的SQL注入。

declare @strDept nvarchar(10), @strUser nvarchar(30), 
     @sql nvarchar(300), @found smallint 
set @strDept = 'f18' 
set @strUser = 'Ted Lee' 

set @found = (SELECT count(*) 
       FROM syscolumns 
       WHERE id=OBJECT_ID('table1') AND name=''[email protected]+'') 

set @sql = 'select x, y, z from table1 where ' + @strDept + ' in ('''[email protected]+''')' 

if @found = 1 exec (@sql) 

SQL注入測試:請參閱SQL FIDDLE:http://www.sqlfiddle.com/#!6/df3f6/18/0

+0

除非他們足夠瘋狂才能使用名爲[1; DROP TABLE USERS] – StingyJack

0

另一種替代方法是使用替代的小位在proc。這仍然使用動態SQL,但您永遠不會執行用戶提供的值。

DECLARE @userSuppliedValue VARCHAR(50) = 'JOHNNY DROP TABLES' 


DECLARE @substValue VARCHAR(50) 

IF @userSuppliedValue = 'Table1' 
    SET @substValue = 'Table1' 

IF @userSuppliedValue = 'Table2' 
    SET @substValue = 'Table2' 

/*Repeat for N permutations*/ 

/* Throw an error if you think its necessary to do so when no match is found*/ 
IF @substValue IS NULL 
    RAISERROR(1,1,'errah') 

EXEC ('SELECT * FROM ' + @substValue) 
+0

非常有趣的方法,謝謝:) – SyD

0
DECLARE @value varchar(10) 
SET @value = 'intStep' 
DECLARE @sqlText nvarchar(1000); 

SET @sqlText = N'SELECT ' + @value + ' FROM dbo.tblBatchDetail' 
Exec (@sqlText)