如果我是对的,你最好升级到 oracle 12。让我解释一下:
Oracle(包括最高版本 11)对于 char/varchar 列的硬限制为 4000 BYTES,并且不能通过简单地将列声明为“varchar2( 4000 个字符)”.
如果您的数据库使用多字节字符集,则该限制仍然存在,因此只有满足这两个条件,您才能实际存储 4000 个字符:
- 在你的字符集中有只占一个字节的字符
-
您要存储的字符串仅由编码为单个字节的字符组成
例如:如果你的数据库字符集是UTF8,“A”字符占用一个字节,而“à”字符占用两个字节:
| 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
所以在 VARCHAR2(4000 CHAR) 列中,在 UTF8 数据库中,您将能够存储由 4000 个“A”字符组成的字符串,但如果您使用 4000 个“à”字符,它将被限制为 2000 个字符:在 UTF8 中,任何代码 unicode 编号 >= 128(即:它不是 ASCII 字符)的字符都需要多个字节。在 UTF16 中 any 字符至少占用 2 个字节。
通过查看您所描述的症状(以及您的姓名),我认为您没有使用单字节字符集...而且我还认为您使用的大多数字符至少需要两个字节,所以这是 2000 个字符实际限制的原因:您面临 4000 个字节的硬限制。
我认为对您来说唯一“简单”的解决方案是将数据库升级到 oracle 12,其中这个硬限制可以提高到 32000 字节(AFAIK 它不会“开箱即用”:您需要在数据库创建期间进行相应的设置)。
如果您使用提高的限制创建 oracle 12 数据库,您的 varchar2(4000 CHAR) 列将不再满足硬限制。
还请记住,当您通常将列声明为 VARCHAR2(4000) 时,oracle 默认将其解释为 VARCHAR2(4000 BYTE)。这个默认值可以通过在你的会话中执行来改变:
alter session set NLS_LENGTH_SEMANTICS='CHAR'
它可以在实例级别为整个数据库和所有会话设置,但是 oracle 警告您不要这样做,因为系统会出现异常,所以请坚持在会话级别使用它。
希望这会有所帮助。
附:也许你会发现这个提示也很有用:
在我的数据库中,我编写了一个“登录后”触发器,它会自动执行,只为我的应用程序的用户更改会话
CREATE OR REPLACE TRIGGER TRG_MYAPP_AFTER_LOGON
AFTER LOGON on database
declare
function IsMyAppUser return boolean is
cnt number;
begin
-- if the user is the owner of the schema, all its commands are expected
-- to use the "char" length semantics
if user = 'MYAPP' then
return true;
end if;
--- this is specific to my app: I have a table that lists the login names
--- of the users who have been created only with the purpose of using the app
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;