插入大于 2000 或 4000 字节的 BLOB 测试字符串
Insert BLOB test string bigger than 2000 or 4000 bytes
我在 oracle 中有一个带有 BLOB
列的 table,它可以存储 XML 以及 XMLs
压缩文件。这些是客户的要求,无法更改。 table 将被创建,我必须阅读和处理 BLOBs
中的一些信息。
我已经研究过,任何不清楚的解决方案都很清楚或对我有用。
我面临的问题是 INSERT
XML
大于 2000 bytes
且 utl_raw.cast_to_raw
的纯数据使用 DBeaver
作为数据库管理器。我收到消息:
SQL Error [6502] [65000]: ORA-06502: PL/SQL: numeric or value error: raw variable length too long ORA-06512: at "SYS.UTL_RAW", line 224
java.sql.SQLException: ORA-06502: PL/SQL: numeric or value error: raw variable length too long
ORA-06512: at "SYS.UTL_RAW", line 224
问题
- 我研究过
UTL_RAW
不能超过2000 bytes
- 看来Oracle
中BLOBs
的4000 bytes
还有一个限制
对于这些情况我能做些什么?
首先,您需要了解什么是 LOB。它们 "large data",可能比 Oracle 中的任何其他数据类型都大。它们就像文件系统上的常规文件。为了写入文件系统上的文件,您必须
- 打开文件进行写入
- 如果您想从头开始填充文件,请截断文件
- 循环读取源数据块
- 在同一个循环中将数据块一个一个地附加到文件
- 关闭文件
LOB 的情况大致相同。在您的 table 中,一个 LOB (CLOB/BLOB/NCLOB) 列只是一个 pointer/reference 到您磁盘存储上保存实际数据的另一个地方。在标准的 Oracle 术语中,指针称为 "LOB locator"。你需要
- open/initialize LOB 定位器
- 截断 LOB 内容,如果您想从头开始填充它
- 将您的数据块逐个循环附加到 LOB 内容
- 关闭 LOB 定位器
在 PL/SQL 中可能如下所示:
-- create table blob_test(id number, b blob);
declare
v_b blob;
aaa raw(32767);
longLine varchar2(32767);
begin
longLine := LPAD('aaaa', 32767,'x');
aaa := UTL_RAW.CAST_TO_RAW(longLine);
insert into blob_test values(1,empty_blob()) returning b into v_b;
dbms_lob.open(v_b,dbms_lob.lob_readwrite);
dbms_lob.writeappend(v_b,UTL_RAW.LENGTH (aaa) ,aaa);
dbms_lob.close(LOB_LOC=>v_b);
commit;
end;
一个解释:
- 初始化 LOB 定位器 =
insert into blob_test values(1,empty_blob()) returning b into v_b;
- 打开用于写入的 LOB 定位器 =
dbms_lob.open(v_b,dbms_lob.lob_readwrite);
- 截断 LOB 内容,如果您希望从头开始填充它...这是由
insert
中的 empty_blob()
调用完成的。
- 在循环中将您的数据块附加到 LOB 内容,一个接一个 = 这里只有
dbms_lob.writeappend()
的一次迭代,仅附加一个长度 aaa
的块 utl_raw.length(aaa)
(最大 32767) 到 LOB v_b
- 关闭 LOB 定位器 =
dbms_lob.close(LOB_LOC=>v_b);
函数utl_raw.cast_to_raw
将数据类型为 VARCHAR2 的值转换为原始值。显然,字符串的长度受限于 VARCHAR2 数据类型。如果您需要将大文本数据转换为 LOB,您可以使用 DBMS_LOB.CONVERTTOBLOB 过程。
例如,您可以创建将大字符串值(clob 作为输入)转换为 blob 的函数。像这样的 -
create or replace function ClobToBlob (p_clob in clob) return blob is
l_dest_offset integer := 1;
l_source_offset integer := 1;
p_csid number := 0;
l_lang_context integer := DBMS_LOB.DEFAULT_LANG_CTX;
l_warning integer := DBMS_LOB.WARN_INCONVERTIBLE_CHAR;
l_tmpblob blob;
begin
dbms_lob.createtemporary(l_tmpblob, true);
DBMS_LOB.CONVERTTOBLOB
(
l_tmpblob,
p_clob,
DBMS_LOB.LOBMAXSIZE,
l_dest_offset,
l_source_offset,
p_csid,
l_lang_context,
l_warning
);
return l_tmpblob;
end;
我在 oracle 中有一个带有 BLOB
列的 table,它可以存储 XML 以及 XMLs
压缩文件。这些是客户的要求,无法更改。 table 将被创建,我必须阅读和处理 BLOBs
中的一些信息。
我已经研究过,任何不清楚的解决方案都很清楚或对我有用。
我面临的问题是 INSERT
XML
大于 2000 bytes
且 utl_raw.cast_to_raw
的纯数据使用 DBeaver
作为数据库管理器。我收到消息:
SQL Error [6502] [65000]: ORA-06502: PL/SQL: numeric or value error: raw variable length too long ORA-06512: at "SYS.UTL_RAW", line 224
java.sql.SQLException: ORA-06502: PL/SQL: numeric or value error: raw variable length too long
ORA-06512: at "SYS.UTL_RAW", line 224
问题
- 我研究过
UTL_RAW
不能超过2000 bytes
- 看来Oracle 中
BLOBs
的4000 bytes
还有一个限制
对于这些情况我能做些什么?
首先,您需要了解什么是 LOB。它们 "large data",可能比 Oracle 中的任何其他数据类型都大。它们就像文件系统上的常规文件。为了写入文件系统上的文件,您必须
- 打开文件进行写入
- 如果您想从头开始填充文件,请截断文件
- 循环读取源数据块
- 在同一个循环中将数据块一个一个地附加到文件
- 关闭文件
LOB 的情况大致相同。在您的 table 中,一个 LOB (CLOB/BLOB/NCLOB) 列只是一个 pointer/reference 到您磁盘存储上保存实际数据的另一个地方。在标准的 Oracle 术语中,指针称为 "LOB locator"。你需要
- open/initialize LOB 定位器
- 截断 LOB 内容,如果您想从头开始填充它
- 将您的数据块逐个循环附加到 LOB 内容
- 关闭 LOB 定位器
在 PL/SQL 中可能如下所示:
-- create table blob_test(id number, b blob);
declare
v_b blob;
aaa raw(32767);
longLine varchar2(32767);
begin
longLine := LPAD('aaaa', 32767,'x');
aaa := UTL_RAW.CAST_TO_RAW(longLine);
insert into blob_test values(1,empty_blob()) returning b into v_b;
dbms_lob.open(v_b,dbms_lob.lob_readwrite);
dbms_lob.writeappend(v_b,UTL_RAW.LENGTH (aaa) ,aaa);
dbms_lob.close(LOB_LOC=>v_b);
commit;
end;
一个解释:
- 初始化 LOB 定位器 =
insert into blob_test values(1,empty_blob()) returning b into v_b;
- 打开用于写入的 LOB 定位器 =
dbms_lob.open(v_b,dbms_lob.lob_readwrite);
- 截断 LOB 内容,如果您希望从头开始填充它...这是由
insert
中的empty_blob()
调用完成的。 - 在循环中将您的数据块附加到 LOB 内容,一个接一个 = 这里只有
dbms_lob.writeappend()
的一次迭代,仅附加一个长度aaa
的块utl_raw.length(aaa)
(最大 32767) 到 LOBv_b
- 关闭 LOB 定位器 =
dbms_lob.close(LOB_LOC=>v_b);
函数utl_raw.cast_to_raw
将数据类型为 VARCHAR2 的值转换为原始值。显然,字符串的长度受限于 VARCHAR2 数据类型。如果您需要将大文本数据转换为 LOB,您可以使用 DBMS_LOB.CONVERTTOBLOB 过程。
例如,您可以创建将大字符串值(clob 作为输入)转换为 blob 的函数。像这样的 -
create or replace function ClobToBlob (p_clob in clob) return blob is
l_dest_offset integer := 1;
l_source_offset integer := 1;
p_csid number := 0;
l_lang_context integer := DBMS_LOB.DEFAULT_LANG_CTX;
l_warning integer := DBMS_LOB.WARN_INCONVERTIBLE_CHAR;
l_tmpblob blob;
begin
dbms_lob.createtemporary(l_tmpblob, true);
DBMS_LOB.CONVERTTOBLOB
(
l_tmpblob,
p_clob,
DBMS_LOB.LOBMAXSIZE,
l_dest_offset,
l_source_offset,
p_csid,
l_lang_context,
l_warning
);
return l_tmpblob;
end;