返回首页

gbase数据、南大通用产品文档:GBase8sCREATE FUNCTION 语句

更新日期:2024年09月11日

使用 CREATE FUNCTION 语句创建用户定义函数,注册外部函数,编写并注册
SPL 函数。
该语句是 SQL ANSI/ISO 标准的扩展。
语法

元素
描述
限制
语法
function
在此定义的函
数的名称
您必须拥有相应的语言特
权,请参阅 GRANT 语句
和 重载函数名
标识符
owner
table_object
的所有者
必须拥有 table_object
所有者名称
pathname
存储编译事件
警告的文件的
路径名
指定的路径名必须存在于
数据库所驻留的计算机之

路径和文件名
必须符合您的
操作系统规则

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 256
元素
描述
限制
语法
table_object 具有可以调用
function 的触
发器的表或视
图的名称或同
义词
在本地数据库中必须存在
标识符
提示: 如果您尝试从独立文件中的源代码文本创建函数,则使用 CREATE
FUNCTION FROM 语句。
用法
GBase 8s 支持这些语言编写的用户定义的函数:

GBase 8s 存储过程语言(SPL)。

GBase 8s 支持的外部语言之一(C 或 Java™)(外部函数)。
当 IFX_EXTEND_ROLE 配置参数设置成 ON 时,只有 DBSA 授予内置
EXTEND 角色的用户才可以创建外部函数。使用 CREATE FUNCTION 语句的其
它要求在 使用 CREATE FUNCTION 时必需的特权 中标识。
一个函数可以返回多少值取决于语言。用 SPL 写的函数可以返回一个或多个值。
用 C 或 Java 语言写的外部函数必须只返回一个值。但是 C 函数可以返回一个
集合类型,而查询的外部函数可以从 OUT 参数(对于 SPL 和 Java 语言,从
INOUT 参数), GBase 8s 可以将这些参数作为语句-局部变量(SLV)处理。
SPL 函数的 OUT 和 INOUT 参数的返回值可以作为 SLV 处理。您还可以使用
SPL 例程的局部变量或参数从拥有 OUT 或 INOUT 参数的 SPL 或 C 例程检
索值。
有关该手册如何使用术语 UDR 、函数和过程以及建议用法的信息,请分别参阅
例程、函数和过程之间的关系 和 使用 CREATE PROCEDURE 与 CREATE
FUNCTION 的对比 。
在 ESQL/C 中,只能在 PREPARE 语句中使用 CREATE FUNCTION 语句。如
果您想要创建用户定义函数(在编译时按该函数识别文本),则必须将文本放在
文件中并用 CREATE FUNCTION FROM 语句指定该文件。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 257
如果您包含了 IF NOT EXISTS 关键字,且指定名称的函数已经在当前数据库中
注册,那么数据库服务器不采取任何操作(而不是向应用程序发送异常)。(因
为函数的标识符可以被重载,所以如果数据库服务器可以解析新函数的参数列表
与当前数据库中任何其它同名函数的参数列表不同,则可能有必要包含这些关键
字。)
函数使用在其创建时生效的排列顺序。请参阅 SET COLLATION 语句 获取关于
非缺省对照的信息。
使用 CREATE FUNCTION 时必需的特权
必需拥有数据库上的 Resource 特权或 DBA 特权,才能在该数据库中创建函
数。
在创建函数之前,您还必须对要编写的函数的程序语言拥有 Usage 特权。当
GRANT USAGE ON LANGUAGE 语授予一个用户或角色语言级别的特权时,它
可以指定 SPL 、C 或 Java™ 语言 。有关更多信息,请参阅 语言级权限 。
缺省情况下,SPL 上的 Usage 特权授予 PUBLIC 。
要以 C 或 Java 外部程序语言中注册函数,除非 IFX_EXTEND_ROLE 配置参数
设置成 0 或 Off ,否则您还必须持有内置 EXTEND 角色。
已创建函数上的 DBA 关键字和 Execute 特权
如果您用 DBA 关键字创建 UDR ,则它将被称为 DBA 特权 UDR。您需要
DBA 特权创建 DBA 特权 UDR 。
在不拥有 DBA 特权的用户中,只有 DBA 授予 Execute 特权的用户才能调用
DBA 特权 UDR 。然而,如果 DBA 授予 PUBLIC Execute 特权,那么所有的
用户都可以使用 DBA 特权 UDR 。有关 DBA 特权 UDR 的其它信息,请参阅
创建数据库对象的所有权。
如果您省略 DBA 关键字,则 UDR 将被称为拥有者特权的 UDR 。
当您在兼容 ANSI 的数据库中创建拥有者特权 UDR 时,只有您自己能执行该
UDR 。它的拥有者必须将 Execute 权限授予个别用户或角色或 PUBLIC 后,其
它用户才能执行拥有者特权 UDR。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 258
如果您在不兼容 ANSI 的数据库中创建拥有者特权 UDR ,则任何人都可以执行
该 UDR,因为缺省地将 Execute 权限授予 PUBLIC 。要让特定用户才能存取拥
有者特权 UDR ,则所有者必须撤销 PUBLIC 的对此 UDR Execute 权限,然后
将该权限授予指定的用户或角色。将 NODEFDAC 环境变量设置为 yes 可以防
止当以 Onwer 方式创建 UDR 后缺省地将 URD 的权限授予 PUBLIC。如果该
环境变量设置成 yes ,除非,所有者将该 UDR 的 Execute 权限授予其它用
户,否则除了该 UDR 所有者其它用户都不能调用此 UDR。
如果外部 C 或 Java™ 语言函数有否定函数,则必须授予对该外部函数及其否定
函数的 Execute 权限,然后用户才能执行外部函数。
REFERENCING 和 FOR 子句
REFERENCING 子句可以声明原始值的相关名称和 FOR 子句指定的
table_object 列中的已更改的值相关名称。
REFERENCING 和 FOR 子句

