Data truncation: Data truncated for column异常的解决

本文探讨了使用程序向MySQL数据库插入中文数据时遇到的问题,特别是某些特定记录无法正确插入的情况,并提供了解决方案。
从excel 读取数据插入mysql库中,
莫名其妙地少数几条记录的中文字段用程序插入不了,而用客户端写sql可以成功,用肉眼看没发现那几条记录数据有什么异常。
Error: 错误:basename=福×××× 口cellId_b=46错误原因:
--- The error occurred in com/fsti/cdr/persistence/sqlmapdao/sql/ImportFile.xml.
--- The error occurred while applying a parameter map.
--- Check the insertCell-InlineParameterMap.
--- Check the statement (update failed).
--- Cause: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data truncated for column 'BASENAME' at row 1
com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/fsti/cdr/persistence/sqlmapdao/sql/ImportFile.xml.
--- The error occurred while applying a parameter map.
--- Check the insertCell-InlineParameterMap.
--- Check the statement (update failed).
--- Cause: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data truncated for column 'BASENAME' at row 1
Caused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data truncated for column 'BASENAME' at row 1
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(GeneralStatement.java:91)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.update(SqlMapExecutorDelegate.java:500)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.update(SqlMapSessionImpl.java:85)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.update(SqlMapClientImpl.java:62)
at com.fsti.cdr.service.ImportFileService.insertCell(ImportFileService.java:42)
at com.fsti.cdr.zte.parser.ExcelParser$1.run(ExcelParser.java:124)
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:121)
Caused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data truncated for column 'BASENAME' at row 1
at com.mysql.jdbc.SQLError.convertShowWarningsToSQLWarnings(SQLError.java:758)
at com.mysql.jdbc.MysqlIO.scanForAndThrowDataTruncation(MysqlIO.java:3570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2128)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2543)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1737)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:998)
at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:168)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:84)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteUpdate(GeneralStatement.java:200)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(GeneralStatement.java:78)
... 6 more

Caused by:
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data truncated for column 'BASENAME' at row 1
at com.mysql.jdbc.SQLError.convertShowWarningsToSQLWarnings(SQLError.java:758)
at com.mysql.jdbc.MysqlIO.scanForAndThrowDataTruncation(MysqlIO.java:3570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2128)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2543)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1737)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:998)
at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:168)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:84)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteUpdate(GeneralStatement.java:200)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(GeneralStatement.java:78)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.update(SqlMapExecutorDelegate.java:500)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.update(SqlMapSessionImpl.java:85)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.update(SqlMapClientImpl.java:62)
at com.fsti.cdr.service.ImportFileService.insertCell(ImportFileService.java:42)
at com.fsti.cdr.zte.parser.ExcelParser$1.run(ExcelParser.java:124)
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:121)

Caused by:
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data truncated for column 'BASENAME' at row 1
at com.mysql.jdbc.SQLError.convertShowWarningsToSQLWarnings(SQLError.java:758)
at com.mysql.jdbc.MysqlIO.scanForAndThrowDataTruncation(MysqlIO.java:3570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2128)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2543)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1737)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:998)
at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:168)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:84)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteUpdate(GeneralStatement.java:200)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeUpdate(GeneralStatement.java:78)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.update(SqlMapExecutorDelegate.java:500)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.update(SqlMapSessionImpl.java:85)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.update(SqlMapClientImpl.java:62)
at com.fsti.cdr.service.ImportFileService.insertCell(ImportFileService.java:42)
at com.fsti.cdr.zte.parser.ExcelParser$1.run(ExcelParser.java:124)
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:121)

