我有以下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代码中更改什么才能实现这一目标?感谢。
答案 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);