元素
描述
限制
语法
correlation
在此定义的触发器例程中限定
旧的或新的列值
( correlation.column)
不能是
table_object
标识

owner
table_object 的所有者
必须拥有
table_object
所有
者名

table_object 具有可以调用 function 的触
发器的表或视图的名称或同义

必须存在于本地数据
库中
标识

如果您在 CREATE FUNCTION 语句列表之后立即包含 REFERENCING 和 FOR
table_object 子句,则您创建的函数被称为触发器函数(或 触发器 UDR 或 触发

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 259
器例程)。 FOR 子句指定触发器可以从它们的 Triggered Action 列表的 FOR
EACH ROW 部分调用函数的表或视图。
在 REFERENCING 子句中,OLD correlation 指定一个前缀,通过该前缀触发器例
程可以引用 table_object 列在触发器例程修改列值之前所具有的值。 NEW
correlation 指定用于引用触发器例程分配给该列的新值的前缀。无论该触发器例
程是否能使用 correlation 名引用 OLD 列值,NEW 列值或者这两种类型的值都
取决于正在触发事件的类型:

由 Insert 触发器调用的触发器例程仅能引用 NEW correlation 名称。

由 Delete 触发器或 Select 触发器调用的触发器例程仅能引用 OLD
correlation 名称。

由 Update 触发器调用的触发器例程能引用 OLD 和 NEW correlation 名
称。
有关如何在触发动作中使用 correlation.column 符号的信息,请参阅
REFERENCING 子句 。
除了任何以 SPL 语言编写 GBase 8s UDR 的一般需求,触发器例程支持某些附
加语法特性,并且受到一定的限制,对于不是触发器例程的一般 UDR ,它们不
支持此功能(或者不受此限制):

触发器必须包含 FOR table_object 子句已指定本地数据库中表或视图的名
称,该触发器可调用此例程。

触发器例程还可以包含 REFERENCING 子句以声明该相关名称为 OLD
和 NEW 值,它们可被 UDR 中的 SPL 语句引用。

触发器例程只能在触发器定义中的 Triggered Action 列表的 FOR EACH
ROW 节被调用。

OLD 或 NEW 值的相关变量可以出现在 SPL 的 IF 语句 和 CASE 表
达式中。

OLD 值的相关变量不能在一个 LET 表达式的左边。

如果 FOR 子句指定一个视图,它的 INSTEAD OF 触发动作列表调用该
触发器例程,则 NEW 值的相关变量不能在一个 LET 表达式的左边。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 260

只有 NEW 值的相关变量可以在引用相关变量的 LET 表达式的左边从
而。然而,在这种情况下,FOR 子句必须指定表而非视图。

