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

如何在写入SQL表前检查数据是否存在?避免主键重复致程序崩溃

嘿,这个主键冲突导致应用崩溃的问题我太熟了!给你几个实用的解决思路,分SQL层面和代码层面,你可以根据自己的场景选:

方案一:在SQL语句层面直接避免插入重复数据

这种方法从根源上减少冲突的可能,适合大部分常规场景。

写法1:用INSERT ... WHERE NOT EXISTS

把你的插入语句改成下面这样,只有当Path不存在时才执行插入:

INSERT INTO [FileTrackLog] (Date, Client, Path, DateAddedToDb)
SELECT @Date, @Client, @Path, @DateAddedToDb
WHERE NOT EXISTS (
    SELECT 1 FROM [FileTrackLog] WHERE Path = @Path
)

执行后如果数据已存在,只会返回0行受影响,不会抛出异常,应用自然不会崩溃。

写法2:用MERGE语句(更灵活)

如果后续需要对已存在的数据做更新操作,MERGE会更合适,它能同时处理插入和更新逻辑:

MERGE INTO [FileTrackLog] AS Target
USING (SELECT @Date, @Client, @Path, @DateAddedToDb) AS Source (Date, Client, Path, DateAddedToDb)
ON Target.Path = Source.Path
WHEN NOT MATCHED THEN
    INSERT (Date, Client, Path, DateAddedToDb)
    VALUES (Source.Date, Source.Client, Source.Path, Source.DateAddedToDb);

如果不需要更新,只保留WHEN NOT MATCHED的分支就行,效果和上面的写法一致。

方案二:在C#代码中捕获异常,优雅处理

如果遇到并发场景(比如两个请求同时检查同一个Path,都判定不存在后同时插入),还是可能触发主键冲突。这时候在代码里捕获异常就能避免应用崩溃:

using (SqlConnection conn = new SqlConnection(connStr))
{
    conn.Open();
    try
    {
        SqlCommand cmd = new SqlCommand(
            "INSERT INTO [FileTrackLog] (Date, Client, Path, DateAddedToDb) " +
            "VALUES (@Date, @Client, @Path, @DateAddedToDb)", conn);
        
        // 记得补充参数赋值,示例如下:
        cmd.Parameters.AddWithValue("@Date", yourDateValue);
        cmd.Parameters.AddWithValue("@Client", yourClientValue);
        cmd.Parameters.AddWithValue("@Path", yourPathValue);
        cmd.Parameters.AddWithValue("@DateAddedToDb", DateTime.Now); // 按你的业务逻辑调整
        
        int rowsAffected = cmd.ExecuteNonQuery();
        if (rowsAffected == 0)
        {
            // 可选:记录日志或提示数据已存在
            Console.WriteLine("该路径已存在,无需重复插入");
        }
    }
    catch (SqlException ex)
    {
        // *错误码2627*是SQL Server主键/唯一约束冲突的专属错误码
        if (ex.Number == 2627)
        {
            // 优雅处理,比如记录日志、给用户友好提示,而不是崩溃
            Console.WriteLine("数据已存在,跳过本次插入");
        }
        else
        {
            // 其他SQL异常,按原有逻辑抛出或处理
            throw;
        }
    }
}
额外建议:两种方案结合使用

单独用SQL层面的判断可能扛不住高并发场景的冲突,而单独捕获异常又不够高效。把两种方案结合起来,用SQL语句过滤掉绝大多数重复请求,再用代码捕获极少数并发导致的冲突,既能保证效率,又能彻底避免应用崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:59:13