【问题标题】:How to select data from joined table as a table type?如何从连接表中选择数据作为表类型?
【发布时间】:2016-11-15 10:51:14
【问题描述】:

我想构建处理表格类型引用数据的非规范化视图。

create table reftab (id number, name varchar2(40), details varchar2(1000));
/
create table basictab (id number, name varchar2(300), contract varchar2 (20));
/
create or replace type reftype is object (id number, name varchar2(40), details varchar2(1000));
/
create or replace type reftypetab as table of reftype;
/
insert into basictab values (1, 'aaa', 'c1');
insert into basictab values (2, 'aab', 'c1');
insert into basictab values (3, 'aaa', 'c2');
insert into basictab values (4, 'aaa', 'c3');

insert into reftab values (1, 'asd', 'aaa');
insert into reftab values (1, 'asg', 'ass');
insert into reftab values (1, 'ash', 'add');
insert into reftab values (1, 'asf', 'agg');
insert into reftab values (3, 'asd', 'aaa');
insert into reftab values (3, 'ad', 'aa');
insert into reftab values (4, 'asd', 'aaa');
insert into reftab values (4, 'as', 'a');
insert into  values (4, 'ad', 'aa');
/

有了这样的数据,我想要一个包含 4 行 basictab 的视图,以及 reftypetab 的附加列,并包含在 id 上加入的所有参考数据。

我知道我可以通过以下方式获得它:

CREATE OR REPLACE FUNCTION pipef (p_id IN NUMBER) RETURN reftypetab PIPELINED AS
BEGIN
  FOR x IN (select * from reftab where id = p_id) LOOP
    PIPE ROW(reftype(x.id, x.name, x.details));   
  END LOOP;

  RETURN;
END;
/

SELECT id, pipef(id)
FROM  reftab
group BY id;
/

但是有没有更好的方法没有函数来获得结果?

【问题讨论】:

    标签: sql database oracle oracle11g


    【解决方案1】:

    您当前的设置:

    SELECT id, pipef(id) as result
    FROM  reftab
    group BY id;
    
            ID RESULT(ID, NAME, DETAILS)                                                                                               
    ---------- ------------------------------------------------------------------------------------------------------------------------
             1 REFTYPETAB(REFTYPE(1, 'asd', 'aaa'), REFTYPE(1, 'asg', 'ass'), REFTYPE(1, 'ash', 'add'), REFTYPE(1, 'asf', 'agg'))      
             4 REFTYPETAB(REFTYPE(4, 'asd', 'aaa'), REFTYPE(4, 'as', 'a'), REFTYPE(4, 'ad', 'aa'))                                     
             3 REFTYPETAB(REFTYPE(3, 'asd', 'aaa'), REFTYPE(3, 'ad', 'aa'))                                                            
    

    您可以使用the collect() function 来简化:

    select id, cast(collect(reftype(id, name, details)) as reftypetab) as result
    from reftab
    group by id;
    
            ID RESULT(ID, NAME, DETAILS)                                                                                               
    ---------- ------------------------------------------------------------------------------------------------------------------------
             1 REFTYPETAB(REFTYPE(1, 'asd', 'aaa'), REFTYPE(1, 'asf', 'agg'), REFTYPE(1, 'ash', 'add'), REFTYPE(1, 'asg', 'ass'))      
             3 REFTYPETAB(REFTYPE(3, 'asd', 'aaa'), REFTYPE(3, 'ad', 'aa'))                                                            
             4 REFTYPETAB(REFTYPE(4, 'asd', 'aaa'), REFTYPE(4, 'ad', 'aa'), REFTYPE(4, 'as', 'a'))                                     
    

    如果您也想要来自basictab 的信息,您可以使用a multiset operator

    select bt.id, bt.name,
      cast(multiset(select reftype(rt.id, rt.name, rt.details)
        from reftab rt where rt.id = bt.id) as reftypetab) as result
    from basictab bt;
    
            ID NAME       RESULT(ID, NAME, DETAILS)                                                                                               
    ---------- ---------- ------------------------------------------------------------------------------------------------------------------------
             1 aaa        REFTYPETAB(REFTYPE(1, 'asd', 'aaa'), REFTYPE(1, 'asg', 'ass'), REFTYPE(1, 'ash', 'add'), REFTYPE(1, 'asf', 'agg'))      
             2 aab        REFTYPETAB()                                                                                                            
             3 aaa        REFTYPETAB(REFTYPE(3, 'asd', 'aaa'), REFTYPE(3, 'ad', 'aa'))                                                            
             4 aaa        REFTYPETAB(REFTYPE(4, 'asd', 'aaa'), REFTYPE(4, 'as', 'a'), REFTYPE(4, 'ad', 'aa'))                                     
    

    【讨论】:

    • 谢谢,这是我在一分钟前发现的。这样看起来好多了。
    • 顺便问一下,您对这种结构有什么经验吗?以这种方式读取数据是否比外部连接慢得多?
    • 我想 collect/multiset 会比你自己的函数快,但还没有测试看有多少。
    • rwijk.blogspot.com/2010/01/… 这里是一些比较的链接。 Multiset 似乎更快。但另一个:oracle-developer.net/display.php?id=514 声称不完全相同
    • @Kacper - 谢谢,虽然我不确定这是否是 OP 的意思。我之前读过那篇文章,但忘记了它为收集创建的额外类型。如果打算合并两个表中的数据,那么 multiset 就是要走的路。
    【解决方案2】:

    进一步的研究给了我另一种方法:

    SELECT id, CAST(COLLECT(reftype(r.id, r.name, r.details)) AS reftypetab) AS customer_ids
        FROM reftab r group by id;
    

    这看起来好多了,但我仍然想问是否有其他方法可以做到这一点。

    编辑

    也许这不是我要问的,但光标表达式可以给出类似的结果。

     SELECT id, cursor(select reftype(r.id, r.name, r.details) from reftab r where r.id = b.id)  AS customer_ids
        FROM basictab b; 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-24
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多