相同Schema的两表复制数据时early_last5列报数据截断错误如何解决
报错根因拆解
出现这个报错的核心矛盾是,文档标注的两张表结构一致,和数据库实际存储的表配置存在偏差,哪怕看到源表对应行的early_last5值是正常的0.0,也可能因为其他配置不匹配触发截断,常见的触发场景有两类:
- 两张表的字段物理存储顺序不一致:用
SELECT *做无字段列表的插入时,数据库会按照列的存储顺序逐个赋值,不会按字段名自动匹配,只要顺序有差异,就会出现值错配,比如把字符串类型的赛道名值传到FLOAT类型的early_last5字段上,触发类型转换截断。 - 目标表的
early_last5字段实际配置和源表有偏差:比如精度范围更小、非空约束未配置默认值,在开启严格SQL模式的情况下,哪怕是合规范围内的数值也可能因为隐式转换不匹配触发截断校验。
很多人排查时会单独查询源表中
early_last5列的数值,觉得0.0完全符合FLOAT类型要求,却没意识到无字段列表的SELECT *是按物理列顺序取值赋值的,根本不会和目标表的字段名做匹配,只要两张表的列建表顺序有差异,就会出现值串列的情况,比如把VARCHAR类型的赛道名称值塞到FLOAT类型的字段上,自然会报数据截断。
分步解决方法
- 第一步:拉取两张表的真实建表语句,逐字段对比配置
分别执行两条命令拿到实际表结构,不要依赖文档记录的Schema:
重点核对SHOW CREATE TABLE sectional_table; SHOW CREATE TABLE window_sectional_table;early_last5字段的类型精度、约束规则、默认值配置,一旦发现和源表不一致,用ALTER语句把目标表的字段配置调整到和源表完全一致:ALTER TABLE window_sectional_table MODIFY COLUMN early_last5 FLOAT(10,1) NULL DEFAULT 0.0; - 第二步:改造插入语句,替换隐式全字段匹配的写法
放弃INSERT INTO ... SELECT * ...的写法,显式指定插入、查询的字段列表,从根源上规避字段顺序不一致导致的值错配问题:INSERT INTO window_sectional_table (date, track, race_number, horse_number, early_last5) SELECT date, track, race_number, horse_number, early_last5 FROM sectional_table; - 第三步:临时调整会话SQL模式做验证
如果调整完字段配置、改完插入语句还报错,可以临时关闭会话级的严格截断校验模式,定位是不是严格SQL模式的误触发:
执行完重新跑插入语句,如果可以正常导入,就说明是字段精度、约束的配置偏差问题,后续再按业务规则修正目标表配置即可。SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';
注意:关闭严格SQL模式仅用于临时排查问题,正式环境下不建议全局修改该配置,否则会静默丢弃不匹配的数值,导致数据异常。
内容的提问来源于stack exchange,提问作者Saurav Pathak
相关产品推荐
相关产品推荐

