MySQL:如何编写UDF_MySQL

Jun 01, 2016 pm 01:44 PM
どうやって ストレージ ユーザー

bitsCN.com

 

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, UDF_ARGS *args, char *is_null, char *error) 

    

    long long num = (*(long long *)args->args[0]);   //获取第一个参数值 

    

    return num; 

 

 

 

2)接受一个浮点数类型的参数,并对每个分组进行求和

 

 

//初始化 

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

    double *total = (double *) malloc (sizeof(double)); 

  

    if (total == NULL){                  //内存分配失败 

        strcpy(message,"udf_floatsum:alloc mem failed!"); 

        return 1; 

    } 

  

    *total = 0; 

    initid->ptr = (char *)total; 

  

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

        strcpy(message, "too moreargs,only one!"); 

        return 1; 

    } 

  

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

        strcpy(message, "wrongtype"); 

        return 1; 

    } 

  

    initid->decimals = 3;         //设置返回值精度 

    return 0; 

 

 

 

//清理、释放在init函数中分配的内存

 

voidudf_floatsum_deinit(UDF_INIT *initid) 

    free(initid->ptr); 

 

 

 

//每一行都会调用到该函数

 

voidudf_floatsum_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) 

    double* float_total; 

    float_total = (double*)initid->ptr; 

  

    if (args->args[0]) 

        *float_total += *(double*)args->args[0]; 

  

 

 

 

//每个分组完成后,返回结果

 

doubleudf_floatsum(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) 

    double* float_total; 

    float_total = (double *)initid->ptr; 

    return *float_total; 

 

 

 

//在进行下一个分组前调用,设置initid->ptr指向的值为0,以便下一次分组统计

 

voidudf_floatsum_clear(UDF_INIT *initid, char *is_null, char *error) 

    double *float_total; 

    float_total = (double *)initid->ptr; 

    *float_total = 0; 

  

 

 

3) Mysql-udf-http是一个开源的UDF,可以利用HTTP协议进行REST操作。什么是REST操作呢?REST是一种web service架构风格,其实现基于HTTP协议的四种方法:POST、GET、PUT以及DELETE操作,在mysql-udf-http里分别对应的函数是http_post、http_get()、http_put()、http_delete()。

源码下载:http://curl.haxx.se/download/curl-7.21.1.tar.gz

./configure–prefix={mysql安装目录} –with-mysql=/usr/local/webserver/mysql/bin/mysql_config

Make&& make install

该UDF的实现原理比较简单,主要使用libcurl库函数来实现http协议通信,总共三百多行代码。这里有使用和介绍http://blog.s135.com/mysql-udf-http/

有些比较有趣的功能:

例如,我们可以通过GET方法获取微博中的个人信息,其中1821798401为用户ID

selecthttp_get('http://api.t.sina.com.cn/statuses/user_timeline/1821798401.json?count=1&source=1561596835')

 

UDF具有非常高的自由度,你可以编写你任何想要实现的功能函数,甚至可以引用MySQL内核的代码和变量。

当然,UDF也有着局限性,如下:

a)        在mysql库下必须有func表,并且在‑‑skip‑grant‑tables开启的情况下,UDF会被禁止;

b)        当UDF挂掉时,有可能会导致mysqld crash掉;

c)        所有的UDF的函数必须是线程安全的,如果非要用全局变量,需要加互斥,尽量在name_init中分配资源,并在name_deinit中释放

d)        需要有insert权限

 

作者 zhaiwx1987

bitsCN.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Xiaohonshu アカウントを使用してユーザーを見つけるにはどうすればよいですか?私の携帯電話番号を見つけることはできますか? Xiaohonshu アカウントを使用してユーザーを見つけるにはどうすればよいですか?私の携帯電話番号を見つけることはできますか? Mar 22, 2024 am 08:40 AM

