C# 使用带存储过程参数的IN运算符

C# 使用带存储过程参数的IN运算符,c#,asp.net,sql,ms-access,C#,Asp.net,Sql,Ms Access,我正在ASP.NET 2.0中创建一个网站,对我正在处理的页面进行了一些描述: ListView显示来自my access db的帖子表,以及一个具有多选模式的列表框,用于按论坛名称筛选行,value=forumId。 我正在将ListBox选择的值转换为一个列表,然后运行以下查询 参数: OleDbParameter("@Q",list.ToString()); 程序: SELECT * FROM sp_feedbacks WHERE forumId IN ([@Q]) 问题是,它不起作用

我正在ASP.NET 2.0中创建一个网站,对我正在处理的页面进行了一些描述: ListView显示来自my access db的帖子表,以及一个具有多选模式的列表框,用于按论坛名称筛选行,value=forumId。 我正在将ListBox选择的值转换为一个列表,然后运行以下查询

参数:

OleDbParameter("@Q",list.ToString());
程序:

SELECT * FROM sp_feedbacks WHERE forumId IN ([@Q])
问题是,它不起作用。即使从MSACCESS 2007使用字符串1,4、1,4或1,4运行它,也不会得到任何结果。当只选择一个论坛时,查询工作。例如,在1中

解决方案 所以我想我可以用WHERE和很多OR,但我真的想避免这个选项。 另一个解决方案是将数据表转换为列表,然后使用LINQ对其进行过滤,这似乎是一个非常混乱的选项。 提前感谢,, BBLN.

当您有:

col in ('1,4')
此测试col是否等于字符串“1,4”。它不是单独测试这些值

解决此问题的一种方法是使用以下方法:

其思想是为每个字符串添加分隔符。因此,值1在列中变为1。如果@Q的值为1,4,则变为1,4,。现在,当您进行比较时,1与10匹配是没有危险的

对于那些不知道的人,请注意。like的通配符是*而不是SQL标准%。但是,这可能因连接方式而异,因此请使用适当的通配符。

如果您有:

col in ('1,4')
此测试col是否等于字符串“1,4”。它不是单独测试这些值

解决此问题的一种方法是使用以下方法:

其思想是为每个字符串添加分隔符。因此,值1在列中变为1。如果@Q的值为1,4,则变为1,4,。现在,当您进行比较时,1与10匹配是没有危险的


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

将此类条件传递给查询始终是一个问题。对于存储过程来说,情况更糟,因为您甚至无法调整查询以适应。目前有2种选择:

老实说,使用表值参数并以这种方式传递多个值有点麻烦 以UDF或通过SQL/CLR编写拆分多值函数,并从查询中调用该函数 为了记录在案,dapper通过以下方式简化了原始命令而非存储过程:

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

它会为您找出如何将其转换为参数等。

将此类条件传递给查询一直是一个问题。对于存储过程来说,情况更糟,因为您甚至无法调整查询以适应。目前有2种选择:

老实说,使用表值参数并以这种方式传递多个值有点麻烦 以UDF或通过SQL/CLR编写拆分多值函数,并从查询中调用该函数 为了记录在案,dapper通过以下方式简化了原始命令而非存储过程:

int[] ids = ...
var list = conn.Query<Foo>(
    "select * from Foo where Id in @ids",
    new { ids } ).ToList();
它为您解决了如何将其转换为参数等问题。

我在这里看到了两个问题: 1 list.ToString并没有达到您期望的效果。试试这个:

List<int> foo = new List<int>();
foo.Add(1);
foo.Add(4);
string x = foo.ToString();
OLEDB提供程序知道字符串周围必须有引号。这是为了保护您免受SQL注入攻击。但您不希望传递字符串:您希望传递数组或未更改的文本值以进入SQL

你不是第一个问这个问题的人,但恐怕OLEDB没有一个很好的解决方案。如果是我,我会完全抛弃OLEDB,使用动态SQL。但是,Google搜索参数化SQL数组在堆栈溢出方面产生了一些非常好的解决方案:

祝你好运!张贴你的方法

我在这里看到两个问题: 1 list.ToString并没有达到您期望的效果。试试这个:

List<int> foo = new List<int>();
foo.Add(1);
foo.Add(4);
string x = foo.ToString();
OLEDB提供程序知道字符串周围必须有引号。这是为了保护您免受SQL注入攻击。但您不希望传递字符串:您希望传递数组或未更改的文本值以进入SQL

你不是第一个问这个问题的人,但恐怕OLEDB没有一个很好的解决方案。如果是我,我会完全抛弃OLEDB,使用动态SQL。但是,Google搜索参数化SQL数组在堆栈溢出方面产生了一些非常好的解决方案:


祝你好运!张贴你的方法

以防任何人正在寻找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
然后我可以按如下方式传递参数

Command.Parameters.AddWithValue("@Parameter", result);
select * from [dbo].[WhateverTable] where [WhateverColumn] in (dbo.splitString(@Parameter, ','))
在存储过程定义中,我将使用上面的参数,如下所示

Command.Parameters.AddWithValue("@Parameter", result);
select * from [dbo].[WhateverTable] where [WhateverColumn] in (dbo.splitString(@Parameter, ','))

以防任何人正在寻找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
然后我可以按如下方式传递参数

Command.Parameters.AddWithValue("@Parameter", result);
select * from [dbo].[WhateverTable] where [WhateverColumn] in (dbo.splitString(@Parameter, ','))
在存储过程定义中,我将使用上面的参数,如下所示

Command.Parameters.AddWithValue("@Parameter", result);
select * from [dbo].[WhateverTable] where [WhateverColumn] in (dbo.splitString(@Parameter, ','))

“1”和“4”不是两个独立的参数吗?@Brian我不知道,有没有办法将数组作为参数传递?没有,是forumIdIN@Q在“1,2,3,4,5”中被视为福鲁米德
. 你应该为每个需要的值创建单独的参数。“1”和“4”不是两个单独的参数吗?@Brian我不知道,有没有办法将数组作为参数传递?没有,是forumIdIN@Q在“1,2,3,4,5”中被视为一个forumID。您应该为所需的每个值创建单独的参数。如果his.Net使用OleDb连接到Access db文件,则Like的通配符必须是%而不是*。如果his.Net使用OleDb连接到Access db文件,Like的通配符必须是%而不是*。我将你的第一个建议与Gordon的答案结合使用。我将你的第一个建议与Gordon的答案结合使用。我非常喜欢Dapper,但这是一个学校项目,所以我需要解释整个过程library@BBLN您可以直接在ADO.NET中完成-这有点繁琐,allI真的很整洁,但这是一个学校项目,所以我需要解释整个过程library@BBLN您可以直接在ADO.NET中执行此操作-仅此而已,这有点繁琐