浅析mysql几种不同的注释风格(代码片段)

老叶茶馆_ 老叶茶馆_     2022-12-06     104

关键词:

前言

MySQL Server当前支持如下3种注释风格:

  • 以'#'开头的单行注释

  • 以'-- '开头的单行注释

  • C语言风格的单行/多行注释

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

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

可执行注释

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

/*! 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.02
50738 -> 5.7.38
80025 -> 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)

结语

MySQL Server提供的可执行注释功能,在横向跨数据库和纵向跨版本兼容上都为数据库用户提供了较大支持,是一个比较便利的特性。

功能实现上,MySQL Server是在词法解析阶段先对语句做了一遍拦截,针对/*!按具体情况做了特殊处理,如有兴趣您可以参考MySQL的词法解析相关源码。

注:以8.0.25版本为例,它的相关解析放在sql_lex.cc的lex_one_token()中,在其中您也能看见MySQL词法解析器是怎么对optimizer hints comments(格式: /*+ optimizer_hints */ )进行处理的。

Enjoy GreatSQL :)


《深入浅出MGR》视频课程

戳此小程序即可直达B站

https://www.bilibili.com/medialist/play/1363850082?business=space_collection&business_id=343928&desc=0



文章推荐:


想看更多技术好文,点个“在看”吧!

mysql注释(代码片段)

...空格、tab、换行符等等)。该语法与标准SQL注释语法稍有不同,后者将在1.8.5.7,“‘--’作为注释起始标记”中讨论。·         从/*序列到后面的*/序列。结束序列不一定在同一行中,因此该语法允许注释跨越多行。下... 查看详情

架构师技能1:java工程规范浅析领域模型vodtodopo优秀命名(代码片段)

把我们之前项目的相关规范做了个总结记录下来,仅供参考,望能有点帮助。每个人的代码风格迥异,通过统一的编码风格使得代码可读性大大提高。编程规约或者编码规范的的本质是提高了代码的可读性,最终... 查看详情

mysql内存管理机制浅析(代码片段)

...用,转载请联系小编并注明来源。MySQL内存管理机制浅析一、placementnew的定义二、placementnew使用场景三、placementnew和MySQL内存管理机制的关系四、MySQL中mem_root使用场景一、placementnew的定义通常情况下,C++中通过用new... 查看详情

mysql-innodb数据页结构浅析(代码片段)

在MySQL-InnoDB行格式浅析中,们简单提了一下页的概念,它是InnoDB管理存储空间的基本单位,一个页的大小一般是16KB。InnoDB为了不同的目的而设计了许多种不同类型的页:存放表空间头部信息的页存放InsertBuffer信息... 查看详情

doxygen教程之注释风格(代码片段)

...成工具。要使用doxygen生成接口文档,就必须遵循它的注释规范,下面对它的注释规范进行简单介绍。1.JavaDoc风格注释:/***yourcommen 查看详情

const浅析(代码片段)

前言c++中使用到const的地方有很多,而且const本身也针对不同的类型可能有不同的含义,比如对指针就有顶层和底层.本节就是探讨关于C++中const的在不同的地方不同表现或含义.const关于const:const修饰的对象一旦创建一般就不能改变,所... 查看详情

各种流行的编程风格(代码片段)

在过去的N年中,我遇到了很多使用囧然不同风格的开发者,下面是我所知道的一些,你还知道其它的吗?散弹枪编程这种编程风格是一种开发者使用非常随意的方式对待代码。“嗯,这个方法调用出错了……那么我会... 查看详情

用doxygen风格注释代码生成文档(代码片段)

目录用doxygen风格注释代码生成文档1.说明2.具体操作2.1生成头部注释2.2安装doxygen2.3工程配置3.总结用doxygen风格注释代码生成文档1.说明目前由代码生成文档的方式将使项目变得简单,同时生成的文档也会将与代码同步起来。要注... 查看详情

技术分析|浅析mysql与elasticsearch的组合使用(代码片段)

* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。1.导入2.ElasticSearch入门2.1.ElasticSearch介绍2.2.ElasticSearch的安装2.3.ElasticSearch概念入门2.4.ElasticSearch简单操作2.5.MySQL与ElasticSearch的实际应用3.小结1.导入... 查看详情

mysql提权的几种方式(代码片段)

MYSQL在windows和linux平台下存在几种不同的提权姿势,以下会做相关阐述,更多的是学习前辈的经验WindowsUDF提权在windows下存在一个叫做动态链接库的东西,俗称DLL。该文件会把程序代码中使用的函数编译成机器码,保存在DLL文件... 查看详情

html原点的不同风格(代码片段)

查看详情

doxygen教程之注释风格(代码片段)

...成工具。要使用doxygen生成接口文档,就必须遵循它的注释规范,下面对它的注释规范进行简单介绍。1.JavaDoc风格注释:/***yourcommenttext.*/2.Qt风格:/*!*yourcommenttext.*/3.仿c++风格://///!///yourcommenttext.或者://!yourcommenttext... 查看详情

mysql性能优化浅析及线上案例(代码片段)

...篇帖子讲的很全面和深刻,这也就是为什么我的标题是‘浅析’,程序员的成长一定是要付出代价和成本,因为只有真的在一线切身体会到当时的紧张和压力,对于一件事情才能印象深刻,但反之也不能太过于强调代价,如果可... 查看详情

浅析jdk中serviceloader的源码(代码片段)

前提紧接着上一篇《通过源码浅析JDK中的资源加载》,ServiceLoader是SPI(ServiceProviderInterface)中的服务类加载的核心类,也就是,这篇文章先介绍ServiceLoader的使用方式,再分析它的源码。ServiceLoader的使用这里先列举一个经典的例子... 查看详情

vim添加多行注释的几种方式(代码片段)

最近需要在阿里云上部署项目,不可避免地会遇到vim这个工具,查了一些资料,总结了一下使用vim多行注释的方法块操作多行注释:首先按esc进入命令行模式下,按下Ctrl+v,进入列(也叫区块)模式;在行首使用上下键选择需要... 查看详情

python相对绝对导入浅析(代码片段)

这篇文章从另外一个不同的视角来分析一下Python的import机制,主要的目的是为了搞懂import中absolute、relativeimport遇到的几个报错。 这里不同的视角是指从Pythonimporthooks这个方面来展开,当然本身关于Pythonimporthooks有很多的文章... 查看详情

技术原理:mysql数据库事务浅析(代码片段)

在SQL编程中,事务编程已然成为必不可少的一个组成部分。本文将基于MySQL对数据库事务进行简单的介绍和分析。一、事务概述事务可以由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成。事务是访问并更新... 查看详情

注解浅析(代码片段)

注解,和反射一样,是Java中最重要却最容易被人遗忘的知识点。哪怕Spring、SpringMVC、SpringBoot等框架中充满了注解,我们还是选择性地忽视它。很多人不明白它是怎么起作用的,甚至有人把它和注释混淆...工作中也只是机械性地... 查看详情