2016-04-12 80 views
0

我有以下Oracle存儲過程,需要對用戶ID的CSV的字符串,將用戶的列表返回到輸出光標的正常工作:存儲過程的參數返回的所有記錄

create or replace PROCEDURE GET_USERS_BY_IDS 
(
    v_cur OUT sys_refcursor 
    ,v_userIdsCsv IN varchar2 DEFAULT '' 
) AS 
BEGIN 
open v_cur for 
with userIds 
as 
(
select 
    trim(substr (txt, 
     instr (txt, ',', 1, level ) + 1, 
     instr (txt, ',', 1, level+1) - instr (txt, ',', 1, level) -1)) 
    as token 
    from (select ','||v_userIdsCsv||',' txt 
      from dual) 
    connect by level <= 
    length(v_userIdsCsv)-length(replace(v_userIdsCsv,',',''))+1 
) 
    select 
    id 
    ,lastname 
    ,firstname 
    from 
     users 
    where 
     id in (select * from userIds); 
END GET_USERS_BY_IDS; 

所以在做exec GET_USERS_BY_IDS(:cur1, '123,456')我可以得到123和456的ID的用戶。但是我想返回所有用戶,如果我傳入一個空字符串,即exec GET_USERS_BY_IDS(:cur1, '')將返回所有用戶。爲了實現這個目標,我需要更改哪些代碼片段?謝謝。

回答

0

我想我現在找到了一個更有效的方法來做到這一點。在where聲明,我可以短路,如果輸入的參數爲空白:使用REGEXP功能,這我覺得簡化的東西

where 
    v_userIdsCsv = '' or 
    id in (select * from userIds); 
+0

我不相信你可以有一個where子句測試,其中空字符串=空字符串。爲v_userIdsCsv'1'設置默認值,然後對v_userIdsCsv ='1'進行where子句測試,它應該可以工作。 –

+0

您接受了一個不起作用的答案。如果v_userIdsCsv是一個空字符串,則不會像所期望的那樣獲得所有用戶。證明:'從雙選擇sysdate,其中''='';'。根據我上面的評論,這可以工作:'從雙選擇sysdate,其中'1'='1';'。請編輯此帖子以顯示有效的工作答案,以免混淆未來的搜索者。 –

0

你的意思是,作爲

BEGIN 
    if v_userIdsCsv = '' then 
    open v_cur for select id, lastname, firstname from users 
    else (rest of your code) 
    end if; 

簡單的東西?

OK,以確認在評論...

看來你應該能夠在最後修改WHERE條件:

where 
    v_userIdsCsv = '' or id in (select * from userIds); 
+0

我當然可以做到這一點,但它會重複選擇代碼... – Niner

0

外部用戶和user_ids之間的連接。聰明的地方。 有幫助嗎?

with csv as (select '321,333' aa from dual) 

     ,userIds 
    as 
(
select 
    trim(substr (txt, 
     instr (txt, ',', 1, level ) + 1, 
     instr (txt, ',', 1, level+1) - instr (txt, ',', 1, level) -1)) 
    as token 
    from (select ','||(select aa from csv)||',' txt 
      from dual) 
    connect by level <= 
    length((select aa from csv))-length(replace((select aa from csv),',',''))+1 
) 
    select 
    user_id 
    ,username 
    from 
     all_users a 
    left join userIds b on a.user_id = b.token 
    where nvl2((select aa from csv),b.token,a.user_id) = a.user_id 
1

考慮這個方案。我也納入了我評論中的測試。注意REGEXP處理一個空列表元素太:

create or replace PROCEDURE GET_USERS_BY_IDS 
(
    v_cur OUT sys_refcursor 
    ,v_userIdsCsv IN varchar2 DEFAULT '1' 
) AS 
BEGIN 
open v_cur for 
with userIds 
as 
(
    select trim(regexp_substr(v_userIdsCsv, '(.*?)(,|$)', 1, level, NULL, 1)) as token 
    from dual 
    connect by level <= regexp_count(v_userIdsCsv, ',') + 1 
) 
    select 
    id 
    ,lastname 
    ,firstname 
    from 
     users 
    where v_userIdsCsv = '1' -- Empty list returns all users 
    OR id in (select * from userIds); 
END GET_USERS_BY_IDS; 

其未經測試,以便讓我們知道,如果你測試它會發生什麼。

相關問題