今天在某个金融客户群看到客户咨询“在Oceanbase数据库中oracle租户,更新clob字段超过4000字符怎么弄?”,我们知道clob可以存储像Varchar类型的字符,如果不使用dbms_lob包处理,可以简单当varchar处理,而varchar的长度又有上限,在oracle和oceanbase中这个问题答案是不同的,下面我来演示。
Oracle
SQL> select length(lpad('a',4000,'x')) from dual; LENGTH(LPAD('A',4000,'X')) -------------------------- 4000 SQL> select length(lpad('a',8000,'x')) from dual; LENGTH(LPAD('A',8000,'X')) -------------------------- 4000 SQL> @pd max_string Show all parameters and session values from x$ksppi/x$ksppcv... NUM N_HEX NAME VALUE DESCRIPTION ---------- ---------- -------------------------------------------------------- ------------------------------ --------------------------------------------------------------------------------------------------- 3472 D90 _max_string_size_bypass 0 controls error checking for the max_string_size parameter 3473 D91 _qkslvc_extended_bind_sz 1 controls error checking for the max_string_size parameter 4226 1082 max_string_size STANDARD controls maximum size of VARCHAR2, NVARCHAR2, and RAW types in SQL SQL> SQL> select to_clob(lpad('a',8000,'x')||lpad('a',8000,'x')) from dual; ERROR: ORA-01489: result of string concatenation is too long no rows selected SQL> select length(lpad('a',4000,'x')) from dual; LENGTH(LPAD('A',4000,'X')) -------------------------- 4000 SQL> select length(lpad('a',8000,'x')) from dual; LENGTH(LPAD('A',8000,'X')) -------------------------- 4000 SQL> @pd max_string Show all parameters and session values from x$ksppi/x$ksppcv... NUM N_HEX NAME VALUE DESCRIPTION ---------- ---------- -------------------------------------------------------- ------------------------------ --------------------------------------------------------------------------------------------------- 3472 D90 _max_string_size_bypass 0 controls error checking for the max_string_size parameter 3473 D91 _qkslvc_extended_bind_sz 1 controls error checking for the max_string_size parameter 4226 1082 max_string_size STANDARD controls maximum size of VARCHAR2, NVARCHAR2, and RAW types in SQL SQL> SQL> select to_clob(lpad('a',8000,'x')||lpad('a',8000,'x')) from dual; ERROR: ORA-01489: result of string concatenation is too long no rows selected SQL> ho oerr ora 1489 01489, 00000, "result of string concatenation is too long" // *Cause: String concatenation result is more than the maximum size. // *Action: Make sure that the result is less than the maximum size. SQL> @pvalid max_string_size Display valid values for multioption parameters matching "max_string_size"... PAR# PARAMETER ORD VALUE DEFAULT ------ -------------------------------------------------- ---------- ------------------------------ ------- 4226 max_string_size 1 STANDARD DEFAULT max_string_size 2 EXTENDED
Note:
在oracle 的标准字符长度下,varchar上限是4000(当然我们在19c中max_string_size改为EXTENDED,来提升到32k的上限)。 另外看到to_clob也是varchar的上限4000, 如果在oracle中处理超4000,需要使用dbms_lob包。
Oceanbase
在去年我整理过一篇《Oceanbase BLOB/CLOB LO(Large Object)注意事项》介绍过LOB对象的上限和oracle的不同,这里不在复述,仅测试to_clob.
OB v4.4
CLOB
用于存储单字节和多字节字符数据。CLOB
支持固定宽度和可变宽度字符集,且都使用数据库字符集。CLOB
可存储字节的长度上限是 536870910 字节,字符集与租户字符集一致。VARCHAR2
类型字段的最大长度为 32767 字节。如果需要保存的字段长度大于 32767 字节,可以使用CLOB
类型。
obclient(SYS@orcl)[SYS]> select * from v$version; +---------------------------------------------------------------------------------------------------------------+--------+ | BANNER | CON_ID | +---------------------------------------------------------------------------------------------------------------+--------+ | OceanBase 4.2.5.3 (r103000142025033110-f5b88cd987f23383677f2eb53cf76ed38a48979b) (Built Mar 31 2025 11:04:29) | 0 | +---------------------------------------------------------------------------------------------------------------+--------+ 1 row in set (0.008 sec) -- test anbob.com obclient(SYS@orcl)[SYS]> select length(lpad('a',4000,'x')) from dual; +----------------------------+ | LENGTH(LPAD('A',4000,'X')) | +----------------------------+ | 4000 | +----------------------------+ 1 row in set (0.004 sec) obclient(SYS@orcl)[SYS]> select length(lpad('a',8000,'x')) from dual; +----------------------------+ | LENGTH(LPAD('A',8000,'X')) | +----------------------------+ | 8000 | +----------------------------+ 1 row in set (0.002 sec) obclient(SYS@orcl)[SYS]> select length(lpad('a',32767,'x')) from dual; +-----------------------------+ | LENGTH(LPAD('A',32767,'X')) | +-----------------------------+ | 32767 | +-----------------------------+ 1 row in set (0.002 sec) obclient(SYS@orcl)[SYS]> select length(lpad('a',32768,'x')) from dual; +-----------------------------+ | LENGTH(LPAD('A',32768,'X')) | +-----------------------------+ | 32767 | +-----------------------------+ 1 row in set (0.002 sec) obclient(SYS@orcl)[SYS]> create table tclob(t clob); Query OK, 0 rows affected (3.727 sec) obclient(SYS@orcl)[SYS]> select * from v$version; +---------------------------------------------------------------------------------------------------------------+--------+ | BANNER | CON_ID | +---------------------------------------------------------------------------------------------------------------+--------+ | OceanBase 4.2.5.3 (r103000142025033110-f5b88cd987f23383677f2eb53cf76ed38a48979b) (Built Mar 31 2025 11:04:29) | 0 | +---------------------------------------------------------------------------------------------------------------+--------+ 1 row in set (0.008 sec) obclient(SYS@orcl)[SYS]> select length(lpad('a',4000,'x')) from dual; +----------------------------+ | LENGTH(LPAD('A',4000,'X')) | +----------------------------+ | 4000 | +----------------------------+ 1 row in set (0.004 sec) obclient(SYS@orcl)[SYS]> select length(lpad('a',8000,'x')) from dual; +----------------------------+ | LENGTH(LPAD('A',8000,'X')) | +----------------------------+ | 8000 | +----------------------------+ 1 row in set (0.002 sec) obclient(SYS@orcl)[SYS]> select length(lpad('a',32767,'x')) from dual; +-----------------------------+ | LENGTH(LPAD('A',32767,'X')) | +-----------------------------+ | 32767 | +-----------------------------+ 1 row in set (0.002 sec) obclient(SYS@orcl)[SYS]> select length(lpad('a',32768,'x')) from dual; +-----------------------------+ | LENGTH(LPAD('A',32768,'X')) | +-----------------------------+ | 32767 | +-----------------------------+ 1 row in set (0.002 sec) obclient(SYS@orcl)[SYS]> create table tclob(t clob); Query OK, 0 rows affected (3.727 sec) obclient(SYS@orcl)[SYS]> insert into tclob values(lpad('a',32767,'x')); Query OK, 1 row affected (0.170 sec) obclient(SYS@orcl)[SYS]> insert into tclob values(to_clob(lpad('a',32767,'x'))); Query OK, 1 row affected (0.005 sec) obclient(SYS@orcl)[SYS]> select 'x'||'y' from dual; +----------+ | 'X'||'Y' | +----------+ | xy | +----------+ 1 row in set (0.004 sec) obclient(SYS@orcl)[SYS]> insert into tclob values(lpad('a',32767,'x')||lpad('a',32767,'x')); ORA-01489: result of string concatenation is too long obclient(SYS@orcl)[SYS]> insert into tclob values(to_clob(lpad('a',32767,'x')||lpad('a',32767,'x'))); ORA-01489: result of string concatenation is too long obclient(SYS@orcl)[SYS]> select length(t) from tclob; +-----------+ | LENGTH(T) | +-----------+ | 32767 | | 32767 | +-----------+ 2 rows in set (0.049 sec)
Note:
在oceanbase oracle租户中varchar的最大长度是32767(类似oracle 的 max_string_size=EXTENDED), 所以to_clob的最大长度是32767. 如果写入更大的值就和oracle数据库中的一样,要求使用dbms_lob package. 如下
obclient(SYS@orcl)[SYS]> DECLARE
-> large_text CLOB;
-> BEGIN
-> -- 创建LOB对象
-> large_text := NULL;
-> DBMS_LOB.createtemporary(large_text, TRUE);
->
-> -- 追加数据
-> DBMS_LOB.append(large_text, lpad('a',32768,'x'));
-> DBMS_LOB.append(large_text, lpad('a',32768,'x'));
-> DBMS_LOB.append(large_text, lpad('a',32768,'x'));
->
-> -- 查看结果
-> DBMS_OUTPUT.put_line(DBMS_LOB.getlength(large_text));
-> insert into tclob values(large_text);
->
-> -- 关闭LOB对象
-> DBMS_LOB.freetemporary(large_text);
-> END;
-> /
Query OK, 1 row affected (0.227 sec)
98301
obclient(SYS@orcl)[SYS]> select length(t) from tclob;
+-----------+
| LENGTH(T) |
+-----------+
| 32767 |
| 32767 |
| 98301 |
+-----------+
3 rows in set (0.005 sec)
小结
在oceanbase数据库中使用to_clob的最大字符也是varchar的长度上限32767, 而oracle数据库中如果没有修改 ax_string_size=EXTENDED时,to_clob最大长度是4000.
— over