背景
在一个Flask + Oracle项目中,使用第三方库cx_oracle
在更新表时突然出现了报错:
1 | cx_Oracle.DatabaseError: ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值 |
表结构如下:
1 | -- Create table |
排查过程
先根据错误号,看下说明,可能原因有如下三种。
1、插入到字符串长度大于4000字节。
2、插入到表中的记录的某个字段数据的实际长度大于2000个字节(如果是UTF-8,则是1333个字节);或者是插入的记录中有两个或两个以上长度大于2000字节的字符串。
3、数据库与客户端的JDBC驱动不匹配。
检查字符串长度
考虑可能是
ip
字段过长,打印一下长度:1
2len(s)
3653虽然比较长,但是还是在表字段定义的长度4000范围之内的。
尝试直接连接数据库操作:
1
update FW_SRC_POOLS set ip = 'xxxx' where id = 'XXX'
发现也是执行成功的。
检查字符串编码类型
的确是
unicode
类型,那么我们通过str()
转换成str
类型试下,果然就成功了。
结论
不同类型的字符编码在oracle中占据的长度是不同的,在python2环境下,使用str
类型要比unicode
类型节省空间,但python3中默认都是unicode
,应该就比较麻烦一点。不过这也仅仅是比较偷懒的做法。
再看下oracle官网的说明,还是建议把字段类型换成CLOB
,可以一劳永逸。
The Oracle docs note this on the ORA-01461 error:
ORA-01461 can bind a LONG value only for insert into a LONG column
Cause: An attempt was made to insert a value from a LONG datatype into another datatype. This is not allowed.
Action: Do not try to insert LONG datatypes into other types of columns.
Answer: The LONG and LONG RAW datatypes have been deprecated and the easiest solution to the ORA-01461 error is to change the column datatype to as CLOB.
http://www.dba-oracle.com/t_ora_01461_can_bind_a_long_value_only_for_insert_into_a_long_column.htm