.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
相关产品推荐
相关产品推荐

