聊聊 MySQL Server 可执行注释,你懂了吗?

网友投稿 493 2023-04-24

聊聊 My*** 可执行注释,你懂了吗?

聊聊 My*** 可执行注释,你懂了吗?

前言

My***当前支持如下3种注释风格:

以'#'开头的单行注释以'-- '开头的单行注释C语言风格的单行/多行注释

如下SQL脚本给出了3种注释风格的示例:

/* 这是一个多行注释示例*/select 1 from dual;select 2 from dual; # 单行注释用例1select 3 from dual; -- 单行注释用例2

可执行注释

为了支持在不同数据库之间的可移植性,My***针对C风格的注释在解析上做了一些扩展,当注释满足如下风格时,My***将会解析并执行注释中的代码:

/*! MySQL-specific code */

通过比较如下两个带注释的SQL语句的执行结果可以比较直观地看出可执行注释语句的行为:

# 普通注释,'+1' 被忽略mysql> select 1 /* +1 */;+---+| 1 |+---+| 1 |+---+# 可执行注释,'+1' 被当成语句的一部分mysql> select 1 /*! +1 */;+-------+| 1 +1 |+-------+| 2 |+-------+

借助这一特性,我们就有机会编写具备较好移植性的SQL语句, 在使用MySQL独有特性的同时,保证了SQL语句在其它数据库也能够成功被执行:

create table t1(col1 int) /*! engine=MyISAM */;select /*! STRAIGHT_JOIN */ col1 from t1;...

/*!version-number SQL*/

在日常使用中,我们还会经常看到如下格式的注释语句:

/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE *//*!80000 SET SESSION information_schema_stats_expiry=0 *//*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */

/*!后跟的5位数字为版本指示器,其与数据库版本的对应规则为:

'/' '*' '!', followed by exactly第1位:主版本号(VERSION_MAJOR), 第2, 3位:小版本号(VERSION_MINOR),第4, 5位:Patch号(VERSION_PATCH)示例:32302 -> 3.23.0250738 -> 5.7.3880025 -> 8.0.25

以上述第一个注释语句为例,它的含义可以描述为:当MySQL数据库版本为5.0.3或更高版本时,将SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE读取出来参与SQL语法解析,并最终被执行;当MySQL版本低于5.0.3时,该行语句被当成一个普通的注释。不难看出,带version_number的可执行注释,是为了解决不同的MySQL版本之间的兼容问题。以8.0.23版本新增的Invisible Columnsw为例, 如下建表语句在8.0.23版本之前将无法执行:

CREATE TABLE t1 (i INT, j DATE INVISIBLE);

如下的语句改造则保证了建表语句的向下版本兼容:

CREATE TABLE t1 (i INT, j DATE /*!80023 INVISIBLE */);

实际上,在我们常用的工具mysqldump也借用这个特性,使得产生的SQL能够兼容不同的数据库版本:

/*mysqldump 代码片段*/ dump_fputs( sql_file, "/*!50717 SELECT COUNT(*) INTO @rocksdb_has_p_s_session_variables" " FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA =" " 'performance_schema' AND TABLE_NAME = 'session_variables'" " */;\n" "/*!50717 SET @rocksdb_get_is_supported = IF" " (@rocksdb_has_p_s_session_variables, 'SELECT COUNT(*) INTO" " @rocksdb_is_supported FROM performance_schema.session_variables" " WHERE VARIABLE_NAME=\\'rocksdb_bulk_load\\'', 'SELECT 0') */;\n" "/*!50717 PREPARE s FROM @rocksdb_get_is_supported */;\n" "/*!50717 EXECUTE s */;\n" "/*!50717 DEALLOCATE PREPARE s */;\n" "/*!50717 SET @rocksdb_enable_bulk_load = IF" " (@rocksdb_is_supported, 'SET SESSION rocksdb_bulk_load = 1'," " 'SET @rocksdb_dummy_bulk_load = 0') */;\n" "/*!50717 PREPARE s FROM @rocksdb_enable_bulk_load */;\n" "/*!50717 EXECUTE s */;\n" "/*!50717 DEALLOCATE PREPARE s */;\n"); check_io(sql_file);

在show create table等语句中我们也能看到类似的应用(sql/sql_show.cc):

mysql> create table t1 (i int, j date invisible);Query OK, 0 rows affected (0.03 sec)mysql> show create table t1;+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+| Table | Create Table |+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+| t1 | CREATE TABLE `t1` ( `i` int DEFAULT NULL, `j` date DEFAULT NULL /*!80023 INVISIBLE */) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.01 sec)

结语

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:MySQL8,体验不一样的安装方式!
下一篇:如何快速上手SQL CTE?
相关文章