Oracle 如何修复“数字或值错误”消息?

Oracle 如何修复“数字或值错误”消息?,oracle,plsql,oracle9i,Oracle,Plsql,Oracle9i,我整个上午都在为这个问题纠缠不清。我在这里看到了这段代码,并决定将其用于我们的目的 我遇到的问题是,当我们执行代码时,有时它会将一个文件从db写入文件夹 其他时候,我们会得到数字或值错误 有专家能帮我修一下吗 以下是我正在使用的代码: create or replace PROCEDURE getfile(pfname VARCHAR2, display_name IN VARCHAR2) IS vblob BLOB; vstart NUMBER := 1; b

我整个上午都在为这个问题纠缠不清。我在这里看到了这段代码,并决定将其用于我们的目的

我遇到的问题是,当我们执行代码时,有时它会将一个文件从db写入文件夹

其他时候,我们会得到数字或值错误

有专家能帮我修一下吗

以下是我正在使用的代码:

create or replace
PROCEDURE getfile(pfname   VARCHAR2, display_name IN VARCHAR2)
IS
  vblob      BLOB;
  vstart     NUMBER := 1;
  bytelen    NUMBER := 32000;
  len        NUMBER;
  my_vr      RAW(32000);
  x          NUMBER;
  v_name     VARCHAR2(32760);
  lv_str_len NUMBER;
  l_output   utl_file.file_type;
BEGIN
  -- define output directory
  --lv_str_len := Length(pfname);

  --v_name := display_name||upper(substr(pfname,lv_str_len-3,lv_str_len));
  v_name := display_name;

  l_output := utl_file.Fopen('My_DIR', v_name, 'w', 32760);

  -- get length of blob
  SELECT dbms_lob.Getlength(FILENAME)
  INTO   len
  FROM   GENERAL.GUBFILE
  WHERE  gubfile_name = pfname;

  -- dbms_output.put_line('Length: '||len);
  -- save blob length
  x := len;

  -- select blob into variable
  SELECT BLOBVALUE
  INTO   vblob
  FROM   FILES
  WHERE  filename = pfname;

  -- if small enough for a single write
  IF len < 32760 THEN
    -- dbms_output.put_line('Single write ');
    utl_file.Put_raw(l_output, vblob);

    utl_file.Fflush(l_output);
  ELSE -- write in pieces
    -- dbms_output.put_line('multi write '||vstart);
    vstart := 1;

    WHILE vstart < len LOOP
        dbms_lob.READ(vblob, bytelen, vstart, my_vr);

        utl_file.Put_raw(l_output, my_vr);

        utl_file.Fflush(l_output);

        -- set the start position for the next cut
        vstart := vstart + bytelen;

        -- set the end position if less than 32000 bytes
        x := x - bytelen;

        IF x < 32000 THEN
          bytelen := x;
        END IF;
    END LOOP;
  END IF;

  dbms_output.Put_line('End');

  utl_file.Fclose(l_output);
END getfile;
确切的错误是:

ORA-06502:PL/SQL:数字或值错误 ORA-06512:在USER.GETFILE的第40行 ORA-06512:第8行的错误来自utl\u file.put\u raw。 缓冲区参数的最大大小为32767字节

您检查len是否<32760,但是,我在代码中看不到任何保证,len变量实际上保存了vblob变量的长度,该变量是put_原始调用中的缓冲区

因此,我假设vblob变量的实际长度大于32767,这就是产生错误的原因

因此,我建议删除这段代码:

  IF len < 32760 THEN
    -- dbms_output.put_line('Single write ');
    utl_file.Put_raw(l_output, vblob);

    utl_file.Fflush(l_output);
  ELSE
编辑

因此,另一个选择是修复用于获取长度的select。这意味着您必须替换此选项:

  -- get length of blob
  SELECT dbms_lob.Getlength(FILENAME)
  INTO   len
  FROM   GENERAL.GUBFILE
  WHERE  gubfile_name = pfname;
为此:

  -- get length of blob
  SELECT dbms_lob.Getlength(BLOBVALUE)
  INTO   len
  FROM   FILES
  WHERE  filename = pfname;

静态解释!非常感谢你。我从选择…文件名改为选择…blobvalue,结果成功了!你能帮我把房子搬到哪里去吗?这样,我们就可以一次抓取所有文件了?@Chidi,谢谢你的反馈!如果这个问题已经解决了,那么我郑重建议您关闭这个线程。通过添加新的请求来制造一个杂乱无章的线程显然违反了SO原则。如果要将多个blob写入文件,则必须打开一个游标,并对游标返回的每个filename/displayname对调用此过程。这里有一个小提示,如何做到这一点,如果这还不够,那么请在新的帖子中寻求帮助。对于c,从文件循环getfilec.filename中选择文件名,c.filename | |'.txt';端环;我是否正确地假设这会将文件写入数据库所在主机上的文件系统,而不是写入我的客户端正在运行的本地驱动器?@Adam,你是对的。utl_文件将在数据库所在的计算机上创建该文件
  -- get length of blob
  SELECT dbms_lob.Getlength(BLOBVALUE)
  INTO   len
  FROM   FILES
  WHERE  filename = pfname;