MySQL客户端允许省略分号,因其仅作为客户端判断语句结束的提示符,服务端实际接收时已剥离分号;单条完整SQL(如SELECT 1)可直接执行,但多语句、SQL文件或特定驱动场景仍需分号。
MySQL 命令行客户端 mysql 本身不是 SQL 引擎,而是一个交互式前端程序。它对输入的处理分两层:先由客户端解析语句边界,再把完整语句发给服务端执行。分号只是客户端用来判断“用户是否输完了”的默认语句结束符,不是 MySQL 服务端语法必需的。
\g 或 \G 结尾,效果等同于分号(\G 还会格式化输出)SELECT 1 没加分号,客户端会直接执行——因为它能明确判断这是完整语句SELECT 1 SELECT * FROM user WHERE id = 1
这两条在 mysql CLI 中都能直接运行,因为客户端能基于关键字和语法结构做简单断句。
MySQL 服务端(mysqld)接收的是已切分好的语句字符串,分号早在客户端就已被剥离。你用其他方式调用(如 Python 的 mysql-connector、Java 的 JDBC),传入的 cursor.execute("SELECT 1") 里带不带分号都无所谓,驱动通常会自动忽略或报错(取决于配置)。
BEGIN...END 块里的语句分隔ERROR 1064 (42000)

source 或 . 执行 SQL 文件时,文件里必须用分号分隔语句,否则只有第一句生效allowMultiQueries=true),仍需显式分号mysql -e "SELECT 1; SELECT 2",这里的分号是 shell 字符串的一部分,不是 MySQL 的,但恰好被 mysql CLI 识别为语句结束不用,也不该加。
mysql-connector-python 遇到语句末尾的分号会警告 Warning: (1785, "Statement is not safe to log in statement format.")(尤其在 GTID 模式下)pymysql 和 mysql2(Node.js)会原样传给服务端,但服务端忽略它;不过混在参数化查询中可能干扰占位符解析admin'; DROP TABLE user; -- ,如果代码拼接时又额外加了分号,风险放大cursor.execute("SELECT * FROM user WHERE name = %s;", ("admin'; DROP TABLE user; -- ",))这种写法看似加了分号,实则让恶意输入更易突破语义边界。
分号看起来只是个标点,但它横跨客户端解析、服务端执行、驱动行为、安全边界四层逻辑——漏掉它不一定报错,加上它却可能悄悄改变语义或暴露漏洞。