oracle ORA-06502:PL/SQL:数字或值错误:批量绑定:截断绑定

Posted

技术标签:

【中文标题】oracle ORA-06502:PL/SQL:数字或值错误:批量绑定:截断绑定【英文标题】:oracle ORA-06502: PL/SQL: numeric or value error: Bulk Bind: Truncated Bind 【发布时间】:2014-03-23 18:54:19 【问题描述】:

当使用游标批量收集 sys.odcivarchar2list 中的结果时,我收到此错误: ORA-06502: PL/SQL: 数字或值错误: 批量绑定: 截断绑定 我的循环多次执行而没有错误,但仅针对我将所有数据收集到 varchar2 列表中的特定表,我收到此错误。我使用了这段代码:

declare
  filehandle1 utl_file.file_type;
  myquery varchar2(4000) := 'select column1 ||''~''|| column2 from mytable';
  mycursor sys_refcursor;
  myresults sys.odcivarchar2list;
begin
  filehandle1 := utl_file.fopen ('D42', 'mydata', 'w');
  open mycursor for myquery; 
  loop
   fetch mycursor bulk collect into myresults;
if myresults.count>0 Then
    for idx in myresults.first..myresults.last loop
      utl_file.put_line(filehandle1, myresults(idx));
    end loop;
End if;
    exit when mycursor%notfound;
  end loop;
  close mycursor;
  utl_file.fclose(filehandle1);
end;

这会返回来自 100 多个表的结果,但只有 1 个表崩溃。 提前感谢您的帮助

【问题讨论】:

可能是因为clob 列,如上一个问题所述。有兴趣看到这一点得到证实。 @Alex.. 如果我将 clob 转换为 char 并将结果写入文件.. 那么 sqlloader 将如何尝试输入数据,因为您正确提到它可能需要特殊处理? 我相信您需要将每个 clob 写入一个单独的文件,以便 SQL*Loader 然后可以引用该文件;如之前的artice I linked to 所示。不过我没试过。 @alex.. 我看了你上面提供的文章.. 我想问你“数据文件中的文件名列被标记为 FILLER,所以它们没有加载到表中,但它们是在 LOBFILE 定义中用于标识 LOB 信息的位置。”我真的需要这些专栏吗?我将在数据文件和加载程序的控制文件中写入所有内容,我将添加 clob_content LOBFILE TERMINATED BY EOF,因为在调用加载程序时,我通过命令中的参数提供控制和数据。上述列定义的说法正确吗? 每个 LOB 值都必须在其自己的文件中。如果您的表有 100 行,那么您将有 100 个 LOB 文件,以及您已经创建的文件中的其余数据,该文件中的每一行都指向特定于行的 LOB 文件名。所以你必须在数据文件中有那个 LOB 文件名;但相关的 LOB 已加载到位。 【参考方案1】:

您需要将每个 CLOB 值写入一个单独的文件中,并将该文件名包含在主数据记录中。像这样的:

declare
  data_file utl_file.file_type;
  clob_file utl_file.file_type;
  buffer varchar2(32767);
  position pls_integer;
  chars pls_integer;

  myquery varchar2(4000) := 'select column1 ||''~''|| column3, '
    || '''column2_'' || rownum, column2 from mytable';
  mycursor sys_refcursor;
  myresult varchar2(4000);
  myfilename varchar2(120);
  myclob clob;
begin
  data_file := utl_file.fopen ('D42', 'mydata', 'w');
  open mycursor for myquery; 
  loop
    fetch mycursor into myresult, myfilename, myclob;
    exit when mycursor%notfound;
    if myclob is not null and dbms_lob.getlength(myclob) > 0 then
      myresult := myresult ||'~'|| myfilename;
      clob_file := utl_file.fopen ('D42', myfilename, 'w', 32767);
      position := 1;
      chars := 32767;
      while position < dbms_lob.getlength(myclob) loop
        dbms_lob.read(myclob, chars, position, buffer);
        utl_file.put(clob_file, buffer);
        utl_file.fflush(clob_file);
        position := position + chars;
      end loop;
      utl_file.fclose(clob_file);
    end if;
    utl_file.put_line(data_file, myresult);
  end loop;
  close mycursor;
  utl_file.fclose(data_file);
end;
/

有一个data_file 包含所有非 CLOB 数据,包括您写入该行的 CLOB 的单个文件的名称。文件名可以是任何东西,只要它是唯一的;我使用了rownum,但你可以使用该行的主键 ID,如果它有一个,例如。

将虚拟表创建为:

create table mytable (column1 number, column2 clob, column3 varchar2(10));
insert into mytable (column1, column2, column3) values (1, null, 'First');
insert into mytable (column1, column2, column3) values (2, 'Second CLOB', 'Second');
insert into mytable (column1, column2, column3) values (3, 'Third CLOB', 'Third');

.. 这会创建 mydata 包含:

1~First
2~Second~column2_2
3~Third~column2_3

和文件 column2_2column2_3 具有相应的 CLOB 值。

然后,如果我使用该数据文件和可用的 CLOB 文件以及控制文件运行 SQL*Loader:

load data
characterset UTF8
truncate
into table mytable2
fields terminated by "~"
trailing nullcols
(
  column1 char(10),
  column3 char(10),
  clob_filename filler char(120),
  column2 lobfile(clob_filename) terminated by EOF
)

...新表填充为:

select * from mytable2;

   COLUMN1 COLUMN2                        COLUMN3  
---------- ------------------------------ ----------
         1                                First      
         2 Second CLOB                    Second
         3 Third CLOB                     Third

(我仍然认为您应该使用内置工具、数据泵或只是在两个模式之间在内部复制数据,如先前问题中所述...)

【讨论】:

非常感谢亚历克斯的帮助和支持。这对我现在唯一关心的问题非常有帮助,毕竟这就是你最后所说的。也许使用带有 clob 列的表的数据泵实用程序并只导出和导入数据会更有效。但我可以告诉你,虽然使用 sqlloader 让我有机会丰富我对光标函数和写入文件的知识,包括 linux 的 shell 脚本 在这一点上,也许我会画线并使用数据泵,因为当您必须导出具有 clob 列的数千行时会发生什么......最终会写出数千文件,然后导入数千个文件。因此,正如您建议的那样,数据泵在这张桌子上会更有效【参考方案2】:

我收到了这个 EXACT 错误,但这是由于我将 Ref 游标返回的结果存储到集合中的一个字段中,该字段太小而无法存储该值。该字段被定义为 VARCHAR2(25 CHAR) 但是我试图在该字段中存储超过 25 个字符。

花了一点时间来剖析。关键是缩小错误发生的确切位置,并且当 Ref Cursor 将数据提取到我的集合中时它是正确的。

FETCH rc BULK COLLECT INTO [collection]

希望这对某人有所帮助。

【讨论】:

以上是关于oracle ORA-06502:PL/SQL:数字或值错误:批量绑定:截断绑定的主要内容,如果未能解决你的问题,请参考以下文章

Oracle ORA-06502 PL/SQL:数字或值错误:字符到数字的转换错误

Oracle 存储过程无法生成 csv 文件 - ORA-06502: PL/SQL: numeric or value error: string buff

Oracle.DataAccess.Client.OracleException ORA-06502:PL/SQL:数字或值错误:字符串缓冲区太小。 ExecuteReader 步骤出错

PL/SQL - 防止 ORA-06502

ORA 06502 错误 PL/SQL

PL/SQL: 数字或值错误 - ORA-06502