ソーシャルメディアの急速な発展に伴い、Xiaohongshuは最も人気のあるソーシャルプラットフォームの1つになりました。ユーザーは、Xiaohongshu アカウントを作成して自分の個人情報を示し、他のユーザーと通信し、対話することができます。ユーザーの小紅樹番号を見つける必要がある場合は、次の簡単な手順に従ってください。 1. Xiaohonshu アカウントを使用してユーザーを見つけるにはどうすればよいですか? 1. 小紅書アプリを開き、右下隅の「検出」ボタンをクリックして、「メモ」オプションを選択します。 2. ノート一覧で、探したいユーザーが投稿したノートを見つけます。クリックしてノートの詳細ページに入ります。 3. ノートの詳細ページで、ユーザーのアバターの下にある「フォロー」ボタンをクリックして、ユーザーの個人ホームページに入ります。 4. ユーザーの個人ホームページの右上隅にある三点ボタンをクリックし、「個人情報」を選択します。

Windows 11 でローカル ユーザーとグループが見つからない: 追加する方法 Windows 11 でローカル ユーザーとグループが見つからない: 追加する方法 Sep 22, 2023 am 08:41 AM

ローカル ユーザーとグループ ユーティリティはコンピュータの管理に組み込まれており、コンソールからまたは独立してアクセスできます。ただし、一部のユーザーは、Windows 11 でローカル ユーザーとグループが見つからないことに気づきます。これにアクセスできる一部のユーザーに対して、このメッセージは、このスナップインがこのバージョンの Windows 10 では動作しない可能性があることを示唆しています。このコンピュータのユーザー アカウントを管理するには、コントロール パネルのユーザー アカウント ツールを使用します。この問題は Windows 10 の以前のバージョンでも報告されており、通常はユーザー側の問題や見落としが原因で発生します。 Windows 11 でローカル ユーザーとグループが表示されないのはなぜですか? Windows Home エディションを実行しています。ローカル ユーザーとグループは、Professional エディション以降で使用できます。活動

スーパーユーザーとして Ubuntu にログインします スーパーユーザーとして Ubuntu にログインします Mar 20, 2024 am 10:55 AM

Ubuntu システムでは、通常、root ユーザーは無効になっています。 root ユーザーをアクティブにするには、passwd コマンドを使用してパスワードを設定し、su-コマンドを使用して root としてログインします。 root ユーザーは、無制限のシステム管理権限を持つユーザーです。彼は、ファイルへのアクセスと変更、ユーザー管理、ソフトウェアのインストールと削除、およびシステム構成の変更を行う権限を持っています。 root ユーザーと一般ユーザーの間には明らかな違いがあり、root ユーザーはシステム内で最高の権限とより広範な制御権限を持ちます。 root ユーザーは、一般のユーザーでは実行できない重要なシステム コマンドを実行したり、システム ファイルを編集したりできます。このガイドでは、Ubuntu の root ユーザー、root としてログインする方法、および通常のユーザーとの違いについて説明します。知らせ

Windows 11 ガイドの探索: 古いハード ドライブ上のユーザー フォルダーにアクセスする方法 Windows 11 ガイドの探索: 古いハード ドライブ上のユーザー フォルダーにアクセスする方法 Sep 27, 2023 am 10:17 AM

特定のフォルダーは権限の関係で常にアクセスできるわけではありません。今日のガイドでは、Windows 11 で古いハード ドライブ上のユーザー フォルダーにアクセスする方法を説明します。このプロセスは簡単ですが、ドライブのサイズによっては、しばらく時間がかかり、場合によっては数時間もかかる場合があるため、特に忍耐強く、このガイドの指示に厳密に従ってください。古いハードドライブ上のユーザーフォルダーにアクセスできないのはなぜですか?ユーザー フォルダーは別のコンピューターによって所有されているため、変更できません。このフォルダーには所有権以外の権限がありません。古いハードドライブ上のユーザーファイルを開くにはどうすればよいですか? 1. フォルダーの所有権を取得し、アクセス許可を変更します。 古いユーザー ディレクトリを見つけて右クリックし、[プロパティ] を選択します。 「An」に移動します

チュートリアル: Ubuntu システムで通常のユーザー アカウントを削除する方法は? チュートリアル: Ubuntu システムで通常のユーザー アカウントを削除する方法は? Jan 02, 2024 pm 12:34 PM

