PL/SQL预先定义的语句在光标定义中
问题描述:
我们有一个select
语句,根据开关的不同而不同。然后我们循环结果。PL/SQL预先定义的语句在光标定义中
目前的代码如下所示:
if switch_a then
for rec in
(
select *
order by decode(x, y,1,0),
decode(x,a,2,0),
decode(x,z,3,0), pos
)
loop ...
end loop;
else
for rec in
(
select *
order by decode(x, y,1,0),
decode(x,z,3,0), pos
)
loop ...
end loop;
end if;
现在我想改变这种代码只有一个循环。所以,我去:
if (switch_a) then
Statement call := select*...
else
Statement call := select*...
end if;
for rec in call
loop
end loop;
的问题是,我不知道这是否在为REC在和我不知道如何定义一个可执行的SQL语句。这是可能的,如果是这样,你能举个例子吗?
答
看到,因为它仅仅是为了通过不同了,我会使用一个非布尔(SQL不知道布尔在Oracle)的标志来决定是否包括由顺序列与否,如:
WITH sample_data AS (SELECT 1 col1, 100 col2, 200 col3 FROM dual UNION ALL
SELECT 2 col1, 90 col2, 210 col3 FROM dual UNION ALL
SELECT 3 col1, 80 col2, 220 col3 FROM dual UNION ALL
SELECT 4 col1, 70 col2, 230 col3 FROM dual UNION ALL
SELECT 5 col1, 60 col2, 240 col3 FROM dual)
SELECT col1,
col2,
col3
FROM sample_data
ORDER BY CASE WHEN :p_switch_a_flag = 'y' THEN col2 END,
col3;
运行与:p_switch_a_flag = 'n'
:
COL1 COL2 COL3
---------- ---------- ----------
1 100 200
2 90 210
3 80 220
4 70 230
5 60 240
运行与:p_switch_a_flag = 'y'
:
COL1 COL2 COL3
---------- ---------- ----------
5 60 240
4 70 230
3 80 220
2 90 210
1 100 200
这样的话,你只有一个光标,不管标志是如何设置的,和你的代码看起来是这样的:
-- if you can't change the switch_a Boolean to a varchar2 flag, then
-- manually set the switch_a flag, otherwise you'd simply pass in
-- the flag as a varchar2, rather than a Boolean.
if switch_a then
switch_a_flag := 'y';
end if;
for rec in (select *
from ....
order by decode(x, y,1,0),
case when switch_a_flag = 'y' then decode(x,a,2,0) end,
decode(x,z,3,0),
pos)
loop
...
end loop;
+0
好像它的工作原理:)非常感谢 – user3655855
答
这可能是类似的东西:
declare
Statement_call varchar2(4000);
rec sys_refcursor;
l_row number;
begin
if (switch_a) then
Statement_call := 'select 1 as q from dual';
else
Statement_call := 'select 2 as q from dual';
end if;
OPEN rec FOR Statement_call;
loop
FETCH rec INTO l_row;
EXIT WHEN rec%NOTFOUND;
dbms_output.put_line(l_row);
end loop;
CLOSE rec;
end;
似乎是部分sollution。然而,我将不得不在函数外定义游标,这将不允许用两个不同的语句填充同一个游标,具体取决于我从If语句中得到的结果。 这将导致我仍然不得不使用两个不同的循环,并且我不会获得更干净的代码。 我错过了什么? – user3655855
它只是在您的查询中的顺序不同吗?你没有在你的例子中包括from和where子句,所以很难说清楚。 I3rutt的答案的一个替代方法是将两个循环内部的所有逻辑放入一个单独的过程(使用必要的参数),然后您只需从两个循环内部调用过程。 – Boneist
该声明仅在“order by”部分有所不同。 如果开关是真的,还有一个额外的条件顺序, – user3655855