MySQL省市区数据表实战:建表、导入与递归查询避坑指南
简介这份 MySQL 版中国省市区数据表 SQL 资源面向需要处理行政区划信息的后端开发者、电商与物流系统设计人员以及正在学习数据库表结构设计的学习者。它提供了一张可直接导入使用的db_yhm_city表通过class_id、class_parent_id、class_name、class_type四个字段构建起国家、省、市、区县的层级关系并配有主键及class_parent_id、class_type索引便于按上级 ID 逐级查询城市或区县。资源包共 1 个文件为 PDF 格式约 495KB内容涵盖建表语句、省市区数据插入示例以及常用查询 SQL可直接参考或迁移到实际项目中。目前已有 1081 人学习下载适合需要快速搭建地址库、实现地址自动填充或进行地理维度数据分析的开发者参考使用。1. 从一张只有四个字段的表说起为什么省市区数据总在项目里翻车做电商下单页、物流面单、用户地址管理绕不开省市区三级联动。很多人第一反应是找一份 JSON 前端写死或者干脆调第三方接口。前端写死的问题在于数据更新要发版第三方接口的问题在于限流和网络抖动一旦挂了整个下单流程就卡住。这份 MySQL 版中国省市区数据表 SQL 走的是另一条路把行政区划直接落库用一张自增主键加父级 ID 的表把国家、省、市三级串起来查询靠class_parent_id递归不依赖任何外部服务。它适合中小型业务快速接入也适合作为地址模块的底座数据。表结构极简四个字段class_id、class_parent_id、class_name、class_type但正是这种极简设计让不少人在导入和查询时踩了坑。下面从建表、导入、查询到避坑一步步拆开讲。2. 建表与字段设计四个字段怎么撑起三级联动2.1 表结构逐字段拆解拿到 SQL 文件第一段就是建表语句。表名db_yhm_city存储引擎 MyISAM字符集 utf8。四个字段各司其职字段名类型作用关键点class_idsmallint(5) unsigned行政区划唯一标识自增主键手动插入时需显式指定值否则自增序列会乱class_parent_idsmallint(5) unsigned上级行政区划 ID顶级节点中国为 0省为 1市为对应省 IDclass_namevarchar(120)行政区划名称utf8 下中文占 3 字节120 足够长名称class_typetinyint(1)层级类型0 国家、1 省、2 市查询时靠它过滤层级避免混查class_type是这份数据表设计里最值得说的一个字段。没有它你查“所有省”只能靠class_parent_id 1来推断但一旦数据里混入直辖市或特别行政区逻辑就会变得脆弱。有了class_typeWHERE class_type 1直接锁定省级语义清晰。class_parent_id上建了普通索引class_type上也建了索引这两个索引是后续所有查询的性能基础。2.2 建表语句执行与字符集确认把建表段单独拿出来执行建议先确认数据库默认字符集。如果库是utf8mb4表是utf8跨表 JOIN 时可能出现排序规则冲突。常见做法是统一改成utf8mb4或者在建表时显式指定COLLATE utf8_general_ci。-- 先建库如果还没有字符集与表保持一致 CREATE DATABASE IF NOT EXISTS demo_region DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; USE demo_region; -- 建表注意 ENGINE 和 CHARSET 与原始 SQL 一致 DROP TABLE IF EXISTS db_yhm_city; CREATE TABLE db_yhm_city ( class_id smallint(5) unsigned NOT NULL AUTO_INCREMENT, class_parent_id smallint(5) unsigned NOT NULL DEFAULT 0, class_name varchar(120) NOT NULL DEFAULT , class_type tinyint(1) NOT NULL DEFAULT 2, PRIMARY KEY (class_id), KEY class_parent_id (class_parent_id), KEY class_type (class_type) ) ENGINEMyISAM AUTO_INCREMENT1 DEFAULT CHARSETutf8;这段代码里DROP TABLE IF EXISTS是必须保留的因为原始 SQL 文件通常包含它重复导入时不会报错。AUTO_INCREMENT1配合后续 INSERT 里显式指定的class_id实际自增值会被推到最大 ID 之后。MyISAM 引擎不支持事务导入中途失败不会回滚所以导入前最好先备份或确认表是空的。提示如果业务需要事务支持可以把ENGINEMyISAM改成ENGINEInnoDB字段和索引定义不用动。InnoDB 在并发查询下表现更稳代价是插入速度略慢。2.3 数据层级关系验证建完表先别急着写业务代码用几条查询确认层级关系是否正确。原始数据里class_id1是中国class_parent_id0class_type0class_id2是北京class_parent_id1class_type1class_id52是北京下的“北京”class_parent_id2class_type2。这种“省名和市名相同”的情况在直辖市里很常见查询时要注意区分。-- 查所有省级节点 SELECT class_id, class_name FROM db_yhm_city WHERE class_type 1 ORDER BY class_id; -- 查北京省下的所有市级节点 SELECT class_id, class_name FROM db_yhm_city WHERE class_parent_id 2 AND class_type 2; -- 验证层级完整性有没有市级节点的父级不是省级 SELECT c.class_id, c.class_name, c.class_parent_id FROM db_yhm_city c LEFT JOIN db_yhm_city p ON c.class_parent_id p.class_id WHERE c.class_type 2 AND (p.class_id IS NULL OR p.class_type ! 1);第三条查询是数据质量检查的常用手段。如果返回空结果说明市级节点的父级都能正确指向省级节点。如果返回了记录说明数据里有“孤儿节点”或者父级类型不对需要手动修正。这类检查在导入任何层级数据后都值得跑一遍。3. 数据导入批量 INSERT 的三种姿势与性能对比3.1 直接执行原始 SQL 文件最省事的方式是用命令行一次性导入。假设文件名为db_yhm_city.sql放在当前目录# 方式一mysql 命令直接导入 mysql -u root -p demo_region db_yhm_city.sql # 方式二进入 mysql 后用 source mysql -u root -p USE demo_region; SOURCE db_yhm_city.sql;方式一适合脚本化部署方式二适合交互式调试。注意SOURCE命令的路径是相对于 mysql 客户端当前工作目录的不是相对于 SQL 文件所在目录。如果文件很大导入过程中可以用SHOW PROCESSLIST;另开一个会话查看进度。3.2 用 Python 脚本拆分导入并做校验原始 SQL 文件里 INSERT 语句是一条一条写的几千条数据直接执行没问题但如果后续要增量更新或做数据清洗用脚本处理更灵活。下面这段 Python 用pymysql连接数据库逐条读取 SQL 文件里的 INSERT 并执行同时统计各层级数量。import re import pymysql # 连接配置按实际环境改 conn pymysql.connect( host127.0.0.1, userroot, passwordyour_password, databasedemo_region, charsetutf8 ) cursor conn.cursor() # 读取 SQL 文件提取所有 INSERT 语句 with open(db_yhm_city.sql, r, encodingutf-8) as f: content f.read() # 匹配 INSERT INTO db_yhm_city VALUES (...); pattern re.compile(rINSERT INTO db_yhm_city VALUES \((.?)\);) matches pattern.findall(content) inserted 0 for values in matches: sql fINSERT INTO db_yhm_city VALUES ({values}) try: cursor.execute(sql) inserted 1 except Exception as e: print(f失败: {sql[:80]}... 原因: {e}) conn.commit() # 校验各层级数量 cursor.execute(SELECT class_type, COUNT(*) FROM db_yhm_city GROUP BY class_type) for row in cursor.fetchall(): print(fclass_type{row[0]}, 数量{row[1]}) print(f共导入 {inserted} 条) cursor.close() conn.close()正则INSERT INTO \db_yhm_city VALUES ((.?));里的.?是非贪婪匹配确保每条 INSERT 单独捕获。class_type 分组统计能快速看出数据是否完整正常应该有 1 条国家、30 多条省级、几百条市级。如果某个层级数量明显偏少说明 SQL 文件可能被截断需要检查文件末尾是否完整。3.3 导入后的索引重建与统计信息更新MyISAM 表在大量 INSERT 之后索引统计信息可能不是最新的。虽然 MyISAM 不像 InnoDB 那样有复杂的统计信息但执行一次ANALYZE TABLE可以让优化器更准确地选择索引。-- 重建索引统计信息 ANALYZE TABLE db_yhm_city; -- 查看表状态确认行数和索引情况 SHOW TABLE STATUS LIKE db_yhm_city; -- 确认最大 ID后续新增数据时参考 SELECT MAX(class_id) FROM db_yhm_city;SHOW TABLE STATUS返回的Rows字段在 MyISAM 下是精确值可以直接用来核对导入条数。MAX(class_id)决定了后续如果手动插入新节点应该从哪个 ID 开始避免主键冲突。4. 查询实战从省查市、从市查区、递归查全路径4.1 基础两级查询与索引命中最常见的需求是“给定省 ID查出所有市”。原始数据里省级class_type1市级class_type2父级关系靠class_parent_id。-- 查广东省class_id6下的所有市 SELECT class_id, class_name FROM db_yhm_city WHERE class_parent_id 6 AND class_type 2 ORDER BY class_id;这条查询会命中class_parent_id索引。用EXPLAIN看一下执行计划EXPLAIN SELECT class_id, class_name FROM db_yhm_city WHERE class_parent_id 6 AND class_type 2;如果key列显示class_parent_id说明索引生效。如果显示NULL或走了全表扫描可能是数据量太小优化器认为全表更快或者索引统计信息过期执行ANALYZE TABLE后再试。4.2 递归查询全路径从区县反查省市业务里经常需要把“区县 ID”还原成“省-市-区”完整地址。这份数据表只有两级父级关系市→省→国用两次 JOIN 就能拼出全路径。-- 假设区县 ID 为 100反查省、市、区名称 SELECT province.class_name AS province_name, city.class_name AS city_name, district.class_name AS district_name FROM db_yhm_city AS district LEFT JOIN db_yhm_city AS city ON district.class_parent_id city.class_id LEFT JOIN db_yhm_city AS province ON city.class_parent_id province.class_id WHERE district.class_id 100;这里用了两次自连接。district是区县节点city是它的父级province是父级的父级。LEFT JOIN保证即使某一级缺失也能返回部分结果方便排查数据问题。如果数据里区县层级是class_type3但原始 SQL 里只到市级那么这条查询的district部分需要根据实际数据调整。4.3 用变量实现递归查询MySQL 8.0 以下MySQL 8.0 之前没有 CTE 递归但可以用会话变量模拟。下面这段 SQL 从任意节点向上追溯所有祖先-- 从 class_id100 向上查所有祖先 SELECT class_id, class_name, class_parent_id, class_type FROM ( SELECT class_id, class_name, class_parent_id, class_type, pid : class_parent_id AS next_pid, lvl : lvl 1 AS level FROM db_yhm_city, (SELECT pid : 100, lvl : 0) vars WHERE class_id pid UNION ALL SELECT c.class_id, c.class_name, c.class_parent_id, c.class_type, pid : c.class_parent_id, lvl : lvl 1 FROM db_yhm_city c JOIN (SELECT pid : pid) tmp WHERE c.class_id pid AND pid ! 0 ) AS tree ORDER BY level;这段 SQL 依赖会话变量pid在每一行更新后传递给下一行。写法比较绕实际项目中更推荐在应用层用循环查询可读性更好。如果数据库是 MySQL 8.0直接用WITH RECURSIVE更清晰WITH RECURSIVE region_tree AS ( SELECT class_id, class_name, class_parent_id, class_type, 0 AS level FROM db_yhm_city WHERE class_id 100 UNION ALL SELECT c.class_id, c.class_name, c.class_parent_id, c.class_type, rt.level 1 FROM db_yhm_city c INNER JOIN region_tree rt ON c.class_id rt.class_parent_id ) SELECT * FROM region_tree ORDER BY level;WITH RECURSIVE的终止条件是INNER JOIN找不到匹配的父级自然停止。level字段从 0 开始递增方便前端按层级展示。5. 避坑与排查导入和查询中最容易翻车的五个点5.1 现象导入后中文显示乱码查询出来是问号原因数据库、表、连接三者的字符集不一致。原始 SQL 是utf8但客户端连接可能默认latin1或gbk。解决在连接字符串里显式指定charsetutf8建库时也指定DEFAULT CHARACTER SET utf8。如果已经乱码需要重新导入不能靠ALTER TABLE修复已损坏的数据。5.2 现象class_parent_id索引没生效查询慢原因MyISAM 表的索引统计信息过期或者查询条件里对class_parent_id做了函数运算如WHERE class_parent_id 0 6。解决执行ANALYZE TABLE db_yhm_city;更新统计信息查询时保持字段裸用不要在索引列上做运算。5.3 现象直辖市查询结果重复北京省下还有一个北京市原因原始数据里直辖市既作为省级节点class_id2class_type1又作为市级节点class_id52class_type2。解决查询时严格用class_type过滤。前端联动时省级选中北京后市级列表里会出现“北京”这是正常设计不要误删。5.4 现象AUTO_INCREMENT冲突新增节点报主键重复原因原始 SQL 里显式插入了class_id但表的AUTO_INCREMENT值没有同步更新。解决导入后执行SELECT MAX(class_id) FROM db_yhm_city;然后ALTER TABLE db_yhm_city AUTO_INCREMENT 最大值1;。或者新增节点时也显式指定class_id不依赖自增。5.5 现象MyISAM 表在并发写入时锁表下单高峰期卡顿原因MyISAM 只支持表级锁写操作会阻塞所有读。解决如果业务有频繁写入地址数据的需求把引擎改成 InnoDB。改法ALTER TABLE db_yhm_city ENGINEInnoDB;。改完后确认索引还在InnoDB 支持行级锁并发读写不会互相阻塞。6. 进阶技巧把省市区数据用出花来的三个习惯第一个习惯是给class_name加前缀索引。如果业务需要按名称模糊搜索比如用户输入“广”要匹配“广东”“广西”“广州”直接LIKE %广%会全表扫描。可以加一个KEY idx_name (class_name(10))让前缀匹配走索引。虽然%广%这种前后模糊仍然无法命中但LIKE 广%可以。-- 添加名称前缀索引 ALTER TABLE db_yhm_city ADD KEY idx_name (class_name(10)); -- 前缀匹配走索引 EXPLAIN SELECT * FROM db_yhm_city WHERE class_name LIKE 广%;第二个习惯是定期用CHECKSUM TABLE校验数据一致性。如果有多套环境开发、测试、生产导入同一份 SQL 后执行CHECKSUM TABLE db_yhm_city;比对校验和是否一致。不一致说明某个环境的导入过程出了问题比如文件截断或字符集转换错误。-- 校验数据一致性 CHECKSUM TABLE db_yhm_city;第三个习惯是导出时用mysqldump带--no-create-info只导数据不导建表语句方便在已有表结构的环境里增量更新。# 只导出数据不导出建表语句 mysqldump -u root -p --no-create-info demo_region db_yhm_city city_data_only.sql # 导入时用 INSERT IGNORE 避免主键冲突 mysql -u root -p demo_region --executeSET SESSION sql_mode; SOURCE city_data_only.sql;--no-create-info适合表结构已经存在、只需要刷新数据的场景。配合INSERT IGNORE或REPLACE INTO可以在不删表的情况下更新行政区划数据。我一般会在每次数据更新前先CHECKSUM TABLE记录旧值导入后再校验一次确认数据确实变了且没有丢行。从那以后我每次导入省市区数据都强制走一遍“建表→导入→ANALYZE→CHECKSUM→抽样查询”的流程再也没出现过上线后地址下拉框空白的事故。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

