我在过程中使用了游标,在这里我没有使用批量收集,因为我对从游标中获取的记录进行了很多计算。
在Cursor的Select语句where子句根据条件更改时,我试图使用以下代码,但它给了我错误:
错误(19,12):PLS-00103:预期以下其中一项时遇到符号“ c_recs”::=。 (@%;
create or replace PROCEDURE "test"
(fromdate_in IN varchar2,
todate_in IN varchar2,
atype_in IN number
)
is
begin
if atype_in = 01 then
cursor c_recs IS SELECT cname FROM A_AUD AA WHERE AA.atime BETWEEN to_date( '' || fromdate_in || '' ,'DD/MM/RRRR')
AND to_date('' || todate_in || '','DD/MM/RRRR') AND AA.CTYPE IN ('RAlert');
elsif atype_in = 02
cursor c_auditrecs IS SELECT cname FROM A_AUD AA WHERE AA.atime BETWEEN to_date( '' || fromdate_in || '' ,'DD/MM/RRRR')
AND to_date('' || todate_in || '','DD/MM/RRRR') AND AA.CTYPE IN ('DAlert');
end if;
end
begin
--more logic
FOR rec IN c_recs LOOP
---calculations
END LOOP;
END test;
我不想从net中使用SYS_REFCURSOR,我读取的游标比参考游标略好。
答案 0 :(得分:1)
CASE
解决了该问题:
DECLARE
CURSOR c_recs
IS
SELECT cname
FROM a_aud aa
WHERE aa.time BETWEEN TO_DATE (fromdate_in, 'dd/mm/rrrr')
AND TO_DATE (todate_in, 'dd/mm/rrrr')
AND aa.ctype =
CASE
WHEN atype_in = '01' THEN 'RAlert'
WHEN atype_in = '02' THEN 'DAlert'
END;
BEGIN
FOR rec IN c_recs
LOOP
NULL;
END LOOP;
END;
我无法评论您的refcursor声明。
答案 1 :(得分:1)
一个更好,更有效的选择是在一个没有任何CURSOR的语句中执行此操作。但是,它确实取决于您要执行的操作。如果必须基于游标记录执行dml,则最好在单个语句中执行。
如果确实要在循环中处理某些内容,请使用与显式游标等效(有时性能更好)的隐式游标循环。
还可以使用条件逻辑而不是IF / ELSE来简化选择查询。
CREATE OR REPLACE PROCEDURE "test" (
fromdate_in IN VARCHAR2,
todate_in IN VARCHAR2,
atype_in
in NUMBER
) is begin
for cur in (
SELECT cname
FROM a_aud aa
WHERE aa.time BETWEEN TO_DATE(fromdate_in,'dd/mm/rrrr')
AND TO_DATE(todate_in,'dd/mm/rrrr') AND (
(
atype_in = '01' AND aa.ctype = 'RAlert'
) OR (
atype_in = '02' AND aa.ctype = 'DAlert'
)
)
) loop
---calculations
do_something_with(cur.cname)
end loop;
end;
/
我还建议您将参数类型作为日期,并直接从调用块传递变量,而不要在sql / cursor中进行转换。这样可以避免TO_DATE
转换。