将List 添加到mysql参数

我有关于.NET连接器的MySqlParameter的这个问题。

我有这个问题:

SELECT * FROM table WHERE id IN (@parameter) 

而MySqlParameter是:

 intArray = new List(){1,2,3,4}; ...connection.Command.Parameters.AddWithValue("parameter", intArray); 

这个有可能? 是否可以将int数组传递给单个MySqlParameter? 另一个解决方案是将int数组转换为像“1,2,3,4”这样的字符串,但是当我将它传递给MySqlParameter并将其识别为字符串时,它会像sql查询一样放入“1 \,2 \,3 \,4”,这不会返回预期值。

@ UPDATE:似乎mysql连接器团队应该更加努力。

当我将它传递给MySqlParameter并且这被识别为字符串时,它会在sql查询中输入“1 \,2 \,3 \,4”,这不会返回预期的值。

我昨晚碰到了这个。 我发现FIND_IN_SET在这里工作:

 SELECT * FROM table WHERE FIND_IN_SET(id, @parameter) != 0 ... intArray = new List(){1,2,3,4}; conn.Command.Parameters.AddWithValue("parameter", string.Join(",", intArray)); 

显然这有一些长度限制(我发现你的post正在寻找替代解决方案),但这可能适合你。

参数不适用于IN。 我总是在查询本身中嵌入诸如字符串之类的东西。 虽然这通常被认为是错误的forms,因为SQL注入,如果您从强类型数字列表构建查询,那么任何外部输入都不应该以有意义的方式破坏它。

你将不得不迭代你的数组并自己创建列表

 // no parameters var sb = new StringBuilder(); for(int i=0;i0) {sb.Length-=1;} string sql = "SELECT * FROM table WHERE id IN (" + sb.ToString() + ")"; 

更新:考虑到这一点,我将回到我原来的答案(下面),这是使用参数。 构建的查询的优化以及数据库引擎可以集合的任何内容都取决于您。

 // no parameters var sb = new StringBuilder(); for(int i=0;i0) {sb.Length-=1;} string sql = "SELECT * FROM table WHERE id IN (" + sb.ToString() + ")"; 

这里有几个选项(按优先顺序排列):

  1. 使用支持表值参数的数据库。 这是获得所需语法的唯一方法。
  2. 数据必须来自某个地方:数据库,用户操作或机器生成的源。

    • 如果数据已存在于数据库中,请改用子查询。
    • 对于其他计算机生成的数据,请使用BULK INSERT,SqlBulkCopy或数据库的首选批量导入工具。
    • 如果它是由用户创建的,则将其添加到每个单独用户操作的单独表中,然后使用子查询。

      一个例子是购物车。 用户可以选择要购买的多个项目。 而不是将这些保留在应用程序中并且需要在签出时一次性将所有项目添加到订单中,在用户选择或更改它时将每个项目添加到数据库中的表。

  3. 有一个sql用户定义的函数,它将字符串参数解包到表中,并将该表作为可以与IN()表达式一起使用的集合返回。 有关其工作原理的详细信息,请参阅下面的链接文章。
  4. 在客户端上动态构建字符串列表或参数列表(如其他答案所示)。 请注意,这是我最不喜欢的选项。

关于这个问题的最终(我的意思是确定的 )工作在这里:

http://www.sommarskog.se/arrays-in-sql.html

文章很长,但是很好。 作者是一个SQL服务器专家,但整体上的概念也适用于MySQL。

据我所知,你不能提供任何数组作为准备语句的参数。 IN()不支持作为数组的参数。

这对于大型列表不起作用,但是如果你必须将列表作为参数传递,那么我发现它是唯一可行的。

代替

 SELECT * FROM table WHERE id IN (@parameter) 

你必须这样做:

 SELECT * FROM table WHERE INSTR(','+@parameter+',', ','+CAST(the_column AS CHAR) + ',') 

然后你可以用string.Join(",", intArray)传入你的列表

这是一个kludge,但它的工作原理。

来自Mud的答案仅适用于参数列表中的第一个int。 这意味着如果id为1,则“2,1,3,4”将不起作用。

请参阅FIND_IN_SET()与IN() 。

现在还没有评论,但也看到了Matt Ellen的回答。 会编辑他的答案,但不能。 INSTR似乎不适用于具有多个id的WHERE情况(仅在结果上返回)。

但是用LOCATE替换INSTR会使他的解决方案工作(使用String.Join(",", intArray)作为参数添加)…来自我的UP VOTE:

 LOCATE(CONCAT(',' , CAST(id AS CHAR) , ',') , CONCAT(',' , CAST(@paramter AS CHAR) , ',')) <> 0 

我不认为你可以像这样添加它们,但也许你可以遍历列表并动态生成查询。

例如:

 var intArray = new List(){1,2,3,4}; if (intArray.Count > 0) { var query = "SELECT * FROM table WHERE id IN ("; for (int i = 0; i < intArray.Count; i++) { //Append the parameter to the query //Note: I'm not sure if mysql uses "@" but you can replace this if needed query += "@num" + i + ","; //Add the value to the parameters collection ...connection.Command.Parameters.AddWithValue("num" + i, intArray[i]); } //Remove the last comma and add the closing bracket query = query.Substring(0, query.Length - 1) + ");"; //Execute the query here } 

这样,您甚至可以使用不同类型的列表,并仍然可以获得参数化查询的好处。 但是,我不知道大型列表是否存在性能问题,但我怀疑情况会是这样。