从这次开始就新的主题“表·函数”进行解说。
大家有没有想过,如果在SELECT文的FROM后边跟的是表或者试图。
如果这个表或者试图如果是函数,这个函数返回的是一个结果list,那我们是不是会很方便呢?
如果这样可以的话,就不需要每个SQL两边写一堆返回大量数据结果的PLSQL块了,
直接用放回数据结果的函数替代就方便了很多。
或者是,程序中表和表结合的时候,其中部分表也可以用返回多条数据的函数来替代,那也很方便。
或者是,游标访问你的表和返回结果集的函数结合起来,也很方便。
也就是说,如果能把返回多条数据的结果集的函数当作一个表来查询的话,
陈序中就可以更加方便的实现各种各样的功能了。
这次解说的表·函数,就是把返回数据的函数作为一个表来使用的。
看一下简单的例子:
首先创建一个包含,把表·函数相关定义放在包的定义部。
1 CREATE OR REPLACE PACKAGE pac1
2 IS
3 //
4 /声明一个记录类型(表·函数的行类型)/
5 //
6 TYPE rec_type is record
7 ( col1 NUMBER,
8 col2 VARCHAR2(10)
9 );
10 //
11 /申明一个记录类型的集合类型*/
12 //
13 TYPE rec_tab_type IS TABLE OF rec_type;
14 –
15 /***********************************************************/
16 /定义一个表·函数:返回集合类型/
17 /************************************************************/
18 FUNCTION f1(p1 IN NUMBER) RETURN rec_tab_type PIPELINED;
19 END PAC1;
/
包已创建。
首先创建了一个包pac1的申明部,表·函数需要几个相关的记录类型和集合的类型的定义,
这些定义一般会定义为包变量,以便直接使用。
从第6行到第9行,定义了一个记录类型(rec_type),这是表·函数返回的1行的数据类型。
也就是说,接下来要创建的表·函数里边的数据行有col 1列、col 2列两列。
这些列的数据类型分别是NUMBER型和VARCHAR2(10)型。
接着,在第13行中申明了该记录的集合类型(rec_tab_type)。
即该记录(行)的集合(集合)的类型。
请注意的是,第13行的定义中没有“INDEX BY BINARY INTERGER”等记述。
一般来说,定义集合的时候,会用“INDEX BY~”这样的记述记述来记述索引的数据类型,
但是如果这样记述的话,集合会变成“带索引的表简称索引表”(或者组合排列、PL/SQL表)这样的类型。
索引表是PL/SQL程序中最常见的变量类型,但不能用于表·函数的返回类型。
如上述(第13行)所示,并没有“INDEX BY~”的字眼,我们称之为“嵌套表”,它可以是表·函数的返回类型。
此外,“VARRAY”也可以作为表·函数的返回类型。
最后在第18行中,声明了一个表·函数(f1),他的返回类型是集合类型的。
关键词“PIPELINE”,是必须的。这个“表·函数”必须是是“管·表·函数”的类型。
这里简答说一下,「管道·表·函数」的性能较高,用的也比较多。
所谓“管道”,是指不积累数据,像管道一样不断流通的意思。
如果是非管道的表·函数,是要把所有的行都放到集合(集合)里边,最后才会返回结果。
如果是“管道”的话,一行一行的数据会不断地放回管道,所以性能能会好。
那么,接下来创建包的主体。
CREATE OR REPLACE PACKAGE BODY pac1
IS
//
/表·函数f1的定义/
//
FUNCTION f1(p1 IN NUMBER) RETURN rec_tab_type PIPELINED
IS
recrec_type;-1行记录变量
BEGIN
FOR I IN 1.p1 LOOP --1~P1的循环
rec.col1 :=I; --col1列设置值
rec.col2 :='ABC’||TO CHAR(I);–col2列的值
PIPE ROW(rec);–将该行穿过管道返回调用方
END LOOP;
RETURN;–因此,RETURN语句不返回值(形式上需要)
END f1;
END PAC1;
/
包主体创建完成。
下面解说一下:
包的主体上定义了表·函数f1的实现,这个函数的数据是对参数p1进行循环处理来生成的行数据。
这里最重要的记述是第13行的“PIPE ROW(rec);”。
这样一来,就把1行(rec)数据放回了管道里。
通过这个方式,如果一行行记录(rec)准备好了的话,就不放在集合里而是直接返还给管道了。
所以循环结束后第15行的RETURN语句就没有返回具体的值了。
但是,正如您所看到的,管道·表·函数中的行是“PIPE ROW”的处理,表示每行数据已经返回给管道了。
最最后需要执行RETURN文,这是作为函数的固定形式,并不是返回行。这个要特别注意。
表·函数做好了,马上试一下把:
SELECT * FROM TABLE (pac1.f1(5));
COL1 COL2
1 ABC1
2 ABC2
3 ABC3
4 ABC4
5 ABC5
如我们所愿,FROM语句对象用的是“TABLE(表·函数名(参数)”。
这里是pac1.f1(5),参数是5,表示通过pac1包的f1函数查询的结果有5行数据。
结果列里有“COL1”列和“COL2”列。
还有从字符位置(数字右对齐、字符左对齐)可以看出COL1列是NUMBER,COL2列是字符类型(VARCHAR2等)。
记录类型里边定义的类型也能反应出来。
当然,SELECT语句处星号(*)职位,我们可以任意书写。
还可以自由选择WERE句、GRUP BY句、ORDER BY句。和普通表的查询完全一样。
那么这次就到此为止,下次关于表·函数的详细注意事项继续进行解说。