UDF介绍
官方介绍请点击http://dev.mysql.com/doc/refman/5.5/en/adding-functions.html
UDF是mysql的一个拓展接口,UDF(Userdefined function)可翻译为用户自定义函数,这个是用来拓展Mysql的技术手段。
背景:select count(*) from table;
上述count是mysql内部的方法,但是毕竟是mysql自己定义的,有时候不能满足我们自己的需求,所以mysql对外提供了这样的接口,允许用户自己定义相应的功能函数;
开发UDF需要使用c/c++,我使用的是c++,IDE是vc++6.0,然后呢编写UDF需要MYSQL提供的文件头,当然你要是用c++编写过访问mysql数据库的程序的话,这个就不是问题;这几个文件头是my_alloc.h,my_global.h,my_list.h,mysql.h,mysql_com.h,mysql_time.h,mysql_version.h,typelib.h;这几个头文件可以从你安装的mysql数据库服务器的include文件夹下找到,当然要是你安装mysql的时候没有选择安装开发包的话,那么你就找不到这个文件夹,所以你就是个悲剧,从网上下相应的头文件,结果没吓到自己想要的,反而下下来一些恶意软件,我也没有安装,所以我很悲剧的把数据库搞崩了,然后重新安装了一个完整版的;
好的,打开vs新建一个win32动态链接库工程,工程名为my_udf;
在新建一个source file;
考入如下简单代码做测试,当然别忘了在工程下考上上面提到的几个头文件(导入mysql库文件);
#if defined(_WIN32) #define DLLEXP __declspec(dllexport) #else #define DLLEXP #endif #include <stdlib.h> #include <string.h> #include <stdio.h> #include <mysql.h> #ifndef __mysqludf #define __mysqludf extern "C"{ #endif /** * my_name */ DLLEXP my_bool my_name_init(UDF_INIT *initid, UDF_ARGS *args, char *message){ return 0; } DLLEXP void my_name_deinit(UDF_INIT *initid){} DLLEXP char* my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error){ return "mysql_udf"; } #ifdef __mysqludf } #endif
很好,现在你可以生成一个动态链库了,我这里生成的是my_udf.dll,将其拷贝到你的mysql安装目录下的lib目录里面的pulgin(E:\MySQL\MySQL Server 5.6\lib\plugin),
当然这里其实只要考到系统路径下都是可以找到的;
然后需要在mysql中注册你定义的函数;
CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL} SONAME shared_library_nameDROP FUNCTION function_name
第一句的意思是创建一个聚合或者是非聚合的函数,sql中调用的名称是function_name,返回类型是{STRING|INTEGER|REAL}其中的一种,然后shared_library_name是你生成的动态链接库的名称,
貌似但是还没有确定的是你的函数名和上述的源代码中的方法必须一致,这点不用怀疑,另外貌似动态链接库的,名称也得喝函数的名称一致;
执行下面SQL语句载入方法:
CREATE FUNCTION my_name RETURNS STRING SONAME 'my_udf.dll';
创建成功后会从mysql服务器的mysql数据库的func表中找到对应的一条记录的添加;
如果想要删除这个自定义函数那么就用第二条语句删之;
DROP FUNCTION IF EXISTS my_name;
至于上述的代码运行时没有问题,但关键是其中的参数是怎么一个情况,在此不做过多介绍,可参考
http://dev.mysql.com/doc/refman/5.1/zh/extending-mysql.html
记录下我需要的信息:
说明主函数xxx()。注意返回值和参数会有所不同,这取决于你说明的SQL函数xxx()在CREATE FUNCTION声明中返回的是STRING,INTEGER类型还是REAL类型示:
对于STRING 型函数:
char *xxx(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
对于INTEGER型函数:
long long xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
对于REAL型函数:
double xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
对主函数的每次调用,args->args 包含为每个当前处理的行传递的实际参量。
如下使用参量i的函数:
给一个STRING_RESULT 型的参量作为一个字符串加一个长度,可以允许所有二进制数或任意长度的数处理。字符串内容作为args->args[i] 而字符串长度为args->lengths[i]。你不能采用null结尾的字符串。
- 对一个INT_RESULT型的参量,你必须转换args->args[i] 为一个long long 值:
longlong int_val; int_val = *((longlong*) args->args[i]);
- 对一个REAL_RESULT型参量,你必须转换args->args[i]为一个双精度值:
double real_val; real_val = *((double*) args->args[i]);
- unsigned long *lengths
对初始化函数,lengths数列表示对每个参量的最大字符串长度。你不要改变它。对主函数的每次调用,lengths包含了对当前处理行传递的任何字符串 参量的实际长度。对于INT_RESULT 或 REAL_RESULT类型的参量,lengths 仍包含参量的最大长度(对初始化函数)。
最后就可以调用select my_name(); 来调用方法,返回的mysql_udf