天天看点

db2自定义函数能返回几个参数_DB2 用户自定义函数

用户自定义函数

DB2 内部提供了大量的函数,例如求某个字段最大值的 MAX() 函数,求某个日期所在年份的 YEAR() 函数,等等。如果在使用 DB2 的过程中,需要反复使用同一个功能,就可以把这个功能定义成用户自定义函数(User Defined Function,简称 UDF)。可以使用 DB2 自带的 SQL PL 语言设计函数,也可以使用一些高级语言(如 C,C++ 和 Java 等)设计函数,并存储在 DB2 数据库中。

用户自定义函数与存储过程比较相像,都可以接收输入参数,在程序体中操作后返回输出结果。二者的不同点在于,存储过程通常与具体的业务关联比较密切,程序体内部涉及到业务逻辑,与某个业务系统内部的表密切相关,而用户自定义函数通常没有复杂的业务逻辑,也不与具体的表发生关联,通常在函数体内部所做的都是通用的操作,这种操作可以套用在任何表上。另外在调用方式上二者也有不同之处,存储过程通过 CALL 命令直接调用,而函数不能直接调用,而是在 SQL 表达式进行调用。

把使用编程语言编写的函数称为外部函数,把从另一个现有的函数改造继承过来的函数称为有源函数。

用户自定义函数分为三种类型:

(1)标量函数。返回一个单值的函数称为标量函数。例如,DB2 内置的 YEAR() 函数就是一个标量函数。标量 UDF 可以是外部函数或有源函数。

(2)列函数。从表的一列中进行统计返回单值答案的函数称为列函数,有时也称为聚集函数或聚合函数。例如,求某个字段平均值的函数 AVG()。不能对 DB2 数据库管理器定义外部列 UDF,但是可以定义源于一个内置列函数的列 UDF。

(3)表函数。返回结果是一个表的函数称为表函数,它将一个表返回至引用它的 SQL 语句,只能在 SELECT 语句的 FROM 子句中引用表函数。此类函数可用于将 SQL 语言处理能力应用于非 DB2 数据的数据,或将此类数据转换为 DB2 表。

例如,表函数可以提取一个文件并将它转换成表,将来自互联网的样本数据制成表。这些信息可以与该数据库中的其他表连接。

表函数只能是外部函数,它不能是有源函数。

很多用户自定义函数在使用的时候需要使用用户自定义数据类型(User Defined Type,简称 UDT),本节首先介绍用户自定义数据类型的创建方法,然后针对这些类型创建用户自定义函数。

用户自定义数据类型可以用于建表时的数据定义或者用户自定义函数中,它主要分为单值类型和结构化类型两种。单值类型继承自 DB2 现有的数据类型,可以对特定领域进行更具有实际意义的描述,例如可以分别定义身高、体重、年龄等类型,它们都继承自整型,但是分别表示不同的含义。结构化类型类似于 C 语言中的结构体,是由多个单值类型组合而构成的复合类型,使用的时候需要对结构化类型中的每一个分项进行设置。

例 3‑26 用户自定义数据类型、用户自定义函数的创建和使用。

创建一个人民币数据类型,并用它进行建表、插入、更新、查询等操作。

CREATE DISTINCT TYPE RMB AS DEC(12,2) WITH COMPARISONS

创建自定义数据类型使用 CREATE DISTINCT TYPE 语句,接着是新数据类型的名称,然后用 AS 子句指出源类型是什么。本例中指定源数据类型为 12 位宽度、2 位小数的十进制类型,WITH COMPARISONS 表示新创建的数据类型能够和具有相同源类型的值进行比较。

CREATE TABLE teacher

(

id CHAR(10) NOT NULL PRIMARY KEY,

name VARCHAR(20) NOT NULL,

salary RMB

)

创建了一张教师表,包括编号、姓名和薪水字段,其中薪水字段就使用了新定义的人民币数据类型。

INSERT INTO teacher VALUES('COMP000001', 'John', RMB(4026.83))

INSERT INTO teacher VALUES('MNGR000002', 'Rose', 3817.35)

这两条插入语句都能够执行成功,严格的写法是第一种。当创建用户自定义数据类型之后,DB2 会自动提供在新类型和源类型之间的转换函数。对本例来说,RMB() 能够把一个普通的十进制类型转换为人民币类型,DECIMAL 能够把人民币类型转换为十进制类型。第二个插入语句在执行的时候,DB2 隐含地进行了类型转换。

UPDATE teacher SET salary=salary*1.1 WHERE name='John'

这条语句在执行的时候会失败,提示“找不到具有兼容自变量的类型为‘ FUNCTION ’的名为‘ * ’的已授权例程”,意思就是对于 RMB 数据类型,原有的乘法操作运算已经无效了。对此有两种解决方案,一种是把 salary 转换成十进制再进行乘法运算,另一种是创建一个用户自定义函数,在函数中定义对 RMB 类型的乘法运算法则。在此我们采用第一种方法:

UPDATE teacher SET salary=DECIMAL(salary)*1.1 WHERE name='John'

接下来进行查询:

SELECT * FROM teacher WHERE salary>4000

这条查询语句也会失败,因为 RMB 类型不能和整型直接进行比较,同样地,在进行比较之前先进行类型转换:

SELECT * FROM teacher WHERE salary>RMB(4000)

或者

SELECT * FROM teacher WHERE DECIMAL(salary)>4000

接下来我们介绍用户自定义函数的创建和使用方法。在创建了上述的 RMB 数据类型之后,需要对这种类型进行一系列新的函数定义。例如,要获取所有教师的平均薪水,采用以下语句:

SELECT AVG(salary) FROM teacher

同样会报错,原因是针对新定义的 RMB 数据类型,没有相对应的求平均值的函数,应该先使用如下的语句定义函数:

CREATE FUNCTION AVG(RMB)

RETURNS RMB

SOURCE SYSIBM.AVG(DECIMAL)

其中参数和返回值只需要指定数据类型即可,最后一行为函数体,指明其运算法则是采用 DB2 内部对十进制类型进行平均值计算的方法。创建成功后,再次发出查询平均值的语句:

SELECT AVG(salary) FROM teacher

就可以得到正确结果了。

关于用户自定义数据类型和函数更深入的知识请参照信息中心或者本丛书的第二本《 DB2 深度解析——高级 DBA 和开发者篇》。

自定义类型的删除使用 DROP DISTINCT TYPE 语句,函数的删除使用 DROP FUNCTION 语句,需要注意的是,删除自定义数据类型之前,要先删除与之相关的表。