如何将MySQL查询的Distinct值传入C#字符串并作为查询参数?
问题分析与解决方案
让我们一步步拆解你代码里的问题,然后给出修复方案:
核心问题1:IN子句的参数传递错误
你现在把拼接好的带单引号的字符串传给@skill参数,但MySQL会把这个整个字符串当成单个值来处理,而不是多个独立的skill值。比如你拼接出'skillA','skillB',MySQL会把它当作一个完整的字符串去匹配skill IN ('\'skillA\',\'skillB\''),这显然不是你想要的结果。而且手动拼接字符串还会有SQL注入的风险。
核心问题2:字符串插值语法错误
你写的hs.Select(item => "'{item}'")是无效的字符串插值,正确的写法应该是hs.Select(item => $"'{item}'")——不过即使修正了这个,上面的IN参数问题依然存在,所以这个写法本身就不推荐。
其他问题:资源未正确释放
你的数据库连接没有用using语句包裹,这会导致连接无法及时释放,长期运行可能造成连接池耗尽。另外第二个查询里的today1和today2直接拼接在SQL里,同样存在SQL注入风险。
修复后的完整代码
我们用参数数组传递IN子句的值,同时用using管理所有资源,并且参数化所有变量:
// 第一步:获取所有distinct的skill2值 List<string> skillList = new List<string>(); using (MySqlConnection cons = new MySqlConnection(MyConString)) { string query = "SELECT DISTINCT skill2 FROM agentdetails"; using (MySqlCommand command = new MySqlCommand(query, cons)) { cons.Open(); using (MySqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { string skill = Convert.ToString(reader[0]); if (!string.IsNullOrEmpty(skill)) // 过滤空值,避免无效参数 { skillList.Add(skill); } } } } } // 第二步:执行统计查询,正确传递IN参数 using (MySqlConnection con2 = new MySqlConnection(MyConString)) { // 注意:IN子句用占位符,然后通过参数数组传递 string hcount = @"SELECT SUM(headCount) AS THC, date AS date1 FROM setshrinkage WHERE skill IN (@skills) AND date BETWEEN @startDate AND @endDate GROUP BY date"; using (MySqlCommand cmd2 = new MySqlCommand(hcount, con2)) { // 传递skill数组参数 cmd2.Parameters.AddWithValue("@skills", skillList); // 参数化日期,避免SQL注入 cmd2.Parameters.AddWithValue("@startDate", today1); cmd2.Parameters.AddWithValue("@endDate", today2); con2.Open(); using (MySqlDataReader myread2 = cmd2.ExecuteReader()) { // 在这里处理查询结果,比如: while (myread2.Read()) { decimal totalHeadCount = myread2.GetDecimal("THC"); DateTime date = myread2.GetDateTime("date1"); // 你的业务逻辑 } } } }
关键说明:
- 参数化IN子句:MySQL Connector/NET支持直接把
List<string>(或数组)传给参数,它会自动处理成IN子句需要的多个值,既安全又避免了手动拼接的错误。 - using语句的使用:所有实现
IDisposable的对象(连接、命令、阅读器)都用using包裹,确保资源自动释放,不会泄漏。 - 过滤空值:读取skill的时候过滤掉空字符串,避免IN子句里出现无效的空值。
- 日期参数化:把
today1和today2改成参数传递,彻底避免SQL注入风险。
这样修改后,你的代码就能正确获取所有distinct的skill值,并且安全地传递给第二个查询的IN子句了。
内容的提问来源于stack exchange,提问作者prkash
相关产品推荐
相关产品推荐

