设为首页 加入收藏

TOP

MySQL:如何编写UDF(一)
2014-11-24 08:11:57 来源: 作者: 【 】 浏览:0
Tags:MySQL: 如何 编写 UDF

1.什么是UDF

UDF顾名思义,就是User defined Function,用户定义函数。我们知道,MySQL本身支持很多内建的函数,此外还可以通过创建存储方法来定义函数。UDF为用户提供了一种更高效的方式来创建函数。

UDF与普通函数类似,有参数,也有输出。分为两种类型:单次调用型和聚集函数。前者能够针对每一行数据进行处理,后者则用于处理Group By这样的情况。

2.为什么用UDF

既然MySQL本身提供了大量的函数,并且也支持定义函数,为什么我们还需要UDF呢?这主要基于以下几点:

1)UDF的兼容性很好,这得益于MySQL的UDF基本上没有变动

2)比存储方法具有更高的执行效率,并支持聚集函数

3)相比修改代码增加函数,更加方便简单

当然UDF也是有缺点的,这是因为UDF也处于mysqld的内存空间中,不谨慎的内存使用很容易导致mysqld crash掉。

3.如何编写UDF

UDF的API包括

name_init():

在执行SQL之前会被调用,主要做一些初始化的工作,比如分配后续用到的内存、初始化变量、检查参数是否合法等。

name_deinit()

在执行完SQL后调用,大多用于内存清理等工作。init和deinit这两个函数都是可选的

name()

UDF的主要处理函数,当为单次调用型时,可以处理每一行的数据;当为聚集函数时,则返回Group by后的聚集结果。

name_add()

在每个分组中每行调用

name_clear()

在每个分组之后调用

为了便于理解,这里给出两种UDF类型的API调用图:

\

下面将就上述几个API进行详细的讲解:

1). name_init

原型:

my_boolname_init(UDF_INIT *initid, UDF_ARGS *args, char *message)

UDF_INIT结构体如下:

字段

类型

描述

maybe_null

my_bool

如果为1表示该UDF可以返回NULL

decimals

unsigned int

返回值为实数时,表示精度,范围0~30

max_length

unsigned long

对于返回值为INTEGER类型值为21,对于REAL类型值为17,对于字符串类型,存储函数最长参数的长度

ptr

char*

额外的指针,我们可以在这里分配内存。通过initd传递给其他API

const_item

my_bool

为1表示函数总是返回相同的值

extension

void*

用于扩展?

UDF_ARGS结构体如下:

字段

类型

描述

arg_count

unsigned int

参数个数

arg_type

enum Item_result*

参数类型数组,记录每一个参数的类型,可以是STRING_RESULT、REAL_RESULT、INT_RESULT以及DECIMAL_RESULT

args

char **

同样是一个数组,用于存储实际数据。

STRING_RESULT与DECIMAL_RESULT类型为char*,INT_RESULT类型为long long*,REAL_RESULT类型为double*,或者一个NULL指针

lengths

unsigned long*

数组,用于存储每一个参数的长度

maybe_null

char *

该数组用于表明每个参数是否可以为NULL,例如

attributes

char **

每个参数的名字

attribute_lengths

unsigned long*

每个参数名字的长度

extension

void*

用于扩展?

Message:用于打印错误信息,该指针本身提供长度为MYSQL_ERRMSG_SIZE,来存储信息;

2).name_deinit

原型:

void name_deinit(UDF_INIT*initid)

该函数会进行一些内存释放和清理的工作,在之前我们提到initid->ptr,我们可以在该区域·进行内存的动态分配,这里就可以直接进行内存释放。

3).name()

原型:针对不同的返回值类型,有不同的函数原型:

返回值类型

函数原型

STRING or DECIMAL

char *name(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)

INTEGER

long long name(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)

REAL

double name(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);

当返回值为STRING类型时,参数result开辟一个buffer来存储返回值,但不超过766字节,在length参数中存储了字符串的长度。

每个函数原型还包括了is_null和error参数,当*is_null被设置为1时,返回值为NULL,设置*error为1,表明发生了错误。

4).name_add()和name_clear()

原型:

void name_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null,char *error)

void name_clear(UDF_INIT *initid, char *is_null, char *error)

对于聚合类型的UDF,name_addd和name_clear会被反复调用。

4. 两个例子

下面将举两个简单的例子,一个单次调用型函数,一个聚集类型函数,来描述写一个UDF的过程。

1)接受一个参数,并返回该参数的值

//初始化

my_booludf_int_init(UDF_INIT *initid, UDF_ARGS *args, char *message)

{

if (args->arg_count != 1){ //检查参数个数

strcpy(message,

"udf_intexample() can onlyaccept one argument");

return 1;

}

if (args->arg_type[0] != INT_RESULT){ //检查参数类型

strcpy(message,

"udf_intexample() argumenthas to be an integer");

return 1;

}

return 0;

}

//清理操作

voidudf_int_deinit(UDF_INIT *initid)

{

}

//主函数

long long udf_int(UDF_INIT *initid, UD

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇MySQL字符型数据区分大小写 下一篇MYSQL时间函数用法宝典

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·我的Linux内核学习笔 (2025-12-26 22:21:10)
·如何评价腾讯开源的 (2025-12-26 22:21:07)
·为什么TCP网络编程中 (2025-12-26 22:21:04)
·Python 数据分析与可 (2025-12-26 21:51:20)
·从零开始学Python之 (2025-12-26 21:51:17)