Oracle PL/SQL:数字或值错误:字符串缓冲区太小
我编写了以下PL/SQL代码来生成报告Oracle PL/SQL:数字或值错误:字符串缓冲区太小,oracle,plsql,Oracle,Plsql,我编写了以下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_PRO
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
/
编辑
我在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;
(最初的“字符串缓冲区太小”错误是由于用于捕获声明太小的输出的SQL*Plus bind变量导致的-这已在注释中澄清。以下几点与后续问题有关,该问题涉及在交替运行时给出结果的代码。)
我可以看到代码中有几个问题(除了未格式化,这使得很难发现错误-我建议整齐地排列所有代码,并使用g_
前缀全局变量,使用p_
的过程参数,使用cp_
的光标参数等)
首先,cursorgetdetails
是全局的(在包体级别声明),但它从来没有关闭过,因此我假设全局数组cacxref\u fetchdata
会在会话的其余部分保留它获取的第一个值。这是有意的吗
全局数组outarr
也让我有点困惑,因为它不是“out”参数,但似乎在解析inp\u str
的过程中使用
有一个全局变量lv\u cnt
(为什么lv
?)从未使用过,但您有一条输出消息说“lv\u cnt是1”
v_cutoff
作为游标参数传递,但不在游标中使用
光标getdetails
可以从四个union
s简化为:
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';
此外,游标参数与一些全局变量具有相同的名称,这是令人困惑的,尽管编译器将使用这些参数(为了清楚起见,我将在它们前面加上前缀cp\
)
大容量获取循环看起来很奇怪-一次获取10行,直到找到一个%notfound
,但直到最后一次获取之后,才对数据执行任何操作
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\u fetchdata
,但只使用最后一个变量(再次使用全局变量,这可能会影响后续调用)
如果不使用表和数据通过调试器运行它,很难判断,但是由于全局变量在过程调用之间保留其值,并且游标只提取一次,我猜某个全局变量的值会影响下一次运行的逻辑。我会整理代码,确保变量只有在绝对必要的情况下才是全局的,并明确地重新初始化您不想保留上次运行的任何内容。也许您应该阅读“ORA-06512:at”CUSTOM.CACXREF,第84行。祝您好运。@BobJarvis,第84行是来自dba\U源的自定义CACRef包体84“out\u rec:=lv\u variable;”。但是我不明白out\u rec怎么会小?out\u rec是怎么定义的?@WilliamRobertson,:out\u rec是VARCHAR2,我没有给出任何大小限制。我甚至不知道你可以这么做。我刚刚尝试过(在Windows上是SQL*加11.0.2.0),它允许这样做,但结果变量只接受最多3个字节的字符串。尝试
varchar2(4000)
。
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';
and rcre_time <= to_date('12-04-2016 22:00:00','DD-MM-YYYY HH24:MI:SS')
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;