存储过程含DELETE仍触发主键约束冲突,请求技术协助
问题分析与解决方案
看起来你的存储过程里的DELETE逻辑存在漏洞,导致本该删除的记录没被清理干净,进而触发主键重复的插入错误。咱们一步步来排查和解决:
核心问题:DELETE语句的过滤逻辑不严谨
你当前的DELETE语句用了IN子句仅匹配zamid,但表的主键是四个字段联合(zamid, cislo_poradace, cislo_vztahu, strana),仅靠zamid无法精准定位要删除的记录。举个例子:如果#tempCrossTable里的某条记录,zamid和原表一致,但cislo_vztahu/cislo_poradace/strana不匹配,那这条原表的type=2记录就不会被删除,插入时自然会和新的type=1记录主键冲突。
修复DELETE语句
把DELETE改成JOIN关联的方式,直接匹配所有主键字段,确保所有对应#tempCrossTable且type=2的记录都被删除:
IF @operace = 'v' BEGIN DELETE f FROM lcs.vztahy_formulare f INNER JOIN #tempCrossTable crossTable ON f.zamid = crossTable.uzivatel AND f.cislo_poradace = crossTable.cislo_poradace AND f.cislo_vztahu = crossTable.cislo_vztahu AND f.strana = crossTable.strana WHERE f.type = 2 -- 可选:添加打印语句验证删除行数 PRINT 'Deleted ' + CAST(@@ROWCOUNT AS VARCHAR) + ' type=2 records' END
额外排查点:临时表是否有重复数据
如果修改DELETE后还是报错,要检查#tempCrossTable里是否存在重复的主键组合(同一uzivatel+cislo_poradace+cislo_vztahu+strana出现多次),插入时会尝试插入多条相同主键的记录,导致冲突。可以用以下语句检查:
SELECT uzivatel, cislo_poradace, cislo_vztahu, strana, COUNT(*) AS duplicate_count FROM #tempCrossTable GROUP BY uzivatel, cislo_poradace, cislo_vztahu, strana HAVING COUNT(*) > 1
如果存在重复,插入时加上DISTINCT去重:
IF @operace = 'v' INSERT INTO lcs.vztahy_formulare SELECT DISTINCT crossTable.uzivatel, crossTable.cislo_poradace, crossTable.vztazeneVztahy, 0, crossTable.strana, 1, 0, 2 FROM #tempCrosstable crossTable
验证步骤
- 执行修改后的存储过程,查看PRINT输出的删除行数,确认是否和预期的
type=2记录数一致 - 如果删除行数为0,说明
#tempCrossTable的数据和原表的type=2记录不匹配,需要核对临时表的生成逻辑
内容的提问来源于stack exchange,提问作者r8w9a5k
相关产品推荐
相关产品推荐