OLD 和 NEW 值都可以在一个 LET 表达式的右边。

Boolean 运算符 SELECTING 、INSERTING 、DELETING 和
UPDATING 在具有有效 Boolean 表达式的上下文内的触发器例程中(和
只在触发动作语句中调用的触发例程和其它 UDR 中)是可用的。如果正
在触发的事件符合由此运算符名称引用的 DML 操作,则这些运算符返回
TRUE ('t'),否则返回 FALSE('f')。

如果一个正在触发的事件激活了同一表或视图上的多个触发器,则所有的
BEFORE 动作在任何 FOR EACH ROW 动作之前发生,并且所有的
AFTER 操作在 FOR EACH ROW 动作之后发生。同一事件上不同触发器
的执行顺序不被保证。

触发器例程必须用 SPL 语言编写。它们不能用外部语言编写,如 C 或
Java™ 语言,但是它们可以包含到外部语言例程的调用,如:应用程序编
程编程接口 mi_trigger ,用于触发器内省。

触发器函数不能引用保存点。由触发动作引起的数据值或数据库结构变更
必须被全部提交或全部回滚。 GBase 8s 不支持触发动作的部分回滚。
有关 mi_trigger API 的更多信息,请参阅 GBase 8s DataBlade API 程序员指南
和 GBase 8s DataBlade API 函数参考 。
如果您包含 REFERENCING 子句但省略了 FOR 子句,或者您包含 FOR 子句
但省略了 REFERENCING 子句,则 CREATE FUNCTION 语句发生错误而失
败。
如果您都省略了 REFERENCING 和 FOR 子句,则 UDR 不能使用
SELECTING 、INSERTING 、DELETING 和 UPDATING 运算符,并且不能声
明可以表示和操纵触发器定义指定的表或视图上触发动作的列值。
有关 Delete 、Insert 、Select 和 Update 触发器的 REFERENCING 子句的语法
的描述,请参阅 CREATE TRIGGER 语句中有关 REFERENCING 子句部分。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 261
重载函数名
因为 GBase 8s 支持例程重载,所有您可以用同一名称定义多个函数,但有不同
的参数列表。您可能希望在以下情况中重载函数:

您使用与内置函数相同的名称创建用户定义函数(如 equal( )),以处理
新拥有定义的数据类型。

您创建类型层次结构,其中子类型从超类型继承数据表示法和函数。

您创建 distinct 类型,它是用于与现有数据类型具有相同的内部存储表示
的数据类型,但是名称不同。并且在没有强制转型的情况下无法与源类型
相比较。Distinct 类型从其源类型继承支持函数。
有关唯一标识每个用户定义函数的例程特征符的简短描述,请参阅例程重载以及
例程签名 。
示例
重载函数通过名称和输入参数列表来唯一标识。除了提供一个长的唯一标识符,
还可以通过特定名称从而在之后使用它。以下示例显示了一个重载函数,它的标
识符是 getArea,具有特定名称 getSquareArea 和 getRectangleArea :
CREATE FUNCTION getArea
(i INT DEFAULT 0)
RETURNING INT SPECIFIC getSquareArea;
DEFINE j INT;
LET j = i * i;
RETURN j;
END FUNCTION;

