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

时间:2011-11-14 16:34:23

标签: oracle plsql oracle9i

我整个上午都被困在这个问题上。我实际上在这里看到了这段代码,并决定将它用于我们的目的。

我遇到的问题是,当我们执行代码时,有时会将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行

1 个答案:

答案 0 :(得分:2)

错误来自utl_file.put_raw。 缓冲区参数的最大大小为32767字节。

您检查IF len < 32760 THEN但是,我在代码中看不到保证len变量实际上保存vblob变量的长度,该变量是{put_raw中的缓冲区1}}来电。

所以我认为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

当然也是END IF;,并且总是去写'片段'分支。

我现在看到,你已经根据Burleson的例子做了这件事http://www.dba-oracle.com/t_writing_blob_clob_os_file.htm

但你看,与你不同,Burleson从同一个表和同一个字段中获取len变量和vblob变量。

-- get length of blob
SELECT dbms_lob.getlength(productblob)
INTO len
FROM products
WHERE id = product_id;

-- save blob length
x := len;

-- select blob into variable
SELECT product_blob
INTO vblob
FROM products
WHERE id = product_id;

编辑

所以另一个选择是修复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;