UDF顾名思义,就是User defined Function,用户定义函数。我们知道,MySQL本身支持很多内建的函数,此外还可以通过创建存储方法来定义函数。UDF为用户提供了一种更高效的方式来创建函数。
既然MySQL本身提供了大量的函数,并且也支持定义函数,为什么我们还需要UDF呢?这主要基于以下几点:
UDF的兼容性很好,这得益于MySQL的UDF基本上没有变动
比存储方法具有更高的执行效率,并支持聚集函数
相比修改代码增加函数,更加方便简单
当然UDF也是有缺点的,这是因为UDF也处于mysqld的内存空间中,不谨慎的内存使用很容易导致mysqld crash掉。
现在我们开始制作一个基本的UDF函数,本例中在Windows平台上开发,故选用Visual Studio 做为开发工具,编写UDF需依赖 MySQL Connector C 的头文件, 所以要先去 MySQL 官网下载 MySQL Connector C 开发库,在Visual Studio 新建一个C++ dll工程,并引入MySQL头文件#include 即可开编写函数了。
我们可以将UDF函数看成一个“对象”(非对象),每个UFD函数分3个阶段执行:初始化,函数执行体,释放内存,感觉上就像一个“对象”的生命周期一样。现我们要写个名为:get_number的函数,则需要分别声明:get_number_init,get_number,get_number_deinit 三个函数,get_number_init 为初始化,get_number为执行体,get_number_deinit为释放函数。
现在我们来具体实现UDF函数,初始化函数:
//在初始化函数中可以做一些初始化和参数判断工作,比如判断参数类型是否合法。
_WINAPI char get_number_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
initid->ptr=NULL; //这根据实际需要进行初始化,在释放函数中也需要对应做释放
if (args->arg_count < 2)
{
//参数不正确,返回失败
return 1;
}
if (args->arg_type[0] != INT_RESULT || args->arg_type[1] != INT_RESULT)
return 1; //参数类型不对
return 0;
}
_WINAPI int get_number(UDF_INIT *initid, UDF_ARGS *args, char* result,
unsigned long *length, char *is_null, char *error)
{
int a = (int)*((int*)args->args[0]);
int b = (int)*((int*)args->args[1]);
return (a+b);
}
_WINAPI void get_number_deinit(UDF_INIT *initid){
//如果在init中做了内存分配的工作,则在这里释放,如:
if(NULL!=initid->ptr)
delete[] initid->ptr;
}
上面的代码已经完成了UDF(get_number)函数的编写,将工程进行编译,并将编译成功的dll复制到MySQL安装目录下libplugin目录下,注意:如果MySQL为64位版本,则UDF也必须编译为64位dll, UDF编译成功了,我们如何在MySQL中调用get_number函数呢,答案是需在MySQL中注册该UDF,如下:
create function get_number returns integer soname myplugin.dll;
上面的语句执行成功后,就可以在MySQL中使用get_number函数了,如下:
declare m_value int default 0;
set m_value=get_number(3,2); //m_value 即为 5
#或
select get_number(3,2) into m_value from dual;
至此就完成了一个基本的MySQL UDF,在实际应用中有很多地方可以借助UDF来减少工作量。