将字段改为varchar(255)和设置默认值都不能解决。其实中文值得程度没有超过255,不是长度不够引起。
将字段类型改为varbinary能解决上面的问题。
读取时要进行转换:convert(col using gb2312)
<think> 我们遇到了一个SQL错误:数据截断,具体是'test_item1'列在导入第14行时数据太长。 原因:要插入的数据长度超过了该列定义的最大长度。 解决方案: 1. 检查数据:查看第14行'test_item1'列的数据内容,确定其实际长度。 2. 修改表结构:根据实际需要,调整该列的长度(VARCHAR的长度)至足够大。 3. 数据清洗:如果数据中有异常的长字符串(比如不应该这么长),可以截断或清洗。 步骤: 步骤1:查看当前表结构,特别是'test_item1'列的定义。 步骤2:确定需要修改为多大的长度。 步骤3:执行ALTER TABLE修改列定义。 示例代码: 假设我们通过查看发现,当前'test_item1'列定义为VARCHAR(50),而实际数据中有超过50个字符的内容。 修改表结构: ```sql -- 将test_item1列的长度增加到100 ALTER TABLE adapter_defect MODIFY test_item1 VARCHAR(100); ``` 如果其他类似列(test_item2, test_item3)也可能有同样问题,可以一并修改: ```sql ALTER TABLE adapter_defect MODIFY test_item1 VARCHAR(100), MODIFY test_item2 VARCHAR(100), MODIFY test_item3 VARCHAR(100); ``` 步骤4:重新导入数据。 如果不想修改表结构,也可以在导入前对数据进行截断处理(不推荐,因为可能丢失信息,除非业务允许)。 使用Python清洗数据(截断超过指定长度的字符串): ```python import pandas as pd # 读取CSV df = pd.read_csv('defect_data.csv') # 定义各列最大长度 max_lengths = { 'test_item1': 50, # 如果不想修改表结构,可以按原长度截断,但这里建议根据修改后的表结构调整 'test_item2': 50, 'test_item3': 50 } # 截断字符串 for col, max_len in max_lengths.items(): if col in df.columns: df[col] = df[col].astype(str).str[:max_len] # 保存清洗后的文件 df.to_csv('truncated_data.csv', index=False) ``` 但是,如果问题只在第14行出现,且其他行都正常,我们可以只处理这一行。但为了健壮性,建议检查整个文件。 如何查看第14行的数据? 在Python中: ```python import pandas as pd df = pd.read_csv('defect_data.csv') # 查看第13行(因为索引从0开始,所以第14行索引为13) print(df.iloc[13]) ``` 如果问题是由于数据中包含换行符或其他特殊字符导致,也需要在导入前处理。 另外,在DBeaver导入设置中,可以设置截断超长字符串(但这样会静默截断,可能不是最佳实践): 在导入向导的“列映射”步骤,选择该列,然后在右侧属性中设置“Truncate strings”为true。 但最好的做法是修改表结构以适应实际数据。 预防措施: 1. 在设计表时,根据业务需求预留足够的长度。 2. 在应用层进行数据验证,确保数据长度不超过数据库列定义。 3. 在导入数据前,进行数据质量检查。 相关SQL:查看列定义 ```sql DESCRIBE adapter_defect; ``` 或者更详细的信息: ```sql SELECT column_name, character_maximum_length FROM information_schema.columns WHERE table_schema = 'your_database' AND table_name = 'adapter_defect' AND column_name LIKE 'test_item%'; ``` 注意:修改表结构可能会影响现有应用,需要评估。 因此,推荐步骤: 1. 暂停导入。 2. 查看错误行数据,分析原因。 3. 修改表结构(增加列长度)或清洗数据(如果数据异常)。 4. 重新导入。 如果问题仍然出现,则继续检查其他列是否也有超长情况。 最后,重新运行导入。 §§相关问题§§: 1. 在MySQL中如何批量修改多个VARCHAR列的长度? 2. 使用Python如何安全地截断字符串而不破坏UTF-8字符? 3. 在DBeaver中导入数据时如何设置自动截断超长字符串? 4. 如何编写SQL查询来找出表中超过指定长度的记录? </think> 这个错误 `SQL 错误 [1406] [22001]: Data truncation: Data too long for column 'test_item1'` 表示你尝试插入的数据长度超过了 `test_item1` 字段定义的最大长度。以下是详细的解决方案: ### 问题分析 1. **列定义过短**:`test_item1` 列定义为 VARCHAR(50),但第14行的数据长度超过50个字符 2. **数据异常**:某些测试项名称可能特别长或包含额外信息 3. **表结构设计不合理**:测试项名称长度不一致,但使用了固定长度的字段 ### 解决方案 #### 方法1:修改表结构(推荐) 扩展相关字段的长度: ```sql -- 查看当前字段定义 SHOW COLUMNS FROM adapter_defect LIKE 'test_item1'; -- 扩展所有测试项字段长度 ALTER TABLE adapter_defect MODIFY test_item1 VARCHAR(255), MODIFY test_item2 VARCHAR(255), MODIFY test_item3 VARCHAR(255); -- 扩展值字段长度(如果也需要) ALTER TABLE adapter_defect MODIFY value1 VARCHAR(255), MODIFY value2 VARCHAR(255), MODIFY value3 VARCHAR(255); ``` #### 方法2:数据预处理(截断超长数据) 使用Python脚本处理CSV,确保数据长度不超过限制: ```python import pandas as pd # 读取CSV文件 df = pd.read_csv('defect_data.csv') # 定义各字段最大长度 MAX_LENGTHS = { 'test_item1': 50, # 或修改为实际需要的长度 'test_item2': 50, 'test_item3': 50, 'value1': 50, 'value2': 50, 'value3': 50 } # 截断超长字符串 def truncate_field(value, max_length): if isinstance(value, str) and len(value) > max_length: return value[:max_length-3] + '...' # 保留指示符 return value # 应用截断函数 for col, max_len in MAX_LENGTHS.items(): if col in df.columns: df[col] = df[col].apply(lambda x: truncate_field(x, max_len)) # 保存处理后的CSV df.to_csv('truncated_defect_data.csv', index=False) print(f"处理完成!共截断 {len(df)} 行数据。") ``` #### 方法3:动态处理导入错误(DBeaver) 在DBeaver导入向导中处理: 1. 在 **Mapping** 步骤 2. 定位到 `test_item1` 列 3. 在右侧属性面板中: - 设置 **Data type** 为 `VARCHAR` - 增加 **Length** 值(如 255) - 勾选 **Truncate strings** 选项 4. 导入完成后检查被截断的数据: ```sql SELECT test_item1, CHAR_LENGTH(test_item1) as length FROM adapter_defect WHERE CHAR_LENGTH(test_item1) = 50; -- 替换为实际长度限制 ``` ### 表结构优化建议(长期方案) ```sql -- 创建规范化的测试结果表 CREATE TABLE test_results ( id INT AUTO_INCREMENT PRIMARY KEY, defect_id INT NOT NULL, test_item VARCHAR(255) NOT NULL, value VARCHAR(255), FOREIGN KEY (defect_id) REFERENCES adapter_defect(id) ); -- 迁移数据 INSERT INTO test_results (defect_id, test_item, value) SELECT id, test_item1, value1 FROM adapter_defect WHERE test_item1 IS NOT NULL UNION ALL SELECT id, test_item2, value2 FROM adapter_defect WHERE test_item2 IS NOT NULL UNION ALL SELECT id, test_item3, value3 FROM adapter_defect WHERE test_item3 IS NOT NULL; -- 删除原表中的冗余列 ALTER TABLE adapter_defect DROP COLUMN test_item1, DROP COLUMN value1, DROP COLUMN test_item2, DROP COLUMN value2, DROP COLUMN test_item3, DROP COLUMN value3; ``` ### 完整导入流程 1. **预处理数据**: ```python # 使用pandas自动扩展过短字段 import pandas as pd df = pd.read_csv('defect_data.csv') # 自动扩展过短字段 for col in df.columns: if df[col].dtype == 'object': max_len = df[col].str.len().max() if max_len > 50: # 当前定义长度 print(f"字段 {col} 需要扩展: 最大长度 {max_len}") df.to_csv('preprocessed.csv', index=False) ``` 2. **修改表结构**: ```sql ALTER TABLE adapter_defect MODIFY test_item1 VARCHAR(255), MODIFY test_item2 VARCHAR(255), MODIFY test_item3 VARCHAR(255); ``` 3. **导入数据**: - 使用DBeaver导入预处理后的CSV - 或使用命令行导入: ```bash mysql -u username -p database_name < preprocessed.csv ``` ### 预防措施 1. **动态字段长度检查**: ```sql -- 创建插入前的长度检查触发器 DELIMITER // CREATE TRIGGER check_test_item_length BEFORE INSERT ON adapter_defect FOR EACH ROW BEGIN IF CHAR_LENGTH(NEW.test_item1) > 50 THEN SET NEW.test_item1 = CONCAT(LEFT(NEW.test_item1, 47), '...'); END IF; -- 为其他字段添加类似检查 END; // DELIMITER ; ``` 2. **应用层验证**: ```javascript // 前端示例:表单验证 document.getElementById('test_item_input').addEventListener('input', (e) => { if (e.target.value.length > 50) { alert('测试项名称不能超过50字符'); e.target.value = e.target.value.substring(0, 50); } }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值