CREATE FUNCTION getArea
(i INT DEFAULT 0, j INT DEFAULT 0)
RETURNING INT SPECIFIC getRectangleArea;
DEFINE k INT;
LET k = i * j;
RETURN k;
END FUNCTION;
现在您可以使用特定名称,如下所示:
GRANT EXECUTE ON SPECIFIC FUNCTION getSquareArea TO gbasedbt;
GRANT EXECUTE ON SPECIFIC FUNCTION getRectangleArea TO gbasedbt;

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 262
若没有特定名称,则您可能需要发出下列语句:
GRANT EXECUTE ON FUNCTION getArea (INTEGER) TO gbasedbt;
GRANT EXECUTE ON FUNCTION getArea (INTEGER,INTEGER) TO
gbasedbt;
使用 SPECIFIC 子句指定特定名称
可以为一个用户定义函数声明一个在数据库中独一无二的特定名称。当您重载函
数时,特定名称就很有用。
DOCUMENT 子句
DOCUMENT 子句中带引号的字符串提供对 UDR 的摘要和描述。该字符串存储
在 sysprocbody 系统目录表中,适用于 UDR 的用户。拥有对数据库访问特权的
任何人均可查询 sysprocbody 系统目录表,以获取对存储在数据库中的一个或全
部 UDR 的描述。
例如,以下查询获取对 SPL 函数 所显示的 SPL 函数 update_by_pct 的描述:
SELECT data FROM sysprocbody b, sysprocedures p
WHERE b.procid = p.procid
--join between the two catalog tables
AND p.procname = 'update_by_pct'
-- look for procedure named update_by_pct
AND b.datakey = 'D'-- want user document;
先前的查询返回以下文本:
USAGE: Update a price by a percentage
Enter an integer percentage from 1 - 100
and a part id number
UDR 或者应用程序可查询系统目录表来取出 DOCUMENT 子句并为用户显示
它。
对于 C 和 Java™ 语言函数,无论您指定是否使用 END FUNCTION 关键字,
均可以在 CREATE FUNCTION 语句末尾包含 DOCUMENT 子句。
WITH LISTING IN 子句
WITH LISTING IN 子句指定编译时发送警告的文件名。编译 UDR 之后,此文件
包含一条或多条警告消息。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 263
如果您不使用 WITH LISTING IN 子句,则编译器不生成警告列表。
在 UNIX™ 平台上,如果您指定文件名而非目录,将在数据库驻留的计算机上的
主目录中创建此列表文件。如果您在此计算机上没有主目录,则在根目录 (名为
“/”的目录)创建此文件。
在 Windows™ 系统中,如果您指定文件名而非目录,则在数据库位于本地计算
机的情况下,在当前工作目录中创建此列表文件。否则,缺省目录
为 %GBASEDBTDIR%\bin。
SPL 函数
SPL 函数是用 SPL 编写的 UDR ,可返回一个或多个值。要编写并注册 SPL
函数,请使用 CREATE FUNCTION 语句。在 CREATE FUNCTION 和 END
FUNCTION 关键字之间嵌入适当的 SQL 和 SPL 语句。还可以将 DOCUMENT
和 WITH FILE IN 选项放在该函数后面。
分析 SPL 函数,(尽可能)优化函数f,并以可执行文件的形式存储在系统目录
表中。SPL 函数的主体存储在 sysprocbody 系统目录表中。关于该函数的其它信
息存储在其它系统目录表中,包括 sysprocedures 、sysprocplan 和
sysprocauth。有关这些系统目录表的更多信息,请参阅 GBase 8s SQL 参考指
南。
END FUNCTION 关键字在每个 SPL 函数中是必需的,并且在紧邻语句块之前的子
句后面要加上分号(;)。以下代码示例创建了 SPL 函数:
CREATE FUNCTION update_by_pct ( pct INT, pid CHAR(10))
RETURNING INT;
UPDATE inventory SET price = price + price * (pct/100)
WHERE part_id = pid;
return (select price from inventory where part_id = pid);
END FUNCTION
DOCUMENT "USAGE: Update a price by a percentage",
"Enter an integer percentage from 1 - 100",
"and a part id number"
WITH LISTING IN '/tmp/warn_file';
有关如何编写 SPL 函数的更多信息,请参阅 GBase 8s SQL 教程指南 中关于
SPL 的章节。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 264
另见 SPL 例程中的事务 一节。
您可以在 SPL 函数中包含有效的 SQL 或 SPL 语言语句。但是,请参阅 其它
语法段 中的以下各节,这些节描述了 SPL 例程中 SQL 和 SPL 语句上的限
制:SPL 语句的子集在语句块中有效 、 SQL 语句在 SPL 语句块中有效 和 在
数据操纵语句中 SPL 例程的限制 。
外部程序
外部函数是用 GBase 8s 支持的外部语言(即,SPL 以外的编程语言)编写的函
数。
创建一个 C 用户定义函数
1. 编写 C 函数。
2. 编译该函数并将编译代码存储在共享库中( C 的共享对象文件)。
3. 使用 CREATE FUNCTION 语句在数据库服务器中注册该函数。
创建以 Java™ 语言编写的用户定义函数
1. 编写 Java 静态方法,该方法可使用 JDBC 函数与数据库服务通信。
2. 编译该 Java 源文件并创建 .jar 文件( Java 的共享对象文件)。
3. 使用 EXECUTE PROCEDURE 语句执行 install_jar( ) 程序以在当数据库
中安装该 JAR 文件。
4. 如果此 UDR 使用用户定义类型,那么请在 SQL 数据类型和 Java 类之
间创建一个映射。使用 EXECUTE PROCEDURE 语句 中说明的
setUDTextName( ) 程序。
5. 使用 CREATE FUNCTION 语句注册该 UDR 。
数据库服务器只将包含已编译的例程的共享对象文件的路径名存储于数据库,而
不是外部例程的内容。当它执行该外部例程时,数据库服务器调用此外部对象代
码。
数据库服务器存储有关系统目标表中外部函数的信息,包括 sysprocbody 和
sysprocauth 。有关系统目录的更多信息,请参阅 GBase 8s SQL 参考指南。

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 265
注册 C 用户定义函数的示例
以下示例将一个名为 equal( ) 的外部 C 用户定义函数注册到数据库中。该函数采
用了两个 basetype1 类型的参数,并返回一个 Boolean 值。外部例程引用名称指
定了到 C 共享库(实际存储函数对象代码)的路径。该库包含 C 函数
basetype1_equal( ) ,可在 equal( ) 函数执行期间调用此函数。
CREATE FUNCTION equal ( arg1 basetype1, arg2 basetype1)
RETURNING BOOLEAN;
EXTERNAL NAME
"/usr/lib/basetype1/lib/libbtype1.so(basetype1_equal)"
LANGUAGE C
END FUNCTION;
注册用 Java 语言编写的 UDR 的示例
以下 CREATE FUNCTION 语句注册用户定义函数
sql_explosive_reaction( ) 。该函数曾在 sqlj.install_jar 中讨论。
CREATE FUNCTION sql_explosive_reaction(INT) RETURNS INT WITH
(class="jvp") EXTERNAL NAME "course_jar:Chemistry.explosiveReaction"
LANGUAGE JAVA;
该函数返回一个 INTEGER 值。EXTERNAL NAME 子句指定
sql_explosive_reaction( ) 函数的 Java™ 实现是称为 explosiveReaction( ) 的方
法,它驻留于驻留在 course_jar JAR 文件中的 Chemistry Java 类中。
已创建数据库对象的所有权
当执行此 UDR 时,除非为建立的对象指定了其它所有者,否则创建所
有者特权 UDR 的用户,而非执行此 UDR 的用户拥有此 UDR 创建
的任何数据库对象。
例如,假设用户 mike 创建了该用户定义函数:
CREATE FUNCTION func1 () RETURNING INT;
CREATE TABLE tab1 (colx INT);
RETURN 1;
END FUNCTION;

