引言
- 在门店中台长期运行过程中,行政区划代码(province / city / area)会因政府区划调整、数据迁移等原因出现旧码。
- 本次任务需要批量修正“非上海门店”的 area / city 字段,确保与国家行政区划最新版本保持一致。
需求拆解
- 找到所有需更新门店:通过业务报表 + 人工确认得到门店清单。
- 获取正确行政区编码:比对国家统计局最新区划发布表。
- 生成脚本并在生产库执行:保证幂等、安全、可回滚。
脚本生成思路
- 源数据整理至 CSV:
STORE_CODE,STORE_TYPE,OLD_AREA,NEW_AREA
。 - 使用简单 Python 模版批量输出:
import csv, datetime
tpl = "update site_store set area = {new} where store_code = '{code}' and store_type = '{typ}';"
with open('mapping.csv') as f, open('update.sql','w') as out:
for row in csv.DictReader(f):
out.write(tpl.format(**row)+'\n')
- 模板优势:
- 可读性强,后期维护仅需修改 CSV。
- 支持追加其他字段(如 city)而无需改脚本主体。
执行前校验
-
备份:
- 利用
CREATE TABLE site_store_bak AS SELECT * FROM site_store WHERE store_code IN (...)
备份受影响行。
- 利用
-
常量检查:
SELECT COUNT(1) FROM site_store_bak
与脚本行数一致。- 编码有效性:通过
sys_area
字典表校验new_area
均存在。
最佳执行姿势
- 会话设置:
SET SERVEROUTPUT ON
WHENEVER SQLERROR EXIT SQL.SQLCODE
- 使用
@update.sql
执行,遇错即停。 - 分批提交:
- 每 500 条 COMMIT 一次,减少回滚体积。
校验与回滚
-
快速校验:
SELECT COUNT(*) WHERE area = new_area
验证成功率。
-
聚合对比:
SUM(old_area)
vsSUM(new_area)
。 -
回滚方案:若发现误更新,使用
MERGE
将备份表写回原表。
常见坑
- 行锁争抢:门店表被其他业务写入,可在夜间窗口操作。
- 错误编码:脚本中若写错
WHERE
条件,可能更新全国门店。务必在测试库实测并EXPLAIN PLAN
确认命中行。 - 权限问题:生产执行需 DBA 协助,提前走变更流程。
优化与扩展
- 改用 MERGE INTO 一次完成:
MERGE INTO site_store s USING tmp_area_map m
ON (s.store_code = m.store_code AND s.store_type = m.store_type)
WHEN MATCHED THEN UPDATE SET s.area = m.new_area;
- 加
CHECK(area IN (SELECT id FROM sys_area))
防止脏数据。 - 自动化校验:脚本执行完触发 Jenkins Job,对比异常差异并出报警。
总结
- 批量数据脚本需求看似简单,核心在于 生成可靠脚本 + 完善备份校验。
- 小型场景用单条
UPDATE
直观易读;大规模可考虑MERGE
或 ETL 工具。 - 数据治理应在源头加约束,降低后期修补成本。
脱敏说明:本文所有出现的表名、字段名、接口地址、变量名、IP地址及示例数据等均非真实,仅用于阐述技术思路与实现步骤,示例代码亦非公司真实代码。示例方案亦非公司真实完整方案,仅为本人记忆总结,用于技术学习探讨。
• 文中所示任何标识符并不对应实际生产环境中的名称或编号。
• 示例 SQL、脚本、代码及数据等均为演示用途,不含真实业务数据,也不具备直接运行或复现的完整上下文。
• 读者若需在实际项目中参考本文方案,请结合自身业务场景及数据安全规范,使用符合内部命名和权限控制的配置。Data Desensitization Notice: All table names, field names, API endpoints, variable names, IP addresses, and sample data appearing in this article are fictitious and intended solely to illustrate technical concepts and implementation steps. The sample code is not actual company code. The proposed solutions are not complete or actual company solutions but are summarized from the author's memory for technical learning and discussion.
• Any identifiers shown in the text do not correspond to names or numbers in any actual production environment.
• Sample SQL, scripts, code, and data are for demonstration purposes only, do not contain real business data, and lack the full context required for direct execution or reproduction.
• Readers who wish to reference the solutions in this article for actual projects should adapt them to their own business scenarios and data security standards, using configurations that comply with internal naming and access control policies.版权声明:本文版权归原作者所有,未经作者事先书面许可,任何单位或个人不得以任何方式复制、转载、摘编或用于商业用途。
• 若需非商业性引用或转载本文内容,请务必注明出处并保持内容完整。
• 对因商业使用、篡改或不当引用本文内容所产生的法律纠纷,作者保留追究法律责任的权利。Copyright Notice: The copyright of this article belongs to the original author. Without prior written permission from the author, no entity or individual may copy, reproduce, excerpt, or use it for commercial purposes in any way.
• For non-commercial citation or reproduction of this content, attribution must be given, and the integrity of the content must be maintained.
• The author reserves the right to pursue legal action against any legal disputes arising from the commercial use, alteration, or improper citation of this article's content.Copyright © 1989–Present Ge Yuxu. All Rights Reserved.