You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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");
                // 你的业务逻辑
            }
        }
    }
}

关键说明:

  1. 参数化IN子句:MySQL Connector/NET支持直接把List<string>(或数组)传给参数,它会自动处理成IN子句需要的多个值,既安全又避免了手动拼接的错误。
  2. using语句的使用:所有实现IDisposable的对象(连接、命令、阅读器)都用using包裹,确保资源自动释放,不会泄漏。
  3. 过滤空值:读取skill的时候过滤掉空字符串,避免IN子句里出现无效的空值。
  4. 日期参数化:把today1和today2改成参数传递,彻底避免SQL注入风险。

这样修改后,你的代码就能正确获取所有distinct的skill值,并且安全地传递给第二个查询的IN子句了。

内容的提问来源于stack exchange,提问作者prkash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:34:18