2016-09-23 10 views
0

レポートを生成するために、次のPL/SQLコードを記述しました。PL/SQL:数値または値のエラー:文字列バッファが小さすぎます

CREATE OR REPLACE 

PACKAGE CAcxref AS 
    PROCEDURE CAcxref_PROC (inp_str  IN VARCHAR2,out_retCode OUT NUMBER,out_rec OUT VARCHAR2); 
END CAcxref; 
/
CREATE OR REPLACE 
PACKAGE BODY CAcxref AS 
OutArr  custom.ArrayType; 
V_PROCESS1 VARCHAR2(100); 
V_PROCESS2 VARCHAR2(100); 
V_PROCESS3 VARCHAR2(100); 
V_PROCESS4 VARCHAR2(100); 
v_CutOff VARCHAR2(100); 
TYPE RecTyp IS RECORD (
rec_PROCESS_NAME custom.c_master_notify_tbl.PROCESS_NAME%type, 
rec_SOL_ID custom.c_master_notify_tbl.SOL_ID%type, 
rec_schm_type custom.c_master_notify_tbl.SCHM_TYPE%type, 
rec_foracid custom.c_master_notify_tbl.FORACID%type, 
rec_RCRE_TIME custom.c_master_notify_tbl.RCRE_TIME%type); 
    TYPE Cacxref_data IS TABLE OF RecTyp 
    INDEX BY BINARY_INTEGER; 
    Cacxref_FetchData Cacxref_data; 

    lv_variable    VARCHAR2 (5000) := ''; 
    lv_cnt     NUMBER  ; 
CURSOR GetDetails (v_Process1 VARCHAR2,v_Process2 VARCHAR2,v_Process3 VARCHAR2,v_Process4 VARCHAR2,v_CutOff VARCHAR2) IS 

SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (V_Process1) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B' 
UNION 
SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (v_Process2) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B' 
UNION 
SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (v_Process3) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B' 
UNION 
SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (v_Process4) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B'; 
PROCEDURE CAcxref_PROC(inp_str IN VARCHAR2, out_retCode OUT NUMBER, out_rec OUT VARCHAR2) 
IS 
BEGIN 
    out_retCode := 0; 
    out_rec := ''; 
    custom.stringToArray.formInputArr (inp_str,OutArr); 
    V_Process1 := OutArr(0); 
    DBMS_OUTPUT.PUT_LINE('Process one:'||V_Process1); 
    V_Process2 := OutArr(1); 
    DBMS_OUTPUT.PUT_LINE('Process two:'||V_Process2); 
    V_Process3 := OutArr(2); 
    DBMS_OUTPUT.PUT_LINE('Process THREE:'||V_Process3); 
    V_Process4 := OutArr(3); 
    DBMS_OUTPUT.PUT_LINE('Process four:'||V_Process4); 
    v_CutOff := OutArr(4); 
    DBMS_OUTPUT.PUT_LINE('Cutoff Time:'||v_CutOff); 
    IF NOT GetDetails%ISOPEN then 
     OPEN GetDetails(v_Process1,v_Process2,v_Process3,v_Process4,v_CutOff); 
     DBMS_OUTPUT.PUT_LINE('CUSRSOR HAS BEEN OPENED'); 
    END IF; 
DBMS_OUTPUT.PUT_LINE('COUNT IS:'||Cacxref_FetchData.COUNT); 

LOOP 
    FETCH GetDetails 
    BULK COLLECT 
    INTO Cacxref_FetchData 
    LIMIT 10; /* WARNING: NUMBER OF RECORDS FETCHED SHOULD MATCH SIZE OF OUTREC VARIABLE */ 
    DBMS_OUTPUT.PUT_LINE('INSIDE THE BULK COLLECT LOOP'); 
    EXIT WHEN GetDetails%NOTFOUND; 
END LOOP; 

FOR indx in 1 .. Cacxref_FetchData.COUNT 
LOOP 
    DBMS_OUTPUT.PUT_LINE('INSIDE THE FOR LOOP'); 
    lv_variable := Cacxref_FetchData(indx).rec_PROCESS_NAME || '|' || Cacxref_FetchData(indx).rec_SOL_ID || '|' || 
    Cacxref_FetchData(indx).rec_SCHM_TYPE || '|' || Cacxref_FetchData(indx).rec_FORACID||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' 
    ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' 
    ||Cacxref_FetchData(indx).rec_RCRE_TIME ; 
    DBMS_OUTPUT.PUT_LINE('lv_cnt is 1 and lv_variable is:'||lv_variable); 
    out_rec := lv_variable; 
