如果我没错的话,你最好升级到Oracle 12。让我解释一下:
Oracle(包括11版本)对char/varchar列有严格的限制,最大只能存储4000个字节。即使把列声明为“varchar2(4000 CHAR)”,也无法突破这一限制。
如果你的数据库使用了多字节字符集,仍然会受到这一限制,因此只有在满足以下两个条件的情况下,你才能真正地存储4000个字符:
- in your charset there are characters that occupy only one byte
the string you want to store is made up only using the characters that are encoded to a single byte
For example: if your database character set is UTF8, the "A" character occupies one byte, but the "à" character needs two bytes:
| Bytes required |Bytes required | Bytes required
string | if database charset |if database charset | if database charset
| is ASCII |is UTF8 | is UTF16
--------- |-------------------------------------------------------------------
"A" | 1 byte | 1 bytes | 2 bytes
"à" | 1 byte | 2 bytes | 2 bytes
"àA" | 2 byte | 3 bytes | 4 bytes
在一个UTF8数据库内的VARCHAR2(4000 CHAR)列中,你可以存储由4000个“A”字符组成的字符串,但如果你使用了由4000个“à”字符组成的字符串,则会限制为2000个字符:在UTF8中,任何代码Unicode编号>= 128(即它不是ASCII字符)的字符都需要多个字节。在UTF16中,任何字符至少占用2个字节。
通过描述的症状(以及您的姓名),我认为您并没有使用单字节字符集……而且我也认为您使用的大多数字符至少需要两个字节,因此这里是实际限制为2000个字符的原因:您面临着4000个字节的硬限制。
我认为你唯一“简单”的解决方案是将数据库升级到Oracle 12,在那里可以将这个硬限制提高到32000字节(据我所知,它不是“开箱即用”的:您需要在数据库创建期间相应地设置它)。
如果你创建了一个带有提高的限制的Oracle 12数据库,你的varchar2(4000 CHAR)列将不再遇到硬限制。
还要记住,当你通常将一个列声明为VARCHAR2(4000)时,Oracle默认将其解释为VARCHAR2(4000 BYTE)。这个默认值可以通过在你的会话中执行以下命令来更改:
alter session set NLS_LENGTH_SEMANTICS='CHAR'
理论上,可以在实例级别上为整个数据库和所有会话设置,但是Oracle警告您不要这样做,因为系统会表现异常,因此请坚持在会话级别使用。
希望这可以帮到您。
P.S. 也许您还会发现这个提示有用:
在我的数据库中,我编写了一个“登录后”触发器,自动执行仅针对我的应用程序用户的alter session。
CREATE OR REPLACE TRIGGER TRG_MYAPP_AFTER_LOGON
AFTER LOGON on database
declare
function IsMyAppUser return boolean is
cnt number;
begin
if user = 'MYAPP' then
return true;
end if;
select count(*) into cnt
from my_app_users u
where u.usr_login=user
and ROWNUM=1;
return cnt>0;
end;
BEGIN
if IsMyAppUser then
execute immediate 'alter session set nls_length_semantics = ''CHAR''';
end if;
END TRG_QBF_AFTER_LOGON;