简介古诗词库中文简体是一份收录中华古诗词的关系型数据库资源面向传统文化研究者、教育工作者及诗词爱好者可用于批量检索、分类整理与文本分析。压缩包共 318 个 SQL 文件整体约 53.85MB文件按数据表拆分为作者表、诗作表、词作表等模块用户借助数据库客户端导入后即可用标准结构化查询语句完成跨表查询与统计。数据内容方面唐诗部分约收 5.5 万首涵盖初唐到晚唐李白、杜甫、王之涣、白居易等名家代表作绝句、律诗、古风等体裁均有涉及宋词部分包含 1564 位作者、21050 首词作苏轼的豪放、李清照的婉约、辛弃疾的壮志、柳永的深情皆可检索原文。除诗词正文外部分诗词还附有注释与赏析便于理解创作背景与艺术内涵。该资源发布以来已有 544 人浏览学习适合搭建古诗词语料库、开展诗词风格分析或用于课程教学与文化内容开发。1. 古诗词库 MySQL一份能直接导入检索的唐诗宋词语料到底值不值得下做中文内容产品的人十有八九都经历过满地找古诗词数据的尴尬网页上扒下来的 HTML 带一堆标签Word 文档排版稀碎PDF 转出来全是乱码光清洗数据就能耗掉一两个晚上。这份《古诗词库(中文简体-MySQL》解决的就是这个痛点——它直接把唐诗、宋词、作者信息做成了 9 个 MySQL 的 SQL 分片文件导入就能查不需要自己做表结构、不需要清洗字段适合做国学内容 App、教育产品、语料分析或者只是想给个人项目补一个诗词检索功能的开发者。它的边界也很清楚核心是数据不附带前端界面也不打包任何 API 服务你要做的事是把它正确导进自己的数据库。下面我按自己拆库的习惯从环境准备讲到导入执行再讲坑和进阶用法。2. 环境准备与表结构预判先摸清字符集和文件底细再动手拿到 SQL 文件第一反应就是source一把梭这是最容易翻车的开场。SQL 文件导入的成败一半在导入前就决定了。这一章先解决两个前置问题用什么字符集导入、这些文件里到底装了什么。2.1 字符集与排序规则utf8mb4 是唯一解别用 utf8古诗词文件里全是中文简体看起来跟编码关系不大但这类资源在制作时往往没有统一声明字符集如果你直接用默认配置导入轻则注释乱码重则整张表出现 ???。MySQL 8.0 的默认字符集已经是 utf8mb4但如果你还在跑 5.7 或者更老的版本服务器端很有可能还是 latin1。我一般会先在命令行确认两件事一是当前连接的字符集二是文件头部有没有 SET NAMES 声明。检查连接字符集的命令很简单SHOW VARIABLES LIKE character_set_server; SHOW VARIABLES LIKE character_set_database; SHOW VARIABLES LIKE collation_server;逻辑说明这三条语句分别查看服务器、数据库、排序规则的当前值。character_set_server是服务器端默认字符集直接决定新建库表时的继承值collation_server是排序规则对中文场景建议用utf8mb4_general_ci或utf8mb4_unicode_ci前者查询性能略优后者对 Unicode 排序更精确诗词搜索没有特殊排序需求选哪个都行。参数说明如果查出来不是 utf8mb4不用急着改全局配置可以在导入前单独指定。我更推荐的做法是在建库时就把字符集钉死CREATE DATABASE IF NOT EXISTS gushici DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;逻辑说明DEFAULT CHARACTER SET和COLLATE会写进库的系统表之后在这个库里建表只要不显式覆盖都会继承 utf8mb4。这一步的作用是让后续导入的每个表都有统一的字符集基线避免出现一张表 latin1、一张表 utf8 的混乱局面。这块的玄学在于你看到的乱码未必来自文件本身而是来自连接层。MySQL 客户端和服务端之间的字符集转换是有状态的如果客户端连接时用了 gbk服务端按 utf8mb4 解析内容就串了。所以导入完成后第一步不是急着数行数而是先抽一条数据肉眼验字符。2.2 文件结构与字段预判用建表语句反向推断9 个 SQL 文件的命名有规律authors.tang.sql、authors.song.sql明显是作者表按朝代拆开poet.tang.0.sql、poet.song.75000.sql这类是诗词正文表按文件名区分朝代和分片。但具体表名叫什么、有哪些字段、主键怎么定义不能靠猜。SQL 文件本身就是最好的说明书。在 Linux 或 macOS 终端下可以用这几条命令快速摸底wc -l *.sql head -n 60 poet.tang.0.sql grep -i CREATE TABLE *.sql逻辑说明wc -l统计每个文件的行数这个数值能帮你预估导入耗时。head -n 60看文件开头的 60 行SQL 文件的头部通常会包含 SET NAMES、DROP TABLE IF EXISTS、CREATE TABLE 定义和少量 INSERT 示例。grep -i CREATE TABLE一次性列出所有文件中定义的表名不用逐个打开就能掌握全貌。参数说明wc -l的-l是 count lines 的意思head -n 60的-n指定行数grep -i中的-i忽略大小写因为 SQL 关键字可能写法不统一。这三条命令组合起来能在 10 秒内帮你判断文件是否完整、表结构是否合理、导入顺序是否依赖。典型情况下这种诗词库的诗词表字段大致为id主键、title标题、author作者、content正文、dynasty朝代、type体裁。作者表则是id、name、dynasty、intro这类设计。拿到建表语句后我还会手动执行一条抽样查询验证字段是否真的是中文而不是 base64 或拼音缩写。2.3 文件名里的数字陷阱分片区间与行数的区别poet.song.75000.sql、poet.song.194000.sql这类文件名里的数字很容易让人误读成“这个文件里有七万五千行”。但如果摘要描述里宋词总共才约两万首一个分片怎么可能单独装下七万五千首这个数字更合理的解释是分片 ID 区间或者导入序号不是行数。所以启动导入之前我习惯先建一个临时数据库做全量导入然后跑一次聚合查询摸清真实体量SELECT dynasty, COUNT(*) FROM poet GROUP BY dynasty;逻辑说明这条 SQL 按朝代分组统计诗词数量用来核对摘要里“唐诗约 5.5 万首、宋词约 2.1 万首”的口径是否与文件一致。如果发现偏差优先怀疑分片文件被重复导入而不是怀疑摘要写错。参数说明GROUP BY dynasty要求该字段存在且值规范如果建表字段不叫dynasty而是poet_type之类需要先SHOW COLUMNS FROM poet;看真实字段名。这一步做完你对这份资源的预期才算校准。3. 导入执行命令行与图形化的完整操作顺序环境准备就绪后进入实操。这一章讲两种导入姿势——命令行和图形化工具以及导入完成后的表间关系处理。核心原则是按依赖顺序导入先作者表后诗词表避免边导边报错。3.1 命令行导入source 与 shell 重定向的取舍命令行导入是后端工程师最常用的方式尤其适合文件较大、需要反复调试的场景。两条路都能走一是进入 mysql 客户端后用source命令二是直接用 shell 的重定向把文件灌进库。先导入作者表mysql -uroot -p --default-character-setutf8mb4 gushici /data/sql/authors.tang.sql mysql -uroot -p --default-character-setutf8mb4 gushici /data/sql/authors.song.sql逻辑说明重定向让 mysql 客户端把文件内容当成 SQL 逐条执行。必须先导作者表因为诗词表里大概率有作者字段如果作者表存在外键约束虽然很多开源库不建物理外键先导诗词会造成违反约束的报错。即便没有物理外键先导作者表也能保证后续关联查询的完整性。参数说明--default-character-setutf8mb4显式指定客户端字符集这是命令行导入最容易漏的参数。漏掉的后果是文件里的中文按 latin1 解析入库查询结果全是乱码。-uroot -p是用户名和密码提示生产环境不建议明文密码。诗词表文件较大逐个导入时我习惯用source而不是重定向原因只有一个source 出错时能看到更清晰的错误上下文定位到具体行号USE gushici; SOURCE /data/sql/poet.tang.0.sql; SOURCE /data/sql/poet.song.75000.sql; SOURCE /data/sql/poet.song.82000.sql; SOURCE /data/sql/poet.song.125000.sql; SOURCE /data/sql/poet.song.150000.sql; SOURCE /data/sql/poet.song.158000.sql; SOURCE /data/sql/poet.song.194000.sql; SOURCE /data/sql/poet.song.63000.sql;逻辑说明USE gushici切换当前库SOURCE是 mysql 客户端的内置命令逐条读取文件里的 SQL 执行。这组顺序把 8 个诗词分片按文件名依次导入没有强依赖顺序因为都是 INSERT 语句。参数说明SOURCE后面的路径必须是 mysql 客户端所在机器能访问的绝对路径不能是相对路径。如果你在 Windows 上用 cmd 操作路径分隔符建议用正斜杠/避免转义问题。导入完成后立刻验证行数这是判断导入是否成功的最低标准SELECT COUNT(*) FROM poet; SELECT COUNT(*) FROM authors;逻辑说明这两条语句统计两个核心表的行数。如果poet表行数明显异常比如为 0优先检查导入顺序和文件路径不要急着DROP TABLE。3.2 图形化导入Workbench 与 Navicat 的操作路径不习惯命令行的读者可以用 MySQL Workbench 或 Navicat步骤差异不大。Workbench 的路径是 Server 菜单下的 Data Import选 Import from Self-Contained File然后选目标库。Navicat 更直接——右键目标数据库选“运行 SQL 文件”。两个工具有一个共通陷阱字符集设置藏在二级菜单里。Workbench 的 Data Import 面板里有个 Advanced 选项Navicat 的运行 SQL 文件窗口底部有字符集下拉框默认可能是 UTF-8 的别名实现或者干脆是空。我建议无论工具显示什么都手动选一次utf8mb4这不花时间但能省掉事后清乱码的大把功夫。图形化工具还有个隐藏问题超大文件容易让界面假死。如果某个分片文件超过 200MBWorkbench 的导入进度条可能长时间不动这不是死机是客户端在解析大事务。遇到这种情况切回命令行导入反而更稳。3.3 多分片合并把 8 张诗词分片合成一张可检索的总表9 个文件导入完成后你会得到若干张表——poet可能是分片表名带后缀也可能是多张独立表。对日常使用来说分片结构不友好查一句诗可能要跨表 UNION。我一般在导入完成后立刻建一张合并总表把分片数据灌进去CREATE TABLE poet_all LIKE poet_tang; INSERT INTO poet_all SELECT * FROM poet_tang; INSERT INTO poet_all SELECT * FROM poet_song_75000; INSERT INTO poet_all SELECT * FROM poet_song_82000;逻辑说明CREATE TABLE ... LIKE完全复制原表的结构包括字段、索引和字符集定义这一步保证了合并表的物理结构一致。INSERT INTO ... SELECT将分片数据逐批迁入总表不需要手动指定字段映射因为前后表结构一致。参数说明这里表名poet_tang、poet_song_75000是示例实际表名以SHOW TABLES;出的结果为准。如果分片表名里带点号比如建表时直接叫poet.song.75000引用时必须用反引号包裹poet.song.75000否则 MySQL 会把它解析成“库.表”结构。合并完成后poet_all就是你的单一查询入口之后所有业务查询都打在总表上逻辑简单、索引可控。这一章操作完之后你的数据库已经具备了一个可检索古诗词库的基本形态。4. 避坑导入与查询环节的高频翻车现场这段内容来自我处理多份语料库资源攒下的血泪经验每条都对应一个真实故障。按“现象 → 原因 → 解决”的格式记录方便你对照排查。4.1 导入阶段的翻车现场第一个坑重复执行导致主键冲突。现象是ERROR 1062 (23000): Duplicate entry 75001 for key PRIMARY导入中断。原因是同一个分片文件被导入了两次第一次已经写入了部分数据第二次执行时主键重复。解决办法不是跳过错误而是先确认这张表是否有业务价值——如果是刚导完发现重复直接 DROP TABLE 重建重导如果已经掺了别的数据用DELETE FROM poet WHERE id IN (SELECT id FROM poet GROUP BY id HAVING COUNT(*) 1);清重再补唯一索引。第二个坑整张表的中文变成问号。现象很直观——查出来的诗句全是???一眼扫过去像乱码。原因大概率是连接层字符集没对上文件里存的是 utf8mb4客户端却用 latin1 解析后写入。解决办法先SHOW VARIABLES LIKE character_set_client;确认连接字符集再用SET NAMES utf8mb4;重设当前会话之后重新导入受影响的表。注意已经变成问号的数据没法靠改会话恢复必须重导。第三个坑大文件导入超时中断。现象是导入到中途报Lost connection to MySQL server during query或者ERROR 2013。原因是客户端的max_allowed_packet或net_read_timeout太小大 INSERT 语句超过限制被切断。解决办法是在导入前把超时参数调大SET GLOBAL max_allowed_packet 1073741824; SET GLOBAL net_read_timeout 300; SET GLOBAL net_write_timeout 300;逻辑说明max_allowed_packet限制单条 SQL 的最大包大小单位是字节这里设成 1GBnet_read_timeout和net_write_timeout是网络读写超时单位秒设 300 秒给大事务留足时间。参数说明这些是全局变量需要 SUPER 权限改完当前连接需重连才生效。4.2 查询阶段的翻车现场第四个坑带点号表名查询报错。现象是SELECT * FROM poet.song.75000直接提示Table gushici.poet doesnt exist。原因是 MySQL 把poet.song.75000里的点号解析成了库表分隔符。解决办法是给表名加反引号SELECT * FROM poet.song.75000;或者像第 3.3 节那样建一个不带点号的总表。个人强烈推荐后者靠反引号活着迟早出事。第五个坑用 REGEXP 搜生僻字直接慢到怀疑人生。现象是SELECT * FROM poet WHERE content REGEXP 月 LIMIT 10;在几十万行的表上跑了 3 秒以上。原因是 REGEXP 全表扫描无法使用索引。解决思路分两层如果只是应急单次查询加LIMIT约束并接受慢如果是高频业务查询必须建全文索引具体做法在下一章展开。避坑这一章的核心逻辑其实只有一句SQL 文件导入出问题先查字符集再查重复执行最后才怀疑文件本身损坏。这个排查顺序能解决 80% 的导入故障。5. 把诗词库做成可检索的服务全文索引与飞花令玩法数据落库只是起点真正产生价值的是检索效率。古诗词场景里最常见的查询是“包含某个字的句子”——飞花令玩法、诗词接龙、主题检索全部依赖这种查询。但 MySQL 的LIKE %月%和REGEXP在这类查询上都很慢因为它们在几十万行里做全表扫。正确做法是建全文索引并且必须用 ngram 解析器。ALTER TABLE poet_all ADD FULLTEXT INDEX ft_poet_ngram (title, content) WITH PARSER ngram;逻辑说明这句 SQL 在poet_all表的title和content两个字段上建立全文索引WITH PARSER ngram指定中文分词解析器。MySQL 默认的全文解析器按空格分词对中文无效中文没有空格ngram 会把句子拆成连续 N 个字的序列默认 N2也就是 bigram。参数说明ngram的分词长度默认是 2适合诗词搜索如果你想按单字搜索比如飞花令必须单字匹配需要修改ngram_token_size全局变量为 1。注意这个参数是只读全局变量必须要修改 MySQL 配置文件并重启才能生效不能动态SET。索引建好后查询语法要从LIKE换成MATCH ... AGAINSTSELECT title, author, LEFT(content, 30) FROM poet_all WHERE MATCH(title, content) AGAINST(月 IN NATURAL LANGUAGE MODE) LIMIT 10;逻辑说明MATCH(title, content)针对之前建的双字段全文索引检索AGAINST指定关键词IN NATURAL LANGUAGE MODE表示自然语言模式适合普通搜句场景。检索时会返回相关性排序的结果前十个片段展示在LEFT(content, 30)截取的首 30 字预览里。参数说明LIMIT 10是安全阀防止返回全表匹配结果。如果ngram_token_size是默认的 2那么搜“月”会被 ngram 处理为词组匹配结果可能不准这也是我把这个参数单独拎出来说的原因——飞花令场景必须改成 1。我早期做诗词检索功能时没注意到 ngram 长度按默认配置建索引结果MATCH AGAINST查“月”几乎查不到数据一度怀疑是文件导入有遗漏折腾了很久才反应过来是分词粒度问题。从那以后我每建一个全文索引都会强制先查一遍SHOW VARIABLES LIKE ngram_token_size再做一轮真实关键词验证而不是建完索引就当收工。索引对查询性能的改善是立竿见影的同样查“月”全文索引上了之后单次响应从秒级降到毫秒级这才是这份古诗词库真正被盘活的样子。希望这篇拆解能让你少走几个弯路顺利把唐诗宋词跑起来。本文还有配套的精品资源点击获取
