MySQL Server可执行注释

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*/

在日常使用中,我们经常看到以下格式的评论语句:

[En]

In our daily use, we often see comment statements in the following format:

/*!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);

以下语句修改确保了表创建语句的向下版本是兼容的:

[En]

The following statement modification ensures that the downward version of the table creation statement is compatible:

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 😃

文章推荐:

有趣的SQL DIGEST

ulimits不生效导致数据库启动失败和相关设置说明
MGR及GreatSQL资源汇总

GreatSQL MGR FAQ

在Linux下源码编译安装GreatSQL/MySQL

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

Gitee:
https://gitee.com/GreatSQL/GreatSQL

GitHub:
https://github.com/GreatSQL/GreatSQL

Bilibili:
https://space.bilibili.com/1363850082/favlist

技术交流群:

微信:扫码添加 GreatSQL社区助手微信好友,发送验证信息 加群

MySQL Server可执行注释

Original: https://www.cnblogs.com/greatsql/p/16600846.html
Author: GreatSQL
Title: MySQL Server可执行注释

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/504986/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 聊天软件的后端架构NIO

    聊天软件等的技术,朋友圈,钉钉,微博分两种技术模式:1.读扩散:也就是拉模式消息会存储到自己的发件箱里面,然后让每个上线的人去拉取未读消息,缺点是每次都要去好多底线去拉取数据,读操…

    数据库 2023年6月16日
    0142
  • 【黄啊码】小程序:九宫格抽奖如何实现?可控制抽奖率

    如果让你用微信小程序获取经纬度,然后在后台计算距离,返回数据 一般人的逻辑就是:getLocation之后直接request 然而,当你request后才发现,根本没有弹窗,wha…

    数据库 2023年6月16日
    0151
  • Redis的五大数据类型(简单使用)

    redis是基于内存的,内存的读写速度非常快 ; redis是单线程的,省去了很多上下文切换线程的时间; *redis因为是基于内存的 不涉及io操作 所以单线程效率是最高的 回归…

    数据库 2023年6月6日
    0101
  • show engine innodb status 输出结果解读

    show engine innodb status 输出结果解读 基于MySQL 5.7.32最近想整理一下show engine innodb status的解读,但是发现中文互…

    数据库 2023年6月16日
    0112
  • ATM系统开发(Java版)

    ATM系统Java模拟开发总结 ATM系统开发 技术点分析 1.面向对象编程 每个用户的账户都是一个对象,所以需要设计账户类Accent用于创建账户对象封装账户信息。 2.使用集合…

    数据库 2023年6月16日
    073
  • MySQL查询性能优化七种武器之链路追踪

    MySQL优化器可以生成Explain执行计划,我们可以通过执行计划查看是否使用了索引,使用了哪种索引? 但我们并不确切地知道为什么使用这个索引。 [En] But we don&…

    数据库 2023年5月24日
    077
  • Markdown学习

    Markdown学习 标题 三级标题 四级标题 字体 hello word hello word hello word hello word 引用 环境更加hi举报 分割线 图片 …

    数据库 2023年6月11日
    0105
  • JUC学习笔记(一)

    1、什么是 JUC 1.1、JUC简介 在 Java 中,线程部分是一个重点,本篇文章说的 JUC 也是关于线程的。JUC 就是 java.util .concurrent 工具包…

    数据库 2023年6月6日
    0101
  • 容器化 | 在 S3 实现定时备份

    让我们来看看该功能是如何使用的。 [En] Let’s take a look at how this feature is used. 可用 Cron 表达式(与 L…

    数据库 2023年5月24日
    072
  • DistSQL 深度解析:打造动态化的分布式数据库

    一、背景 自 ShardingSphere 5.0.0 版本发布以来,DistSQL 为 ShardingSphere 生态带来了强大的动态管理能力,通过 DistSQL,用户可以…

    数据库 2023年6月16日
    076
  • 内部类

    🐓内部类 可以将一个类定义在另一个类或方法中,这样的类称为内部类 将类定义在另一个类中成员的位置 public class Inner { // 定义在类内部 class Demo…

    数据库 2023年6月14日
    075
  • Java学习-第一部分-第一阶段-第八节:项目-房屋出租系统

    项目-房屋出租系统 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 房屋出租系统-需求 ●项目需求说明 实现基于…

    数据库 2023年6月11日
    078
  • leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树(中等)

    一、题目大意 给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节…

    数据库 2023年6月16日
    0108
  • 第07章 MySQL单行函数

    第07章 MySQL单行函数 1. 函数的理解 1.1 什么是函数 函数在计算机语言的使用中贯穿始终,函数的作用是什么呢?它可以把我们经常使用的代码封装起来,需要的时候直接调用即可…

    数据库 2023年5月24日
    073
  • JUC学习笔记(七)

    1.1、读写锁介绍 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取…

    数据库 2023年6月6日
    0105
  • 详解在Linux中安装配置MongoDB

    最近在整理自己私人服务器上的各种阿猫阿狗,正好就顺手详细记录一下清理之后重装的步骤,今天先写点数据库的内容,关于在 Linux中安装配置 MongoDB 说实话为什么会装 Mong…

    数据库 2023年6月11日
    0165
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球