MySQL的UDF(User Defined Function)类似于一种API, 用户根据一定的规范用C/C++(或采用C调用规范的语言)编写一组函数(UDF),然后编译成动态链接库,通过CREATE FUNCTION和DROP FUNCTION语句来加载和卸载UDF。UDF被加载后可以像调用MySQL的内置函数一样来调用它,并且服务器在启动时会自动加载原来存在的UDF。
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变量所指定的插件目录中。
DROP FUNCTION function_name
对于每个UDF,需要编写若干相关C/C++函数,下面用XXX()代表在SQL语句中调用UDF,xxx()代表相应的C/C++函数调用,实际使用时,两者应相同。
SQL类型 C/C++类型 STRING/DECIMAL char * INTEGER long long REAL double
对于聚合UDF, 还需要另外两个函数。
所以函数必须是线程安全的。可以参考《MySQL参考手册》第30章第3节以获得更详细的说明。此外,在MySQL源代码包中有编写UDF的示例,位置为sql/udf_example.c.
当SQL语句调用XXX()时,服务器首先调用xxx_init()进行参数检查或内存分配,若xxx_init()出错,则SQL语句被终止,主函数和清理函数将不会被调用。然后,服务器对每一行记录调用一次主函数,最后清理函数xxx_deinit()被调用。
用类似的命令来编译UDF:
shell> gcc -shared -o udf_example.so udf_example.c
将经过编译得到的动态链接库(.so文件)放到系统可以找到并加载该文件的目录中。然后通过CREATE FUNCTION语句让服务器加载动态链接库中的函数。
udf_test.c
#include <mysql.h>#include <time.h>#include <string.h>
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)
存储过程中的函数是一组SQL语句的集合,其能力受限于SQL的表达能力,它还要受限于MySQL自身的一些限制。它主要用于较高层次的数据处理。
UDF的限制相对来说要小很多,与编写服务器代码时的限制相同,只要符合相应的约定即可。它的定位偏向于底层,主要用于提供一些基础的数据处理功能。另外要注意的是,UDF一旦出错,会导致服务器崩溃!
联系客服