Pandas Series使用to_sql带索引写入MySQL报BLOB/TEXT键长度错误
报错根因
你碰到的MySQL报错"BLOB/TEXT column 'atc_code' used in key specification without a key length",核心原因是传给to_sql的dtype参数没有正确定义数据库侧的限长字符串类型,最终数据库把要做索引的atc_code列识别为无长度约束的TEXT/BLOB类型——而MySQL的规则是,这类大文本类型不能不加前缀长度说明就创建索引。
代码里的具体问题:
- 你导入使用的
String(16)、小写string并不是SQLAlchemy层面的数据库字段类型,属于误把Pandas内置的Python侧字符串类型传入了数据库映射逻辑。SQLAlchemy遇到不认识的类型定义时,会自动给所有字符串列推导为无长度限制的TEXT类型,你写的长度约束完全不会生效。 - 哪怕
String(16)的写法形式是对的,如果导入来源错了,这个长度参数根本不会传递给数据库建表逻辑,最终还是会生成TEXT类型的索引列。
可直接运行的修正方案
- 从SQLAlchemy模块导入正确的限长字符串类型,不要用Pandas内置的字符串类型做数据库字段映射
- 给Series的值列(也就是建表后的
atc_class列)设置合理的存储长度,从你提供的法语ATC类名示例来看,255位长度完全覆盖存储需求,不会出现字段过长的问题
修正后的完整可运行代码:
from sqlalchemy import String # 必须导入SQLAlchemy的类型,不能用Pandas的StringDtype/内置string类型 my_series = pd.read_json("some_path", typ="series") my_series.to_sql(**{ "name": "atc_classes", "if_exists": "replace", "index": True, "index_label": "atc_code", "dtype": { # 两个列都显式指定存储长度,避免被自动推导为TEXT类型 "atc_code": String(16), "atc_class": String(255) } })
补充提示:如果你使用的是MySQL 5.x版本,哪怕列是正常的VARCHAR类型,创建总长度超阈值的联合索引时也会触发同类报错。按照上面的显式限长定义,完全可以覆盖你当前单主键索引的场景,不会再出现类型推导错误的问题。
内容的提问来源于stack exchange,提问作者Jordan Gomette
相关产品推荐
相关产品推荐

