事前に2つのTYPEを使い列、テーブルの定義が必要となり少し手間ですが、ファンクションの戻り値をテーブル形式にする事ができます。以下は簡単な例題となっていますが、VIEWでは実現できないような複雑なロジックも実装できて便利です。
検証環境作成
-- テーブルの作成
--
create table fruit
(
fid number,
name varchar2(40),
price number,
discount number
);
-- データ投入
--
insert into fruit(fid,name,price,discount) values(101,'バナナ',200,10);
insert into fruit(fid,name,price,discount) values(102,'リンゴ',100,15);
insert into fruit(fid,name,price,discount) values(103,'メロン',300,70);
insert into fruit(fid,name,price,discount) values(104,'ブドウ',260,40);
----------------------------------------------
--typeの作成(レコードイメージ)
-- create or replaceとしているけれど、このtypeを使い以下fruit_arrを
-- 作成した後(関係づけができた後)はcreate or replaceはエラーになります。
-- むりやり削除するなら forceオプション付けると可能
create or replace TYPE fruit_rec as object (
fid number,
name varchar2(40),
price number,
discount number
);
--typeの作成(上記typeをレコードにみたてたテーブルイメージ)
--
create or replace type fruit_arr as table of fruit_rec
;
-- type を削除するなら以下
drop type fruit_rec force
;
テーブルファンクション例
販売価格のfrom,toを指定し、fruitテーブルのデータを出力します。
CREATE OR REPLACE FUNCTION SOONI.fnc_fruit
(
from_price IN number
,to_price IN number
)
RETURN fruit_arr
IS
result_rec fruit_arr := fruit_arr();
cursor cur(from_price in number,to_price in number) is
select fid,name,price,discount
from fruit
where price >= from_price and price <= to_price
order by price
;
fruit_tbl_rec cur%ROWTYPE;
i number;
begin
i := 1;
for fruit_tbl_rec in cur(from_price,to_price) loop
exit when cur%NOTFOUND;
result_rec.extend;
result_rec(i) :=
fruit_rec(
fruit_tbl_rec.fid,
fruit_tbl_rec.name,
fruit_tbl_rec.price,
fruit_tbl_rec.discount
);
i := i + 1;
end loop;return result_rec;
END;
/
実行例
-- まずはテストのデータを確認
--
SQL> select * from fruit order by price;
FID NAME PRICE DISCOUNT
---------- ---------- ---------- ----------
102 リンゴ 100 15
101 バナナ 200 10
104 ブドウ 260 40
103 メロン 300 70
SQL>
--
-- 12.1までは table句が必要ですが、12.2以降のバージョンではtable句は不要です
-- 100円以上260円以下の一覧出力
--
SQL> select * from table(fnc_fruit(100,260));
FID NAME PRICE DISCOUNT
---------- ---------- ---------- ----------
102 リンゴ 100 15
101 バナナ 200 10
104 ブドウ 260 40
--
-- 結果セットをさらにwhere句を使い条件で絞る事も可能です
--
SQL> select * from table(fnc_fruit(100,260)) where name ='バナナ';
FID NAME PRICE DISCOUNT
---------- ---------- ---------- ----------
101 バナナ 200 10
SQL>
パイプライン・テーブル・ファンクションは以下です
大量な結果セットを返却するようなシーンでは活躍します。


