字段定义 varchar2(20),插十个汉字报 ORA-12899 value too large for column,实际字符数只有 10。日志里能对上时间点,这种反而好排。

varchar2 默认按字节语义,UTF-8 下一个汉字占三字节,20 字节只放得下六个汉字。字符语义要显式写 char 或者改 NLS_LENGTH_SEMANTICS。这一点先确认清楚,后面就不用反复试。

SELECT * FROM nls_session_parameters WHERE parameter = 'NLS_LENGTH_SEMANTICS';
ALTER TABLE users MODIFY nickname VARCHAR2(20 CHAR);
SELECT lengthb(nickname), length(nickname) FROM users;

这次卡住的地方就在「ORA-12899」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。

把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。

处理上按这个顺序:建表时用 varchar2(20 char) 明确字符语义;存量表用 alter table modify 调整 注意有数据时的长度校验;连接层确认 NLS_LENGTH_SEMANTICS 的值;迁移脚本按字节估算最长值 留出余量。

结果对不对很好判断,十个汉字能正常插入 lengthb 和 length 的差值符合预期。

作者 9823189