2017-08-10 21 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;