CSV输入的存储过程参数,用于返回所有记录

时间:2016-04-12 23:47:39

标签: oracle stored-procedures

我有以下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')我可以获得ID为123和456的用户。但是如果我传入一个空字符串,我想返回所有用户,即exec GET_USERS_BY_IDS(:cur1, '')将返回所有用户。我需要在sproc代码中更改什么才能实现这一目标?感谢。

4 个答案:

答案 0 :(得分:1)

考虑使用REGEXP函数的这个解决方案,我觉得简化了事情。我也从我的评论中加入了测试。注意REGEXP也处理一个NULL列表元素:

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;

未经测试,请告知我们测试后会发生什么。

答案 1 :(得分:0)

你的意思是,像

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

好的,评论中的确认......

您似乎应该能够在最后更改WHERE条件:

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

答案 2 :(得分:0)

user和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

答案 3 :(得分:0)

我想我现在找到了一种更有效的方法。在where语句中,如果输入参数为空白,我可以将其短路:

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