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

如何让T-SQL Upsert仅返回单个INT结果集适配C# ExecuteScalar

解决T-SQL Upsert单结果集返回问题(适配ExecuteScalar)

方案一:使用MERGE语句(无IF ELSE,单结果集)

MERGE是T-SQL原生的Upsert单语句操作,能统一处理更新/插入逻辑,且仅生成一个结果集,完美适配ExecuteScalar的读取需求:

MERGE INTO Film WITH (UPDLOCK, SERIALIZABLE) AS target
USING (SELECT @FilmNumber AS FilmNumber, @FilmName AS FilmName) AS source
ON target.FilmNumber = source.FilmNumber
WHEN MATCHED THEN
    UPDATE SET FilmName = source.FilmName
WHEN NOT MATCHED THEN
    INSERT (FilmName, FilmNumber)
    VALUES (source.FilmName, (SELECT MAX(FilmNumber) FROM OtherTable) + 1)
OUTPUT INSERTED.FilmNumber;

方案说明:

  • 单语句执行,无论触发更新还是插入,仅输出一个结果集,ExecuteScalar可直接读取到有效FilmNumber
  • 保留原代码的UPDLOCK, SERIALIZABLE锁提示,确保并发场景下的数据一致性,避免幻读或丢失更新
  • 匹配时返回原FilmNumber,不匹配时返回新生成的FilmNumber,两种场景均能正确返回目标值

方案二:修改原IF ELSE逻辑(兼容现有写法)

若倾向保留IF ELSE结构,可调整代码避免生成空结果集,确保两种分支都仅返回一个有效结果:

UPDATE Film WITH (UPDLOCK, SERIALIZABLE)
SET FilmName = @FilmName
WHERE FilmNumber = @FilmNumber

IF @@ROWCOUNT > 0
BEGIN
    -- 更新成功时直接返回传入的FilmNumber
    SELECT @FilmNumber AS FilmNumber
END
ELSE
BEGIN
    -- 插入时返回新生成的FilmNumber
    INSERT INTO Film (FilmName, FilmNumber)
    OUTPUT INSERTED.FilmNumber
    VALUES(@FilmName, (SELECT MAX(FilmNumber) FROM OtherTable) + 1)
END

方案说明:

  • 移除UPDATE语句的OUTPUT子句,避免生成空结果集
  • 更新分支通过SELECT返回已知的@FilmNumber,插入分支通过OUTPUT返回新值,两种情况均仅生成一个结果集,ExecuteScalar可正确读取

注意事项:

(SELECT MAX(FilmNumber) FROM OtherTable) + 1的ID生成逻辑在高并发场景下可能出现重复值问题。若业务允许,建议改用IDENTITY列或SEQUENCE对象生成自增ID,规避并发冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 14:33:15