2013-05-17 22 views
1

我正在ASP.NET 2.0中构建一个网站,我正在处理的页面的一些描述:ListView显示一个来自我的访问数据库的表(帖子)和一个带有多个选择用于过滤行的模式(通过论坛名称,值= forumId)。 我将列表框选定值转换为列表,然后运行以下查询。使用IN运算符与存储过程参数

参数:

OleDbParameter("@Q",list.ToString()); 

步骤:

SELECT * FROM sp_feedbacks WHERE forumId IN ([@Q]) 

问题是,好了,这是行不通的。即使当我从字符串1,4,“1”,“4”或“1,4”的MSACCESS 2007中运行时,我也会得到零结果。只有一个论坛被选中时,查询才有效。 (例如(1))。

  • 解决方案? 所以我想我可以在很多OR中使用WHERE,但我真的很想避免这个选项。 另一种解决方案是将DataTable转换为列表,然后使用LINQ进行过滤,这看起来非常麻烦。

在此先感谢, BBLN。

+0

岂不“1”和“4”是**两个**单独的参数? – Brian

+0

@Brian我不知道,有没有办法将一个数组作为参数传递? – BBLN

+1

不,'forumId IN(@Q)'被视为'forumID IN('1,2,3,4,5')'。您应该为每个需要的值创建单独的参数。 – Steve

回答

1

当你有:

col in ('1,4') 

这是测试山坳等于字符串'1,4'。它不是单独测试值。要解决这个

一种方法是使用like

where ','&@Q&',' like '*,'&col&',*' 

的想法是分隔符添加到每个字符串。因此,列中的值“1”变为“,1”。 @Q的值为“1,4”变为“,1,4”。现在当你进行比较时,没有“1”与“10”匹配的危险。

注意(对于那些不知道的人)。 like的通配符是*而不是SQL标准%。但是,根据连接方式的不同,这可能会有所不同,所以请使用适当的通配符。

+3

如果他的'.Net'使用OleDb连接到Access数据库文件,'Like'的通配符必须是'%'而不是'*'。 – HansUp

+0

@HansUp。 。 。那时我纠正了。 –

1

将这样的条件传递给查询一直是个问题。对于存储过程来说更糟的是因为你甚至无法调整查询来适应。目前2种选择:

  • 使用一个表值参数,并通过在多个值那样(有点讨厌的是诚实)
  • 写“分裂”多值函数,可以是UDF或经由SQL/CLR和调用从查询

为了记录在案,“短小精悍”,使这个容易通过原始命令(不存储过程):

int[] ids = ... 
var list = conn.Query<Foo>(
    "select * from Foo where Id in @ids", 
    new { ids }).ToList(); 

它计算出如何将其转换成参数等为你。

+0

我真的很喜欢Dapper,但它的一个学校项目,所以我需要解释整个库 – BBLN

+0

@BBLN你可以直接在ADO.NET中做 - 它有点乏味,全是 –

2

我在这里看到2个问题: 1)list.ToString()没有达到你的期望。试试这个:

List<int> foo = new List<int>(); 
foo.Add(1); 
foo.Add(4); 
string x = foo.ToString(); 

“X”将是“System.Collections.Generic.List`1 [System.Int32]”而不是“1,4” 要创建一个逗号分隔的列表,使用字符串的值。加入()。

2)OleDbParameter不理解数组或列表。你必须做别的事情。让我解释一下:

假设您成功使用string.Join()来创建参数。由此产生的SQL将是:

SELECT * FROM sp_feedbacks WHERE forumId IN ('1,4') 

OLEDB提供程序知道字符串必须带有引号。这是为了防止SQL注入攻击。但是你不想传递一个字符串:你想传递一个数组或者一个字面值不变的值进入SQL。

你不是第一个问这个问题,但我恐怕OLEDB没有一个很好的解决方案。如果是我,我会完全丢弃OLEDB并使用动态SQL。然而,谷歌搜索“参数化SQL阵”导致这里一些非常好的解决方案堆栈溢出:

WHERE IN (array of IDs)

Passing an array of parameters to a stored procedure

祝您好运!发布你的方法!

+0

我用你的第一个建议与Gordon的答案结合。 – BBLN

0

万一有人正在寻找一个SQL Server解决方案

CREATE FUNCTION [dbo].[SplitString] 
( 
    @Input NVARCHAR(MAX), 
    @Character CHAR(1) 
) 
RETURNS @Output TABLE (
    Item NVARCHAR(1000) 
) 
    AS BEGIN 
    DECLARE @StartIndex INT, @EndIndex INT 

    SET @StartIndex = 1 
    IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character 
    BEGIN 
     SET @Input = @Input + @Character 
    END 

    WHILE CHARINDEX(@Character, @Input) > 0 
    BEGIN 
     SET @EndIndex = CHARINDEX(@Character, @Input) 

     INSERT INTO @Output(Item) 
     SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1) 

     SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input)) 
    END 

    RETURN 

END

给予字符串数组,我将其转换为一个逗号用下面的代码

分隔字符串列表
var result = string.Join(",", arr); 

然后我可以传递参数如下

Command.Parameters.AddWithValue("@Parameter", result); 

的存储过程Definision,我会如下

select * from [dbo].[WhateverTable] where [WhateverColumn] in (dbo.splitString(@Parameter, ',')) 

希望这可以帮助别人

快乐编码使用的参数从上面