C#参数化查询MySQL带有`in`子句

时间:2009-03-16 13:40:02

标签: c# mysql parameters

我正在将几个硬编码的查询转换为应用程序并立即构建到参数化查询。我遇到一个特定查询时遇到问题,该查询有一个in子句:

UPDATE TABLE_1 SET STATUS = 4 WHERE ID IN (1, 14, 145, 43);

第一个参数很简单,因为它只是一个普通参数:

MySqlCommand m = new MySqlCommand("UPDATE TABLE_1 SET STATUS = ? WHERE ID IN (?);");
m.Parameters.Add(new MySqlParameter("", 2));

但是,第二个参数是一个整数列表,表示需要更新的行的ID。如何传递单个参数的整数列表?或者,您将如何设置此查询,以便您不必在每次调用时都完全构建它,并且可以防止SQL注入攻击?

8 个答案:

答案 0 :(得分:5)

这在MySQL中是不可能的。 您可以创建所需数量的参数并执行UPDATE ... IN(?,?,?,?)。这可以防止注入攻击(但仍然需要您为每个参数计数重建查询)。

其他方法是传递逗号分隔的字符串并解析它。

答案 1 :(得分:4)

您可以根据(可能)可变数量的参数“动态”建立参数化查询,并迭代它以传递它们。

所以,比如:

List foo; // assuming you have a List of items, in reality, it may be a List<int> or a List<myObject> with an id property, etc.

StringBuilder query = new StringBuilder( "UPDATE TABLE_1 SET STATUS = ? WHERE ID IN ( ?")
for( int i = 1; i++; i < foo.Count )
{   // Bit naive 
    query.Append( ", ?" );
}

query.Append( " );" );

MySqlCommand m = new MySqlCommand(query.ToString());
for( int i = 1; i++; i < foo.Count )
{
    m.Parameters.Add(new MySqlParameter(...));
}

答案 2 :(得分:2)

您不能将参数用于IN子句。

答案 3 :(得分:2)

老问题,但如果有人通过谷歌遇到这个问题,请点击此处使用:

int status = 4;  
string ids = "1,14,145,43";      

m.Parameters.AddWithValue("@Status", status);
m.Parameters.AddWithValue("@IDs", ids);

UPDATE TABLE_1 SET STATUS = @Status WHERE FIND_IN_SET(ID, @IDs) > 0;

注意:FIND_IN_SET是mySQL特定的功能。

信用,信用到期:请参阅此问题:Add List<int> to a mysql parameter

答案 4 :(得分:0)

循环整数列表并执行单独更新。

MSSQL 2008提供了表值参数来避免这个问题,我不知道MySQL中有任何类似的功能。

答案 5 :(得分:0)

从MySQL 4.0开始,您可以使用 FIND_IN_SET 函数创建带有“ in子句”的参数化SQL。

您的代码:

UPDATE TABLE_1 SET STATUS = 4 WHERE ID IN (1, 14, 145, 43);

已更改为使用FIND_IN_SET:

UPDATE TABLE_1 SET STATUS = 4 WHERE FIND_IN_SET(ID, 1, 14, 145, 43);

最后,您可以使用变量对查询进行参数设置:

var s = "UPDATE TABLE_1 SET STATUS = 4 WHERE FIND_IN_SET(ID, ?)";
var params = "1, 14, 145, 43";

dataSource.Execute(s, params);

请参见W3Schools referenceMySQL Tutorial

由于 FIND_IN_SET 是MySQL函数,它不仅可用于C#,还可用于每种语言

答案 6 :(得分:0)

我最近发现 find_in_set 有多慢,所以我尽量避免它。我也尽量避免构建我的 sql 来帮助防止注入攻击。我发现您可以实现所需的内容并同时使用参数化查询。

int[] ids = new int[] { 1, 2, 3};

command.CommandText = @"
  SET @temp = @ids;
  SELECT * FROM table_name WHERE table_name_id IN @temp;
";

command.Parameters.AddWithValue("ids", string.Join(",", ids));

老问题,但它证实了我的怀疑,我想出了这个解决方法。

答案 7 :(得分:-1)

我建议创建一个函数(假设mysql支持用户定义的函数)将参数分开以返回表。