您可以在主表中添加not exists 检查作为归档分支的一部分:
select o.status_code,o.order_id
from order o
where o.order_id=p_order_id
union all
select a.status_code,a.order_id
from order_archive a
where a.order_id=p_order_id
and not exists (
select *
from order o
where o.order_id=p_order_id
);
当然,这意味着它将查看两个分支中的主表;但它可能仍然更快,具体取决于您的数据、索引、统计信息等。
另一个选项,如果 ID 存在于主表中,将阻止查看存档表,它是先对主表进行简单计数,然后有条件地打开 ref 游标以针对两个可能的查询之一每人一张桌子;即在 PL/SQL 中而不是在 SQL 中分支,完全消除联合。比如:
procedure status(p_order_id in varchar2, p_stat out sys_refcursor) is
l_count pls_integer;
begin
select count(*) into l_count
from order o
where o.order_id=p_order_id;
if l_count > 0 then
-- exists in main table so only query that
open p_stat for
select o.status_code,o.order_id
from order o
where o.order_id=p_order_id;
else
-- does not exist in main table so only query archive
open p_stat for
select a.status_code,a.order_id
from order_archive a
where a.order_id=p_order_id;
end if;
end status;
/
如果 ID 在主表中不是唯一的,那么您可以将 and rownum = 1 添加到初始查询中,以便在找到任何匹配的行后立即停止(因此 l_count 最多可以为 1)而不是获得准确的计数,因为您并不真正关心找到的实际数字。
我们可以在订单表的数据集上使用 fetch 和 loop 吗?如果找到然后只去存档表
并非如此,因为 fetch 会消耗结果的第一行。这是一个非常人为的例子:
var rc refcursor;
declare
x varchar2(1);
begin
open :rc for
select 'A' from dual where 1 = 0
union all
select 'B' from dual where 1 = 0;
fetch :rc into x;
if :rc%notfound then
open :rc for select 'C' from dual;
end if;
end;
/
PL/SQL procedure successfully completed.
print rc
'
-
C
使用此设置,“主”查询找不到任何行(因为 1 = 0 检查);获取后游标是notfound,因此它会重新打开“归档”查询的游标,调用者会看到预期的结果。
但如果第一个查询确实返回行:
declare
x varchar2(1);
begin
open :rc for
select 'A' from dual where 1=1
union all
select 'B' from dual where 1=1;
fetch :rc into x;
if :rc%notfound then
open :rc for select 'C' from dual;
end if;
end;
/
PL/SQL procedure successfully completed.
print rc
'
-
B
然后在 fetch 之后,游标是 found,因此它不会为归档查询重新打开游标,并且现有的 ref 游标会被传递回调用者。但是游标的第一行已经被提取到x 变量中并且丢失了,所以调用者不再看到它。 print 仅显示带有'B' 的单行,而另一行应该带有'A' 的行丢失了。
要让调用者仍然看到这两行,您必须使用“主”查询重新打开游标:
declare
x varchar2(1);
begin
open :rc for
select 'A' from dual where 1=1
union all
select 'B' from dual where 1=1;
fetch :rc into x;
if :rc%found then
open :rc for
select 'A' from dual where 1=1
union all
select 'B' from dual where 1=1;
else
open :rc for select 'C' from dual;
end if;
end;
/
PL/SQL procedure successfully completed.
print rc
'
-
A
B
我想,从逻辑上讲,这实际上与我在上面所做的初始计数相同,但不太清楚。