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

.NET 6 Web API中MERGE Upsert查询始终执行插入而非更新问题

问题分析与解决:ASP.NET Core 6 Web API中SQL Server Upsert仅执行插入的问题

问题现象

在ASP.NET Core 6 Web API中使用SQL Server的MERGE语句实现Upsert(存在则更新,不存在则插入)时,无论数据库中是否存在匹配的记录,始终执行插入操作。但相同的查询在SSMS中可以正常完成插入和更新逻辑,且数据库允许重复条目、已确认存在匹配值的记录。

核心原因

你的MERGE查询存在参数引用错误:在SOURCE子查询中,你用了字符串字面量'@Appt_ID'和'@OPID',而非真正的SQL参数引用。这导致SOURCE中的值始终是固定字符串"@Appt_ID"和"@OPID",而非你传入的实际业务数据,自然无法匹配数据库中已有的真实记录,所以每次都会走WHEN NOT MATCHED分支执行插入。

而在SSMS测试时,你应该是直接将@Appt_ID和@OPID替换成了真实值,所以逻辑正常生效。

解决方案

1. 修正MERGE查询

将SOURCE子查询中的字符串字面量改为参数引用,去掉单引号:

MERGE SG_APPOINTMENT_DATA AS TARGET 
USING (SELECT @Appt_ID AS ApptID, @OPID AS OPID) AS SOURCE 
      ON TARGET.ApptID = SOURCE.ApptID 
         AND TARGET.OPID = SOURCE.OPID    

WHEN NOT MATCHED THEN    
    INSERT (ApptID, OPID, -- 补充需要插入的其他字段
            Column1, Column2)    
    VALUES (SOURCE.ApptID, SOURCE.OPID, 
            @Value1, @Value2) -- 对应插入字段的参数

WHEN MATCHED THEN     
    UPDATE SET Column1 = @Value1, 
               Column2 = @Value2; -- 补充需要更新的字段和参数

2. 确认C#参数传递正确性

调用ExecuteQuery方法时,确保传入的参数键名与SQL中的参数名完全一致(SQL Server默认不区分大小写,但建议保持统一):

var parameters = new Dictionary<string, object>
{
    { "@Appt_ID", "实际预约ID" },
    { "@OPID", "实际OPID" },
    { "@Value1", "待更新/插入的值1" },
    { "@Value2", "待更新/插入的值2" }
};
await yourService.ExecuteQuery(updatedMergeQuery, parameters);

额外检查点

  • 确认ApptID和OPID的参数数据类型与数据库表中对应字段类型完全匹配,避免因类型不匹配(如字符串长度不一致、数值类型不兼容)导致匹配失败。
  • 若存在隐式类型转换风险,建议创建SqlParameter时显式指定类型:
command.Parameters.Add(new SqlParameter("@Appt_ID", SqlDbType.VarChar, 50) { Value = param.Value });

内容的提问来源于stack exchange,提问作者Sai Kiran Vedire

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 11:23:22