Ubuntu システムに多くのユーザーが追加されました。使用しなくなったユーザーを削除したいのですが、どうすればよいですか?以下の詳細なチュートリアルを見てみましょう。 1. ターミナルのコマンドラインを開き、userdel コマンドを使用して、指定したユーザーを削除します。下図に示すように、必ず sudo 権限コマンドを追加してください。 2. 削除するときは、必ず管理者ディレクトリにいることを確認してください。一般ユーザー以下の図に示すように、この権限がありません。 3. 削除コマンドを実行した後、本当に削除されたかどうかをどのように判断しますか?次に、下の図に示すように、cat コマンドを使用して passwd ファイルを開きます。 4. 次の図に示すように、削除されたユーザー情報が passwd ファイル内になくなっていることがわかり、ユーザーが削除されたことがわかります。 5. 次に、ホームファイルを入力します

sudo とは何ですか?なぜ重要ですか? sudo とは何ですか?なぜ重要ですか? Feb 21, 2024 pm 07:01 PM

sudo (スーパーユーザー実行) は、一般ユーザーが root 権限で特定のコマンドを実行できるようにする、Linux および Unix システムの重要なコマンドです。 sudo の機能は主に次の側面に反映されています。 権限制御の提供: sudo は、ユーザーにスーパーユーザー権限を一時的に取得することを許可することで、システム リソースと機密性の高い操作を厳密に制御します。一般のユーザーは、必要な場合にのみ sudo を介して一時的な権限を取得できるため、常にスーパーユーザーとしてログインする必要はありません。セキュリティの向上: sudo を使用すると、日常的な操作中に root アカウントの使用を回避できます。すべての操作に root アカウントを使用すると、誤った操作や不注意な操作には完全な権限が与えられるため、予期しないシステムの損傷につながる可能性があります。そして

Windows 11 KB5031455 のインストールに失敗し、一部のユーザーに他の問題が発生する Windows 11 KB5031455 のインストールに失敗し、一部のユーザーに他の問題が発生する Nov 01, 2023 am 08:17 AM

Microsoft は、Windows 503145511H22 以降のオプションの更新プログラムとして KB2 の一般公開を開始しました。これは、サポートされている領域での Windows Copilot、スタート メニューの項目のプレビュー サポート、タスク バーのグループ解除などを含む、Windows 11 Moment 4 の機能をデフォルトで有効にする最初の更新プログラムです。さらに、メモリ リークを引き起こす潜在的なパフォーマンスの問題など、Windows 11 のいくつかのバグも修正されています。しかし皮肉なことに、2023 年 9 月のオプションのアップデートは、アップデートをインストールしようとしているユーザーにとっても、すでにインストールしているユーザーにとっても大惨事となるでしょう。多くのユーザーはこの Wi をインストールしないでしょう

ファーウェイは革新的なMEDストレージ製品を来年発売予定:ラック容量は10PBを超え、消費電力は2kW未満 ファーウェイは革新的なMEDストレージ製品を来年発売予定:ラック容量は10PBを超え、消費電力は2kW未満 Mar 07, 2024 pm 10:43 PM

このウェブサイトは3月7日、ファーウェイのデータストレージ製品ラインの社長である周岳峰博士が最近MWC2024カンファレンスに出席し、特にウォームデータ(WarmData)とコールドデータ(ColdData)用に設計された新世代のOceanStorArctic磁電ストレージソリューションをデモンストレーションしたと報じた。ファーウェイのデータストレージ製品ラインの社長である周岳峰氏は、一連の革新的なソリューションをリリースした 画像出典: このサイトに添付されているファーウェイの公式プレスリリースは次のとおりです: このソリューションのコストは磁気テープのコストより 20% 低く、そのコストは磁気テープのコストよりも 20% 低くなります。消費電力はハードディスクよりも90%低いです。外国のテクノロジーメディアのblocksandfilesによると、ファーウェイの広報担当者も磁気電子ストレージソリューションに関する情報を明らかにした:ファーウェイの磁気電子ディスク(MED)は磁気ストレージメディアの主要な革新である。初代ME

See all articles