我有以下查询。如果输入参数不为null并传递了值,则它将返回该URL的所有匹配记录。 如果Input参数为空,则应返回所有记录。如何修复更新条件?
CREATE OR REPLACE PROCEDURE GetDatesList (
p_URL IN varchar2,
P_RECORDSET OUT SYS_REFCURSOR
)
as
begin
OPEN P_RECORDSET FOR
select
PCBS.KeyId as Key, PCBS.PublishDate
from (select
Serlog.*, PS.ServerType, row_number() over (partition by Serlog.KeyId order by Serlog.PublishDate desc) as RowNu
from PConfigByServerLog Serlog
join PServer PS on PS.ServerName = Serlog.ServerName
and Serlog.URL = PS.URL
where Serlog.URL = p_URL
--Here if we pass a value f p_podURL, we get those matching records back. If it is empty, then it should bring all the records back
) PCBS
where PCBS.RowNu = 1 and PCBS.IsActive = 'T';
end;
答案 0 :(得分:3)
where Serlog.URL = p_URL OR p_URL is null
或
where Serlog.URL = nvl(p_URL, Serlog.URL)
其他一个答案警告性能。
如果Serlog.URL
被编入索引,那么如果p_URL
不为空,Oracle将足够聪明地使用它。
考虑这样的SQL:
SELECT * FROM sys.obj$
where obj# = nvl(:b1, obj# )
计划如下:
7 SELECT STATEMENT
6 CONCATENATION
2 FILTER
1 TABLE ACCESS FULL SYS.OBJ$
5 FILTER
4 TABLE ACCESS BY INDEX ROWID SYS.OBJ$
3 INDEX RANGE SCAN SYS.I_OBJ1
两个过滤操作(#2和#5)分别为:b1 is null
和:b1 is not null
。因此,Oracle将只执行计划中的任何一个分支,具体取决于是否已给出参数。
答案 1 :(得分:2)
只需写下
where (Serlog.URL = p_URL) OR p_URL is null
而不是
where Serlog.URL = p_URL
请记住,这会给您次优的执行计划:如果url参数已编入索引,则可能不会使用该索引。
如果需要关注性能,你最好用两种不同的游标分别处理这两种情况
答案 2 :(得分:0)
如果合适,您还可以在过程定义中为p_URL设置默认值:
CREATE OR REPLACE PROCEDURE GetDatesList (
p_URL IN varchar2 DEFAULT '//svr1/dir1/folder2/etc',
P_RECORDSET OUT SYS_REFCURSOR
)
as
因此,如果传递NULL,则将使用此值。