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

问题描述 投票:7回答:7

我正在将几个已硬编码到应用程序中的查询转换为参数化查询。我在处理一个具有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注入攻击?

c# mysql parameters
7个回答
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(...));
}

5
投票

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

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


3
投票

旧问题,但是如果有人通过Google遇到了这个问题,这就是我的用法:

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


2
投票

您不能为IN子句使用参数。


0
投票

环绕您的整数列表并执行单独的更新。

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


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#,而且适用于每种语言。


-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.