GBase 8s SQL 指南:语法
南大通用数据技术股份有限公司 266
如果用户 joan 现在执行 func1 函数,用户 mike 而非用户 joan 是新建的表
tab1 的所有者。
然而,在 DBA 特权 UDR 的情况中,除非在此 UDR 中的数据库对象被指定给
其它所有者,否则执行 UDR 的用户(而非 UDR 的所有者)拥有此 UDR 创建
的任何数据库对象。
例如,假设用户 mike 创建了该用户定义函数::
CREATE DBA FUNCTION func2 () RETURNING INT;
CREATE TABLE tab2 (coly INT);
RETURN 1;
END FUNCTION;
如果用户 joan 现在执行 func2 函数,用户 joan 而非用户 mike 是新建的表
tab2 的所有者。
另见 对用户身份.和角色的支持 一节。

函数说明

返回N 的二进制形式,N 是BIGINT 类型数值;

如果N 是一个NULL,返回值为NULL。
示例

GBase 8a MPP Cluster 产品手册
5 数据库管理指南
文档版本953(2022-09-15)
南大通用数据技术股份有限公司
683
示例1:N 的值为“12”,返回“12”对应的二进制形式。
gbase> SELECT BIN(12) FROM dual;
+---------+
| BIN(12) |
+---------+
| 1100
|
+---------+
1 row in set

概述
全文索引的字典采用静态哈希结构存储,更新索引需要多次查询该哈希表,当单
词数过多时会导致字典的冲突链非常长,
而冲突链过长会导致更新速度急剧变慢。