2017-08-10 40 views
0

我们有一个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语句。这是可能的,如果是这样,你能举个例子吗?

+0

似乎是部分sollution。然而,我将不得不在函数外定义游标,这将不允许用两个不同的语句填充同一个游标,具体取决于我从If语句中得到的结果。 这将导致我仍然不得不使用两个不同的循环,并且我不会获得更干净的代码。 我错过了什么? – user3655855

+0

它只是在您的查询中的顺序不同吗?你没有在你的例子中包括from和where子句,所以很难说清楚。 I3rutt的答案的一个替代方法是将两个循环内部的所有逻辑放入一个单独的过程(使用必要的参数),然后您只需从两个循环内部调用过程。 – Boneist

+0

该声明仅在“order by”部分有所不同。 如果开关是真的,还有一个额外的条件顺序, – user3655855

回答

0

看到,因为它仅仅是为了通过不同了,我会使用一个非布尔(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

0

这可能是类似的东西:

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;