mysqludf_json將關係數據以JSON編碼


1. 前言

sphinx2.1版本引入了json屬性,該如何構建json格式數據呢?mysql觸發器與gearman結合應用時,只能向gearman worker傳遞單一的字符串參數,若是要將mysql表中的某些列的數據傳遞給worker處理呢?這些問題,在我工做當中遇到過的,後面再一一整理出來與你們分享。那麼,這樣將數據以json格式編碼呢,下面先介紹下lib_mysqludf_json,後續會使用到這個UDF。


lib_mysqludf_json UDF庫函數將關係數據映射爲JSON格式。
javascript

一般,數據庫中的數據映射爲JSON格式,是經過程序來轉換的。好比,PHP的json擴展,將PHP數據結構轉換爲JSON,這一般是須要遍歷整個結果集後來建立JSON格式。使用UDF來進行JSON編碼更快。 html

2. 一般用法說明

JSON UDFs在設計時考慮到在大部分狀況下,只有一個簡單和直接的映射是必須的。所以,JSON UDFs儘可能簡單的映射,儘可能少的開銷。不過,也能產生更復雜的映射。 java

2.1 lib_mysqludf_json提供的功能有:
1). 可變長度的參數列表容許直接映射
在不少狀況下, 須要映射行級別數據爲JSON數組或JSON對象。可變參數列表容許單一方法調用來接受一個完整的項目,隨後被映射爲JSON結構。 mysql

2). 字符串數據的正確轉義
字符串值映射到JSON字符串時,自動轉義以符合JSON語法。必要時,繞過自動專業行爲是很是簡單的。 git

3). 一致的NULL處理
根據數據類型對數據庫NULL值進行處理。字符串的NULL值映射到javascript null,數字的NULL值映射到javascript NaN。 github

4). 表達式自動映射成JSON對象成員
一般狀況下, 從關係型數據建立JSON對象時, 很完美的使用列名來做爲對象成員名稱。 在這種狀況下, 不須要明確提供成員名稱。 該函數簡單的複用參數表達式的文本。同時,很容易的將成員映射到一個自定義的名稱。 web

5). JSON成員名稱基本的有效性檢查
常量對象成員的名稱檢查,是不是有效的JSON成員名稱。 sql

6). 支持嵌套的JSON結構
某些狀況下,須要一個嵌套的JSON對象和/或數組。經過狀況下,由一個內部函數返回的一個字符串結果會被外部函數轉義。當使用UDF嵌套的JSON時,並不是如此。 數據庫

3. 字符串數據的轉義和引用

參數字符串一般自動的映射到JSON雙引號的字符串。字符串值轉義成一個有效的JSON值。下面的字符須要轉義:
「轉義成\"
換行轉義成\n
回車轉義成\r
\轉義成\

4. 表達式映射到對象成員

爲了儘量容易的將行數據映射成JSON對象,json_object函數將每一個參數映射成一個成員。表達式文本做爲成員名稱,值做爲成員值。這能夠絕不費力的處理許多常見的狀況。
然而,這並非說json_object函數盲目的使用表達式文本。除了少數例外,須要對錶達式進行檢查,是不是有效的JSON成員名稱。在有些狀況下,使用修改後表達式文本。如aTableAlias.columnName改成columnName.
老是能夠覆蓋自動成員名稱映射,這是經過內部函數調用一個包含別名的表達式。

5. 函數

lib_mysqludf_json庫的目的是提供了一系列將關係數據映射到JSON格式函數。當前支持的函數有:
1). json_array:映射可變數目參數到JSON數組
2). json_members:映射可變數目的name-value對到JSON對象成員
3). json_object:映射可變數目的參數到JSON對象
4). json_values:映射可變數目的參數到JSON值

使用lib_mysqludf_json_info()來獲取當前安裝的lib_mysqludf_json信息。 json


