手把手教你写mysql的udf

手把手教你写mysql的udf

UDF 的特性

| 函数能返回字符串,整数或实数。

| 你可以定义一次作用于一行的简单函数,或作用于多行的组的集合函数。

提供给函数的信息使得函数可以检查传递给它们的参量的数目和类型。

| 你可以让 MySQL 在将某参量传递给函数之前强制其为某一类型。

| 你可以表示函数返回 NULL 或发生错误。

CREATE FUNCTION/DROP FUNCTION语法

CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL}
SONAME shared_library_name
DROP FUNCTION function_name

一个自定义函数 (UDF) 就是用一个象ABS()或SUM()这样的固有(内建)函数一样作用的新函数去扩展MySQL。

function_name 是用在SQL声明中以备调用的函数名字。RETURNS 子句说明函数返回值的类型。shared_library_name 是共享目标文件的基本名,共享目标文件含有实现函数的代码。该文件必须位于一个能被你系统的动态连接者搜索的目录里。

你必须有mysql 数据库的INSERT 权限才能创建一个函数,你必须有mysql 数据库的DELETE权限才能撤销一个函数。这是因为CREATE FUNCTION 往记录函数名字,类型和共享名的mysql.func系统表里添加了一行,而DROP FUNCTION则是从表中删掉这一行。
值得注意的是,要使得UDF机制能够起作用,必须使用C或者C++编写函数,你的系统必须支持动态加载,而且你必须是动态编译的mysqld(非静态)。

定义UDF

对于每个你想要使用在SQL声明中的函数,你应该定义相应的C(或C++)函数。

你为xxx()编写来实现接口的C/C++函数如下:

xxx() (必有)

主函数。这是函数结果被计算的地方。SQL函数数据类型与C/C++函数返回类型的对应关系如下:

SQL 类型

C/C++ 类型

STRING

char *

INTEGER

long long

REAL

double

xxx_init() (可选)

对xxx()的初始化函数。它可以被用来:

检查传递给xxx()的参量数目。

检查参量是否为必需的类型,或者,除此之外,在主函数被调用的时候告诉MySQL将参量强制为想要的类型。

分配主函数需要的内存。

指定结果的最大长度。

指定(对于REAL 函数)小数的最多位数。

指定结果是否可以为 NULL。

xxx_deinit() (可选)

对xxx()的去初始化函数。它释放初始化函数分配的内存。

当SQL声明调用XXX()时,MySQL调用初始化函数xxx_init(),让它执行必要的设置,比如,检查参量或分配内存。如果xxx_init()返回一个错误,SQL声明会退出并给出错误信息,而主函数和去初始化函数并没有被调用。否则,主函数xxx()对每一行都被调用一次。所有行都处理完之后,调用去初始化函数xxx_deinit()执行必要的清除。

对于象SUM()一样工作的集合函数,你也必须提供如下的函数:

xxx_clear()(在5.1版本中必须)

对一个新组重置当前集合值为初试集合值,但不插入任何参量。

xxx_add()(必须)

添加参量到当前集合值。

MySQL按下列操作来处理集合UDF:

1. 调用 xxx_init() 让集合函数分配它需要用来存储结果的内存。

2. 按照GROUP BY表达式来排序表。

3. 为每个新组中的第一行调用xxx_clear()函数。

4. 为属于同组的每一个新行调用xxx_add()函数。

5. 当组改变时或每组的最后一行被处理完之后,调用xxx()来获取集合结果。

6. 重复,以上3步直到所有行被处理完。

7. 调用xxx_deinit() 函数去释放UDF分配的内存。

所有函数必须时线程安全的,这不仅对主函数,对初始化和去初始化函数也一样,也包括集合函数要求的附加函数。这个要求的一个结果就是,你不能分配任何变化的全局或静态变量。如果你需要内存,你可以在xxx_init()函数分配内存,然后在xxx_deinit()函数释放掉。

主要数据结构

发表评论

您必须登录才能发表评论!