2008-09-18 58 views
10

我們都知道準備好的語句是防止SQL注入攻擊的最佳方法之一。使用「IN」子句創建準備好的語句的最佳方法是什麼?有沒有簡單的方法來做到這一點與未指定數量的值?以下面的查詢爲例。使用SQL參數處理IN子句中的數據?

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (1,2,3) 

目前我正在使用一個循環來覆蓋我可能的值來構建一個字符串,例如。

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (@IDVAL_1,@IDVAL_2,@IDVAL_3) 

是否可以使用傳遞數組作爲查詢參數的值並使用查詢如下?

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (@IDArray) 

在情況下,它是我在與SQL Server 2000的工作,在VB.Net

+0

添加一個SQLServer標記 – MotoWilliams 2008-09-18 14:41:23

+0

一個t-sql標記也可能是合適的。 – 2008-09-18 14:51:09

回答

1

如果你想傳遞一個數組重要的,你需要在SQL的功能,可以把該數組一個子選擇。

這些功能非常普遍,大多數自制系統都利用它們。

大多數商業或專業的ORM都是通過做一堆變量來實現的,所以如果你有這樣的工作,我認爲這是標準方法。

-1

在SQL Server 2008中,他們終於通過添加新的「表」數據類型來解決這個經典問題。顯然,這可以讓你傳入一個值的數組,可以在子選擇中使用,以完成與IN語句相同的操作。

如果您使用的是SQL Server 2008,那麼您可以查看一下。

+0

「萬一重要,我正在使用SQL Server 2000」 – digiguru 2008-09-18 14:50:01

5

在這裏你去 - 第一次創建下面的函數...

Create Function [dbo].[SeparateValues] 
(
    @data VARCHAR(MAX), 
    @delimiter VARCHAR(10) 
) 
    RETURNS @tbldata TABLE(col VARCHAR(10)) 
As 
Begin 
    DECLARE @pos INT 
    DECLARE @prevpos INT 

    SET @pos = 1 
    SET @prevpos = 0 

    WHILE @pos > 0 
     BEGIN 

     SET @pos = CHARINDEX(@delimiter, @data, @prevpos+1) 

     if @pos > 0 
     INSERT INTO @tbldata(col) VALUES(LTRIM(RTRIM(SUBSTRING(@data, @prevpos+1, @[email protected])))) 

     else 

     INSERT INTO @tbldata(col) VALUES(LTRIM(RTRIM(SUBSTRING(@data, @prevpos+1, len(@data)[email protected])))) 

     SET @prevpos = @pos 
    End 

    RETURN 

END 

然後用下面...

Declare @CommaSeparated varchar(50) 
Set @CommaSeparated = '112,112,122' 
SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (select col FROM [SeparateValues](@CommaSeparated, ',')) 

我想的SQL Server 2008將允許表函數。

UPDATE

你會使用以下語法榨出一些額外的性能...

SELECT ID,Column1,Column2 FROM MyTable 
Cross Apply [SeparateValues](@CommaSeparated, ',') s 
Where MyTable.id = s.col 

因爲以前的語法導致SQL Server運行使用一個額外的「排序」命令「 IN「條款。另外 - 在我看來它看起來更好:D!

+0

這確實解決了這個問題,因爲它提供了一個很好的功能,可以根據您希望的任何分隔值列表創建表格 - 爲什麼投票下降? – digiguru 2008-09-18 17:45:45

-2

這裏有一個技巧我用

ALTER Procedure GetProductsBySearchString 
@SearchString varchar(1000), 
as 
set nocount on 
declare @sqlstring varchar(6000) 
select @sqlstring = 'set nocount on 
select a.productid, count(a.productid) as SumOf, sum(a.relevence) as CountOf 
from productkeywords a 
where rtrim(ltrim(a.term)) in (''' + Replace(@SearchString,' ', ''',''') + ''') 
group by a.productid order by SumOf desc, CountOf desc' 

exec(@sqlstring) 
0

您可以創建一個單獨列的值一個臨時表不是Temptable並插入所有ID。然後你可以使用子查詢:

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (SELECT VALUE FROM TempTable) 
0

請使用digiguru發佈的解決方案。這是一個偉大的可重用解決方案,我們也使用相同的技術。新的團隊成員喜歡它,因爲它節省了時間並保持了存儲過程的一致性。該解決方案也適用於SQL Reports,因爲傳遞給存儲過程以創建記錄集的參數在varchar(8000)中傳遞。你只要把它掛起來就行了。