调用存储过程时SQL重复记录问题:Excel刷新触发重复插入
问题原因
- PowerQuery多次执行存储过程:PowerQuery在刷新流程中,可能会触发多次存储过程执行(比如获取元数据一次、实际加载数据一次)。若两次执行间隔极短,事务未及时提交会导致第二次执行时
NOT EXISTS判断失效;或者FPRIM表中存在重复的ID_SOLICIT值,第一次插入后,第二次执行仍会插入同ID下的其他关联记录。 - 存储过程幂等性不足:跨服务器查询(
OPENQUERY)的执行计划可能导致NOT EXISTS判断逻辑异常,例如远程表数据未及时同步、查询优化器延后判断时机,最终引发重复插入。
修正方案
方案1:增强存储过程的幂等性
方法A:添加唯一约束阻止重复插入
直接在数据库层面拦截重复数据,即使存储过程被多次执行也不会产生重复记录:
-- 给FP_SPV表的IDD列添加唯一约束 ALTER TABLE FP_SPV ADD CONSTRAINT UQ_FP_SPV_IDD UNIQUE (IDD); -- 修改存储过程,增加错误处理(可选) CREATE OR ALTER PROCEDURE SP_testSPV01 AS BEGIN SET NOCOUNT ON; BEGIN TRY INSERT INTO FP_SPV ([CIF Client], [CIF Furnizor], [IDD], [IDE]) SELECT CIF, CUI, ID_SOLICIT, ID FROM OPENQUERY(FB, 'SELECT CIF, ID_SOLICIT, ID, CUI FROM FPRIM WHERE DATAF >= ''2024-07-01''; ') WHERE NOT EXISTS (SELECT 1 FROM FP_SPV WHERE FP_SPV.IDD = ID_SOLICIT); END TRY BEGIN CATCH -- 仅捕获唯一约束冲突错误,其他错误正常抛出 IF ERROR_NUMBER() = 2601 PRINT '已存在相同IDD的记录,无需重复插入'; ELSE THROW; END CATCH END
方法B:使用MERGE语句替代INSERT逻辑
MERGE的匹配逻辑更明确,能避免执行计划异常导致的判断失效:
CREATE OR ALTER PROCEDURE SP_testSPV01 AS BEGIN SET NOCOUNT ON; MERGE INTO FP_SPV AS Target USING ( SELECT CIF, CUI, ID_SOLICIT, ID FROM OPENQUERY(FB, 'SELECT CIF, ID_SOLICIT, ID, CUI FROM FPRIM WHERE DATAF >= ''2024-07-01''; ') ) AS Source ON Target.IDD = Source.ID_SOLICIT WHEN NOT MATCHED THEN INSERT ([CIF Client], [CIF Furnizor], [IDD], [IDE]) VALUES (Source.CIF, Source.CUI, Source.ID_SOLICIT, Source.ID); END
方案2:调整PowerQuery逻辑,分离插入与查询操作
如果你的核心需求是展示FP_SPV的最新数据,而非在Excel刷新时执行插入,建议将插入和查询分离:
- 手动执行存储过程(或通过SQL Agent定时执行)完成数据同步;
- 修改PowerQuery直接查询FP_SPV表:
let Source = Sql.Database("SRV-DB3\SQLONE", "iScalaDB", [Query="SELECT * FROM FP_SPV"]), #"Added Custom" = Table.AddColumn(Source, "Data actualizare SQL", each DateTime.LocalNow()) in #"Added Custom"
若必须在Excel刷新时执行插入,可添加SET NOCOUNT ON;到存储过程中(方案1已包含),并禁用PowerQuery的「后台刷新」功能,减少多次执行的概率。
内容的提问来源于stack exchange,提问作者Cip
相关产品推荐
相关产品推荐

