插入大于 2000 或 4000 字节的 BLOB 测试字符串

Posted

技术标签:

【中文标题】插入大于 2000 或 4000 字节的 BLOB 测试字符串【英文标题】:Insert BLOB test string bigger than 2000 or 4000 bytes 【发布时间】:2016-01-14 23:28:18 【问题描述】:

我在 oracle 中有一个带有 BLOB 列的表,它可以存储 XML 以及 XMLs 压缩。这些是客户的要求,不能更改。这些表将被创建,我必须阅读和处理BLOBs 中的一些信息。

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

我面临的问题是 INSERT XML 普通数据大于 2000 bytesutl_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 似乎4000 bytes 在Oracle 中对BLOBs 有另一个限制

我可以为这些情况做些什么?

【问题讨论】:

你想做什么?将 zip 文件加载到 blob 列中? 感谢您的关注。我面临的问题是使用 utl_raw.cast_to_raw 插入大于 2000 字节的 XML 纯数据 你用什么插入数据。 SQPLUS 还是 java 应用? 我使用 DBeaver,但我敢打赌 SQLPlus 和其他人也会遇到问题。 如果我理解,您正在尝试使用常规 SQL 插入 zip-ed xml 文档?正在做类似的事情insert into table values(utl_file.UTL_RAW.CAST_TO_RAW('.....') 【参考方案1】:

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

    打开文件进行写入 如果您希望从头开始填充文件,请截断文件 在循环中分块读取源数据 在同一个循环中将您的数据块逐个添加到文件中 关闭文件

对于 LOB 来说,情况大致相同。在您的表中,LOB (CLOB/BLOB/NCLOB) 列只是指向磁盘存储上保存实际数据的另一个位置的指针/引用。在标准的 Oracle 术语中,指针称为“LOB 定位器”。你需要

    打开/初始化 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 @ 987654331@ 关闭 LOB 定位器 = dbms_lob.close(LOB_LOC=>v_b);

【讨论】:

我看不懂,也不知道应该怎么用。您能否解释一下我应该如何详细使用该脚本以将其包含在我自己的具有多个插入的脚本中,例如我的表被称为“MYTABLE”并且我想插入一个字符串或 5000 个字符的 XML,它会是什么样子? *)有关 oracle direcroty 和 BFILENAME 的信息 Info *)加载文件 Example 1) 将您的 xml 复制到 oracle_server。 2)创建oracle目录。 3) 授予目录权限。 4) 效仿。 LOB 操作的用例过于依赖操作本身的实际位置。这个答案很好地提供了一个普遍的例子,其余的应该是OP的自学能力。【参考方案2】:

函数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;

【讨论】:

以上是关于插入大于 2000 或 4000 字节的 BLOB 测试字符串的主要内容,如果未能解决你的问题,请参考以下文章

Cisco VLAN大于1006-4000创建

实体框架oracle:将超过2000个字符插入VARCHAR2(4000 CHAR)失败

MyBatis 批量插入包含 BLOB 类型的数据到 Oracle 异常问题分析

MyBatis 批量插入包含 BLOB 类型的数据到 Oracle 异常问题分析

表的创建和管理

如何将字节数组插入 Informix blob