向量距离度量加速进阶:利用 AVX-512 VNNI 指令集优化高维浮点内积计算

向量距离度量加速进阶:利用 AVX-512 VNNI 指令集优化高维浮点内积计算

在大规模向量检索系统(如 Milvus、Faiss 或自研分布式向量引擎)的生产环境中,距离度量计算往往占据检索阶段 70% 以上的 CPU 周期。当单节点承载数千万甚至数亿条 768 维或 1536 维向量时,粗排与精排阶段的每秒浮点运算量&#xf…

2026/10/11 1:53:36 阅读更多 →
RadixTree 树修剪与冷热分级存储:GPU 显存与 Host 主存异步置换架构

RadixTree 树修剪与冷热分级存储:GPU 显存与 Host 主存异步置换架构

在生产级大模型推理网关持续承接复杂业务流量的过程中,RadixAttention 依赖其敏锐的前缀基数树结构,为多轮对话、Agent 循环调用以及固定系统提示词带来了跨数量级的首字延迟改善。 然而,物理显存是有限且极其昂贵的。当 GPU 显存占用率突破预…

2026/10/9 23:33:43 阅读更多 →
020_长属性协议数据分片传输中的偏移错误定位

020_长属性协议数据分片传输中的偏移错误定位

020、长属性协议数据分片传输中的偏移错误定位 一个让人熬夜的偏移量故障 去年做某个分布式采集项目时,产线反馈过来一批设备偶发数据错乱。现象很怪:只有长度超过单个传输单元的长属性会出问题,短属性一切正常。具体表现是,接收端…

