2012-07-13 34 views
1

我想解決一些PL/SQL代碼,試圖測試性能。能夠做到這一點將允許我們減少對數據庫的調用次數,但是我不確定如何填充我創建的返回類型。這是一個設計不佳的表格結構,展示了我想要完成的事情。PLSQL通過1-N表的連接批量收集到UDT中?

create table emp_group (
    gid number, 
    gname varchar2(10) 
); 

create table emp (
    empID number, 
    gid number, 
    empname varchar2(10) 
); 

create or replace type t_emp_obj as object (
    empID number, 
    gid number, 
    empname varchar2(10) 
); 

create or replace type t_emp is table of t_emp_obj; 

create or replace type t_group_emp as object 
(
    gid number, 
    gname varchar2(10), 
    g_emps t_emp 
); 

insert into emp(empID, gid, empName) values (1, 10, 'Rob'); 
insert into emp(empID, gid, empName) values (2, 10, 'Ken'); 
insert into emp(empID, gid, empName) values (3, 10, 'Dave'); 
insert into emp(empID, gid, empName) values (4, 10, 'Ron'); 
insert into emp(empID, gid, empName) values (5, 11, 'Joe'); 
insert into emp_group(gid, gname) values (10, 'DDP'); 
insert into emp_group(gid, gname) values (11, 'DDD'); 
commit; 


create or replace function f_test1 return t_emp as 
    ret t_emp; 
begin 
    select t_emp_obj(empID, gid, empname) bulk collect into ret from emp; 

    return ret; 
end; 


create or replace function f_test2 return t_group_emp as 
    ret t_group_emp; 
begin 
    select t_group_emp(????) bulk collect into ret 
    from emp, emp_group 
    where emp.gid = emp_group.gid; 

    return ret; 
end; 

這裏是一個函數來運行它。

set serveroutput on size 10000 

declare 
    x t_emp; 
begin 
    x := f_test1; 

    for r in (select * from table(cast(x as t_emp))) loop 
    dbms_output.put_line(r.empID || ', ' || r.gid || ', ' || r.empname); 
    end loop; 

end; 

我們有兩張表,一張是員工名單,另一張是員工組名單。忽略emp_group和emp之間應該有一個連接表,這樣一個僱員可以屬於多個團隊......演示代碼。 8)

我想返回給定組ID的所有員工以及組的行,在一個返回的類型中。返回的類型是t_group_emp,它有一個emp行表。 f_test2的語法是什麼?

1)這可能嗎?

2)我將如何構造select語句來填充返回的類型?在這裏「批量收集」正確的方法嗎?我發現this page是一個很好的起點。

3)這個表現有多差?一旦我得到語法排序後,我可以運行自己的數字,但總體而言,這是從多個表中返回具有1-N關係的數據的好方法嗎?

編寫應用程序以消耗返回的類型很容易,所以我並不擔心這一點。

編輯:我們正在使用Oracle 10.3.something ...

編輯:這是接近我想要的東西,但並不完全。

create or replace 
function f_test2 return t_group as 
    ret t_group; 
begin 
    select t_group_emp(emp_group.gid, emp_group.gname, t_emp(t_emp_obj(emp.empID, emp.gid, emp.empName))) bulk collect into ret 
    from emp, emp_group 
    where emp.gid = emp_group.gid; 

    return ret; 
end; 

,並通過一個運行函數...

set serveroutput on size 10000 

declare 
    x t_group; 
begin 
    x := f_test2; 

    for r in (select * from table(cast(x as t_group))) loop 
    dbms_output.put_line('group ' || r.gid || ', ' || r.gname ); 
    for s in (select * from table(cast(r.g_emps as t_emp))) loop 
     dbms_output.put_line('emp ' || s.empID || ', ' || s.empname ); 
    end loop; 
    end loop; 

end; 

提供了以下的輸出:

group 10, DDP 
emp 1, Rob 
group 10, DDP 
emp 2, Ken 
group 10, DDP 
emp 3, Dave 
group 10, DDP 
emp 4, Ron 
group 11, DDD 
emp 5, Joe 

這是偉大的,但我想輸出看起來像這樣,以顯示1-N關係。

group 10, DDP 
emp 1, Rob 
emp 2, Ken 
emp 3, Dave 
emp 4, Ron 
group 11, DDD 
emp 5, Joe 

我需要改變f_test2函數來實現這個功能嗎?

+0

什麼是'f_robtest'? – Sebas 2012-07-13 19:04:26

+0

謝謝,修正了在plsql – MonkeyWrench 2012-07-13 19:06:45

回答

1

首先:我目前無法訪問/使用oracle安裝。我嘗試了SQL小提琴,但這種問題似乎太複雜了(或者我太愚蠢了,這太可能:))。所以我無法測試這一點。

無論如何,你應該能夠像這樣來實現自己的目標:

select t_group_emp(g.gid, 
        g.gname, 
        cast(multiset(select e.empID, 
              e.gid, 
              e.empname 
            from emp e 
            where e.gid = g.gid 
           ) as t_emp 
         ) 
        ) 
    from emp_group g 

別名可能不是neccessary,這是我做自動減少打字。

+0

那是做到了。謝謝。看起來我還有幾個plsql關鍵字可供學習。 – MonkeyWrench 2012-07-16 13:25:21