END LOOP; 
END CAcxref_PROC; 
END CAcxref; 
/
DROP PUBLIC SYNONYM CAcxref 
/
CREATE PUBLIC SYNONYM CAcxref FOR CAcxref 
/
Grant EXECUTE ON CAcxref TO TBAADM, TBAUTIL,TBAGEN,SYSTEM 
/
SET SERVEROUTPUT ON 
/

私はエラーになっていないのですが、何行がいずれかのカーソルでフェッチなっていないのに私は二度目の、初めてcharacter string buffer too smallエラーを取得しています実行します。私は、このエラーがスローされている変数のために理解することはできませんよ

Screenshot

以下は私の実行のスクリーンショットです。

実行プロンプト:

SQL> SET SERVEROUTPUT ON 
SQL> exec custom.CAcxref.CAcxref_Proc ('ACOPN!ACMOD!TEST!TEST1!12042016220000',:out_retCode,:out_rec); 
Process one:ACOPN 
Process two:ACMOD 
Process THREE:TEST 
Process four:TEST1 
Cutoff Time:12042016220000 
CUSRSOR HAS BEEN OPENED 
COUNT IS:0 
INSIDE THE BULK COLLECT LOOP 
INSIDE THE FOR LOOP 
lv_cnt is 1 and lv_variable 
is:ACMOD|102|SBA|99101000036||||||||||||||||||||||12-APR-16 
BEGIN custom.CAcxref.CAcxref_Proc ('ACOPN!ACMOD!TEST!TEST1!12042016220000',:out_retCode,:out_rec); END; 

* 
ERROR at line 1: 
ORA-06502: PL/SQL: numeric or value error: character string buffer too small 
ORA-06512: at "CUSTOM.CACXREF", line 84 
ORA-06512: at line 1 


SQL> exec custom.CAcxref.CAcxref_Proc ('ACOPN!ACMOD!TEST!TEST1!12042016220000',:out_retCode,:out_rec); 
Process one:ACOPN 
Process two:ACMOD 
Process THREE:TEST 
Process four:TEST1 
Cutoff Time:12042016220000 
COUNT IS:2 
INSIDE THE BULK COLLECT LOOP 

PL/SQL procedure successfully completed. 

SQL> print :out_rec 

OUT_REC 
-------------------------------- 

EDIT 私は、PL/SQLとだけ、私は大きなVARCHAR2値とout_rec変数を設定した場合、今ではすべての代替の時間を働いている中にいくつかの変更を行いました。

CREATE OR REPLACE 
PACKAGE CAcxref AS 
    PROCEDURE CAcxref_PROC (inp_str  IN VARCHAR2,out_retCode OUT NUMBER,out_rec OUT VARCHAR2); 
END CAcxref; 
/
CREATE OR REPLACE 
PACKAGE BODY CAcxref AS 
OutArr  tbaadm.basp0099.ArrayType; 
V_PROCESS1 VARCHAR2(20); 
V_PROCESS2 VARCHAR2(20); 
V_PROCESS3 VARCHAR2(20); 
V_PROCESS4 VARCHAR2(20); 
v_CutOff VARCHAR2(14); 
TYPE RecTyp IS RECORD (
rec_PROCESS_NAME custom.c_master_notify_tbl.PROCESS_NAME%type, 
rec_SOL_ID custom.c_master_notify_tbl.SOL_ID%type, 
rec_schm_type custom.c_master_notify_tbl.SCHM_TYPE%type, 
rec_foracid custom.c_master_notify_tbl.FORACID%type, 
rec_RCRE_TIME custom.c_master_notify_tbl.RCRE_TIME%type); 
    TYPE Cacxref_data IS TABLE OF RecTyp 
    INDEX BY BINARY_INTEGER; 
    Cacxref_FetchData Cacxref_data; 

    lv_variable    VARCHAR2 (3000) := ''; 
    lv_cnt     NUMBER  ; 
CURSOR GetDetails (v_Process1 VARCHAR2,v_Process2 VARCHAR2,v_Process3 VARCHAR2,v_Process4 VARCHAR2,v_CutOff VARCHAR2) IS 

SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (V_Process1) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B' 
UNION 
SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (v_Process2) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B' 
UNION 
SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (v_Process3) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B' 
UNION 
SELECT PROCESS_NAME,SOL_ID,SCHM_TYPE,FORACID,RCRE_TIME 
FROM custom.C_MASTER_NOTIFY_TBL 
WHERE PROCESS_NAME IN (v_Process4) 
AND TO_CHAR(RCRE_TIME,'DD-MM-YYYY HH24:MI:SS') <= TO_CHAR(TO_DATE('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
AND CXREF_STATUS IN ('O') AND DEL_FLG='N' AND ONLINE_OR_BATCH='B'; 
PROCEDURE CAcxref_PROC(inp_str IN VARCHAR2, out_retCode OUT NUMBER, out_rec OUT VARCHAR2) 
IS 
BEGIN 
    out_retCode := 0; 
    out_rec := ''; 
    tbaadm.basp0099.formInputArr (inp_str,OutArr); 
    V_Process1 := OutArr(0); 
    DBMS_OUTPUT.PUT_LINE('Process one:'||V_Process1); 
    V_Process2 := OutArr(1); 
    DBMS_OUTPUT.PUT_LINE('Process two:'||V_Process2); 
    V_Process3 := OutArr(2); 
    DBMS_OUTPUT.PUT_LINE('Process THREE:'||V_Process3); 
    V_Process4 := OutArr(3); 
    DBMS_OUTPUT.PUT_LINE('Process four:'||V_Process4); 
    v_CutOff := OutArr(4); 
    DBMS_OUTPUT.PUT_LINE('Cutoff Time:'||v_CutOff); 
    IF NOT GetDetails%ISOPEN then 
     OPEN GetDetails(v_Process1,v_Process2,v_Process3,v_Process4,v_CutOff); 
     DBMS_OUTPUT.PUT_LINE('CUSRSOR HAS BEEN OPENED'); 
    END IF; 
DBMS_OUTPUT.PUT_LINE('COUNT OF FETCHDATA IS:'||Cacxref_FetchData.COUNT); 

IF GetDetails%ISOPEN THEN 
--LOOP 
    FETCH GetDetails 
    BULK COLLECT 
    INTO Cacxref_FetchData 
    LIMIT 10; /* WARNING: NUMBER OF RECORDS FETCHED SHOULD MATCH SIZE OF OUTREC VARIABLE */ 
    DBMS_OUTPUT.PUT_LINE('INSIDE THE BULK COLLECT LOOP'); 
       IF (Cacxref_FetchData.COUNT = 0) THEN 
        CLOSE GetDetails; 
        out_retcode := 1; 
        RETURN; 
       END IF; 
-- EXIT WHEN GetDetails%NOTFOUND; 
--END LOOP; 

FOR indx in 1 .. Cacxref_FetchData.COUNT 
LOOP 
    DBMS_OUTPUT.PUT_LINE('INSIDE THE FOR LOOP'); 
    lv_variable := Cacxref_FetchData(indx).rec_PROCESS_NAME || '|' || Cacxref_FetchData(indx).rec_SOL_ID || '|' || 
    Cacxref_FetchData(indx).rec_SCHM_TYPE || '|' || Cacxref_FetchData(indx).rec_FORACID||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' 
    ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' ||'|' 
    ||Cacxref_FetchData(indx).rec_RCRE_TIME ; 
    DBMS_OUTPUT.PUT_LINE('lv_cnt is 1 and lv_variable is:'||lv_variable); 
    out_rec := out_rec || lv_variable; 
        IF (indx = Cacxref_FetchData.COUNT) THEN 
         out_rec := out_rec || lv_variable;    

        ELSE 

         out_rec := out_rec || lv_variable || CHR (10);    

        END IF; 
END LOOP; 
RETURN; 
END IF; 
END CAcxref_PROC; 
END CAcxref; 
/
GRANT EXECUTE ON CUSTOM.CAcxref TO TBAGEN; 
GRANT EXECUTE ON CUSTOM.CAcxref TO TBAADM WITH GRANT OPTION; 
GRANT EXECUTE ON CUSTOM.CAcxref TO TBAUTIL; 

そして今、結果はout_rec VARCHAR2(4000)を設定した後、次のようになります。使用

SQL> set serveroutput on 
SQL> exec custom.CAcxref.CAcxref_Proc ('ACOPN!ACMOD!TEST!TEST1!12042016220000',:out_retCode,:out_rec) 
Process one:ACOPN 
Process two:ACMOD 
Process THREE:TEST 
Process four:TEST1 
Cutoff Time:12042016220000 
CUSRSOR HAS BEEN OPENED 
COUNT OF FETCHDATA IS:0 
INSIDE THE BULK COLLECT LOOP 
INSIDE THE FOR LOOP 
lv_cnt is 1 and lv_variable 
is:ACMOD|102|SBA|99101000036||||||||||||||||||||||12-APR-16 
INSIDE THE FOR LOOP 
lv_cnt is 1 and lv_variable 
is:ACOPN|101|SBA|99101000116||||||||||||||||||||||12-APR-16 

PL/SQL procedure successfully completed. 

SQL> exec custom.CAcxref.CAcxref_Proc ('ACOPN!ACMOD!TEST!TEST1!12042016220000',:out_retCode,:out_rec) 
Process one:ACOPN 
Process two:ACMOD 
Process THREE:TEST 
Process four:TEST1 
Cutoff Time:12042016220000 
COUNT OF FETCHDATA IS:2 
INSIDE THE BULK COLLECT LOOP 

PL/SQL procedure successfully completed. 

SQL> exec custom.CAcxref.CAcxref_Proc ('ACOPN!ACMOD!TEST!TEST1!12042016220000',:out_retCode,:out_rec) 
Process one:ACOPN 
Process two:ACMOD 
Process THREE:TEST 
Process four:TEST1 
Cutoff Time:12042016220000 
CUSRSOR HAS BEEN OPENED 
COUNT OF FETCHDATA IS:0 
INSIDE THE BULK COLLECT LOOP 
INSIDE THE FOR LOOP 
lv_cnt is 1 and lv_variable 
is:ACMOD|102|SBA|99101000036||||||||||||||||||||||12-APR-16 
INSIDE THE FOR LOOP 
lv_cnt is 1 and lv_variable 
is:ACOPN|101|SBA|99101000116||||||||||||||||||||||12-APR-16 

PL/SQL procedure successfully completed. 
+0

"ORA-06512:" CUSTOM.CACXREF "、84行目の行を読んでください。運が良かった。 –

+0

@BobJarvis、84行目は 'CUSTOM \t CACXREF \tパッケージ本体" out_rec:= lv_variable; "からdba_sourceです。しかし、私はどのようにout_recが小さいのか理解できません。 – Mistu4u

+0

どのように:out_recは定義されていますか? –

答えて

1

(元「文字列バッファが小さすぎ」というエラーがSQLによるものであった* Plusは、バインド変数を以下の点は、代替実行で結果を与えるコードに関するフォローアップの質問に関連しています)。

私はいくつかの問題をコード(フォーマットされていないことを除けば、hエラーを見つけるには - すべてのコードをきちんとレイアウトし、グローバル変数の前にg_、プロシージャのパラメータをp_、カーソルのパラメータをcp_などに置くことをお勧めします。

最初に、カーソルgetdetailsはグローバル(パッケージ本体レベルで宣言されています)でも決して閉じないので、グローバル配列cacxref_fetchdataは残りのセッションで取得する最初の値を保持していると思います。それは意図されていますか?

グローバル配列outarrは、 'out'パラメータではありませんが、構文解析の手順ではinp_strのために使用されているようですので、少し混乱してしまいます。

グローバル変数lv_cnt(理由はlv?)は使用されませんが、出力メッセージは'lv_cnt is 1'です。

v_cutoffはカーソルパラメータとして渡されますが、カーソル内では使用されません。あなたは1-DEC-2016 00:00:002-JAN-1997 23:59:59 '前' になりたい場合を除き、日付の比較は、間違って見える

cursor getdetails 
    (v_process1 varchar2 
    , v_process2 varchar2 
    , v_process3 varchar2 
    , v_process4 varchar2 
    ) -- not used: v_cutoff varchar2) 
is 
    select distinct process_name, sol_id, schm_type, foracid, rcre_time 
    from custom.c_master_notify_tbl 
    where process_name in (v_process1, v_process2, v_process3, v_process4) 
    and to_char(rcre_time,'DD-MM-YYYY HH24:MI:SS') 
      <= to_char(to_date('12042016220000','DDMMYYYY HH24:MI:SS'),'DD-MM-YYYY HH24:MI:SS') 
    and cxref_status = 'O' 
    and del_flg = 'N' 
    and online_or_batch = 'B'; 

カーソルgetdetailsは、4つのunion sから単純化することができます。(私は接頭辞です。また、カーソルのパラメータは、コンパイラはパラメータを使用しますが、混乱していくつかのグローバル変数と同じ名前を持つ

and rcre_time <= to_date('12-04-2016 22:00:00','DD-MM-YYYY HH24:MI:SS') 

rcre_timedateであると仮定すると、私はあなたにそれを変更する必要があると思います分かりやすくするためにcp_)。

バルクフェッチループが奇妙に見える - %notfoundにヒットするまで一度に10行をフェッチしますが、最後のフェッチ後までデータで何もしません。

loop 
    fetch getdetails bulk collect into cacxref_fetchdata limit 10; 
    /* warning: number of records fetched should match size of out_rec variable */ 
    dbms_output.put_line('inside the bulk collect loop'); 
    exit when getdetails%notfound; 
end loop; 

cacxref_fetchdataて次にループが、あなただけの(再び後続の呼び出しに影響を与える可能性があり、グローバル変数を使用して)最後のいずれかを使用します。

テーブルやデータでデバッガを実行しないと伝えるのは難しいですが、グローバル変数は手続き呼び出しの間に値を保持するので、カーソルが一度だけフェッチされるため、実行のグローバル値が影響しています次のためのロジック。コードを整理し、変数が絶対に必要な場合は変数がグローバルであることを確認し、前回の実行から保留したくないものは明示的に再初期化します。

関連する問題