2026/10/9 23:33:42 阅读更多 →

最新新闻

手机怎么控制电脑远程办公 手机控制电脑的远程软件

手机怎么控制电脑远程办公 手机控制电脑的远程软件

手机怎么控制电脑远程办公?外出出差、居家休整时突发工作需求,电脑不在身边就容易耽误工作进度,多数远控工具体验差、不适配办公场景。手机怎么控制电脑远程办公更方便?建议使用无界趣连2.0,操作简单、实用性强&#x…

2026/10/11 1:53:42 阅读更多 →
手机怎么连接电脑用电脑操作 手机怎样连接电脑

手机怎么连接电脑用电脑操作 手机怎样连接电脑

手机怎么连接电脑用电脑操作?很多用户想在大屏上处理手机应用,或者远程帮家人操作手机,却不知道具体方法。其实选对远程控制工具即可,无界趣连2.0连接简单、延迟低、画质清晰,能轻松实现手机与电脑互控。综合来看&…

2026/10/11 1:53:42 阅读更多 →
242页PPT,战略落地难?真正缺的不是规划,而是从愿景到行动的闭环

242页PPT,战略落地难?真正缺的不是规划,而是从愿景到行动的闭环

很多企业并不缺战略。缺的是战略落地。每年战略会开得很热闹,愿景很宏大,目标很振奋,口号也很有力量。可到了第二季度,业务还是按老办法跑,部门还是按旧边界协同,绩效还是考原来的指标,一线员工…

