请教:为什么我的ORACLE无法插入超过一定数量的字符串信息(怪)?

最近碰到一个关于JDBC的怪问题,我们用STRUTS+TORQUE做项目,前台显示用VELOCITY,数据库是ORACLE的,但是在做数据录入时(通过BS的界面),总是报错,说“数据大小超出了此类型的最大值”,但在数据库中该字段是VARCHAR2,4000,而在表单中该字段所对应的输入框(TEXTAREA),我只能输入最多1322字节的内容,一旦超过哪怕一个字节,数据就无法录入。

和同事讨论来去感觉是JDBC驱动的问题。不知道你们是否遇到过类似的问题?有什么好的解决办法吗?或者是我们哪里有错误?还请不吝赐教。

相关信息:
使用CLASS12.JAR为JDBC驱动ORACLE8i,该提交的表单共有10个字段。另有2个HIDDEN字段。

你这个1322字节长度是在什么地方测到的?
你用什么方法得到1322字节,String.length()吗?他显示的可是字符数。
你输入的都是汉字吗?还是什么都有?

oracle字符集的问题,在你选择的字符集里面,显然一个汉字占3个字节
当然,汉字双字节,你也是要考虑的

回lizh:
我的信息输入表单有多个Input field,比如主题,关键字什么的,出现问题的是在输入内容的Textarea。在ActionForm中是定义为String的,但在表单中我输入的内容(中英文都有,中文为主)最大长度是1322个字符。此数据是将允许输入的内容COPY到Ultraedit中用Byte Count得到的,它是将汉字作为双字节进行统计的。一旦超过信息录入就失败。

回crogers:
关于oracle字符集的问题,恕我才疏,不是很理解,烦请详述。

谢谢你们的回复!

要获得输入的长度,建议你最好在你的action中获得。
至于数据库字符集的问题,简单的测试方法是你可以设置一个varchar2(2)的字段看看能不能插入汉字。(varchar2最多也只能插入2000个汉字)
如果你想多插入一些汉字又不想使用lob,我向你推荐使用nvarchar2(4000)
nvarchar2 类型是按照字符存放的(可存放4000个汉字)。不受字符集设置的影响。

关于字符集的问题这里有一篇文章:
http://www.vchelp.net/cndevforum/subject_view.asp?subject_id=59339&forum_id=72

Oracle有两种JDBC连接方式,用另一种就会OK.

谢谢几位热心朋友的帮助。今天工作忙了点,到现在才回复。

中午时我照lizh的意见做了个测试,发现字段设置为VARCHAR2(4000),最多只允许输入1334个字符(666个汉字),也就是说我们这边ORACLE的字符集里,1个字符是作为3个字节来处理的。

但当我将字段设置为VARCHAR2(2)时,系统允许我输入2个字符或者1个汉字。如此“偏心”,真是气死我了:)

后来我又照lizh的建议把VARCHAR2改成NVARCHAR2,SQL又给我仍EXCEPTION了:character set mismatch. 因为面向数据库的相关对象都是由TORQUE自动生成的,我也糊涂了到哪里去改这个character set.于是又去检查了一下Torque生成类的模板,发现在ORACLE数据库相关的字段定义中,竟然找不到关于NVARCHAR2的定义。只有有VARCHAR2,LONGVARCHAR2(=VARCHAR2(2000)),还有BLOB。

在另一个论坛,有个朋友的回复比较经典:
“这是很经典的OracleJDBC问题。一般直接用ps.setString()设置字符串数据时,Oracle的JDBC驱动会将中文转换为2字节或3字节,不固定的,因此经常会越界。如果你改为ps.setCharacterStream()就是固定的每个中文两个字节 ”。

可问题是,TORQUE里面似乎没给我机会来写什么PrepareStatement,除非改源码。问题看起来似乎更复杂了。

兄弟,你查了你的oracle是使用什么字符集没有?... ...~~

查过了,我用SQL*PLUS查的,是 ZHS16GBK 。

如果是ZHS的话,那就真不知道了,~

在oracle中varchar2和Nvarchar2是两个不同的字符集


select SYS.V_$NLS_PARAMETERS.PARAMETER,
SYS.V_$NLS_PARAMETERS.VALUE
from SYS.V_$NLS_PARAMETERS

NLS_CHARACTERSET是varchar2的字符集
NLS_NCHAR_CHARACTERSET是Nvarchar2的字符集
你自己看一下吧

在ORACLE中,varchar2(XXX)的XXX设置的很大不是很有意义,除非你用plsql,因为ORACLE中的binding variable的长度有限制,好像就是2000,就是666个汉字,不知道怎么改这个binding variable,你可以去问问别的oracle的高手。
如果不改这个,在jdbc中的长字符就只能是2000个,用GB2312的话,就是666个汉字,所以长字符串干脆就用blob或是clob,性能还是不错的,用流模式总比都搞到内存里要好。

是的,在网上查了很多资料发现ORACLE的JDBC对长字符的支持就只到2000。看来只能用BLOB了。我用的是STRUTS,在使用流模式做GET或SET时有什么需要注意的吗?而且在用TORQUE实现数据库操作时与通常情况有什么不同吗?

BTW,我查过数据库的字符集定义了,两个CHARACTER SET都是一样的 ZHS16GBK 。

> 是的,在网上查了很多资料发现ORACLE的JDBC对长字符的支持
> 椭坏?000。看来只能用BLOB了。我用的是STRUTS,在使用流?> 式做GET或SET时有什么需要注意的吗?而且在用TORQUE实现数

应该和STRUTS没什么关系,传递给到STRUTS layer的对象的属性就是String,blob的处理限制在TORQUE里面

TORQUE没用过,查查文档吧