当前位置: 首页 > 工具软件 > udf-sample > 使用案例 >

mysql udf官方文档_Mysql UDF

鄢晔
2023-12-01

1. 简介

MySQL的UDF(User Defined Function)类似于一种API, 用户根据一定的规范用C/C++(或采用C调用规范的语言)编写一组函数(UDF),然后编译成动态链接库,通过CREATE FUNCTION和DROP FUNCTION语句来加载和卸载UDF。UDF被加载后可以像调用MySQL的内置函数一样来调用它,并且服务器在启动时会自动加载原来存在的UDF。

2. 特性

UDF的参数和返回值的类型可以为字符串,整数或实型。

UDF分为简单UDF和聚合UDF。

服务器会向UDF提供相应的信息以便UDF检查实参的数量、类型和名称。

UDF也可以强制服务器在调用UDF前检查实参类型。

UDF可以指明返回值为NULL或发生了错误。

3. CREATE FUNCTION的语法

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

function_name为函数名 ,RETURNS子句表明UDF的返回值类型,目前DECIMAL和STRING类型是等价的 。

shared_library_name是UDF所在的动态链接库的名称(不含路径),该文件需放在可被系统搜索到的目录中。在MySQL 5.1中,动态链接库需要放在由plugin_dir变量所指定的插件目录中。

4. DROP FUNCTION的语法

DROP FUNCTION function_name

5. 编写UDF

对于每个UDF,需要编写若干相关C/C++函数,下面用XXX()代表在SQL语句中调用UDF,xxx()代表相应的C/C++函数调用,实际使用时,两者应相同。xxx()  ——必须,主函数,该函数的返回值即为UDF的返回值。返回值类型与SQL数据类型的对应关系如下:

STRING/DECIMAL

char *

INTEGER

long long

REAL

double

xxx_init()  ——  可选,xxx()的初始化函数,它可被用来

检查XXX()的实参个数和类型,或强制由服务器来检查。

为主函数分配内存。

指明UDF返回值的最大长度或精度,以及返回值是否可能为NULL.

xxx_deinit()——  可选,xxx()的清理函数,用来释放在xxx_init()中分配的内存

对于聚合UDF, 还需要另外两个函数。xxx_clear()——  必须(MySQL5.1),重置当前聚合值。

xxx_add()——  必须,将参数加到当前聚合值中去。

xxx_reset()—— 必须(MySQL 5.1以下版本),重置当前聚合值,并将参数作为初始聚合值。

所以函数必须是线程安全的。可以参考《MySQL参考手册》第30章第3节以获得更详细的说明。此外,在MySQL源代码包中有编写UDF的示例,位置为sql/udf_example.c.

6. 简单UDF的调用顺序

当SQL语句调用XXX()时,服务器首先调用xxx_init()进行参数检查或内存分配,若xxx_init()出错,则SQL语句被终止,主函数和清理函数将不会被调用。然后,服务器对每一行记录调用一次主函数,最后清理函数xxx_deinit()被调用。

7. 聚合UDF的调用顺序

调用xxx_init()进行初始化。

根据GROUP BY表达式对表进行排序。

对每个新组调用xxx_clear()重置聚合值。

对组中每一行记录调用xxx_add().

当该组数据处理完后,调用xxx()计算聚合值.

重复步骤3-5直到所有数据处理完毕。

调用xxx_deinit()进行清理。

8. 编译和安装UDF

用类似的命令来编译UDF:

shell> gcc -shared -o udf_example.so udf_example.c

将经过编译得到的动态链接库(.so文件)放到系统可以找到并加载该文件的目录中。然后通过CREATE FUNCTION语句让服务器加载动态链接库中的函数。

9. 示例

udf_test.c

#include

#include

#include

my_bool datetime_now_init(UDF_INIT *initid, UDF_ARGS *args, char *message)

{

if (args->arg_count)

{

strcpy(message, "datetime_now() does not need any argument.");

return 1;

}

return 0;

}

char *datetime_now(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args __attribute__((unused)),

char *result, unsigned long *length, char *is_null, char *error __attribute__((unused)))

{

const time_t now_time = time(NULL);

strftime(result, 255, "%Y/%m/%d %I:%M:%S %p %Z %z", localtime(&now_time));

*length = strlen(result);

return result;

}

编译

shell> gcc -fPIC -Wall -O3 -I/usr/local/mysql/include -shared -o udf_test.so udf_test.c

安装

mysql> CREATE FUNCTION datetime_now RETURNS STRING SONAME 'udf_test.so';

Query OK, 0 rows affected (0.00 sec)

使用

mysql> SELECT datetime_now();

+----------------------------------+

| datetime_now() |

+----------------------------------+

| 2008/06/27 05:27:03 PM CST +0800 |

+----------------------------------+

1 row in set (0.00 sec)

10. 与存储过程函数的区别

存储过程中的函数是一组SQL语句的集合,其能力受限于SQL的表达能力,它还要受限于MySQL自身的一些限制。它主要用于较高层次的数据处理。

UDF的限制相对来说要小很多,与编写服务器代码时的限制相同,只要符合相应的约定即可。它的定位偏向于底层,主要用于提供一些基础的数据处理功能。另外要注意的是,UDF一旦出错,会导致服务器崩溃!

11. 参考资料

TopicClassification?

ItemDone?

DueDate?

2008/06/30

Priority

Low

Type

其他

Intro

研究如何编写和使用MySQL UDF

Plan

阅读官方文档

ResearchMethod?

阅读官方文档

WorkProducts?

本Wiki和Sample

Summary

实用性不是很大

 类似资料: