2011-11-14 2 views
0

나는 아침 내내이 문제에 갇혀있다. 실제로이 코드를 여기에서 보았고 여기에 목적으로 사용하기로 결정했습니다."숫자 또는 값 오류"메시지를 수정하려면 어떻게합니까?

내가 실행중인 문제는 코드를 실행할 때 가끔 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에서 여기

내가 사용하고있는 코드입니다 ", line 40 ORA-06512 : at line 8

답변

2

오류는 utl_file.put_raw에서 비롯됩니다. 버퍼 매개 변수의 최대 크기는 32767 바이트입니다.

당신은 그러나, 나는 len 변수가 실제로 put_raw 호출에서 버퍼입니다 vblob 변수의 길이를 보유하고 있음을, 코드에서 보장을 볼 수 없습니다, IF len < 32760 THEN을 확인합니다.

그래서 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;, 항상 분기 '조각 쓰기'에 대한 이동 :

는 그러므로 나는이 코드 조각을 삭제하는 것이 좋습니다.

지금 볼

, 당신은 http://www.dba-oracle.com/t_writing_blob_clob_os_file.htm

좋은입니다 Burleson의 예에 따라이 일을했지만 당신과는 달리, 참조, Burleson의는 렌 변수와 같은 테이블에서 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; 

편집

는 그래서 다른 옵션은 길이를 얻기를위한 선택 수정하는 것입니다. 이것은 당신이 선택 바꿔야합니다 의미 :이와

-- 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; 
+0

Fanstatic 설명을! 고맙습니다. 선택에서 파일 이름을 ... blobvalue로 변경했습니다. 어디서 제거 할 수 있겠 니? 이렇게하면 모든 파일을 한꺼번에 가져올 수 있습니다. –

+0

@Chidi, 큰 의견에 감사드립니다! 이 문제가 해결되면이 스레드를 닫을 것을 제안합니다. 새로운 요청을 추가하여 스레드의 커다란 지저분한 스파게티를 만드는 것은 분명히 SO 원칙에 위배됩니다. 여러 blob을 파일에 쓰려면 커서를 열고 커서가 리턴 한 모든 파일 이름/표시 이름 쌍에 대해이 프로 시저를 호출해야합니다.여기에 약간의 힌트가 있습니다, 그렇게하는 방법, 충분하지 않다면, 새로운 포스트에서 도움을 요청하십시오. 'for (파일에서 파일 이름 선택) 루프 getfile (c.filename, c.filename || '.txt'); 끝 루프, ' – bpgergo

+0

오케이, 죄송합니다. 나는 그것을 지금 닫을 것이다. –

관련 문제