我当前正在使用Oracle 11g。根据我的要求,我需要将前4000个(最大限制)字符存储到变量(用于触发器)中。
为此,我正在使用VarName = SUBSTR函数(VarName,1,4000),但似乎没有存储任何内容(我要传递“ 111 ...”(要存储4096个字符))只能存储(“ 111 ...”)前4000个字符)。
它适用于4个字符,但不适用于最大限制。我尝试使用3999,3000的长度,但对我没有任何帮助。
请仔细研究一下,并为我提出一些解决方案。
(**:由于该列已具有数百万的旧数据,因此我无法将变量类型从varchar更改为clob。)
*修改:我尝试使用Substr长度2048 ,它是有效的,但是一旦我提供2049个字符进行替换,它又再次变为空。 但是在数据类型中,字段值定义为VARCHAR2(4000 CHAR)。
答案 0 :(得分:2)
如果我是对的,则最好升级到oracle12。让我解释一下:
Oracle(包括最高11版)对char / varchar列的HARD限制为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
因此,在UTF8数据库的VARCHAR2(4000 CHAR)列中,您将能够存储由4000个“ A”字符组成的字符串,但是如果您使用4000个“à”字符,则该字符串将被限制为2000个字符:在UTF8中,其代码Unicode编号> = 128(即,它不是ASCII字符)的任何字符都需要多个字节。在UTF16中,任何字符至少占用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'
可以在整个数据库和所有会话的实例级别上设置 TEORICALLY,但
希望这会有所帮助。
P.S。也许您会发现以下提示也很有用:
在数据库中,我编写了一个“登录后”触发器,该触发器自动执行,仅更改应用程序用户的会话
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;
答案 1 :(得分:0)
RPAD
或LPAD
:我可以这样获得4000个字符的单元格:
select rpad('x',3999, '-'), v.*
from v$version v
where rownum=1
给予
|x------[3999 times] | Oracle Database 11g Release 11.2.0.4.0 - 64bit dev|