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

C# SqlCommand实现数据不存在时插入的异常问题排查

解决BetEntities表避免重复插入的问题

先排查核心语法问题

你之前的错误大概率是SQL语法结构写错了——INSERT语句本身不支持直接跟WHERE NOT EXISTS,必须用IF NOT EXISTS块包裹INSERT逻辑。

错误写法(会导致语法报错):

INSERT INTO BetEntities (Col1, Col2) VALUES (@Val1, @Val2) WHERE NOT EXISTS (...)

正确的单条插入判断语法:

IF NOT EXISTS (SELECT 1 FROM BetEntities WHERE [唯一标识列] = @标识值)
BEGIN
    INSERT INTO BetEntities (Col1, Col2, ...) VALUES (@Val1, @Val2, ...)
END

这里的[唯一标识列]要换成你表中用来判断重复的字段(比如Id、订单号这类唯一值)。

优化你的异步实现方案

方案1:修正循环构建的参数化SQL

不要直接拼接字符串(容易出语法错误+SQL注入风险),改用参数化查询:

public async Task SaveBetEntityAsync(List<BetEntity> betEntities)
{
    var connectionString = "你的数据库连接字符串";
    using var conn = new SqlConnection(connectionString);
    await conn.OpenAsync();

    foreach (var entity in betEntities)
    {
        // 构建带判断的参数化SQL
        var sql = @"
IF NOT EXISTS (SELECT 1 FROM BetEntities WHERE Id = @Id)
BEGIN
    INSERT INTO BetEntities (Id, BetAmount, CreateTime)
    VALUES (@Id, @BetAmount, @CreateTime)
END";

        using var cmd = new SqlCommand(sql, conn);
        // 添加参数
        cmd.Parameters.AddWithValue("@Id", entity.Id);
        cmd.Parameters.AddWithValue("@BetAmount", entity.BetAmount);
        cmd.Parameters.AddWithValue("@CreateTime", entity.CreateTime);

        await cmd.ExecuteNonQueryAsync();
    }
}

方案2:批量处理(更高效,推荐)

循环单条插入效率低,尤其数据量大时,用表值参数+MERGE语句一次性处理整个DataTable:

  1. 先在SQL Server创建用户定义表类型:
CREATE TYPE dbo.BetEntityTableType AS TABLE
(
    Id INT PRIMARY KEY, -- 唯一标识列,用来判断重复
    BetAmount DECIMAL(18,2),
    CreateTime DATETIME
)
  1. C#异步实现代码:
public async Task SaveBetEntityBatchAsync(DataTable betDataTable)
{
    var connectionString = "你的数据库连接字符串";
    using var conn = new SqlConnection(connectionString);
    await conn.OpenAsync();

    var sql = @"
MERGE INTO BetEntities AS Target
USING @BetEntities AS Source
ON Target.Id = Source.Id -- 这里的匹配条件就是判断重复的规则
WHEN NOT MATCHED THEN
    INSERT (Id, BetAmount, CreateTime)
    VALUES (Source.Id, Source.BetAmount, Source.CreateTime);";

    using var cmd = new SqlCommand(sql, conn);
    // 添加表值参数
    var tvpParam = cmd.Parameters.AddWithValue("@BetEntities", betDataTable);
    tvpParam.SqlDbType = SqlDbType.Structured;
    tvpParam.TypeName = "dbo.BetEntityTableType";

    await cmd.ExecuteNonQueryAsync();
}

额外注意事项

  • 确保你用来判断重复的字段(比如Id)在数据库表上有唯一约束,即使SQL逻辑有疏漏,数据库层面也能拦截重复数据。
  • 避免直接拼接SQL字符串,参数化查询不仅能避免语法错误,还能防止SQL注入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:55:35