2026/10/11 1:53:42 阅读更多 →
WPF嵌入D3D11渲染:共享纹理与D3DImage桥接实践

WPF嵌入D3D11渲染:共享纹理与D3DImage桥接实践

简介:一份面向WPF开发者的D3D视频渲染示例,演示在Windows Presentation Foundation中借助Direct3D硬件加速,高效处理并显示YUV颜色空间的视频帧。项目核心提供完整的C#源代码,涵盖YUV数据到D3D纹理的转换、渲染源封装、Win32互操作…

2026/10/11 1:53:42 阅读更多 →
Windows下ffmpeg下载安装与配置避坑指南

Windows下ffmpeg下载安装与配置避坑指南

简介:Windows 版 FFmpeg 最新静态构建压缩包,内置 FFmpeg 4.3.1 的 64 位可执行程序,专为需要批量转码、音视频剪辑、流媒体推送及格式分析的开发者和内容创作者准备,特别适合不愿自行编译源码、希望直接解压使用的 Windows 用户。…

2026/10/11 1:53:42 阅读更多 →
基于 Raft 协议的强一致分布式锁选型:Etcd vs Redis 在金融级场景下的对比

基于 Raft 协议的强一致分布式锁选型:Etcd vs Redis 在金融级场景下的对比

在分布式锁的选型会议上,架构师们经常会面对两派激烈的技术争吵: 一派是“性能实用主义者”,他们力挺 Redis:“Redisson 封装完备,单机吞吐破 10 万 QPS,看门狗自动续期极其优雅,全网普及度最高…

2026/10/11 1:52:42 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →