1. 程式人生 > >字串與數字轉換函式 | 全方位認識 sys 系統庫

字串與數字轉換函式 | 全方位認識 sys 系統庫

本系列在之前的文章中我們為大家介紹了sys 系統庫的快捷檢視、函式,本期開始我們將為大家介紹 sys 系統庫的函式。

PS:下文中如果函式定義文字較短的會列出部分函式的定義文字,以便大家更直觀地學習它們。過長的函式定義文字請自行按照《初相識|全方位認識 sys 系統庫》一文中介紹的下載路徑下載檢視。

| extract_schema_from_file_name()

從給定檔案的絕對路徑中提取schema名稱,該函式在sys.x$ps_schema_table_statistics_io檢視中呼叫,當然你也可以在自定義檢視中呼叫

  • 此函式假定給定的所有資料檔案都位於datadir目錄下,因此,如果說表是分割槽表或者使用了單獨的表選項定義了自己的DATA_DIRECTORY路徑,那麼雖然能夠正確返回資料庫的名稱,但是後續使用這個資料庫名稱與其他檢視聯結使用時將無法在datadir下找到相應的表資料檔案

  • 該函式在擁有一個數據檔案的完整路徑時用這個路徑作為傳入引數提取performance_schema中的檔案I/O資訊非常實用, 它提供了一種便捷的方式來獲取schema名,比完整路徑名更容易理解,並且該返回的schema名稱字串值後續可以用於聯結查詢

引數:

  • path VARCHAR(512):一個用於提取schema名稱的完整資料檔案路徑

返回值:是一個VARCHAR(64)字串,即schema名稱字串

函式定義語句文字

DROP FUNCTION IF EXISTS extract_schema_from_file_name;
DELIMITER $$
CREATE DEFINER='root'@'localhost' FUNCTION extract_schema_from_file_name (
    path VARCHAR(512)
)
RETURNS VARCHAR(64)
COMMENT '
        Description
        -----------

        Takes a raw file path, and attempts to extract the schema name from it.

        Useful for when interacting with Performance Schema data 
        concerning IO statistics, for example.

        Currently relies on the fact that a table data file will be within a 
        specified database directory (will not work with partitions or tables
        that specify an individual DATA_DIRECTORY).

        Parameters
        -----------

        path (VARCHAR(512)):
          The full file path to a data file to extract the schema name from.

        Returns
        -----------

        VARCHAR(64)

        Example
        -----------

        mysql> SELECT sys.extract_schema_from_file_name(\'/var/lib/mysql/employees/employee.ibd\');
        +----------------------------------------------------------------------------+
        | sys.extract_schema_from_file_name(\'/var/lib/mysql/employees/employee.ibd\') |
        +----------------------------------------------------------------------------+
        | employees                                                                  |
        +----------------------------------------------------------------------------+
        1 row in set (0.00 sec)
        '
SQL SECURITY INVOKER
DETERMINISTIC
NO SQL
BEGIN
RETURN LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(path, '\\', '/'), '/', -2), '/', 1), 64);
END$$
DELIMITER ;

| extract_table_from_file_name()

從給定檔案絕對路徑名中提取表名,該函式在sys.x$ps_schema_table_statistics_io檢視中呼叫,當然你也可以在自定義檢視中呼叫

  • 該函式在擁有一個數據檔案的完整路徑時用這個路徑作為傳入引數提取performance_schema中的檔案I/O資訊非常實用, 它提供了一種便捷的方式來獲取表名,比完整路徑名更容易理解,並且該返回的表名稱字串值後續可以用於聯結查詢

引數:

  • path VARCHAR(512):一個用於提取表名稱的完整資料檔案路徑

返回值:是一個VARCHAR(64)字串,即表名稱字串

函式定義語句文字

DROP FUNCTION IF EXISTS extract_table_from_file_name;
DELIMITER $$
CREATE DEFINER='root'@'localhost' FUNCTION extract_table_from_file_name (
    path VARCHAR(512)
)
RETURNS VARCHAR(64)
COMMENT '
        Description
        -----------

        Takes a raw file path, and extracts the table name from it.

        Useful for when interacting with Performance Schema data 
        concerning IO statistics, for example.

        Parameters
        -----------

        path (VARCHAR(512)):
          The full file path to a data file to extract the table name from.

        Returns
        -----------

        VARCHAR(64)

        Example
        -----------

        mysql> SELECT sys.extract_table_from_file_name(\'/var/lib/mysql/employees/employee.ibd\');
        +---------------------------------------------------------------------------+
        | sys.extract_table_from_file_name(\'/var/lib/mysql/employees/employee.ibd\') |
        +---------------------------------------------------------------------------+
        | employee                                                                  |
        +---------------------------------------------------------------------------+
        1 row in set (0.02 sec)
        '
SQL SECURITY INVOKER
DETERMINISTIC
NO SQL
BEGIN
RETURN LEFT(SUBSTRING_INDEX(REPLACE(SUBSTRING_INDEX(REPLACE(path, '\\', '/'), '/', -1), '@0024', '$'), '.', 1), 64);
END$$
DELIMITER ;

| format_bytes()

將位元組值轉換為其他單位的值(可讀性更好的格式),根據位元組數值大小,自動轉換為KB、MB、GB、TB、PB這些可讀單位(返回值由轉換過的值+單位組成),該函式在其他檢視中大量使用

引數:

  • bytes TEXT:要格式化的位元組文字值

回報值:一個TEXT文字值

函式定義語句文字

 DROP FUNCTION IF EXISTS format_bytes;
 DELIMITER $$
 CREATE DEFINER='root'@'localhost' FUNCTION format_bytes (
    -- We feed in and return TEXT here, as aggregates of
    -- bytes can return numbers larger than BIGINT UNSIGNED
    bytes TEXT
)
RETURNS TEXT
COMMENT '
        Description
        -----------

        Takes a raw bytes value, and converts it to a human readable format.

        Parameters
        -----------

        bytes (TEXT):
          A raw bytes value.

        Returns
        -----------

        TEXT

        Example
        -----------

        mysql> SELECT sys.format_bytes(2348723492723746) AS size;
        +----------+
        | size    |
        +----------+
        | 2.09 PiB |
        +----------+
        1 row in set (0.00 sec)

        mysql> SELECT sys.format_bytes(2348723492723) AS size;
        +----------+
        | size    |
        +----------+
        | 2.14 TiB |
        +----------+
        1 row in set (0.00 sec)

        mysql> SELECT sys.format_bytes(23487234) AS size;
        +-----------+
        | size      |
        +-----------+
        | 22.40 MiB |
        +-----------+
        1 row in set (0.00 sec)
        '
SQL SECURITY INVOKER
DETERMINISTIC
NO SQL
BEGIN
IF bytes IS NULL THEN RETURN NULL;
ELSEIF bytes >= 1125899906842624 THEN RETURN CONCAT(ROUND(bytes / 1125899906842624, 2), ' PiB');
ELSEIF bytes >= 1099511627776 THEN RETURN CONCAT(ROUND(bytes / 1099511627776, 2), ' TiB');
ELSEIF bytes >= 1073741824 THEN RETURN CONCAT(ROUND(bytes / 1073741824, 2), ' GiB');
ELSEIF bytes >= 1048576 THEN RETURN CONCAT(ROUND(bytes / 1048576, 2), ' MiB');
ELSEIF bytes >= 1024 THEN RETURN CONCAT(ROUND(bytes / 1024, 2), ' KiB');
ELSE RETURN CONCAT(ROUND(bytes, 0), ' bytes');
END IF;
END$$
DELIMITER ;

| format_path()

用變數符號值替換路徑名中匹配到的datadir、tmpdir、slave_load_tmpdir、innodb_data_home_dir、innodb_log_group_home_dir、basedir、innodb_undo_directory系統變數值,給定null值返回null,給定值不匹配的直接返回原值,該函式在其他檢視中大量使用

  • 在MySQL 5.7.14之前,Windows路徑名中的反斜槓()將在返回值中轉換為正斜槓(/)

引數:

  • path VARCHAR(512):要格式化轉換的完整路徑名

返回值:一個VARCHAR(512) CHARACTER SET utf8 值

示例

mysql> SELECT format_path('/usr/local/mysql/data/world/City.ibd');
+-----------------------------------------------------+
| format_path('/usr/local/mysql/data/world/City.ibd') |
+-----------------------------------------------------+
| @@datadir/world/City.ibd                            |
+-----------------------------------------------------+

| format_statement()

將長SQL語句文字截斷為固定長度,該長度由配置變數@sys.statement_truncate_len控制,預設值在sys_config表中為64位元組,如果語句文字少於statement_truncate_len,@sys.statement_truncate_len配置選項的長度則語句不會被截斷,如果大於了配置選項指定的長度,則語句會被截斷,執行擷取操作時,中間部分被省略號替換(擷取前30位元組+'... '+ 後30位元組,然後把這64位元組中包含的\n字元替換為空格),該函式在其他檢視中大量使用

  • 該函式在其他檢視,儲存過程中大量使用,用於把performance_schema中的超長語句格式化為固定的長度

引數:

  • statement LONGTEXT:需要執行格式化的SQL語句文字

配置選項:可以使用以下配置選項或其相應的使用者定義變數來修改format_statement()函式的截斷最大長度

  • statement_truncate_len,@sys.statement_truncate_len:format_statement()函式返回的語句文字的最大長度。超長的語句文字將被截斷。預設值為64位元組

返回值:一個LONGTEXT長文字值

函式定義語句文字

DROP FUNCTION IF EXISTS format_statement;
DELIMITER $$
CREATE DEFINER='root'@'localhost' FUNCTION format_statement (
    statement LONGTEXT
)
RETURNS LONGTEXT
COMMENT '
        Description
        -----------

        Formats a normalized statement, truncating it if it is > 64 characters long by default.

        To configure the length to truncate the statement to by default, update the `statement_truncate_len`
        variable with `sys_config` table to a different value. Alternatively, to change it just for just 
        your particular session, use `SET @sys.statement_truncate_len := <some new value>`.

        Useful for printing statement related data from Performance Schema from 
        the command line.

        Parameters
        -----------

        statement (LONGTEXT): 
          The statement to format.

        Returns
        -----------

        LONGTEXT

        Example
        -----------

        mysql> SELECT sys.format_statement(digest_text)
            ->  FROM performance_schema.events_statements_summary_by_digest
            ->  ORDER by sum_timer_wait DESC limit 5;
        +-------------------------------------------------------------------+
        | sys.format_statement(digest_text)                                |
        +-------------------------------------------------------------------+
        | CREATE SQL SECURITY INVOKER VI ... KE ? AND `variable_value` > ?  |
        | CREATE SQL SECURITY INVOKER VI ... ait` IS NOT NULL , `esc` . ... |
        | CREATE SQL SECURITY INVOKER VI ... ait` IS NOT NULL , `sys` . ... |
        | CREATE SQL SECURITY INVOKER VI ...  , `compressed_size` ) ) DESC  |
        | CREATE SQL SECURITY INVOKER VI ... LIKE ? ORDER BY `timer_start`  |
        +-------------------------------------------------------------------+
        5 rows in set (0.00 sec)
        '
SQL SECURITY INVOKER
DETERMINISTIC
NO SQL
BEGIN
-- Check if we have the configured length, if not, init it
IF @sys.statement_truncate_len IS NULL THEN
  SET @sys.statement_truncate_len = sys_get_config('statement_truncate_len', 64);
END IF;

IF CHAR_LENGTH(statement) > @sys.statement_truncate_len THEN
  RETURN REPLACE(CONCAT(LEFT(statement, (@sys.statement_truncate_len/2)-2), ' ... ', RIGHT(statement, (@sys.statement_truncate_len/2)-2)), '\n', ' ');
ELSE
  RETURN REPLACE(statement, '\n', ' ');
END IF;
END$$
DELIMITER ;

| format_time()

將皮秒值轉換為其他可讀性更好的單位值,根據皮秒值大小,自動轉換為ns、us、ms、s、m、h、d、w這些可讀單位(返回值由轉換過的值+單位組成),該函式在其他檢視中大量使用

引數:

  • picoseconds TEXT:要進行單位轉換的皮秒文字值

返回值:一個TEXT文字值

函式定義語句文字

DROP FUNCTION IF EXISTS format_time;
DELIMITER $$
CREATE DEFINER='root'@'localhost' FUNCTION format_time (
    -- We feed in and return TEXT here, as aggregates of
    -- picoseconds can return numbers larger than BIGINT UNSIGNED
    picoseconds TEXT
)
RETURNS TEXT CHARSET UTF8
COMMENT '
        Description
        -----------

        Takes a raw picoseconds value, and converts it to a human readable form.

        Picoseconds are the precision that all latency values are printed in 
        within Performance Schema, however are not user friendly when wanting
        to scan output from the command line.

        Parameters
        -----------

        picoseconds (TEXT): 
          The raw picoseconds value to convert.

        Returns
        -----------

        TEXT

        Example
        -----------

        mysql> select format_time(342342342342345);
        +------------------------------+
        | format_time(342342342342345) |
        +------------------------------+
        | 00:05:42                    |
        +------------------------------+
        1 row in set (0.00 sec)

        mysql> select format_time(342342342);
        +------------------------+
        | format_time(342342342) |
        +------------------------+
        | 342.34 us              |
        +------------------------+
        1 row in set (0.00 sec)

        mysql> select format_time(34234);
          +--------------------+
        | format_time(34234) |
        +--------------------+
        | 34.23 ns          |
        +--------------------+
        1 row in set (0.00 sec)
        '
SQL SECURITY INVOKER
DETERMINISTIC
NO SQL
BEGIN
IF picoseconds IS NULL THEN RETURN NULL;
ELSEIF picoseconds >= 604800000000000000 THEN RETURN CONCAT(ROUND(picoseconds / 604800000000000000, 2), ' w');
ELSEIF picoseconds >= 86400000000000000 THEN RETURN CONCAT(ROUND(picoseconds / 86400000000000000, 2), ' d');
ELSEIF picoseconds >= 3600000000000000 THEN RETURN CONCAT(ROUND(picoseconds / 3600000000000000, 2), ' h');
ELSEIF picoseconds >= 60000000000000 THEN RETURN CONCAT(ROUND(picoseconds / 60000000000000, 2), ' m');
ELSEIF picoseconds >= 1000000000000 THEN RETURN CONCAT(ROUND(picoseconds / 1000000000000, 2), ' s');
ELSEIF picoseconds >= 1000000000 THEN RETURN CONCAT(ROUND(picoseconds / 1000000000, 2), ' ms');
ELSEIF picoseconds >= 1000000 THEN RETURN CONCAT(ROUND(picoseconds / 1000000, 2), ' us');
ELSEIF picoseconds >= 1000 THEN RETURN CONCAT(ROUND(picoseconds / 1000, 2), ' ns');
ELSE RETURN CONCAT(picoseconds, ' ps');
END IF;
END$$
DELIMITER ;

| list_add()

將指定文字新增到一個指定名稱的列表中,由兩個傳參定義,傳入一個列表和一個字串,返回值為在這個傳入列表基礎上添加了傳入字串的列表,如新增會話級別的sql_mode:set sql_mode=select sys.list_add(@@sql_mode,'ANSI_QUOTES');利用該函式來操作一些列表型系統變數可以減少人工賦值的失誤

  • 此函式和list_drop()函式一起可用於操作具有列表型別值的系統變數值的新增和刪除,例如:sql_mode和optimizer_switch系統變數值具有一個逗號分隔的列表值

  • 此函式在MySQL 5.7.9中新增

引數:

  • in_list TEXT:要修改值的列表變數名稱,注意:該引數只能傳入變數型別值,不能是字串值,詳見函式定義語句註釋部分示例

  • in_add_value TEXT:要新增到列表變數中的具體字串值

返回值:一個TEXT文字值

函式定義語句文字

DROP FUNCTION IF EXISTS list_add;
DELIMITER $$
CREATE DEFINER='root'@'localhost' FUNCTION list_add (
    in_list TEXT,
    in_add_value TEXT
)
RETURNS TEXT
COMMENT '
        Description
        -----------

        Takes a list, and a value to add to the list, and returns the resulting list.

        Useful for altering certain session variables, like sql_mode or optimizer_switch for instance.

        Parameters
        -----------

        in_list (TEXT):
          The comma separated list to add a value to

        in_add_value (TEXT):
          The value to add to the input list

        Returns
        -----------

        TEXT

        Example
        --------

        mysql> select @@sql_mode;
        +-----------------------------------------------------------------------------------+
        | @@sql_mode                                                                        |
        +-----------------------------------------------------------------------------------+
        | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
        +-----------------------------------------------------------------------------------+
        1 row in set (0.00 sec)

        mysql> set sql_mode = sys.list_add(@@sql_mode, ''ANSI_QUOTES'');
        Query OK, 0 rows affected (0.06 sec)

        mysql> select @@sql_mode;
        +-----------------------------------------------------------------------------------------------+
        | @@sql_mode                                                                                    |
        +-----------------------------------------------------------------------------------------------+
        | ANSI_QUOTES,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
        +-----------------------------------------------------------------------------------------------+
        1 row in set (0.00 sec)

        '
SQL SECURITY INVOKER
DETERMINISTIC
CONTAINS SQL
BEGIN

IF (in_add_value IS NULL) THEN
    SIGNAL SQLSTATE '02200'
      SET MESSAGE_TEXT = 'Function sys.list_add: in_add_value input variable should not be NULL',
          MYSQL_ERRNO = 1138;
END IF;

IF (in_list IS NULL OR LENGTH(in_list) = 0) THEN
    -- return the new value as a single value list
    RETURN in_add_value;
END IF;

RETURN (SELECT CONCAT(TRIM(BOTH ',' FROM TRIM(in_list)), ',', in_add_value));
END$$
DELIMITER ;

| list_drop()

與list_add()函式類似,只是是從傳入列表中刪除傳入字串

  • 此函式在MySQL 5.7.9中新增

引數:

  • in_list TEXT:要修改值的列表變數名稱,注意:該引數只能傳入變數型別值,不能是字串值,詳見函式定義語句註釋部分示例

  • in_drop_value TEXT:要從列表變數中刪除的文字值

返回值:一個TEXT文字值

函式定義語句文字

DROP FUNCTION IF EXISTS list_drop;
DELIMITER $$
CREATE DEFINER='root'@'localhost' FUNCTION list_drop (
    in_list TEXT,
    in_drop_value TEXT
)
RETURNS TEXT
COMMENT '
        Description
        -----------

        Takes a list, and a value to attempt to remove from the list, and returns the resulting list.

        Useful for altering certain session variables, like sql_mode or optimizer_switch for instance.

        Parameters
        -----------

        in_list (TEXT):
          The comma separated list to drop a value from

        in_drop_value (TEXT):
          The value to drop from the input list

        Returns
        -----------

        TEXT

        Example
        --------

        mysql> select @@sql_mode;
        +-----------------------------------------------------------------------------------------------+
        | @@sql_mode                                                                                    |
        +-----------------------------------------------------------------------------------------------+
        | ANSI_QUOTES,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
        +-----------------------------------------------------------------------------------------------+
        1 row in set (0.00 sec)

        mysql> set sql_mode = sys.list_drop(@@sql_mode, ''ONLY_FULL_GROUP_BY'');
        Query OK, 0 rows affected (0.03 sec)

        mysql> select @@sql_mode;
        +----------------------------------------------------------------------------+
        | @@sql_mode                                                                |
        +----------------------------------------------------------------------------+
        | ANSI_QUOTES,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
        +----------------------------------------------------------------------------+
        1 row in set (0.00 sec)

        '
SQL SECURITY INVOKER
DETERMINISTIC
CONTAINS SQL
BEGIN

IF (in_drop_value IS NULL) THEN
    SIGNAL SQLSTATE '02200'
      SET MESSAGE_TEXT = 'Function sys.list_drop: in_drop_value input variable should not be NULL',
          MYSQL_ERRNO = 1138;
END IF;

IF (in_list IS NULL OR LENGTH(in_list) = 0) THEN
    -- return the list as it was passed in
    RETURN in_list;
END IF;

-- ensure that leading / trailing commas are remove, support values with either spaces or not between commas
RETURN (SELECT TRIM(BOTH ',' FROM REPLACE(REPLACE(CONCAT(',', in_list), CONCAT(',', in_drop_value), ''), CONCAT(', ', in_drop_value), '')));
END$$
DELIMITER ;

本期內容就介紹到這裡,本期內容參考連結如下:

https://dev.mysql.com/doc/refman/5.7/en/sys-list-drop.html

https://dev.mysql.com/doc/refman/5.7/en/sys-extract-schema-from-file-name.html

https://dev.mysql.com/doc/refman/5.7/en/sys-format-bytes.html

https://dev.mysql.com/doc/refman/5.7/en/sys-format-path.html

https://dev.mysql.com/doc/refman/5.7/en/sys-format-statement.html

https://dev.mysql.com/doc/refman/5.7/en/sys-format-time.html

https://dev.mysql.com/doc/refman/5.7/en/sys-list-add.html

https://dev.mysql.com/doc/refman/5.7/en/sys-extract-table-from-file-name.html

| 作者簡介

羅小波·沃趣科技高階資料庫技術專家

IT從業多年,歷任運維工程師,高階運維工程師,運維經理,資料庫工程師,曾參與版本釋出系統,輕量級監控系統,運維管理平臺,資料庫管理平臺的設計與編寫,熟悉MySQL的體系結構時,InnoDB儲存引擎,喜好專研開源技術,追求完美。