下面分別介紹這四個函數:
4.1 json_array([arg1,..,argN])
json_array接受任何類型的參數,返回一個字符串。
4.1.1 [arg1,..,argN]
能夠是任何數據類型,包含空。
1. 數值類型映射到十進制數
2. 字符串、位、時間類型映射到雙引號的字符串
3. 對數字類型NULL值,映射爲NaN。對字符串類型NULL值,映射爲null
4. 參數列表能夠爲空,這種狀況下,返回一個空字符串,也就是一個空數組

4.1.2 返回
求javascript表達式的數組值

4.1.3 安裝

# wget https://github.com/mysqludf/lib_mysqludf_json/archive/master.zip
# unzip master.zip
# cd lib_mysqludf_json-master
# mv lib_mysqludf_json.so  lib_mysqludf_json.so_bak
# gcc $(/usr/local/mysql5.6/bin/mysql_config --cflags) -shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
# cp lib_mysqludf_json.so /usr/local/mysql5.6/lib/plugin/
# mysql -uroot -p -h127.0.0.1
mysql> CREATE FUNCTION json_array RETURNS STRING SONAME 'lib_mysqludf_json.so';
Query OK, 0 rows affected (0.00 sec)

lib_mysqludf_json位數必定要和mysql一致。不然會報下面錯誤:
ERROR 1126 (HY000): Can't open shared library 'lib_mysqludf_json.so' (errno: 11 /usr/local/mysql5.6/lib/plugin/lib_mysqludf_json.so: wrong ELF class: ELFCLASS32)
https://github.com/mysqludf/lib_mysqludf_json提供的是32位的。
查看是否安裝成功:

mysql> select * from mysql.func;
+------------+-----+----------------------+----------+
| name       | ret | dl                   | type     |
+------------+-----+----------------------+----------+
| json_array |   0 | lib_mysqludf_json.so | function |
+------------+-----+----------------------+----------+
1 row in set (0.00 sec)

卸載該函數:

mysql> DROP FUNCTION json_array;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from mysql.func;
Empty set (0.00 sec)

4.1.4 實例
建立一張表:

