8

我在 oracle 中有一个带有BLOB列的表,它可以存储 XML,也可以XMLs压缩。这些是客户的要求,不能更改。表格将被创建,我必须阅读并使用BLOBs.

我进行了研究,任何不清楚的解决方案都很清楚或对我有用。

我面临的问题是普通INSERT XML数据比用作数据库管理器2000 bytes更大。我收到消息:utl_raw.cast_to_rawDBeaver

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

问题

  1. 我研究过,UTL_RAW不能超过2000 bytes
  2. 似乎Oracle中的4000 bytesfor还有另一个限制BLOBs

我能为这些情况做些什么?

4

2 回答 2

6

首先,您需要了解 LOB 是什么。它们是“大数据”,可能比 Oracle 中的任何其他数据类型都大。它们就像文件系统上的常规文件。为了写入文件系统上的文件,您必须

  1. 打开文件进行写入
  2. 如果您想从头开始填充文件,请截断文件
  3. 循环读取源数据
  4. 在同一个循环中将您的数据块逐个附加到文件中
  5. 关闭文件

LOB 或多或少也是如此。在您的表中,LOB (CLOB/BLOB/NCLOB) 列只是指向磁盘存储上保存实际数据的另一个位置的指针/引用。在标准的 Oracle 术语中,指针称为“LOB 定位器”。你需要

  1. 打开/初始化 LOB 定位器
  2. 截断 LOB 内容,如果您希望从头开始填充它
  3. 将您的数据块逐个附加到循环中的 LOB 内容
  4. 关闭 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;

一个解释:

  1. 初始化 LOB 定位器 =insert into blob_test values(1,empty_blob()) returning b into v_b;
  2. 打开 LOB 定位器进行写入 =dbms_lob.open(v_b,dbms_lob.lob_readwrite);
  3. 截断 LOB 内容,如果您希望从头开始填充它...这是通过empty_blob()insert.
  4. 将数据块附加到循环中的 LOB 内容中,一个接一个 = 这里只有一次迭代dbms_lob.writeappend(),仅将单个aaa长度块utl_raw.length(aaa)(最大 32767)附加到 LOBv_b
  5. 关闭 LOB 定位器 =dbms_lob.close(LOB_LOC=>v_b);
于 2015-10-16T12:56:40.970 回答
-1

函数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;
于 2015-11-06T14:03:59.890 回答