1

PL / SQLコードを整理し、パフォーマンスをテストしようとしています。これができると、DBの呼び出しを大幅に減らすことができますが、作成した返されたタイプを入力する方法がわかりません。これは、私が達成しようとしていることを示す、不十分に設計されたテーブル構造です。

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;

2つのテーブルがあります。1つは従業員のリストで、もう1つは従業員グループのリストです。従業員が複数のグループに属することができるように、emp_groupとempの間に結合テーブルが必要であるという事実を無視してください...デモコード。8)

特定のグループIDのすべての従業員を、グループ行とともに、単一の返されるタイプで返したいと思います。返されるタイプはt_group_empで、これにはemp行のテーブルがあります。f_test2の構文は何ですか?

1)これは可能ですか?

2)返されたタイプを埋めるためにselectステートメントをどのように構成しますか?ここで「一括収集」は正しい方法ですか?このページは良い出発点であることがわかりました。

3)これはどれほどうまく機能しませんか?構文を並べ替えると、自分の数値を実行できますが、全体として、これは1-Nの関係を持つ複数のテーブルからデータを返すための優れたアプローチですか?

返された型を使用するようにアプリケーションをコーディングするのは簡単なので、私はそれについて心配していません。

編集:Oracle10.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関数で何を変更する必要がありますか?

4

1 に答える 1

1

まず最初に:現在、Oracleインストールにアクセス/使用できません。SQL Fiddleを試しましたが、この種の問題は複雑すぎるようです(または、私はあまりにも愚かで、すべて可能です:))。だから私はこれをテストすることができませんでした。

とにかく、あなたはこのようなものであなたの目標を達成することができるはずです:

  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

エイリアスは必要ないかもしれません、それは私がタイピングを減らすために自動的に行うことです。

于 2012-07-15T14:45:48.103 に答える