MySQL 可載入函數的介面提供以下功能與特性:
函數可以傳回字串、整數或實數值,並且可以接受相同類型的引數。
您可以定義每次操作單一列的簡單函數,或操作多列群組的彙總函數。
提供給函數的資訊使其能夠檢查傳遞給它們的引數數量、類型和名稱。
您可以告知 MySQL 在將引數傳遞給函數之前,將引數強制轉換為指定的類型。
您可以指出函數傳回
NULL
或發生錯誤。
為了使可載入函數機制正常運作,函數必須以 C++ 撰寫,並且您的作業系統必須支援動態載入。MySQL 原始碼發行版包含一個檔案 sql/udf_example.cc
,其中定義了五個可載入函數介面函數。請參考此檔案以了解可載入函數的呼叫慣例如何運作。include/mysql_com.h
標頭檔定義了可載入函數相關的符號和資料結構,雖然您不需要直接包含此標頭檔;它會被 mysql.h
包含。
可載入函數包含會成為執行中伺服器一部分的程式碼,因此當您撰寫可載入函數時,您必須遵守所有適用於撰寫伺服器程式碼的約束。例如,如果您嘗試使用 libstdc++
程式庫中的函數,可能會遇到問題。這些約束可能會在伺服器的未來版本中變更,因此伺服器升級可能會需要修訂最初為舊伺服器撰寫的可載入函數。有關這些約束的資訊,請參閱 MySQL 原始碼組態選項和處理編譯 MySQL 時的問題。
為了能夠使用可載入函數,您必須動態連結 mysqld。如果您想要使用需要存取 mysqld 中符號的可載入函數(例如,sql/udf_example.cc
中的 metaphone
函數使用 default_charset_info
),您必須使用 -rdynamic
連結該程式(請參閱 man dlopen
)。
對於您想要在 SQL 陳述式中使用的每個函數,您應該定義對應的 C++ 函數。在以下討論中,範例函數名稱使用 「xxx」。為了區分 SQL 和 C++ 的用法,XXX()
(大寫)表示 SQL 函數呼叫,而 xxx()
(小寫)表示 C++ 函數呼叫。
當使用 C++ 時,請將您的 C 函數封裝在此建構中
extern "C" { ... }
這確保您的 C++ 函數名稱在完成的函數中保持可讀。
以下清單描述您撰寫的 C++ 函數,以實作名為 XXX()
的函數介面。主要函數 xxx()
是必要的。此外,可載入函數至少需要此處描述的其他函數之一,原因在可載入函數安全注意事項中討論。
-
xxx()
主要函數。這是計算函數結果的地方。SQL 函數資料類型與 C++ 函數傳回類型之間的對應關係如下所示。
也可以宣告
DECIMAL
函數,但該值會以字串形式傳回,因此您應該將該函數撰寫為STRING
函數。ROW
函數未實作。 -
xxx_init()
xxx()
的初始化函數。如果存在,它可以用於以下目的檢查
XXX()
的引數數量。驗證引數是否為所需的類型,或者告知 MySQL 在呼叫主要函數時將引數強制轉換為所需的類型。
配置主要函數所需的任何記憶體。
指定結果的最大長度。
指定(對於
REAL
函數)結果中的最大小數位數。指定結果是否可以為
NULL
。
-
xxx_deinit()
xxx()
的取消初始化函數。如果存在,它應該釋放初始化函數所配置的任何記憶體。
當 SQL 陳述式調用 XXX()
時,MySQL 會呼叫初始化函數 xxx_init()
,使其執行任何必要的設定,例如引數檢查或記憶體配置。如果 xxx_init()
傳回錯誤,MySQL 會以錯誤訊息中止 SQL 陳述式,並且不會呼叫主要或取消初始化函數。否則,MySQL 會為每列呼叫主要函數 xxx()
一次。處理完所有列後,MySQL 會呼叫取消初始化函數 xxx_deinit()
,使其執行任何必要的清理。
對於像 SUM()
一樣運作的彙總函數,您還必須提供以下函數
-
xxx_clear()
重置目前的彙總值,但不會將引數作為新群組的初始彙總值插入。
-
xxx_add()
將引數新增至目前的彙總值。
MySQL 處理彙總可載入函數的方式如下
呼叫
xxx_init()
,使彙總函數配置其需要用於儲存結果的任何記憶體。根據
GROUP BY
運算式排序資料表。針對每個新群組中的第一列呼叫
xxx_clear()
。針對屬於同一群組的每一列呼叫
xxx_add()
。當群組變更或處理完最後一列後,呼叫
xxx()
以取得彙總的結果。重複步驟 3 到 5,直到處理完所有列
呼叫
xxx_deinit()
,使函數釋放它所配置的任何記憶體。
所有函數都必須是執行緒安全的。這不僅包括主要函數,還包括初始化和取消初始化函數,以及彙總函數所需的其他函數。此要求的結果是,您不得配置任何會變更的全域或靜態變數!如果您需要記憶體,您必須在 xxx_init()
中配置它,並在 xxx_deinit()
中釋放它。
本節描述您必須定義以建立簡單可載入函數的不同介面函數。有關 MySQL 呼叫這些函數的順序資訊,請參閱可載入函數介面函數。
主要的 xxx()
函數應如本節所示宣告。請注意,傳回類型和參數會因您宣告 SQL 函數 XXX()
為傳回 STRING
、INTEGER
,還是 REAL
而有所不同,這取決於 CREATE FUNCTION
陳述式中的宣告。
針對 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);
DECIMAL
函數會傳回字串值,且宣告方式與 STRING
函數相同。ROW
函數尚未實作。
宣告初始化和反初始化函數,如下所示
bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
void xxx_deinit(UDF_INIT *initid);
initid
參數會傳遞至所有三個函數。它指向一個 UDF_INIT
結構,該結構用於在函數之間傳遞資訊。UDF_INIT
結構成員如下。初始化函數應填寫任何它想要變更的成員。(若要使用成員的預設值,請保持不變。)
-
bool maybe_null
如果
xxx()
可能會傳回NULL
,xxx_init()
應將maybe_null
設定為1
。如果任何引數宣告為maybe_null
,則預設值為1
。 -
unsigned int decimals
小數點右邊的小數位數。預設值是傳遞至主函數的引數中小數位數的最大值。例如,如果函數傳遞了
1.34
、1.345
和1.3
,則預設值會是 3,因為1.345
有 3 個小數位數。對於沒有固定小數位數的引數,
decimals
值會設定為 31,這比DECIMAL
、FLOAT
和DOUBLE
資料類型允許的最大小數位數多 1。此值在mysql_com.h
標頭檔案中以常數NOT_FIXED_DEC
提供。在以下情況下,引數會使用 31 的
decimals
值:例如,FLOAT
或DOUBLE
資料行宣告時沒有明確的小數位數(例如,FLOAT
而非FLOAT(10,3)
),以及浮點常數(例如1345E-3
)。它也用於字串和其他可能在函數中轉換為數值形式的非數字引數。decimals
成員初始化的值只是預設值。可以在函數內變更它以反映執行的實際計算。預設值的決定方式為使用引數的最大小數位數。如果甚至有一個引數的小數位數為NOT_FIXED_DEC
,則該值會用於decimals
。 -
unsigned int max_length
結果的最大長度。預設的
max_length
值會因函數的結果類型而異。對於字串函數,預設值是最長引數的長度。對於整數函數,預設值為 21 位數。對於實數函數,預設值為 13 加上initid->decimals
指示的小數位數。(對於數值函數,長度會包含任何符號或小數點字元。)如果您想要傳回 blob 值,您可以將
max_length
設定為 65KB 或 16MB。此記憶體不會配置,但該值會用於決定是否需要暫時儲存資料時要使用哪種資料類型。 -
char *ptr
函數可以用於自身用途的指標。例如,函數可以使用
initid->ptr
在彼此之間傳遞配置的記憶體。xxx_init()
應配置記憶體並將其指派給此指標initid->ptr = allocated_memory;
在
xxx()
和xxx_deinit()
中,請參閱initid->ptr
以使用或釋放記憶體。 -
bool const_item
如果
xxx()
總是傳回相同的值,xxx_init()
應將const_item
設定為1
,否則設為0
。
本節說明在您建立彙總可載入函數時需要定義的不同介面函數。如需 MySQL 呼叫這些函數的順序資訊,請參閱可載入函數介面函數。
-
xxx_reset()
當 MySQL 在新的群組中找到第一列時,會呼叫此函數。它應重設任何內部摘要變數,然後使用給定的
UDF_ARGS
引數作為群組中內部摘要值的起始值。宣告xxx_reset()
,如下所示void xxx_reset(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
在 MySQL 9.0 中不需要或使用
xxx_reset()
,在該版本中,可載入函數介面會改用xxx_clear()
。但是,如果您想要讓函數與舊版伺服器搭配使用,您可以定義xxx_reset()
和xxx_clear()
。(如果您同時包含這兩個函數,在許多情況下,可以透過呼叫xxx_clear()
來重設所有變數,然後呼叫xxx_add()
將UDF_ARGS
引數新增為群組中的第一個值,以在內部實作xxx_reset()
函數。) -
xxx_clear()
當 MySQL 需要重設摘要結果時,會呼叫此函數。它會在每個新群組的開頭呼叫,但也可以呼叫它來重設沒有相符列的查詢值。宣告
xxx_clear()
,如下所示void xxx_clear(UDF_INIT *initid, char *is_null, char *error);
在呼叫
xxx_clear()
之前,is_null
會設定為指向CHAR(0)
。如果發生錯誤,您可以將值儲存在
error
引數指向的變數中。error
指向單一位元組變數,而不是字串緩衝區。MySQL 9.0 需要
xxx_clear()
。 -
xxx_add()
針對屬於相同群組的所有列呼叫此函數。您應使用它將
UDF_ARGS
引數中的值新增至您的內部摘要變數。void xxx_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
彙總可載入函數的 xxx()
函數應以與非彙總可載入函數相同的方式宣告。請參閱簡單函數的可載入函數呼叫順序。
對於彙總可載入函數,在處理完群組中的所有列之後,MySQL 會呼叫 xxx()
函數。您通常不應在此處存取其 UDF_ARGS
引數,而是應根據您的內部摘要變數傳回值。
xxx()
中的傳回值處理應以與非彙總可載入函數相同的方式完成。請參閱可載入函數傳回值和錯誤處理。
xxx_reset()
和 xxx_add()
函數處理其 UDF_ARGS
引數的方式與非彙總 UDF 的函數相同。請參閱可載入函數引數處理。
對於所有對 xxx_reset()
、xxx_clear()
、xxx_add()
和 xxx()
的呼叫,is_null
和 error
的指標引數都相同。您可以使用它來記住您收到錯誤,或者 xxx()
函數是否應傳回 NULL
。您不應將字串儲存到 *error
中!error
指向單一位元組變數,而不是字串緩衝區。
*is_null
會針對每個群組重設(在呼叫 xxx_clear()
之前)。*error
永遠不會重設。
如果在 xxx()
傳回時設定了 *is_null
或 *error
,則 MySQL 會傳回 NULL
作為群組函數的結果。
args
參數指向一個 UDF_ARGS
結構,該結構具有此處列出的成員
-
unsigned int arg_count
引數的數量。如果您要求您的函數使用特定數量的引數來呼叫,請在初始化函數中檢查此值。例如
if (args->arg_count != 2) { strcpy(message,"XXX() requires two arguments"); return 1; }
對於其他為陣列的
UDF_ARGS
成員值,陣列參照是以零為基礎的。也就是說,使用索引值 0 到args->arg_count
− 1 來參照陣列成員。 -
enum Item_result *arg_type
指向包含每個引數類型的陣列的指標。可能的值類型為
STRING_RESULT
、INT_RESULT
、REAL_RESULT
和DECIMAL_RESULT
。為了確保引數屬於給定類型,並且在引數不屬於該類型時傳回錯誤,請在初始化函數中檢查
arg_type
陣列。例如if (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != INT_RESULT) { strcpy(message,"XXX() requires a string and an integer"); return 1; }
DECIMAL_RESULT
類型的引數會以字串形式傳遞,因此您會以與STRING_RESULT
值相同的方式處理它們。作為要求函數引數為特定類型的替代方法,您可以使用初始化函數將
arg_type
元素設定為您想要的類型。這會導致 MySQL 在每次呼叫xxx()
時強制轉換引數為這些類型。例如,若要指定前兩個引數應分別強制轉換為字串和整數,請在xxx_init()
中執行此動作args->arg_type[0] = STRING_RESULT; args->arg_type[1] = INT_RESULT;
精確值十進位引數(例如
1.3
或DECIMAL
資料行值)會以DECIMAL_RESULT
類型傳遞。但是,這些值會以字串形式傳遞。若要接收數字,請使用初始化函數指定引數應強制轉換為REAL_RESULT
值args->arg_type[2] = REAL_RESULT;
-
char **args
args->args
會將關於傳遞給您函數之引數的一般性質的資訊傳達給初始化函數。對於常數引數i
,args->args[i]
指向引數值。(請參閱後續說明,了解如何正確存取值。)對於非常數引數,args->args[i]
為0
。常數引數是僅使用常數的表示式,例如3
或4*7-2
或SIN(3.14)
。非常數引數是指向可能會逐列變更之值的表示式,例如欄名稱或使用非常數引數呼叫的函數。對於主要函數的每個調用,
args->args
都包含目前正在處理的列所傳遞的實際引數。如果引數
i
代表NULL
,則args->args[i]
為空指標 (0)。如果引數不是NULL
,函數可以透過以下方式參考它-
類型為
STRING_RESULT
的引數會以字串指標加上長度的形式給定,以允許處理二進位資料或任意長度的資料。字串內容可作為args->args[i]
使用,字串長度則為args->lengths[i]
。請勿假設字串以 null 結尾。有關字串引數的其他資訊,請參閱可載入函數字元集處理。
-
對於類型為
INT_RESULT
的引數,您必須將args->args[i]
轉換為long long
值long long int_val; int_val = *((long long*) args->args[i]);
-
對於類型為
REAL_RESULT
的引數,您必須將args->args[i]
轉換為double
值double real_val; real_val = *((double*) args->args[i]);
對於類型為
DECIMAL_RESULT
的引數,該值會以字串形式傳遞,並且應該像STRING_RESULT
值一樣處理。ROW_RESULT
引數未實作。
-
-
unsigned long *lengths
對於初始化函數,
lengths
陣列會指出每個引數的最大字串長度。您不應變更這些。對於主要函數的每個調用,lengths
都會包含目前正在處理的列所傳遞之任何字串引數的實際長度。對於類型為INT_RESULT
或REAL_RESULT
的引數,lengths
仍然包含引數的最大長度 (如同初始化函數一樣)。 -
char *maybe_null
對於初始化函數,
maybe_null
陣列會指出每個引數的引數值是否可能為 null (如果否則為 0,如果是則為 1)。 -
char **attributes
args->attributes
會傳達關於函數引數名稱的資訊。對於引數i
,屬性名稱會以字串形式在args->attributes[i]
中提供,而屬性長度則為args->attribute_lengths[i]
。請勿假設字串以 null 結尾。預設情況下,函數引數的名稱是指定引數所用之表示式的文字。對於可載入函數,引數也可能具有選用的
[AS]
子句,在這種情況下,引數名稱為別名
別名
。因此,每個引數的attributes
值取決於是否提供了別名。假設可載入函數
my_udf()
的調用方式如下SELECT my_udf(expr1, expr2 AS alias1, expr3 alias2);
在此情況下,
attributes
和attribute_lengths
陣列將具有以下值args->attributes[0] = "expr1" args->attribute_lengths[0] = 5 args->attributes[1] = "alias1" args->attribute_lengths[1] = 6 args->attributes[2] = "alias2" args->attribute_lengths[2] = 6
-
unsigned long *attribute_lengths
attribute_lengths
陣列會指出每個引數名稱的長度。
如果沒有發生錯誤,初始化函數應傳回 0
,否則傳回 1
。如果發生錯誤,xxx_init()
應將以 null 結尾的錯誤訊息儲存在 message
參數中。該訊息會傳回給用戶端。訊息緩衝區的長度為 MYSQL_ERRMSG_SIZE
個字元。請盡量將訊息保持在 80 個字元以下,使其符合標準終端畫面的寬度。
主要函數 xxx()
的傳回值是函數值,適用於 long long
和 double
函數。字串函數應傳回指向結果的指標,並將 *length
設定為傳回值的長度 (以位元組為單位)。例如
memcpy(result, "result string", 13);
*length = 13;
MySQL 會使用 result
參數將緩衝區傳遞給 xxx()
函數。此緩衝區的長度足以容納 255 個字元,這些字元可以是多位元組字元。xxx()
函數可以在此緩衝區中儲存結果 (如果該結果適合的話),在這種情況下,傳回值應為指向該緩衝區的指標。如果函數將結果儲存在不同的緩衝區中,則應傳回指向該緩衝區的指標。
如果您的字串函數未使用提供的緩衝區 (例如,如果需要傳回長度超過 255 個字元的字串),則您必須使用 malloc()
在 xxx_init()
函數或 xxx()
函數中配置您自己的緩衝區空間,並在 xxx_deinit()
函數中釋放它。您可以將配置的記憶體儲存在 UDF_INIT
結構中的 ptr
插槽中,以供未來 xxx()
呼叫重複使用。請參閱簡單函數的可載入函數呼叫序列。
有關字串引數的其他資訊,請參閱可載入函數字元集處理。
若要在主要函數中指示傳回值為 NULL
,請將 *is_null
設定為 1
*is_null = 1;
若要在主要函數中指示錯誤傳回,請將 *error
設定為 1
*error = 1;
如果 xxx()
為任何列將 *error
設定為 1
,則對於目前列和 XXX()
調用所在的陳述式所處理的任何後續列,函數值均為 NULL
。(甚至不會為後續列呼叫 xxx()
)。
預設情況下,可載入函數不考慮字串引數或傳回值的字元集或定序。實際上,字串引數和傳回值會被視為二進位字串,這表示只有包含單一位元組字元的字串引數才能可靠地處理。
在 MySQL 9.0 中,用於撰寫可載入函數的介面可讓可載入函數判斷字串引數的字元集和定序,並傳回具有特定字元集和定序的字串。這些功能對於可載入函數撰寫者而言是選用的,他們可以根據需要利用這些功能。
在 MySQL 隨附散佈的可載入函數中,與以下功能和擴充功能相關聯的那些函數會利用這些字元集功能:MySQL Enterprise Audit、MySQL Enterprise Firewall、MySQL Enterprise Data Masking and De-Identification、MySQL Keyring (只有通用金鑰環可載入函數,不包括特定於特定金鑰環外掛程式的那些函數) 和 Group Replication。這僅適用於有意義的地方。例如,傳回加密資料的可載入函數是預期傳回二進位字串,而不是字元字串。
可載入函數的字元集功能是使用 mysql_udf_metadata
伺服器元件服務實作的。有關此服務的資訊,請參閱 MySQL Server Doxygen 文件,網址為 https://mysqldev.dev.org.tw/doc/index-other.html (搜尋 s_mysql_mysql_udf_metadata
和 udf_metadata_imp
)。MySQL Keyring 可載入函數的原始程式碼可在社群來源散佈中取得,第三方可載入函數撰寫者可以將其作為範例來檢查,以修改他們自己的可載入函數以支援字元集。
如果可載入函數採用字串引數或傳回字串值,並且修改為支援字元集,則以下相容性考量適用
關於它們傳遞給可載入函數的引數,應用程式將繼續運作,因為該函數現在能夠處理任何字元集中的字串引數,包括二進位字串。
如果要讓可載入函數以與其引數字元集不同的字元集傳回字串結果,則該函數必須在內部執行字元集轉換。例如,如果函數接受
latin1
引數但傳回utf8mb4
結果,就會發生這種情況。
實作可載入函數的檔案必須在執行伺服器的主機上編譯和安裝。此處描述了包含在 MySQL 來源散佈中的範例可載入函數檔案 sql/udf_example.cc
的程序。有關可載入函數安裝的其他資訊,請參閱安裝和解除安裝可載入函數。
如果將在將複寫到複本的陳述式中參考可載入函數,則您必須確保每個複本也都有可用的函數。否則,當複本嘗試調用該函數時,複寫會在複本上失敗。
udf_example.cc
檔案包含以下函數
metaphon()
會傳回字串引數的 metaphon 字串。這有點像 soundex 字串,但它更適合英文。myfunc_double()
會傳回其引數中字元的 ASCII 值總和,除以其引數長度的總和。myfunc_int()
會傳回其引數長度的總和。sequence([const int])
會傳回從給定數字開始的序列,如果未給定數字則傳回 1。lookup()
會傳回主機名稱的 IP 位址。reverse_lookup()
會傳回 IP 位址的主機名稱。可以使用'xxx.xxx.xxx.xxx'
形式的單一字串引數或四個數字來呼叫該函數。avgcost()
會傳回平均成本。這是一個彙總函數。
在 Unix 和類似 Unix 的系統上,請使用以下程序來編譯可載入函數
動態載入檔案應編譯為可共享的程式庫檔案,並使用類似如下的命令
gcc -shared -o udf_example.so udf_example.cc
如果您正在將 gcc 與 CMake 搭配使用 (這就是 MySQL 本身的組態方式),您應該能夠使用更簡單的命令來建立 udf_example.so
make udf_example
在編譯包含可載入函數的共享物件之後,您必須安裝它並告知 MySQL。使用 gcc 直接從 udf_example.cc
編譯共享物件會產生一個名為 udf_example.so
的檔案。將共享物件複製到伺服器的外掛程式目錄,並將其命名為 udf_example.so
。此目錄由 plugin_dir
系統變數的值給定。
在某些系統上,配置動態連結器的 ldconfig 程式不會識別共享物件,除非其名稱以 lib
開頭。在這種情況下,您應該將檔案 (例如 udf_example.so
) 重新命名為 libudf_example.so
。
在 Windows 上,請使用以下程序來編譯可載入函數
取得 MySQL 來源散佈。請參閱如何取得 MySQL。
如有需要,請從 http://www.cmake.org 取得 CMake 建置工具。(需要 2.6 或更新版本)。
在原始碼樹狀結構中,於
sql
目錄中尋找名為udf_example.def
和udf_example.cc
的檔案。將這兩個檔案從此目錄複製到您的工作目錄。-
建立一個包含以下內容的 CMake
makefile
(CMakeLists.txt
)PROJECT(udf_example) # Path for MySQL include directory INCLUDE_DIRECTORIES("c:/mysql/include") ADD_DEFINITIONS("-DHAVE_DLOPEN") ADD_LIBRARY(udf_example MODULE udf_example.cc udf_example.def) TARGET_LINK_LIBRARIES(udf_example wsock32)
-
建立 VC 專案和解決方案檔案,並替換成適當的
generator
值cmake -G "generator"
呼叫 cmake --help 會顯示有效的產生器列表。
-
建立
udf_example.dll
devenv udf_example.sln /build Release
在所有平台上,將共享程式庫檔案複製到 plugin_dir
目錄後,使用以下語句通知 mysqld 有新的函數。檔案名稱後綴會因平台而異(例如,Unix 和類 Unix 系統為 .so
,Windows 為 .dll
),因此請根據您的平台調整 .so
後綴。
CREATE FUNCTION metaphon RETURNS STRING
SONAME 'udf_example.so';
CREATE FUNCTION myfunc_double RETURNS REAL
SONAME 'udf_example.so';
CREATE FUNCTION myfunc_int RETURNS INTEGER
SONAME 'udf_example.so';
CREATE FUNCTION sequence RETURNS INTEGER
SONAME 'udf_example.so';
CREATE FUNCTION lookup RETURNS STRING
SONAME 'udf_example.so';
CREATE FUNCTION reverse_lookup RETURNS STRING
SONAME 'udf_example.so';
CREATE AGGREGATE FUNCTION avgcost RETURNS REAL
SONAME 'udf_example.so';
一旦安裝,函數將保持安裝狀態,直到解除安裝。
若要移除函數,請使用 DROP FUNCTION
DROP FUNCTION metaphon;
DROP FUNCTION myfunc_double;
DROP FUNCTION myfunc_int;
DROP FUNCTION sequence;
DROP FUNCTION lookup;
DROP FUNCTION reverse_lookup;
DROP FUNCTION avgcost;
CREATE FUNCTION
和 DROP FUNCTION
語句會更新 mysql.func
系統資料表,該表作為可載入函數的註冊表。這些語句需要 mysql
資料庫的 INSERT
和 DELETE
權限。
在正常的啟動順序中,伺服器會載入 mysql.func
表中註冊的函數。如果伺服器使用 --skip-grant-tables
選項啟動,則不會載入表中註冊的函數,且這些函數將不可用。
MySQL 採取多項措施來防止濫用可載入函數。
可載入函數程式庫檔案不能放置在任意目錄中。它們必須位於伺服器的外掛程式目錄中。此目錄由 plugin_dir
系統變數的值給定。
若要使用 CREATE FUNCTION
或 DROP FUNCTION
,您必須分別具有 mysql
資料庫的 INSERT
或 DELETE
權限。這是必要的,因為這些語句會從 mysql.func
表中新增和刪除列。
可載入函數除了對應於主 xxx()
函數的 xxx
符號之外,至少應定義一個符號。這些輔助符號對應於 xxx_init()
、xxx_deinit()
、xxx_reset()
、xxx_clear()
和 xxx_add()
函數。mysqld 也支援 --allow-suspicious-udfs
選項,該選項控制是否可以載入只有 xxx
符號的可載入函數。預設情況下,該選項處於禁用狀態,以防止嘗試從除包含合法可載入函數之外的共享程式庫檔案中載入函數。如果您有僅包含 xxx
符號且無法重新編譯以包含輔助符號的舊可載入函數,則可能需要指定 --allow-suspicious-udfs
選項。否則,您應該避免啟用它。