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

使用StringBuilder循环构建SQL查询时的参数引号问题

解决SQL拼接中字符串值缺少引号及SQL注入问题

首先,你的核心问题是当MatchValue2And不为null时,直接拼接字符串值没有添加单引号导致SQL语法错误,同时还存在潜在的SQL注入风险(直接拼接用户输入的字符串是高危操作)。另外你提到无法使用序号重复的命名参数,那我们可以分两种方式解决:

方案1:安全格式化字符串拼接(适合无法使用参数化的场景)

先写一个辅助方法来处理SQL字符串的格式化,自动处理null和单引号转义:

// 辅助方法:安全生成SQL中的字符串值,处理null和单引号转义
private string SafeSqlString(string input)
{
    if (input == null)
        return "NULL";
    
    // 转义单引号,避免SQL注入攻击
    return $"'{input.Replace("'", "''")}'";
}

然后修改你的循环代码,用这个方法来格式化所有需要拼接的字符串值:

var sb = new StringBuilder();
for (var i = 0; i < query.BlackWhiteListFieldMatchProxy.Count; i++)
{
    var matchProxy = query.BlackWhiteListFieldMatchProxy[i];
    // 提前格式化所有需要的参数值
    var matchValue2AndFormatted = SafeSqlString(matchProxy.MatchValue2And);
    var matchValue2OrFormatted = SafeSqlString(matchProxy.MatchValue2Or);
    var matchValue1Formatted = SafeSqlString(matchProxy.MatchValue1);

    sb.Append($@"(
                        MatchType = {(int)matchProxy.MatchType}
                AND     EntityType = {(int)matchProxy.EntityType}
                AND     MatchFieldType = {(int)matchProxy.MatchFieldType}
                AND     (
                            (
                                MatchValue = {matchValue1Formatted}
                                OR MatchValue = {matchValue2OrFormatted}
                            )
                        AND
                            (
                                {matchValue2AndFormatted} is NULL
                                OR MatchValue2 is NULL
                                OR MatchValue2 = {matchValue2AndFormatted}
                            )
                         )
                  )");

    if (i != query.BlackWhiteListFieldMatchProxy.Count - 1)
        sb.Append($@"
                    OR");
}

这样不管MatchValue2And是null还是有值,都会生成正确的SQL语法:

  • 当值为null时:NULL is NULL
  • 当值不为null时:'xxx' is NULL(带单引号,且单引号已转义)

方案2:参数化查询(推荐,彻底避免SQL注入)

如果你用的是Dapper、EF Core或者ADO.NET,推荐用参数化查询来彻底解决问题,同时避免参数名称冲突。这里以Dapper为例,我们给每个循环项的参数加上唯一前缀:

var sb = new StringBuilder();
var parameters = new DynamicParameters(); // 需要引用Dapper

for (var i = 0; i < query.BlackWhiteListFieldMatchProxy.Count; i++)
{
    var matchProxy = query.BlackWhiteListFieldMatchProxy[i];
    var paramPrefix = $"item_{i}_"; // 每个循环项的参数唯一前缀

    // 添加参数到参数集合
    parameters.Add($"{paramPrefix}MatchType", (int)matchProxy.MatchType);
    parameters.Add($"{paramPrefix}EntityType", (int)matchProxy.MatchType);
    parameters.Add($"{paramPrefix}MatchFieldType", (int)matchProxy.MatchFieldType);
    parameters.Add($"{paramPrefix}MatchValue1", matchProxy.MatchValue1);
    // 处理null值,映射到数据库的DBNull
    parameters.Add($"{paramPrefix}MatchValue2Or", matchProxy.MatchValue2Or ?? (object)DBNull.Value);
    parameters.Add($"{paramPrefix}MatchValue2And", matchProxy.MatchValue2And ?? (object)DBNull.Value);

    sb.Append($@"(
                        MatchType = @{paramPrefix}MatchType
                AND     EntityType = @{paramPrefix}EntityType
                AND     MatchFieldType = @{paramPrefix}MatchFieldType
                AND     (
                            (
                                MatchValue = @{paramPrefix}MatchValue1
                                OR MatchValue = @{paramPrefix}MatchValue2Or
                            )
                        AND
                            (
                                @{paramPrefix}MatchValue2And is NULL
                                OR MatchValue2 is NULL
                                OR MatchValue2 = @{paramPrefix}MatchValue2And
                            )
                         )
                  )");

    if (i != query.BlackWhiteListFieldMatchProxy.Count - 1)
        sb.Append($@"
                    OR");
}

// 执行查询(示例用Dapper)
using var connection = new SqlConnection("你的连接字符串");
var results = connection.Query<YourEntityModel>(sb.ToString(), parameters);

这种方式不仅解决了引号问题,还彻底杜绝了SQL注入,同时每个参数都有唯一名称(比如item_0_MatchValue2And、item_1_MatchValue2And),不会出现参数映射冲突的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:13:54