2017-08-11 35 views
0

我有函數返回sys_refcursor我給你我的代碼示例。如何在oracle中爲sys_refcursor創建動態sql

function myfunc(p_city   IN VARCHAR2, 
p_order   IN VARCHAR2) 
RETURN SYS_REFCURSOR IS 
    v_result   SYS_REFCURSOR; 
begin 
OPEN v_result FOR WITH all_prb AS(
select * from tableA ta inner join tableB tb) 


'select * from all_prb ff where (:p_city is null or (LOWER(ff.city) like ''%''||:p_city||''%'')) order by ' || p_order || 'asc' using p_city,p_city; 
return v_result; 
end myfunc; 

,當我試圖編譯它,我有ORA-00928: missing SELECT keyword,但此錯誤的目標線在那裏我有動態sql'select * from all_prb ff where ...'

如何解決它,我怎麼能寫正確的動態SQL?我正在編寫用於排序的動態sql。

+0

爲什麼你使用'with'子句,爲什麼沒有連接條件? (您發佈的代碼獲得ORA-00905,而不是ORA-00928,所以這似乎不是你實際上運行的...) –

+0

我試過立即執行('select * from all_prb ff where(:p_city爲null或(LOWER(ff.city)like''%''||:p_city ||''%''))order by || || p_order ||'asc'using p_city,p_city;)too and did not word我是這樣寫第一次動態sql所以如果你知道你可以寫我的代碼解決方案我怎麼寫? –

+1

您已將光標的一部分創建爲靜態,並將其一部分創建爲動態。它必須是全部靜態或全部動態sql - 即你需要在動態sql中包含with子句。 – Boneist

回答

2

我不確定爲什麼你打擾with條款,沒有CTE就更簡單;你只需要確定哪些表city列是:

function myfunc(p_city IN VARCHAR2, 
    p_order IN VARCHAR2) 
RETURN SYS_REFCURSOR IS 
    v_result   SYS_REFCURSOR; 
begin 
    OPEN v_result FOR 
    'select * from tableA ta 
    inner join tableB tb on tb.some_col = ta.some_col 
    where :p_city is null or LOWER(ta.city) like ''%''||:p_city||''%'' 
    order by ' || p_order || ' asc' 
    using p_city, p_city; 

    return v_result; 
end myfunc; 
/

我已經猜到了議席,只是改變了別名,如果它是另一個。您還需要指定兩個表之間的連接條件。 (也注意到我在asc之前添加了一個空格來停止將它連接到順序字符串中)。

這個編譯沒有錯誤;當運行時我得到ORA-00942:表或視圖不存在這是合理的。如果我創建虛擬數據:

create table tablea (some_col number, city varchar2(30)); 
create table tableb (some_col number); 

insert into tablea values (1, 'London'); 
insert into tablea values (2, 'Londonderry'); 
insert into tablea values (3, 'East London'); 
insert into tablea values (4, 'New York'); 

insert into tableb values (1); 
insert into tableb values (2); 
insert into tableb values (3); 
insert into tableb values (4); 

然後調用它得到:

select myfunc('lond', 'city') from dual; 

    SOME_COL CITY        SOME_COL 
---------- ------------------------------ ---------- 
     3 East London        3 
     1 London         1 
     2 Londonderry        2 

如果你真的想與CTE堅持出於某種原因,然後(如@boneist說),需要成爲其中的一部分動態聲明:

OPEN v_result FOR 
    'with all_prb as (
     select * from tableA ta 
     inner join tableB tb on tb.some_col = ta.some_col 
    ) 
    select * from all_prb ff 
    where :p_city is null or LOWER(ff.city) like ''%''||:p_city||''%'' 
    order by ' || p_order || ' asc' 
    using p_city, p_city; 
+0

謝謝你的工作。現在我還有其他問題,我想在這個動態sql中調用其他函數,即'從all_prb ff'選擇col1,col2,otherFunc(col3),在這種情況下,我有錯誤ORA-00904:「otherFunc」:無效標識符。你能幫我在這種情況下如何調用函數嗎? –

+0

@giorgigoginashvili - 如果你有新問題,你應該問一個新問題。如果'otherFunc'存在並且你有權執行它(如果它不是你的,那麼執行直接授予你不是通過角色),那麼它就會工作。我可能會猜測 - 看起來你可能在包中定義了'myfunc','otherFunc'也在包中?如果是這樣的話,即使在同一個包中調用SQL時,也必須使用包名稱。 –

+0

yaaah我有兩個功能相同的包,我也寫包名,但我穿它不正確:X抱歉的人現在它是好的一切工作正常非常感謝你 –