使用IN运算符和存储过程参数

时间:2013-05-17 17:34:49

标签: c# asp.net sql ms-access

我正在ASP.NET 2.0中构建一个网站,我正在处理的页面的一些描述: ListView显示来自我的访问数据库的表(帖子),以及用于过滤行的多选模式的ListBox(按论坛名称,值= forumId)。 我正在将ListBox选定的值转换为List,然后运行以下查询。

参数:

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

步骤:

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

问题是,它不起作用。即使我使用字符串1,4,“1”,“4”或“1,4”从MSACCESS 2007运行它,我也得到零结果。只有一个论坛被选中时,查询才有效。 (例如在(1)中)。

  • 解? 所以我想我可以使用WHERE和许多OR,但我真的想避免这个选项。 另一种解决方案是将DataTable转换为列表,然后使用LINQ对其进行过滤,这似乎是非常混乱的选项。

提前致谢, BBLN。

4 个答案:

答案 0 :(得分: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” 要创建逗号分隔列表,请使用string.Join()。

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

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

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

OLEDB提供程序知道字符串必须在它们周围加上引号。这是为了保护您免受SQL注入攻击。但是你不想传递一个字符串:你想要传递一个数组或一个文字未更改的值来进入SQL。

你不是第一个提出这个问题的人,但我担心OLEDB没有很好的解决方案。如果是我,我会完全丢弃OLEDB并使用动态SQL。但是,谷歌搜索“参数化SQL数组”在Stack Overflow上得到了一些非常好的解决方案:

WHERE IN (array of IDs)

Passing an array of parameters to a stored procedure

祝你好运!发布你采用的方法!

答案 1 :(得分:1)

当你有:

col in ('1,4')

这测试col等于字符串'1,4'。它没有单独测试这些值。

解决此问题的一种方法是使用like

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

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

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

答案 2 :(得分:1)

将这样的条件传递给查询一直是个问题。对于存储过程而言,它更糟糕,因为您甚至无法调整查询以适应。目前有2个选项:

  • 使用表值参数并以这种方式传递多个值(说实话有点麻烦)
  • 将“拆分”多值函数编写为UDF或通过SQL / CLR编写并从查询中调用

对于记录,“dapper”通过以下方式使原始命令(不是sprocs)变得容易:

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

它会弄清楚如何将它变成参数等。

答案 3 :(得分: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);

在In Stored Procedure Definition中,我将使用上面的参数如下

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