我目前正在使用 Oracle 11g。根据我的要求,我需要将前 4000 个(最大限制)字符存储到我的变量(在触发器中使用)。
为此,我正在使用 VarName = SUBSTR 函数(VarName, 1, 4000),但它似乎没有存储任何内容(我正在传递 '111...'(要存储的 4096 个字符),我想从中存储 (' 111...') 仅限前 4000 个字符)。
它适用于 4 个字符,但不适用于最大限制。我尝试将长度设为 3999、3000,但没有任何效果。
请仔细研究一下,并为此建议我一些解决方案。
(*注意:我无法将变量类型从 varchar 更改为 clob,因为此列已经拥有数百万个遗留数据。)
*修改:我尝试使用 Substr 长度 2048 ,是工作 但一旦我是 为 substr 提供 2049 个字符,它再次变为空 .
但在 数据类型字段值定义为 VARCHAR2(4000 CHAR) .
最佳答案
如果我是对的,你最好升级到oracle 12。让我解释一下:
Oracle(包括版本 11)对 char/varchar 列的硬限制为 4000 BYTES,并且无法通过简单地将列声明为“varchar2(4000 CHAR)”来克服此限制 .
如果您的数据库使用多字节字符集,则该限制仍然存在,因此只有满足以下两个条件,您才能实际存储 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 number >= 128(即:它不是 ASCII 字符)的字符都需要多个字节。在 UTF16 中,任何字符至少占用 2 个字节。
通过查看您所描述的症状(以及您的名字),我认为您没有使用单字节字符集……而且我还认为您使用的大多数字符至少需要两个字节,所以这里是2000 个字符实际限制的原因:您面临 4000 个字节的硬限制。
我认为对你来说唯一“简单”的解决方案是将数据库升级到 oracle 12,在那里这个硬限制可以提高到 32000 字节(AFAIK 它不会“开箱即用”:你需要设置它相应地,在数据库创建期间)。
如果您使用提高的限制创建 oracle 12 数据库,您的 varchar2(4000 CHAR) 列将不再满足硬限制。
还要记住,当您通常将列声明为 VARCHAR2(4000) 时,oracle 默认将其解释为 VARCHAR2(4000 BYTE)。这个默认值可以通过在你的 session 中执行来改变:
alter session set NLS_LENGTH_SEMANTICS='CHAR'
TEORICALLY 可以在整个数据库和所有 session 的实例级别设置它,但是 oracle 警告您不要这样做,因为系统会行为不端,因此请坚持在 session 级别使用它。
希望这可以帮助。
附言也许你会发现这个提示也很有用:
在我的数据库中,我编写了一个“登录后”触发器,该触发器自动执行该更改 session 仅适用于我的应用程序的用户
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;
关于oracle - 修复 Oracle 4000 字符中允许的最大长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52040355/