SQL导入JSON数据时如何替换旧记录实现Customers表数据更新
核心问题原因分析
- 原子性缺失:当前DELETE和INSERT操作没有事务包裹,两个操作之间存在时间窗口,此时查询对应站点的数据会返回空结果;如果中间出现异常导致INSERT失败,还会永久丢失该站点的所有客户数据
- 字段匹配错误:你提到的查询语句使用
location_name作为筛选字段,但从导入逻辑看,表中存储站点信息的字段是Location,字段名不匹配会直接导致查询无结果 - 临时表使用不严谨:
SELECT INTO创建临时表如果存在同名对象会执行失败,直接导致整个流程中断
优化方案
1. 增加事务保证操作原子性
当前逻辑复杂度较低,无需拆分多个存储过程,将核心操作包裹在事务中即可。事务会保证DELETE和INSERT要么全部执行成功,要么全部回滚,不会出现中间空数据的状态,其他查询要么看到操作前的旧数据,要么看到操作完成后的新数据,不会返回空结果。如果后续导入逻辑复杂度大幅提升,再考虑拆分为独立的解析、写入子存储过程,由主存储过程统一调用即可。
2. 优化临时存储方式
改用表变量存储解析后的JSON数据,你当前全表只有400条数据,表变量完全可以承载,无需落盘IO,性能更高也不需要手动删除,避免临时表残留问题。
3. 统一查询字段名
后续查询时确认筛选字段为Location而非location_name,避免因字段名不匹配导致的无结果问题。
优化后的存储过程示例
CREATE OR ALTER PROCEDURE [dbo].[ImportCustomersByLocation] @JSON NVARCHAR(MAX), @location_name NVARCHAR(30) AS BEGIN SET NOCOUNT ON; BEGIN TRANSACTION; BEGIN TRY -- 表变量结构需和Customers表完全对齐,以下为示例字段,需补充剩余32个字段 DECLARE @CustomersTemp TABLE ( CustomerID nvarchar(100), Location nvarchar(30), FirstName nvarchar(50), LastName nvarchar(75), ClosedReason nvarchar(200), FileSuspended nvarchar(19), FileSuspendedReason nvarchar(200), RelevantHistory nvarchar(500) -- 补充其余32个和Customers表对齐的字段 ); INSERT INTO @CustomersTemp SELECT j2.* FROM OPENJSON(@JSON) WITH ( Customers nvarchar(max) '$.customers' as JSON ) j1 CROSS APPLY OPENJSON(J1.Customers) WITH ( CustomerID nvarchar(100) '$.customerID', Location nvarchar(30) '$.location', FirstName nvarchar(50) '$.firstName', LastName nvarchar(75) '$.lastName', ClosedReason nvarchar(200) '$.closedReason', FileSuspended nvarchar(19) '$.fileSuspended', FileSuspendedReason nvarchar(200) '$.fileSuspendedReason', RelevantHistory nvarchar(500) '$.relevantHistory' -- 补充其余32个字段的JSON映射 ) j2 WHERE j2.Location = @location_name; -- 删除对应站点旧数据 DELETE FROM [Customers] WHERE Location = @location_name; -- 插入新数据 INSERT INTO [Customers] SELECT * FROM @CustomersTemp; COMMIT TRANSACTION; END TRY BEGIN CATCH -- 出错自动回滚,避免数据丢失 IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; THROW; END CATCH END
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