mysql> create table `ttlsa_users` (
    -> `uid` int(11) unsigned,
    -> `username` varchar(40) NOT NULL,
    -> `password` varchar(40) NOT NULL,
    -> `createtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    -> PRIMARY KEY (`uid`)
    -> );

插入數據:

mysql> insert into `ttlsa_users` values (888,'ttlsa_admin',md5('websiteadmin'),null);
Query OK, 1 row affected (0.00 sec)

建立數組:

mysql> select json_array(uid,username,password,createtime) as userinfo from ttlsa_users;
+------------------------------------------------------------------------------+
| userinfo                                                                     |
+------------------------------------------------------------------------------+
| [888,"ttlsa_admin","6a6e41c9b741f740cfa5f266b249d452","2013-08-10 11:04:00"] |
+------------------------------------------------------------------------------+
1 row in set (0.01 sec)

建立嵌套數組:

mysql> select json_array(uid,json_array(username,password),createtime) as userinfo from ttlsa_users;                             
+--------------------------------------------------------------------------------+
| userinfo                                                                       |
+--------------------------------------------------------------------------------+
| [888,["ttlsa_admin","6a6e41c9b741f740cfa5f266b249d452"],"2013-08-10 11:04:00"] |
+--------------------------------------------------------------------------------+
1 row in set (0.00 sec)

遇到特殊字符會自動轉義:

mysql> select json_array('\"\"');
+--------------------+
| json_array('\"\"') |
+--------------------+
| ["\"\""]           |
+--------------------+
1 row in set (0.00 sec)
mysql> select json_array('""');
+------------------+
| json_array('""') |
+------------------+
| ["\"\""]         |
+------------------+
1 row in set (0.00 sec)

有時候,須要避免這種自動轉義,直接將原數據存入到數據庫,可使用json_前綴來避免,以下所示:

mysql> select json_array('""'json_);   
+-----------------------+
| json_array('""'json_) |
+-----------------------+
| [""]                  |
+-----------------------+
1 row in set (0.00 sec)
mysql> select json_array('\"\"' json_);
+--------------------------+
| json_array('\"\"' json_) |
+--------------------------+
| [""]                     |
+--------------------------+
1 row in set (0.00 sec)

當表達式自身已是以json_開頭的名字,那麼json_別名是不須要的。如,若是有一個列名爲json_data的表,那麼該列的值將不會轉義。若是真但願它轉義,可使用一個除json_外的任何列名。以下所示:

mysql> update ttlsa_users set json_data='\\website\\ - "http://www.ttlsa.com"' where uid=888;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from ttlsa_users;
+-----+-------------+----------------------------------+---------------------+------------------------------------+
| uid | username    | password                         | createtime          | json_data                          |
+-----+-------------+----------------------------------+---------------------+------------------------------------+
| 888 | ttlsa_admin | 6a6e41c9b741f740cfa5f266b249d452 | 2013-08-10 11:27:01 | \website\ - "http://www.ttlsa.com" |
+-----+-------------+----------------------------------+---------------------+------------------------------------+
1 row in set (0.00 sec)

mysql> select json_array(json_data) as userinfo from ttlsa_users;   
+--------------------------------------+
| userinfo                             |
+--------------------------------------+
| [\website\ - "http://www.ttlsa.com"] |
+--------------------------------------+
1 row in set (0.00 sec)

能夠看到」和\沒有轉義。

mysql> select json_array(json_data xuhh) as userinfo from ttlsa_users;  
+--------------------------------------------+
| userinfo                                   |
+--------------------------------------------+
| ["\\website\\ - \"http://www.ttlsa.com\""] |
+--------------------------------------------+
1 row in set (0.00 sec)

能夠看到「和\都轉義了。 直接的說就是定義別名。

4.2 json_object([arg1,..,argN])
json_object接受可變數目的參數,並將它們映射到JSON值,並返回一個關聯數組。

4.2.1 [arg1,..,argN]
值能夠是任何類型包括空。 表達式文本做爲成員名稱,也就是鍵。目的是很容易的將純表中的數據轉換成JSON對象。表達式會被檢查以確認產生的是一個有效的javascript標識符。
有時,使用表達式做爲成員名稱並不恰當,可使用別名。

4.2.2 返回
求javascript表達式的javascript值(關聯數組)

4.2.3 安裝

mysql> CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
Query OK, 0 rows affected (0.00 sec)

查看:

mysql> select * from mysql.func;
+-------------+-----+----------------------+----------+
| name        | ret | dl                   | type     |
+-------------+-----+----------------------+----------+
| json_array  |   0 | lib_mysqludf_json.so | function |
| json_object |   0 | lib_mysqludf_json.so | function |
+-------------+-----+----------------------+----------+
2 rows in set (0.00 sec)

卸載:

mysql> DROP FUNCTION json_object;

4.2.4 實例

mysql> select json_object(uid, username as name, password as pw, createtime) from ttlsa_users;
+-------------------------------------------------------------------------------------------------------------+
| json_object(uid, username as name, password as pw, createtime)                                              |
+-------------------------------------------------------------------------------------------------------------+
| {"uid":888,"name":"ttlsa_admin","pw":"6a6e41c9b741f740cfa5f266b249d452","createtime":"2013-08-10 11:27:01"} |
+-------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

json_object能夠與json_members結合使用。

4.3 json_members(name1,value1[,..,..,nameN,valueN])
該函數能夠用來對任意的名稱設置name-value對的JSON對象成員列表。
自動映射不會處理嵌套的對象,說白了就是關聯數組的關聯數組,如array('website'=>array('網址'=>'www.ttlsa.com','QQ羣'=>39514058)),json_members至關於'website',json_object至關於array('網址'=>'www.ttlsa.com','QQ羣'=>39514058)。
json_members函數的目的是方便建立嵌套的JSON對象。

4.3.1 name1,value1[,..,..,nameN,valueN]
一系列的name-value對。name做爲JSON對象成員的成員名稱,value是該成員的值。

4.3.2 返回
以逗號分割的JSON關聯值的JSON成員名稱。
若是名稱是一個常量表達式,須要檢查是不是有效的JSON成員名稱。若是名稱不是常量,不執行檢查。

4.3.3 安裝

mysql> CREATE FUNCTION json_members RETURNS STRING SONAME 'lib_mysqludf_json.so';
Query OK, 0 rows affected (0.00 sec)

查看:

mysql> select * from mysql.func;
+--------------+-----+----------------------+----------+
| name         | ret | dl                   | type     |
+--------------+-----+----------------------+----------+
| json_array   |   0 | lib_mysqludf_json.so | function |
| json_object  |   0 | lib_mysqludf_json.so | function |
| json_members |   0 | lib_mysqludf_json.so | function |
+--------------+-----+----------------------+----------+
3 rows in set (0.00 sec)

卸載:

mysql> DROP FUNCTION json_members;

4.3.4 實例

mysql> select json_object(uid,json_members('user_info',json_object(username as name)),json_data) from ttlsa_users; 
+------------------------------------------------------------------------------------+
| json_object(uid,json_members('user_info',json_object(username as name)),json_data) |
+------------------------------------------------------------------------------------+
| {"uid":888,"user_info":{"name":"ttlsa_admin"},\website\ - "http://www.ttlsa.com"}  | 
+------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select json_object(uid,json_members('user_info',json_object(json_data da))) from ttlsa_users;

ERROR 2013 (HY000): Lost connection to MySQL server during query
會失去鏈接,數據庫被重啓了。why?詳細信息請看:《lib_mysqludf_json致使mysql重啓緣由分析》

4.4 json_values([arg1,..,argN])
接收可變數目的參數,並返回一個關聯javascript對象的字符串。

4.4.1 [arg1,..,argN]
能夠是任何數據類型,包含空。
1. 數值類型映射到十進制數
2. 字符串、位、時間類型映射到雙引號的字符串
3. 對數字類型NULL值,映射爲NaN。對字符串類型NULL值,映射爲null
4. 參數列表能夠爲空,這種狀況下,返回一個空字符串,也就是一個空數組

4.4.2 返回
一個javascript值

4.4.3 安裝

mysql> CREATE FUNCTION json_values RETURNS STRING SONAME 'lib_mysqludf_json.so';
Query OK, 0 rows affected (0.02 sec)

查看:

mysql> select * from mysql.func;
+--------------+-----+----------------------+----------+
| name         | ret | dl                   | type     |
+--------------+-----+----------------------+----------+
| json_array   |   0 | lib_mysqludf_json.so | function | 
| json_object  |   0 | lib_mysqludf_json.so | function | 
| json_members |   0 | lib_mysqludf_json.so | function | 
| json_values  |   0 | lib_mysqludf_json.so | function | 
+--------------+-----+----------------------+----------+
4 rows in set (0.00 sec)

卸載:

mysql> DROP FUNCTION json_values;

4.4.4 實例

mysql> select json_values(json_data) from ttlsa_users;   
+------------------------------------+
| json_values(json_data)             |
+------------------------------------+
| \website\ - "http://www.ttlsa.com" | 
+------------------------------------+
1 row in set (0.00 sec)

mysql> select json_values(json_data xx) from ttlsa_users;
+------------------------------------------+
| json_values(json_data xx)                |
+------------------------------------------+
| "\\website\\ - \"http://www.ttlsa.com\"" | 
+------------------------------------------+
1 row in set (0.00 sec)

如需轉載請註明出處:mysqludf_json將關係數據以JSON編碼 http://www.ttlsa.com/html/2269.html

相關文章
相關標籤/搜索