2010-03-23 62 views
4

SQL Server能够返回一个往返多个查询结果,e.g:多个结果,没有refcursors

select a, b, c from y; 
select d, e, f from z; 

Oracle不喜欢这种语法。它是可以使用的参考指针,就像这样:

begin 
    open :1 for select count(*) from a; 
    open :2 for select count(*) from b; 
end; 

但是,你招致开启/关闭游标一个点球,你可以保存数据库锁较长时间。我想要做的是使用Odp.net一次性检索这两个查询的结果。可能吗?

+1

在oracle中,选择不锁。无论如何,游标都是隐式使用的,所以我认为除了网络往返之外,你不会节省很多。 – 2010-03-23 22:45:11

+0

@加里网络往返费用昂贵。如果您在SQL Server中的一个命令中运行多个查询,您的性能会得到显着提升,特别是如果您一次执行很多操作。我不明白为什么在Oracle中这是不可能的。 Oracle如何在不锁定的情况下支持可重复读取? – 2010-03-24 07:28:27

+1

Oracle使用多版本并发控制。基本上它保留了所做更改的历史记录(至少与最早的活动事务一样),并且如果它遇到已更改的数据,它将查看历史记录以查看查询开始时数据的状态。 SQL Server 2005添加了它并称之为快照隔离。 – 2010-03-24 22:51:10

回答

6

在Oracle中,引用游标是指向数据的指针,而不是数据本身。 因此,如果一个过程返回两个引用游标,则客户端仍然需要从这些游标中获取行(并引发网络命中)。

因此,如果数据量很小,您可能需要调用一个只返回值的过程。 如果数据量很大(数千行),那么它不会是一个单一的网络旅程,所以当您在光标之间切换时,多出一两个数据就不会有太大的区别。

另一种选择是有一个select返回所有行。这可能是一个简单的UNION ALL

select a, b, c from y union all select d, e, f from z; 

这可能是一个流水线表函数

create or replace package test_pkg is 
    type rec_two_cols is record 
     (col_a varchar2(100), 
     col_b  varchar2(100)); 
    type tab_two_cols is table of rec_two_cols; 
    function ret_two_cols return tab_two_cols pipelined; 
end; 
/

create or replace package body test_pkg is 
    function ret_two_cols return tab_two_cols pipelined 
    is 
     cursor c_1 is select 'type 1' col_a, object_name col_b from user_objects; 
     cursor c_2 is select 'type 2' col_a, object_name col_b from user_objects; 
     r_two_cols rec_two_cols; 
    begin 
     for c_rec in c_1 loop 
      r_two_cols.col_a := c_rec.col_a; 
      r_two_cols.col_b := c_rec.col_b; 
      pipe row (r_two_cols); 
     end loop; 
     for c_rec in c_2 loop 
      r_two_cols.col_a := c_rec.col_a; 
      r_two_cols.col_b := c_rec.col_b; 
      pipe row (r_two_cols); 
     end loop; 
     return; 
    end; 
end; 
/
select * from table(test_pkg.ret_two_cols); 

相信ODP为11g中的最新版本允许用户定义的类型可能帮助。