MySQL UDF(自定義函數)


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM