10

We all know that prepared statements are one of the best way of fending of SQL injection attacks. What is the best way of creating a prepared statement with an "IN" clause. Is there an easy way to do this with an unspecified number of values? Take the following query for example.

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

Currently I'm using a loop over my possible values to build up a string such as.

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

Is it possible to use just pass an array as the value of the query paramter and use a query as follows?

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

In case it's important I'm working with SQL Server 2000, in VB.Net

4

6 回答 6

6

给你 - 首先创建以下函数......

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, @pos-@prevpos-1))))

        else

        INSERT INTO @tbldata(col) VALUES(LTRIM(RTRIM(SUBSTRING(@data, @prevpos+1, len(@data)-@prevpos))))

        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 将允许表函数。

更新

您将使用以下语法获得一些额外的性能...

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

因为前面的语法导致 SQL Server 使用“IN”子句运行额外的“排序”命令。另外-在我看来它看起来更好:D!

于 2008-09-18T14:49:03.470 回答
1

If you would like to pass an array, you will need a function in sql that can turn that array into a sub-select.

These functions are very common, and most home grown systems take advantage of them.

Most commercial, or rather professional ORM's do ins by doing a bunch of variables, so if you have that working, I think that is the standard method.

于 2008-09-18T14:43:08.213 回答
0

您可以使用单列 VALUE 创建一个临时表 TempTable 并插入所有 ID。然后你可以用一个子选择来做:

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (SELECT VALUE FROM TempTable)
于 2008-09-18T21:47:04.980 回答
0

使用 digiguru 发布的解决方案。这是一个很好的可重用解决方案,我们也使用相同的技术。新团队成员喜欢它,因为它可以节省时间并保持我们的存储过程一致。该解决方案也适用于 SQL 报告,因为传递给存储过程以创建记录集的参数在 varchar(8000) 中传递。你只要把它挂起来就可以了。

于 2008-09-28T02:18:31.520 回答
-1

在 SQL Server 2008 中,他们终于通过添加新的“表”数据类型来解决这个经典问题。显然,这可以让您传入一个值数组,可以在子选择中使用它来完成与 IN 语句相同的操作。

如果您使用的是 SQL Server 2008,那么您可能会对此进行研究。

于 2008-09-18T14:46:51.790 回答
-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)
于 2008-09-18T14:49:51.723 回答