目录
本章介绍 MySQL支持 的 SQL 语句 的语法 。
MySQL 8.0支持原子数据定义语言(DDL)语句。 此功能称为 原子DDL 。 原子DDL语句将与DDL操作关联的数据字典更新,存储引擎操作和二进制日志写入组合到单个原子事务中。 即使服务器在操作期间停止,也会提交事务,并将适用的更改保留到数据字典,存储引擎和二进制日志中,或者回滚事务。
通过在MySQL 8.0中引入MySQL数据字典,可以实现Atomic DDL。 在早期的MySQL版本中,元数据存储在元数据文件,非事务性表和存储引擎特定的字典中,这需要中间提交。 MySQL数据字典提供的集中式事务元数据存储消除了这一障碍,使得将DDL语句操作重组为原子事务成为可能。
原子DDL功能在本节的以下主题中描述:
原子DDL功能支持表和非表DDL语句。
与表相关的DDL操作需要存储引擎支持,而非表DDL操作则不需要。
目前,只有
InnoDB
存储引擎支持原子DDL。
受支持的表DDL语句包括
CREATE
,
ALTER
和
DROP
对数据库,表,表和索引,以及语句
TRUNCATE
TABLE
声明。
支持的非表DDL语句包括:
原子DDL功能不支持以下语句:
与表相关的DDL语句涉及除以外的存储引擎
InnoDB
。
CREATE
SERVER
,
ALTER
SERVER
和
DROP
SERVER
语句。
原子DDL语句的特征包括以下内容:
元数据更新,二进制日志写入和存储引擎操作(如果适用)将合并为单个事务。
在DDL操作期间,SQL层没有中间提交。
适用时:
数据字典,例程,事件和UDF高速缓存的状态与DDL操作的状态一致,这意味着更新高速缓存以反映DDL操作是成功完成还是回滚。
DDL操作中涉及的存储引擎方法不执行中间提交,并且存储引擎将自身注册为DDL事务的一部分。
存储引擎支持DDL操作的重做和回滚,这在DDL操作的 Post-DDL 阶段执行。
DDL操作的可见行为是原子的,这会更改某些DDL语句的行为。 请参阅 DDL语句行为中的更改 。
原子或其他DDL语句隐式结束当前会话中处于活动状态的任何事务,就好像您
COMMIT
在执行语句之前
完成了
一样。
这意味着DDL语句不能在另一个事务中,在事务控制语句中执行
START TRANSACTION ...
COMMIT
,或者与同一事务中的其他语句结合使用。
本节介绍由于引入原子DDL支持而导致的DDL语句行为的更改。
DROP
TABLE
如果所有命名表都使用原子DDL支持的存储引擎,则操作是完全原子的。
该语句要么成功删除所有表,要么回滚。
DROP
TABLE
如果命名表不存在,并且未进行任何更改(无论存储引擎如何),则会失败并显示错误。
以下示例演示了此行为更改,其中
DROP
TABLE
语句失败,因为命名表不存在:
mysql>CREATE TABLE t1 (c1 INT);
mysql>DROP TABLE t1, t2;
ERROR 1051(42S02):未知表'test.t2' MySQL的>SHOW TABLES;
+ ---------------- + | Tables_in_test | + ---------------- + | t1 | + ---------------- +
在引入原子DDL之前,
DROP
TABLE
报告指定表的错误,该错误不存在但成功存在于已存在的命名表中:
mysql>CREATE TABLE t1 (c1 INT);
mysql>DROP TABLE t1, t2;
ERROR 1051(42S02):未知表'test.t2' MySQL的>SHOW TABLES;
空集(0.00秒)
由于行为的这种变化,
DROP
TABLE
MySQL 5.7主服务器上
的部分完成
语句在MySQL 8.0从服务器上复制时失败。
要避免此故障情形,请
IF
EXISTS
在
DROP
TABLE
语句中
使用
语法
以防止对不存在的表发生错误。
DROP
DATABASE
如果所有表都使用原子DDL支持的存储引擎,则为atomic。
该语句要么成功删除所有对象,要么回滚。
但是,从文件系统中删除数据库目录最后发生,并且不是原子事务的一部分。
如果由于文件系统错误或服务器暂停而导致数据库目录的删除失败,
DROP
DATABASE
则不会回滚事务。
对于不使用原子DDL支持的存储引擎的表,表删除发生在原子
DROP
TABLE
或
DROP
DATABASE
事务之外。
这样的表删除被单独写入二进制日志,这在中断
DROP
TABLE
或
DROP
DATABASE
操作
的情况下将存储引擎,数据字典和二进制日志之间的差异限制为最多一个表
。
对于删除多个表的操作,不使用原子DDL支持的存储引擎的表将在执行之前删除。
CREATE
TABLE
,
ALTER
TABLE
,
RENAME
TABLE
,
TRUNCATE
TABLE
,
CREATE TABLESPACE
,和
DROP
TABLESPACE
对使用原子DDL支持的存储引擎表执行的操作要么完全提交或如果服务器的操作时停止回滚。
在早期的MySQL版本中,这些操作的中断可能会导致存储引擎,数据字典和二进制日志之间的差异,或者留下孤立文件。
RENAME
TABLE
如果所有命名表都使用原子DDL支持的存储引擎,则操作只是原子操作。
DROP VIEW
如果命名视图不存在且未进行任何更改,则会失败。
在此示例中演示了行为更改,其中
DROP
VIEW
语句失败,因为命名视图不存在:
mysql>CREATE VIEW test.viewA AS SELECT * FROM t;
mysql>DROP VIEW test.viewA, test.viewB;
ERROR 1051(42S02):未知表'test.viewB' MySQL的>SHOW FULL TABLES IN test WHERE TABLE_TYPE LIKE 'VIEW';
+ ---------------- + ------------ + | Tables_in_test | Table_type | + ---------------- + ------------ + | viewA | 查看| + ---------------- + ------------ +
在引入原子DDL之前,
DROP
VIEW
为命名视图返回一个错误,该错误不存在但成功存在于存在的命名视图中:
mysql>CREATE VIEW test.viewA AS SELECT * FROM t;
mysql>DROP VIEW test.viewA, test.viewB;
ERROR 1051(42S02):未知表'test.viewB' MySQL的>SHOW FULL TABLES IN test WHERE TABLE_TYPE LIKE 'VIEW';
空集(0.00秒)
不再允许部分执行帐户管理声明。 帐户管理语句对所有命名用户成功或回滚,如果发生错误则无效。 在早期的MySQL版本中,为多个用户命名的帐户管理语句可能对某些用户成功,而对其他用户则失败。
在此示例中演示了行为更改,其中第二个
CREATE
USER
语句返回错误但失败,因为它无法对所有命名用户成功。
mysql>CREATE USER userA;
mysql>CREATE USER userA, userB;
ERROR 1396(HY000):'userA'@'%'的操作CREATE USER失败 MySQL的>SELECT User FROM mysql.user WHERE User LIKE 'user%';
+ ------- + | 用户| + ------- + | userA | + ------- +
在引入原子DDL之前,第二个
CREATE USER
语句为命名用户返回一个错误,该错误不存在但成功存在的命名用户:
mysql>CREATE USER userA;
mysql>CREATE USER userA, userB;
ERROR 1396(HY000):'userA'@'%'的操作CREATE USER失败 MySQL的>SELECT User FROM mysql.user WHERE User LIKE 'user%';
+ ------- + | 用户| + ------- + | userA | | userB | + ------- +
由于行为的这种变化,MySQL 5.7主服务器上部分完成的帐户管理语句在MySQL 8.0从服务器上复制时会失败。
要避免此故障情形,请
在帐户管理语句中
使用
IF EXISTS
或
IF NOT EXISTS
语法,以防止与命名用户相关的错误。
目前,只有
InnoDB
存储引擎支持原子DDL。
不支持原子DDL的存储引擎免于DDL原子性。
涉及豁免存储引擎的DDL操作仍然能够引入操作中断或仅部分完成时可能发生的不一致。
要支持重做和回滚DDL操作,
InnoDB
请将DDL日志写入
mysql.innodb_ddl_log
表,该表是驻留在
mysql.ibd
数据字典表空间
中的隐藏数据字典表
。
要
mysql.innodb_ddl_log
在DDL操作期间
查看写入
表的
DDL日志
,请启用
innodb_print_ddl_logs
配置选项。
有关更多信息,请参阅
查看DDL日志
。
mysql.innodb_ddl_log
无论
innodb_flush_log_at_trx_commit
设置
如何,对表的
更改的重做日志
都会立即刷新到磁盘
。
立即刷新重做日志可以避免DDL操作修改数据文件的情况,但是
mysql.innodb_ddl_log
由这些操作产生的
对
表的
更改的重做日志
不会持久保存到磁盘。
这种情况可能会在回滚或恢复期间导致错误。
该
InnoDB
存储引擎分阶段执行DDL操作。
DDL操作
ALTER
TABLE
可以
在
Commit
阶段
之前多次
执行
Prepare
和
Perform
阶段
。
准备
:创建所需对象并将DDL日志写入
mysql.innodb_ddl_log
表中。
DDL日志定义了如何前滚和回滚DDL操作。
执行
:执行DDL操作。
例如,为
CREATE
TABLE
操作
执行创建例程
。
提交 :更新数据字典并提交数据字典事务。
Post-DDL
:重播并从
mysql.innodb_ddl_log
表中
删除DDL日志
。
为了确保可以安全地执行回滚而不引入不一致,在最后阶段执行文件操作,例如重命名或删除数据文件。
这一阶段还从删除的动态元数据
mysql.innodb_dynamic_metadata
的数据字典表
DROP
TABLE
,
TRUNCATE
TABLE
和该重建表其他DDL操作。
无论事务是提交还是回滚,
DDL日志都会
mysql.innodb_ddl_log
在
Post-DDL
阶段
重播并从
表中
删除
。
mysql.innodb_ddl_log
如果服务器在DDL操作期间暂停,则
DDL日志应仅保留在
表中。
在这种情况下,DDL日志将在恢复后重播并删除。
在恢复情况下,可以在重新启动服务器时提交或回滚DDL事务。
如果
在重做日志和二进制日志中存在DDL操作
的
提交
阶段
期间执行的数据字典事务,则
该操作被视为成功并且前滚。
否则,在
InnoDB
重放数据字典重做日志
时回滚不完整的数据字典事务
,并回滚DDL事务。
要
mysql.innodb_ddl_log
在涉及
InnoDB
存储引擎的
原子DDL操作期间
查看写入
数据字典表
innodb_print_ddl_logs
的DDL日志
,请启用
MySQL以将DDL日志写入
stderr
。
根据主机操作系统和MySQL配置,
stderr
可能是错误日志,终端或控制台窗口。
请参见
第5.4.2.2节“默认错误日志目标配置”
。
InnoDB
将DDL日志写入
mysql.innodb_ddl_log
表以支持重做和回滚DDL操作。
该
mysql.innodb_ddl_log
表是隐藏在
mysql.ibd
数据字典表空间
中的隐藏数据字典表
。
与其他隐藏数据字典表一样,
mysql.innodb_ddl_log
在非调试版本的MySQL中无法直接访问
该
表。
(请参见
第14.1节“数据字典模式”
。)
mysql.innodb_ddl_log
表
的结构
对应于此定义:
CREATE TABLE mysql.innodb_ddl_log( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, thread_id BIGINT UNSIGNED NOT NULL, 类型INT UNSIGNED NOT NULL, space_id INT UNSIGNED, page_no INT未签名, index_id BIGINT UNSIGNED, table_id BIGINT UNSIGNED, old_file_path VARCHAR(512)COLLATE UTF8_BIN, new_file_path VARCHAR(512)COLLATE UTF8_BIN, KEY(thread_id单) );
id
:DDL日志记录的唯一标识符。
thread_id
:为每个DDL日志记录分配一个
thread_id
,用于重播和删除属于特定DDL事务的DDL日志。
涉及多个数据文件操作的DDL事务会生成多个DDL日志记录。
type
:DDL操作类型。
类型包括
FREE
(删除索引树),
DELETE
(删除文件),
RENAME
(重命名文件)或
DROP
(从
mysql.innodb_dynamic_metadata
数据字典表中
删除元
数据)。
space_id
:表空间ID。
page_no
:包含分配信息的页面;
例如,索引树根页面。
index_id
:索引ID。
table_id
:表ID。
old_file_path
:旧的表空间文件路径。
由创建或删除表空间文件的DDL操作使用;
也用于重命名表空间的DDL操作。
new_file_path
:新的表空间文件路径。
由重命名表空间文件的DDL操作使用。
此示例演示
innodb_print_ddl_logs
如何查看
strderr
为
CREATE TABLE
操作
写入的DDL日志
。
mysql> SET GLOBAL innodb_print_ddl_logs = 1; mysql> CREATE TABLE t1(c1 INT)ENGINE = InnoDB;
[注意] [000000] InnoDB:DDL日志插入:[DDL记录:DELETE SPACE,id = 18,thread_id = 7, space_id = 5,old_file_path =。/ test / t1.ibd] [注意] [000000] InnoDB:DDL日志删除:按id 18 [注意] [000000] InnoDB:DDL日志插入:[DDL记录:REMOVE CACHE,id = 19,thread_id = 7, table_id = 1058,new_file_path = test / t1] [注意] [000000] InnoDB:DDL日志删除:按id 19 [注意] [000000] InnoDB:DDL日志插入:[DDL记录:FREE,id = 20,thread_id = 7, space_id = 5,index_id = 132,page_no = 4] [注意] [000000] InnoDB:DDL日志删除:按id 20 [注意] [000000] InnoDB:DDL log post ddl:begin for thread id:7 [注意] [000000] InnoDB:DDL日志发布ddl:end for thread id:7
ALTER {DATABASE | SCHEMA} [db_name
]alter_specification
......alter_specification
: [DEFAULT] CHARACTER SET [=]charset_name
| [DEFAULT] COLLATE [=]collation_name
| DEFAULT ENCRYPTION [=] {'Y'| 'N'}
ALTER
DATABASE
使您可以更改数据库的整体特征。
这些特征存储在数据字典中。
要使用
ALTER
DATABASE
,您需要
ALTER
数据库
的
权限。
ALTER
SCHEMA
是...的同义词
ALTER
DATABASE
。
可以从第一个语法中省略数据库名称,在这种情况下,该语句将应用于默认数据库。
该
CHARACTER SET
子句更改默认数据库字符集。
该
COLLATE
子句更改默认数据库排序规则。
第10章,
字符集,排序规则,Unicode
,讨论字符集和排序规则名称。
您可以分别使用
SHOW CHARACTER
SET
和
SHOW
COLLATION
语句
查看可用的字符集和排序规则
。
有关更多
信息,
请参见
第13.7.6.3节“显示字符集语法”
和
第13.7.6.4
节“显示字符集语法”
。
如果更改数据库的默认字符集或排序规则,则必须删除并重新创建使用数据库默认值的存储例程,以便它们使用新的默认值。 (在存储例程中,如果未明确指定字符集或排序规则,则具有字符数据类型的变量将使用数据库缺省值。请参见 第13.1.17节“创建过程和创建函数语法” 。)
DEFAULT ENCRYPTION
MySQL 8.0.16中引入的
该
子句定义了默认数据库加密,该加密由数据库中创建的表继承。
更改数据库的默认加密不会更改与架构关联的现有表的加密。
只有新创建的表才会继承默认的数据库加密。
在
ALTER
DATABASE
没有
DEFAULT
ENCRYPTION
子句的情况下
执行的
语句会保留现有的默认数据库加密。
如果
table_encryption_privilege_check
启用
该
变量,
TABLE_ENCRYPTION_ADMIN
则需要
该
权限才能指定与设置不同的默认加密
default_table_encryption
设置。
有关更多信息,请参阅
为架构和常规表空间定义加密默认值
。
改变 [DEFINER =user
] 活动event_name
[安排时间表schedule
] [完成[NOT] PRESERVE] [重命名new_event_name
] [ENABLE | 禁用| 禁止在[SLAVE] [评论'string
'] [DOevent_body
]
该
ALTER
EVENT
语句更改现有事件的一个或多个特征,而无需删除和重新创建它。
的语法的每个的
DEFINER
,
ON SCHEDULE
,
ON COMPLETION
,
COMMENT
,
ENABLE
/
DISABLE
,和
DO
条款是完全一样的当用于如
CREATE
EVENT
。
(请参见
第13.1.13节“创建事件语法”
。)
任何用户都可以更改在该用户具有该
EVENT
权限
的数据库上定义的事件
。
当用户执行成功的
ALTER
EVENT
语句时,该用户将成为受影响事件的定义者。
ALTER
EVENT
仅适用于现有事件:
的MySQL>ALTER EVENT no_such_event
>ON SCHEDULE
> ERROR 1517(HY000):未知事件'no_such_event'EVERY '2:3' DAY_HOUR;
在以下每个示例中,假设命名事件
myevent
的定义如下所示:
创造事件myevent 按照时间表 每6个小时 评论'示例评论。' 做 更新myschema.mytable SET mycol = mycol + 1;
以下语句将计划
myevent
从立即开始每六小时
更改为
每十二小时一次,从语句运行开始四小时开始:
改变事件myevent 按照时间表 每12个小时 STARTS CURRENT_TIMESTAMP + INTERVAL 4小时;
可以在单个语句中更改事件的多个特征。
此示例将执行的SQL语句更改为
myevent
删除所有记录的
语句
mytable
;
它还会更改事件的计划,使其在
ALTER
EVENT
运行
此
语句
后一天执行一次
。
改变事件myevent 按照时间表 在CURRENT_TIMESTAMP + INTERVAL 1天 做 TRUNCATE TABLE myschema.mytable;
ALTER
EVENT
仅为要更改的特征
在
语句中
指定选项
;
省略的选项保留其现有值。
这包括任何默认值
CREATE
EVENT
,例如
ENABLE
。
要禁用
myevent
,请使用以下
ALTER
EVENT
语句:
改变事件myevent 禁用;
该
ON SCHEDULE
子句可以使用涉及内置MySQL函数和用户变量的表达式来获取
它包含的
任何
timestamp
或
interval
值。
您不能在此类表达式中使用存储的例程或用户定义的函数,也不能使用任何表引用;
但是,你可以使用
SELECT FROM DUAL
。
对于这两个
ALTER
EVENT
和
CREATE
EVENT
陈述
都是如此
。
在这种情况下,特别不允许引用存储例程,用户定义函数和表,并且会因错误而失败(参见Bug#22830)。
虽然
在其
子句
ALTER
EVENT
中包含另一个
ALTER
EVENT
语句的
DO
语句似乎成功,但是当服务器尝试执行生成的已调度事件时,执行将失败并显示错误。
要重命名事件,请使用
ALTER
EVENT
语句的
RENAME TO
子句。
此语句将事件重命名
myevent
为
yourevent
:
改变事件myevent 重命名给你;
您还可以使用
ALTER EVENT ... RENAME TO ...
和
表示法
将事件移动到其他数据库
,如下所示:
db_name.event_name
ALTER EVENT olddb.myevent 重命名为newdb.myevent;
要执行前一个语句,执行它的用户必须
EVENT
同时拥有
olddb
和
newdb
数据库
的
权限
。
没有
RENAME EVENT
声明。
该值
DISABLE ON SLAVE
用于复制从站而不是
ENABLE
或
DISABLE
表示在主站上创建并复制到从站的事件,但不在从站上执行。
通常,
DISABLE ON
SLAVE
根据需要自动设置;
但是,在某些情况下,您可能需要或需要手动更改它。
有关
更多信息
,
请参见
第17.4.1.16节“调用的特性的复制”
。
改变功能func_name
[characteristic
...]characteristic
: 评论'string
' | 语言SQL | {包含SQL | 没有SQL | 读取SQL数据| 修改SQL DATA} | SQL SECURITY {DEFINER | INVOKER}
此语句可用于更改存储函数的特征。
可以在
ALTER FUNCTION
语句中
指定多个更改
。
但是,您无法使用此语句更改存储函数的参数或正文;
要进行此类更改,您必须使用
DROP
FUNCTION
和
删除并重新创建函数
CREATE
FUNCTION
。
您必须拥有
ALTER ROUTINE
该功能
的
权限。
(该权限自动授予函数创建者。)如果启用了二进制日志记录,则该
ALTER FUNCTION
语句可能还需要该
SUPER
特权,如
第24.7节“存储程序二进制日志记录”中所述
。
更改实例instance_action
instance_action
:{ 旋转INNODB MASTER KEY | 旋转BINLOG MASTER KEY | RELOAD TLS [没有错误的错误] }
ALTER INSTANCE
定义适用于MySQL服务器实例的操作。
该声明支持以下操作:
ALTER INSTANCE ROTATE INNODB MASTER KEY
此操作将旋转用于
InnoDB
表空间加密
的主加密密钥
。
密钥轮换需要
ENCRYPTION_KEY_ADMIN
或
SUPER
特权。
要执行此操作,必须安装和配置密钥环插件。
有关说明,请参见
第6.4.4节“MySQL密钥环”
。
ALTER INSTANCE ROTATE INNODB MASTER KEY
支持并发DML。
但是,它不能与
CREATE TABLE ...
ENCRYPTION
或
同时
ALTER
TABLE ...
ENCRYPTION
运行,并且会采取锁定来防止因并发执行这些语句而引起的冲突。
如果其中一个冲突的语句正在运行,则必须先完成,然后才能继续。
ALTER INSTANCE ROTATE INNODB MASTER KEY
语句将写入二进制日志,以便它们可以在复制的服务器上执行。
有关其他
ALTER INSTANCE ROTATE INNODB MASTER
KEY
用法信息,请参见
第15.6.3.9节“InnoDB静态数据加密”
。
ALTER INSTANCE ROTATE BINLOG MASTER KEY
此操作将旋转用于二进制日志加密的二进制日志主密钥。
二进制日志主密钥的密钥轮换需要
BINLOG_ENCRYPTION_ADMIN
或
SUPER
特权。
如果
binlog_encryption
系统变量设置为,
则不能使用该语句
OFF
。
要执行此操作,必须安装和配置密钥环插件。
有关说明,请参见
第6.4.4节“MySQL密钥环”
。
ALTER INSTANCE ROTATE BINLOG MASTER KEY
操作不会写入二进制日志,也不会在复制从服务器上执行。
因此,二进制日志主密钥轮换可以在包括混合MySQL版本的复制环境中执行。
要在所有适用的主服务器和从属服务器上安排定期轮换二进制日志主密钥,可以在每台服务器上启用MySQL事件调度程序,并
ALTER INSTANCE ROTATE BINLOG
MASTER KEY
使用
CREATE EVENT
语句
发出
语句。
如果您因为怀疑当前或任何以前的二进制日志主密钥可能已被泄露而轮换二进制日志主密钥,请在每个适用的主从服务器上发出该语句,这样您就可以验证是否立即符合。
有关其他
ALTER INSTANCE ROTATE BINLOG MASTER
KEY
使用信息,包括如果进程未正确完成或由于意外服务器暂停而中断操作,请参见
第17.3.10节“加密二进制日志文件和中继日志文件”
。
此操作从定义上下文的系统变量的当前值重新配置SSL上下文。
它还会更新反映活动上下文值的状态变量。
此操作需要该
CONNECTION_ADMIN
权限。
默认情况下,
RELOAD TLS
如果配置值不允许创建新的SSL上下文
,则
操作将回滚并显示错误,并且无效。
先前的上下文值继续用于新连接。
如果
NO ROLLBACK ON ERROR
给出
了可选
子句并且无法创建新上下文,则不会发生回滚。
而是生成警告,并为新连接禁用SSL。
ALTER INSTANCE RELOAD TLS
语句不会写入二进制日志(因此不会被复制)。
SSL配置是本地的,取决于所有涉及的服务器上不一定存在的本地文件。
有关重新配置SSL上下文的其他信息,包括与上下文相关的系统和状态变量,请参阅 加密连接的服务器端运行时配置 。
ALTER LOGFILE GROUPlogfile_group
ADD UNDOFILE'file_name
' [INITIAL_SIZE [=]size
] [等待] 发动机[=]engine_name
此语句将
UNDO
名为'
file_name
'
的
文件
添加
到现有日志文件组
logfile_group
。
一个
ALTER LOGFILE GROUP
语句有一个且只有一个
ADD UNDOFILE
条款。
DROP UNDOFILE
目前不支持
任何
条款。
所有NDB Cluster Disk Data对象共享相同的命名空间。 这意味着 必须唯一地命名 每个磁盘数据对象 (而不仅仅是给定类型的每个磁盘数据对象)。 例如,您不能拥有具有相同名称的表空间和撤消日志文件,也不能具有撤消日志文件和具有相同名称的数据文件。
可选
INITIAL_SIZE
参数设置
UNDO
文件的初始大小(以字节为单位);
如果未指定,则初始大小默认为134217728(128 MB)。
您可以选择
size
使用一个字母的缩写,一个数量级,类似于中使用的那些
my.cnf
。
通常,这是字母
M
(兆字节)或
G
(千兆字节)之一。
(Bug#13116514,Bug#16104705,Bug#62858)
在32位系统上,支持的最大值为
INITIAL_SIZE
4294967296(4 GB)。
(Bug#29186)
允许的最小值为
INITIAL_SIZE
1048576(1 MB)。
(Bug#29574)
WAIT
被解析但被忽略。
此关键字目前无效,可用于将来的扩展。
的
ENGINE
参数(必需)确定这是由该日志文件组所使用的,与存储引擎
engine_name
是所述存储引擎的名称。
目前,唯一可接受的值
engine_name
是
“
NDBCLUSTER
”
和
“
NDB
”
。
这两个值是等价的。
下面是一个示例,它假定
lg_3
已经使用创建
了日志文件组
CREATE LOGFILE GROUP
(请参见
第13.1.16节“CREATE LOGFILE GROUP语法”
):
ALTER LOGFILE GROUP lg_3 添加UNDOFILE'under_10.dat' INITIAL_SIZE = 32M ENGINE = NDBCLUSTER;
当
ALTER LOGFILE GROUP
与
ENGINE = NDBCLUSTER
(替代地
ENGINE = NDB
)一起使用时,
UNDO
在每个NDB集群数据节点上创建日志文件。
您可以
UNDO
通过查询
INFORMATION_SCHEMA.FILES
表
来验证
文件是否已创建并获取有关它们的信息
。
例如:
mysql>SELECT FILE_NAME, LOGFILE_GROUP_NUMBER, EXTRA
- >FROM INFORMATION_SCHEMA.FILES
- >WHERE LOGFILE_GROUP_NAME = 'lg_3';
+ ------------- + ---------------------- + ------------ ---- + | FILE_NAME | LOGFILE_GROUP_NUMBER | 额外| + ------------- + ---------------------- + ------------ ---- + | newdata.dat | 0 | CLUSTER_NODE = 3 | | newdata.dat | 0 | CLUSTER_NODE = 4 | | undo_10.dat | 11 | CLUSTER_NODE = 3 | | undo_10.dat | 11 | CLUSTER_NODE = 4 | + ------------- + ---------------------- + ------------ ---- + 4行(0.01秒)
(参见 第25.11节“INFORMATION_SCHEMA文件表” 。)
用于的内存
UNDO_BUFFER_SIZE
来自全局池,其大小由
SharedGlobalMemory
数据节点配置参数
的值确定
。
这包括通过设置
InitialLogFileGroup
数据节点配置参数
对此选项隐含的任何默认值
。
ALTER LOGFILE GROUP
仅适用于NDB Cluster的磁盘数据存储。
有关更多信息,请参见
第22.5.13节“NDB集群磁盘数据表”
。
更改程序proc_name
[characteristic
...]characteristic
: 评论'string
' | 语言SQL | {包含SQL | 没有SQL | 读取SQL数据| 修改SQL DATA} | SQL SECURITY {DEFINER | INVOKER}
此语句可用于更改存储过程的特征。
可以在
ALTER PROCEDURE
语句中
指定多个更改
。
但是,您无法使用此语句更改存储过程的参数或主体;
要进行此类更改,您必须使用
DROP
PROCEDURE
和
删除并重新创建该过程
CREATE
PROCEDURE
。
您必须拥有
ALTER ROUTINE
该过程
的
特权。
默认情况下,该权限自动授予过程创建者。
可以通过禁用
automatic_sp_privileges
系统变量
来更改此行为
。
请参见
第24.2.2节“存储例程和MySQL特权”
。
更改服务器server_name
选项(option
[,option
] ...)
更改服务器信息
,调整
server_name
CREATE
SERVER
语句中
允许的任何选项
。
mysql.servers
表中
的相应字段会相应
更新。
此声明需要该
SUPER
权限。
例如,要更新
USER
选项:
ALTER SERVER的选项(USER'sally');
ALTER SERVER
导致隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
ALTER SERVER
无论正在使用的日志记录格式如何,都不会写入二进制日志。
ALTER TABLEtbl_name
[alter_specification
[,alter_specification
] ...] [partition_options
]alter_specification
:table_options
| 添加[栏目] [第一个| 之后]col_name
column_definition
col_name
| 添加[栏目](,...)col_name
column_definition
| 添加{INDEX | KEY} [index_name
] [index_type
](key_part
,...)[index_option
] ...... | ADD {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name
] (key_part
,......)[index_option
] ...... | 添加[CONSTRAINT [symbol
]] PRIMARY KEY [index_type
](key_part
,...) [index_option
] ...... | ADD [CONSTRAINT [symbol
]] UNIQUE [INDEX | KEY] [index_name
] [index_type
](key_part
,...) [index_option
] ...... | 添加[CONSTRAINT [symbol
]]外键 [index_name
](col_name
,...)reference_definition
| ADDcheck_constraint_definition
| DROP CHECKsymbol
| 更改检查symbol
[NOT]强制执行 | 算法[=] {DEFAULT | INSTANT | INPLACE | COPY} | ALTER [COLUMN]col_name
{SET DEFAULTliteral
| DROP DEFAULT} | ALTER INDEXindex_name
{VISIBLE | 无形} | 更改[栏目] [第一|后]old_col_name
new_col_name
column_definition
col_name
| [DEFAULT] CHARACTER SET [=]charset_name
[COLLATE [=]collation_name
] | 转换为字符集charset_name
[COLLATEcollation_name
] | {DISABLE | ENABLE} KEYS | {DISCARD | IMPORT} TABLESPACE | DROP [COLUMN]col_name
| DROP {INDEX | KEY}index_name
| DROP PRIMARY KEY | DROP FOREIGN KEYfk_symbol
| 力 | LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE} | 修改[专栏] [第一个| 之后]col_name
column_definition
col_name
| ORDER BYcol_name
[,col_name
] ...... | RENAME COLUMNold_col_name
TOnew_col_name
| 重命名{INDEX | KEY}old_index_name
至new_index_name
| 重命名[TO | AS]new_tbl_name
| {WITHOUT | WITH}验证 | 添加分区(partition_definition
) | DROP PARTITIONpartition_names
| DISCARD PARTITION {partition_names
| ALL} TABLESPACE | IMPORT PARTITION {partition_names
| ALL} TABLESPACE | TRUNCATE PARTITION {partition_names
| 所有} | COALESCE PARTITIONnumber
| 重新划分partition_names
(partition_definitions
) |partition_name
表tbl_name
[[WITH | WITHOUT}验证]的交换分区 | 分析分区{partition_names
| 所有} | 检查分区{partition_names
| 所有} | OPTIMIZE PARTITION {partition_names
| 所有} | REBUILD PARTITION {partition_names
| 所有} | 修复分区{partition_names
| 所有} | 删除分区key_part
:{col_name
[(length
)] | (expr
)} [ASC | DESC]index_type
: 使用{BTREE | HASH}index_option
: KEY_BLOCK_SIZE [=]value
|index_type
| 与PARSERparser_name
| 评论'string
' | {VISIBLE | 无形}check_constraint_definition
: [CONSTRAINT [symbol
]] CHECK(expr
)[[NOT] ENFORCED]table_options
:table_option
[[,]table_option
] ......table_option
: AUTO_INCREMENT [=]value
| AVG_ROW_LENGTH [=]value
| [DEFAULT] CHARACTER SET [=]charset_name
| CHECKSUM [=] {0 | 1} | [DEFAULT] COLLATE [=]collation_name
| 评论[=]'string
' | COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'} | 连接[=]'connect_string
' | {DATA | INDEX} DIRECTORY [=]'absolute path to directory
' | DELAY_KEY_WRITE [=] {0 | 1} | ENCRYPTION [=] {'Y'| 'N'} | 发动机[=]engine_name
| INSERT_METHOD [=] {NO | 第一个| 最后} | KEY_BLOCK_SIZE [=]value
| MAX_ROWS [=]value
| MIN_ROWS [=]value
| PACK_KEYS [=] {0 | 1 | 默认} | 密码[=]'string
' | ROW_FORMAT [=] {DEFAULT | DYNAMIC | FIXED | COMPRESSED | REDUNDANT | COMPACT} | STATS_AUTO_RECALC [=] {DEFAULT | 0 | 1} | STATS_PERSISTENT [=] {DEFAULT | 0 | 1} | STATS_SAMPLE_PAGES [=]value
| TABLESPACEtablespace_name
[STORAGE {DISK | MEMORY}] | UNION [=](tbl_name
[,tbl_name
] ......)partition_options
: (见CREATE TABLE
选项)
ALTER
TABLE
改变表的结构。
例如,您可以添加或删除列,创建或销毁索引,更改现有列的类型,或重命名列或表本身。
您还可以更改特征,例如用于表的存储引擎或表注释。
要使用
ALTER
TABLE
,你需要
ALTER
,
CREATE
和
INSERT
权限表。
重命名表需要
ALTER
和
DROP
对旧表,
ALTER
,
CREATE
,和
INSERT
对新表。
在表名后面,指定要进行的更改。
如果没有给出,
ALTER
TABLE
什么都不做。
许多允许的更改的语法类似于
CREATE TABLE
语句的
子句
。
column_definition
条款使用相同的语法
ADD
和
CHANGE
作为
CREATE
TABLE
。
有关更多信息,请参见
第13.1.20节“CREATE TABLE语法”
。
该字
COLUMN
是可选的,可以省略,除了
RENAME COLUMN
(区分列重命名操作和
RENAME
表重命名操作)。
多
ADD
,
ALTER
,
DROP
,和
CHANGE
条款,允许在一个单一的
ALTER
TABLE
声明中,用逗号隔开。
这是标准SQL的MySQL扩展,每个
ALTER
TABLE
语句
只允许每个子句中的一个
。
例如,要在单个语句中删除多个列,请执行以下操作:
ALTER TABLE t2 DROP COLUMN c,DROP COLUMN d;
如果存储引擎不支持尝试的
ALTER
TABLE
操作,则可能会出现警告。
可以显示此类警告
SHOW WARNINGS
。
请参见
第13.7.6.40节“显示警告语法”
。
有关故障排除的信息
ALTER
TABLE
,请参见
第B.4.6.1节“ALTER TABLE的问题”
。
有关生成的列的信息,请参见 第13.1.9.2节“ALTER TABLE和生成的列” 。
有关用法示例,请参见 第13.1.9.3节“ALTER TABLE示例” 。
使用
mysql_info()
C API函数,您可以找出复制的行数
ALTER
TABLE
。
请参见
第28.7.7.36节“mysql_info()”
。
该
ALTER
TABLE
语句
还有其他几个方面
,本节中的以下主题对此进行了描述:
table_options
意味着可以在可以使用的一种表选项
CREATE
TABLE
语句,比如
ENGINE
,
AUTO_INCREMENT
,
AVG_ROW_LENGTH
,
MAX_ROWS
,
ROW_FORMAT
,或
TABLESPACE
。
有关所有表选项的说明,请参见
第13.1.20节“CREATE TABLE语法”
。
但是,
ALTER
TABLE
忽略
DATA
DIRECTORY
并
INDEX DIRECTORY
作为表选项给出。
ALTER
TABLE
仅允许它们作为分区选项,并要求您拥有该
FILE
权限。
使用表选项
ALTER
TABLE
提供了一种更改单个表特征的便捷方法。
例如:
如果
t1
当前不是
InnoDB
表,则此语句将其存储引擎更改为
InnoDB
:
ALTER TABLE t1 ENGINE = InnoDB;
有关
将表
切换到
InnoDB
存储引擎
时的注意
事项,
请参见
第15.6.1.3节“将表从MyISAM转换为InnoDB”
。
指定
ENGINE
子句时,
ALTER TABLE
重建表。
即使表已具有指定的存储引擎,也是如此。
在现有
表
上
运行
会执行
“
null
”
操作,该操作可用于对
表
进行碎片整理
,如
第15.11.4节“对表进行碎片整理”中所述
。
在
表
上
运行
执行相同的功能。
ALTER
TABLE
tbl_name
ENGINE=INNODBInnoDB
ALTER
TABLE
InnoDB
ALTER TABLE
tbl_name
FORCEInnoDB
ALTER
TABLE
并
使用
在线DDL
。
有关更多信息,请参见
第15.12节“InnoDB和在线DDL”
。
tbl_name
ENGINE=INNODBALTER TABLE
tbl_name
FORCE
尝试更改表的存储引擎的结果受所需存储引擎是否可用以及
NO_ENGINE_SUBSTITUTION
SQL模式
设置的影响
,如
第5.1.11节“服务器SQL模式”中所述
。
为防止意外丢失数据,
ALTER TABLE
不能用于将表的存储引擎更改为
MERGE
或
BLACKHOLE
。
要更改
InnoDB
表以使用压缩行存储格式:
ALTER TABLE t1 ROW_FORMAT = COMPRESSED;
该
ENCRYPTION
子句启用或禁用表的页级数据加密
InnoDB
。
必须安装密钥环插件并将其配置为启用加密。
如果
table_encryption_privilege_check
启用
该
变量,
TABLE_ENCRYPTION_ADMIN
则需要使用具有
ENCRYPTION
与默认架构加密设置不同的设置
的
子句
的
权限
。
在MySQL 8.0.16之前,
ENCRYPTION
仅在更改驻留在每个表文件表空间中的表时才支持
该
子句。
从MySQL 8.0.16开始,
ENCRYPTION
对于驻留在一般表空间中的表也支持
该
子句。
对于驻留在常规表空间中的表,表和表空间加密必须匹配。
如果没有明确指定
ENCRYPTION
子句,
则不允许通过将表移动到不同的表空间或更改存储引擎来更改表加密
。
从MySQL 8.0.16开始,
如果表使用不支持加密的存储引擎,则
指定
ENCRYPTION
一个值不是
'N'
或
''
不允许
的
子句
。
此前,该条款被接受。
尝试
ENCRYPTION
使用不支持加密的存储引擎在启用加密的模式中
创建没有
子句
的表
也是不允许的。
有关更多信息,请参见 第15.6.3.9节“InnoDB静态数据加密” 。
要重置当前的自动增量值:
ALTER TABLE t1 AUTO_INCREMENT = 13;
您无法将计数器重置为小于或等于当前正在使用的值的值。
对于两者
InnoDB
和
MyISAM
,如果该值小于或等于
AUTO_INCREMENT
列中当前的最大值,则将该值重置为当前最大
AUTO_INCREMENT
列值加1。
要更改默认表格字符集:
ALTER TABLE t1 CHARACTER SET = utf8;
另请参阅 更改字符集 。
添加(或更改)表注释:
ALTER TABLE t1 COMMENT ='新表评论';
ALTER TABLE
与
TABLESPACE
选项一起
使用
可
InnoDB
在现有
通用表空间
,
每表文件表
空间和
系统表空间
之间
移动
表
。
请参阅
使用ALTER TABLE在表空间之间移动表
。
ALTER TABLE ... TABLESPACE
即使
TABLESPACE
属性未从其先前值更改,
操作也始终会导致完整表重建
。
ALTER TABLE ... TABLESPACE
语法不支持将表从临时表空间移动到持久表空间。
不支持
该
DATA DIRECTORY
子句,但
CREATE TABLE
... TABLESPACE
不支持
该
子句,
ALTER TABLE ... TABLESPACE
如果指定则忽略
该
子句
。
有关该
TABLESPACE
选项
的功能和限制的详细信息
,请参阅
CREATE TABLE
。
MySQL NDB Cluster 8.0支持设置
NDB_TABLE
用于控制表的分区平衡(片段计数类型),从任何副本读取,完全复制或这些的任意组合的选项,作为
ALTER TABLE
语句
的表注释的一部分
以相同的方式至于
CREATE TABLE
,如本例所示:
ALTER TABLE t1 COMMENT =“NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RA_BY_NODE”;
请记住,
ALTER TABLE ... COMMENT
...
丢弃该表的任何现有注释。
有关
其他信息和示例,
请参阅
设置NDB_TABLE选项
。
要验证表选项是否按预期更改,请使用
SHOW CREATE TABLE
或查询
INFORMATION_SCHEMA.TABLES
表。
ALTER
TABLE
使用以下算法之一处理操作:
COPY
:对原始表的副本执行操作,并将表数据从原始表逐行复制到新表。
不允许并发DML。
INPLACE
:操作避免复制表数据,但可能会重建表。
可以在操作的准备和执行阶段期间简要地对表进行独占元数据锁定。
通常,支持并发DML。
INSTANT
:操作仅修改数据字典中的元数据。
在准备和执行期间,不会在表上采用独占元数据锁,并且表数据不受影响,从而使操作立即生效。
允许并发DML。
(在MySQL 8.0.12中引入)
该
ALGORITHM
条款是可选的。
如果
ALGORITHM
省略
该
子句,MySQL将使用
支持它的
ALGORITHM=INSTANT
存储引擎和
ALTER
TABLE
子句。
否则,
ALGORITHM=INPLACE
使用。
如果
ALGORITHM=INPLACE
不支持,
ALGORITHM=COPY
则使用。
指定
ALGORITHM
子句需要操作将指定的算法用于支持它的子句和存储引擎,否则将失败并返回错误。
指定
ALGORITHM=DEFAULT
与省略该
ALGORITHM
子句
相同
。
ALTER
TABLE
使用该
COPY
算法的操作等待修改表的其他操作完成。
对表副本应用更改后,将复制数据,删除原始表,并将表副本重命名为原始表的名称。
在
ALTER
TABLE
执行操作时,原始表可由其他会话读取(不久之后会注明)。
ALTER
TABLE
操作开始
后启动的表的更新和写入将
停止,直到新表准备就绪,然后自动重定向到新表。
除非是a,否则表的临时副本将在原始表的数据库目录中创建
RENAME TO
将表移动到驻留在不同目录中的数据库的操作。
前面提到的异常是
ALTER
TABLE
块在准备从表和表定义高速缓存中清除过时的表结构时读取(而不仅仅是写入)。
此时,它必须获得独占锁。
为此,它等待当前读者完成,并阻止新的读写。
ALTER TABLE
使用该
COPY
算法
的
操作
可防止并发DML操作。
仍然允许并发查询。
也就是说,表复制操作总是至少包括
LOCK=SHARED
(允许查询但不是DML)
的并发限制
。
您可以
LOCK
通过指定
进一步限制支持该
子句的
操作的并发性
LOCK=EXCLUSIVE
,从而阻止DML和查询。
有关更多信息,请参阅
并发控制
。
要强制将
COPY
算法用于
ALTER
TABLE
不使用
该
算法的
操作,请指定
ALGORITHM=COPY
或启用
old_alter_table
系统变量。
如果
old_alter_table
设置与
ALGORITHM
具有非其他值
的
子句
之间存在冲突
DEFAULT
,则该
ALGORITHM
子句优先。
对于
InnoDB
表,
在驻留在
共享表空间中
的表上
ALTER
TABLE
使用该
COPY
算法
的
操作
可以增加
表
空间使用的空间量。
此类操作需要与表中的数据和索引一样多的额外空间。
对于驻留在共享表空间中的表,操作期间使用的额外空间不会释放回操作系统,因为它是驻留在
每个表文件表
空间中的表。
有关在线DDL操作的空间要求的信息,请参见 第15.12.3节“在线DDL空间要求” 。
ALTER TABLE
支持该
INPLACE
算法的
操作
包括:
ALTER TABLE
InnoDB
在线DDL
功能
支持的操作
。
请参见
第15.12.1节“在线DDL操作”
。
重命名表格。
MySQL重命名与表对应的文件
tbl_name
而不进行复制。
(您也可以使用该
RENAME
TABLE
语句重命名表。请参见
第13.1.36节“RENAME TABLE语法”
。)专门为重命名表授予的权限不会迁移到新名称。
必须手动更改它们。
仅修改表元数据的操作。 这些操作是立即的,因为服务器不接触表内容。 仅元数据操作包括:
重命名列。
更改列的默认值(
NDB
表
除外
)。
通过将新枚举或集成员添加到
有效成员值列表
的
末尾
来
修改
ENUM
或
SET
列
的定义
,只要数据类型的存储大小不会更改。
例如,将成员添加到
具有8个成员
的
列会将每个值所需的存储空间从1个字节更改为2个字节;
这需要一个表副本。
在列表中间添加成员会导致重新编号现有成员,这需要表副本。
SET
更改空间列的定义以删除该
SRID
属性。
(添加或更改
SRID
属性确实需要重建,并且无法在适当的位置完成,因为服务器必须验证所有值都具有指定的SRID值。)
从MySQL 8.0.14开始,在这些条件适用时更改列字符集:
从MySQL 8.0.14开始,在适用这些条件时更改生成的列:
对于
InnoDB
表,修改生成的存储列但不更改其类型,表达式或可为空性的语句。
对于非
InnoDB
表,修改生成的存储列或虚拟列但不更改其类型,表达式或可为空性的语句。
An example of such a change is a change to the column comment.
Renaming an index.
Adding or dropping a secondary index, for
InnoDB
and
NDB
tables. See
Section 15.12.1,
“Online DDL Operations”.
For NDB
tables, operations that
add and drop indexes on variable-width columns. These
operations occur online, without table copying and without
blocking concurrent DML actions for most of their duration.
See Section 22.5.14,
“Online Operations with ALTER TABLE in NDB Cluster”.
Modifying index visibility with an ALTER
INDEX
operation.
Column modifications of tables containing generated columns
that depend on columns with a DEFAULT
value
if the modified columns are not involved in the generated
column expressions. For example, changing the
NULL
property of a separate column can be
done in place without a table rebuild.
ALTER TABLE
operations that support the
INSTANT
algorithm include:
Adding a column. This feature is referred to as “Instant
ADD COLUMN
”. Limitations apply. See
Section 15.12.1,
“Online DDL Operations”.
Adding or dropping a virtual column.
Adding or dropping a column default value.
Modifying the definition of an
ENUM
or
SET
column.
The same
restrictions apply as described above for
ALGORITHM=INSTANT
.
Changing the index type.
Renaming a table. The same restrictions apply as described
above for ALGORITHM=INSTANT
.
For more information about operations that support
ALGORITHM=INSTANT
, see
Section 15.12.1,
“Online DDL Operations”.
ALTER TABLE
upgrades MySQL 5.5
temporal columns to 5.6 format for ADD COLUMN
,
CHANGE COLUMN
, MODIFY
COLUMN
, ADD INDEX
, and
FORCE
operations. This conversion cannot be
done using the INPLACE
algorithm because the
table must be rebuilt, so specifying
ALGORITHM=INPLACE
in these cases results in an
error. Specify ALGORITHM=COPY
if necessary.
If an ALTER TABLE
operation on a multicolumn
index used to partition a table by KEY
changes
the order of the columns, it can only be performed using
ALGORITHM=COPY
.
The WITHOUT VALIDATION
and WITH
VALIDATION
clauses affect whether
ALTER TABLE
performs an in-place
operation for
virtual generated
column modifications. See
Section 13.1.9.2,
“ALTER TABLE and Generated Columns”.
NDB Cluster 8.0 supports online operations using the same
ALGORITHM=INPLACE
syntax used with the standard
MySQL Server. See
Section 22.5.14,
“Online Operations with ALTER TABLE in NDB Cluster”, for more
information.
ALTER TABLE
with DISCARD ... PARTITION
... TABLESPACE
or IMPORT ... PARTITION ...
TABLESPACE
does not create any temporary tables or
temporary partition files.
ALTER TABLE
with ADD
PARTITION
, DROP PARTITION
,
COALESCE PARTITION
, REBUILD
PARTITION
, or REORGANIZE PARTITION
does not create temporary tables (except when used with
NDB
tables); however, these
operations can and do create temporary partition files.
ADD
or DROP
operations for
RANGE
or LIST
partitions are
immediate operations or nearly so. ADD
or
COALESCE
operations for HASH
or KEY
partitions copy data between all
partitions, unless LINEAR HASH
or
LINEAR KEY
was used; this is effectively the
same as creating a new table, although the ADD
or COALESCE
operation is performed partition by
partition. REORGANIZE
operations copy only
changed partitions and do not touch unchanged ones.
For MyISAM
tables, you can speed up index
re-creation (the slowest part of the alteration process) by
setting the
myisam_sort_buffer_size
system
variable to a high value.
For ALTER
TABLE
operations that
support it, you can use the LOCK
clause to
control the level of concurrent reads and writes on a table while
it is being altered. Specifying a non-default value for this
clause enables you to require a certain amount of concurrent
access or exclusivity during the alter operation, and halts the
operation if the requested degree of locking is not available.
Only LOCK = DEFAULT
is permitted for operations
that use ALGORITHM=INSTANT
. The other
LOCK
clause parameters are not applicable.
The parameters for the LOCK
clause are:
LOCK = DEFAULT
Maximum level of concurrency for the given
ALGORITHM
clause (if any) and
ALTER TABLE
operation: Permit concurrent
reads and writes if supported. If not, permit concurrent reads
if supported. If not, enforce exclusive access.
LOCK = NONE
If supported, permit concurrent reads and writes. Otherwise, an error occurs.
LOCK = SHARED
If supported, permit concurrent reads but block writes. Writes
are blocked even if concurrent writes are supported by the
storage engine for the given ALGORITHM
clause (if any) and ALTER TABLE
operation.
If concurrent reads are not supported, an error occurs.
LOCK = EXCLUSIVE
实施独家访问。
即使存储引擎支持给定
ALGORITHM
子句(如果有)和
ALTER TABLE
操作的
并发读/写,也会执行此
操作。
用于
ADD
向表中添加新列,以及
DROP
删除现有列。
是标准SQL的MySQL扩展。
DROP
col_name
要在表格行中的特定位置添加列,请使用
FIRST
或
。
默认是最后添加列。
AFTER
col_name
如果表只包含一列,则无法删除该列。
如果您打算删除表,请改用该
DROP
TABLE
语句。
如果从表中删除列,则列也将从它们所属的任何索引中删除。
如果删除构成索引的所有列,则也会删除索引。
如果使用
CHANGE
或
MODIFY
缩短列上存在索引的列,并且结果列长度小于索引长度,MySQL会自动缩短索引。
对于
ALTER TABLE ... ADD
,如果列具有使用非确定性函数的表达式默认值,则该语句可能会产生警告或错误。
有关详细信息,请参见
第17.1.3.6节“使用GTID进行复制的限制”
。
在
CHANGE
,
MODIFY
,
RENAME COLUMN
,和
ALTER
条款允许的名称和现有列的定义被改变。
它们具有以下比较特征:
CHANGE
:
可以重命名列并更改其定义,或两者。
具有比
MODIFY
或
更多的能力
RENAME COLUMN
,但是以某些操作的便利性为代价。
CHANGE
如果不重命名,则需要将列命名两次,如果仅重命名,则需要重新指定列定义。
使用
FIRST
或
AFTER
可以重新排序列。
MODIFY
:
可以更改列定义但不能更改其名称。
比
CHANGE
不更改列定义更改列定义
更方便
。
使用
FIRST
或
AFTER
可以重新排序列。
RENAME COLUMN
:
可以更改列名但不能更改其定义。
比重
CHANGE
命名列而不更改其定义
更方便
。
ALTER
:仅用于更改列默认值。
CHANGE
是标准SQL的MySQL扩展。
MODIFY
并且
RENAME COLUMN
是Oracle兼容性的MySQL扩展。
要更改列以更改其名称和定义,请使用
CHANGE
,指定旧名称和新名称以及新定义。
例如,重命名
INT NOT
NULL
从塔
a
到
b
并改变其定义为使用
BIGINT
的数据类型,同时保留
NOT NULL
属性,操作如下:
ALTER TABLE t1 CHANGE ab BIGINT NOT NULL;
要更改列定义但不更改其名称,请使用
CHANGE
或
MODIFY
。
使用时
CHANGE
,语法需要两个列名,因此必须指定两次相同的名称才能保持名称不变。
例如,要更改列的定义
b
,请执行以下操作:
ALTER TABLE t1 CHANGE bb INT NOT NULL;
MODIFY
更改定义而不更改名称更方便,因为它只需要列名称一次:
ALTER TABLE t1 MODIFY b INT NOT NULL;
要更改列名但不更改其定义,请使用
CHANGE
或
RENAME COLUMN
。
使用时
CHANGE
,语法需要列定义,因此要保持定义不变,必须重新指定列当前具有的定义。
例如,要重命名
INT NOT NULL
的列
b
到
a
,这样做:
ALTER TABLE t1 CHANGE ba INT NOT NULL;
RENAME COLUMN
更改名称而不更改定义更方便,因为它只需要旧名称和新名称:
ALTER TABLE t1 RENAME COLUMN b TO a;
通常,您不能将列重命名为表中已存在的名称。
但是,有时情况并非如此,例如当您交换名称或将其移动一个循环时。
如果表具有名为
a
,,
b
和的
列
c
,则这些是有效的操作:
- 交换a和b ALTER TABLE t1 RENAME COLUMN a TO b, RENAME COLUMN b TO a; - 通过循环“旋转”a,b,c ALTER TABLE t1 RENAME COLUMN a TO b, RENAME COLUMN b TO c, RENAME COLUMN c TO a;
对于使用
CHANGE
或的
列定义更改
MODIFY
,定义必须包括应该应用于新列的数据类型和所有属性,而不是索引属性(如
PRIMARY KEY
或)
UNIQUE
。
原始定义中存在但未为新定义指定的属性不会继续使用。
假设列
col1
被定义为
INT UNSIGNED DEFAULT 1 COMMENT 'my
column'
,您按如下方式修改列,打算仅更改
INT
为
BIGINT
:
ALTER TABLE t1 MODIFY col1 BIGINT;
这种说法从改变数据类型
INT
来
BIGINT
,但它也下降了
UNSIGNED
,
DEFAULT
和
COMMENT
属性。
为了保留它们,声明必须明确包含它们:
ALTER TABLE t1 MODIFY col1 BIGINT UNSIGNED DEFAULT 1 COMMENT'my column';
对于使用
CHANGE
或的
数据类型更改
MODIFY
,MySQL尝试尽可能将现有列值转换为新类型。
此转换可能导致数据更改。
例如,如果缩短字符串列,则可能会截断值。
要防止操作成功,如果转换为新数据类型会导致数据丢失,
ALTER
TABLE
请
在使用前启用严格SQL模式
(请参见
第5.1.11节“服务器SQL模式”
)。
如果使用
CHANGE
或
MODIFY
缩短列上存在索引的列,并且结果列长度小于索引长度,MySQL会自动缩短索引。
对于由
CHANGE
or
RENAME COLUMN
重命名的
列
,MySQL会自动将这些引用重命名为重命名的列:
引用旧列的索引,包括不可见索引和禁用
MyISAM
索引。
引用旧列的外键。
对于由
CHANGE
or
RENAME COLUMN
重命名的
列
,MySQL不会自动将这些引用重命名为重命名的列:
生成的列和分区表达式,用于引用重命名的列。
您必须使用
CHANGE
在与
ALTER
TABLE
重命名列的语句
相同的
语句中
重新定义此类表达式
。
引用重命名列的视图和存储程序。 您必须手动更改这些对象的定义以引用新列名称。
要重新排序表中的列,请使用
FIRST
and
AFTER
in
CHANGE
或
MODIFY
operations。
ALTER ... SET DEFAULT
或者
ALTER ...
DROP DEFAULT
为列指定新的默认值或分别删除旧的默认值。
如果删除旧的默认值并且列可以是
NULL
,则新的默认值为
NULL
。
如果列不能
NULL
,则MySQL按
第11.7节“数据类型默认值”中
所述分配
默认值
。
DROP PRIMARY KEY
丢弃
主键
。
如果没有主键,则会发生错误。
有关主键性能特征的信息,尤其是
InnoDB
表
的性能特征
,请参见
第8.3.2节“主键优化”
。
如果您
向表中
添加一个
UNIQUE INDEX
或
PRIMARY
KEY
多个表,MySQL会在任何非唯一索引之前存储它,以便尽早检测重复键。
DROP INDEX
删除索引。
这是标准SQL的MySQL扩展。
请参见
第13.1.27节“DROP INDEX语法”
。
要确定索引名称,请使用
。
SHOW INDEX FROM
tbl_name
某些存储引擎允许您在创建索引时指定索引类型。
index_type
说明符
的语法
是
。
有关详细信息
,请参见
第13.1.15节“CREATE INDEX语法”
。
首选位置在列列表之后。
在将来的MySQL版本中,将删除在列列表之前使用该选项的支持。
USING
type_name
USING
index_option
values指定索引的其他选项。
USING
就是这样一个选择。
有关允许
index_option
值的
详细信息
,请参见
第13.1.15节“CREATE INDEX语法”
。
RENAME INDEX
重命名索引。
这是标准SQL的MySQL扩展。
表的内容保持不变。
old_index_name
TO
new_index_name
old_index_name
必须是表中未被同一
ALTER
TABLE
语句
删除的现有索引的名称
。
new_index_name
是新索引名称,在应用更改后,不能复制结果表中索引的名称。
索引名称都不能
PRIMARY
。
如果
ALTER
TABLE
在
MyISAM
表
上使用
,则所有非唯一索引都在单独的批处理中创建(至于
REPAIR
TABLE
)。
ALTER
TABLE
当你有很多索引时,
这应该会
快得多。
对于
MyISAM
表,可以显式控制密钥更新。
使用
ALTER TABLE ... DISABLE
KEYS
要告诉MySQL停止更新非唯一索引。
然后使用
ALTER TABLE ... ENABLE KEYS
重新创建缺失的索引。
MyISAM
使用比逐个插入密钥快得多的特殊算法来做到这一点,因此在执行批量插入操作之前禁用密钥应该会带来相当大的加速。
除了前面提到
ALTER TABLE ... DISABLE KEYS
的
INDEX
权限之外,
使用还
需要
特权。
虽然非唯一索引被禁用,它们将被忽略语句,如
SELECT
和
EXPLAIN
,否则会使用它们。
在
ALTER
TABLE
声明之后,可能需要运行
ANALYZE
TABLE
以更新索引基数信息。
请参见
第13.7.6.22节“SHOW INDEX语法”
。
该
ALTER INDEX
操作允许索引可见或不可见。
优化程序不使用不可见索引。
索引可见性的修改适用于主键以外的索引(显式或隐式)。
此功能是存储引擎中性(支持任何引擎)。
有关更多信息,请参见
第8.3.12节“不可见索引”
。
在
FOREIGN KEY
和
REFERENCES
条款由支持
InnoDB
和
NDB
存储引擎,它实现
。
请参见
第15.6.1.5节“InnoDB和FOREIGN KEY约束”
。
对于其他存储引擎,将解析子句但忽略这些子句。
ADD [CONSTRAINT
[
symbol
]] FOREIGN KEY
[index_name
] (...) REFERENCES ...
(...)
对于
ALTER
TABLE
不像
CREATE
TABLE
,
ADD FOREIGN
KEY
忽略了
index_name
如果给,并使用自动生成的外键的名称。
作为解决方法,请包含
CONSTRAINT
指定外键名称
的
子句:
添加约束外name
键(......)......
MySQL默默地忽略内联
REFERENCES
规范,其中引用被定义为列规范的一部分。
MySQL仅接受
REFERENCES
作为单独
FOREIGN KEY
规范的
一部分定义的子句
。
分区
InnoDB
表不支持外键。
此限制不适用于
NDB
表,包括那些明确分区的表
[LINEAR] KEY
。
有关更多信息,请参见
第23.6.2节“分区与存储引擎相关的限制”
。
MySQL Server和NDB Cluster都支持使用
ALTER
TABLE
删除外键:
ALTER TABLEtbl_name
DROP FOREIGN KEYfk_symbol
;
ALTER TABLE
支持
在同一
语句中
添加和删除外键
ALTER
TABLE ...
ALGORITHM=INPLACE
但不支持
ALTER
TABLE ...
ALGORITHM=COPY
。
服务器禁止更改可能导致参照完整性丢失的外键列。
解决方法是
ALTER
TABLE
... DROP FOREIGN KEY
在更改列定义之前和
ALTER
TABLE ... ADD FOREIGN KEY
之后使用。
禁止更改的示例包括:
对可能不安全的外键列的数据类型的更改。
例如,
允许
更改
VARCHAR(20)
为
VARCHAR(30)
,但将其更改
VARCHAR(1024)
为不是因为这会更改存储单个值所需的长度字节数。
禁止将
NULL
列
更改
NOT
NULL
为非严格模式,以防止将
NULL
值
转换
为默认的非
NULL
值,在引用的表中没有相应的值。
在严格模式下允许该操作,但如果需要任何此类转换,则会返回错误。
ALTER TABLE
更改内部生成的外键约束名称和以字符串
“
tbl_name
RENAME
new_tbl_name
tbl_name
_ibfk_
”
开头
以反映新表名称的
用户定义的外键约束名称
。
InnoDB
将以字符串
“
tbl_name
_ibfk_
”
开头的外键约束名称解释
为内部生成的名称。
在MySQL 8.0.16之前,
ALTER
TABLE
仅允许以下限制版本的
CHECK
约束添加语法,该语法被解析并被忽略:
添加检查(expr
)
从MySQL 8.0.16开始,
ALTER
TABLE
允许
CHECK
添加,删除或更改现有表的约束:
添加新约束:
ALTER TABLEtbl_name
ADD CONSTRAINT [symbol
] CHECK(expr
)[[NOT] ENFORCED];
约束语法元素的含义与for相同
CREATE
TABLE
。
请参见
第13.1.20.7节“检查约束”
。
删除名为的现有约束
symbol
:
ALTER TABLEtbl_name
DROP CHECKsymbol
;
更改是否
symbol
强制执行
现有约束
:
ALTER TABLEtbl_name
ALTER CHECKsymbol
[NOT] ENFORCED;
在
DROP CHECK
和
ALTER
CHECK
条款是MySQL的扩展标准SQL。
如果表更改导致违反强制
CHECK
约束,则会发生错误并且不会修改表。
发生错误的操作示例:
尝试将该
AUTO_INCREMENT
属性
添加
到
CHECK
约束中
使用的列
。
尝试添加强制
CHECK
约束或强制执行
非强制
约束
CHECK
,现有行违反约束条件。
尝试修改,重命名或删除
CHECK
约束中
使用的列
,除非该约束也在同一语句中删除。
例外:如果
CHECK
约束仅引用单个列,则删除列会自动删除约束。
ALTER TABLE
更改内部生成的和用户定义的
tbl_name
RENAME
new_tbl_name
CHECK
约束名称,以字符串
“
tbl_name
_chk_
”
开头
以反映新的表名。
MySQL
CHECK
将以字符串
“
tbl_name
_chk_
”
开头的约束名称
解释
为内部生成的名称。
要更改默认的表字符集和所有字符列(
CHAR
,
VARCHAR
,
TEXT
)到一个新的字符集,使用这样的语句:
ALTER TABLEtbl_name
CONVERT TO CHARACTER SETcharset_name
;
该语句还会更改所有字符列的排序规则。
如果指定no
COLLATE
子句指示要使用的排序规则,则该语句将对字符集使用默认排序规则。
如果此排序规则不适合预期的表使用(例如,如果它将从区分大小写的排序规则更改为不区分大小写的排序规则),请明确指定排序规则。
对于具有的数据类型的列
VARCHAR
或一个
TEXT
种类,
CONVERT TO
CHARACTER SET
改变了数据类型必须确保新列足够长,以尽可能多的字符存储为原始列。
例如,一
TEXT
列有两个长度字节,用于存储列中值的字节长度,最大值为65,535。
对于
latin1
TEXT
列,每个字符都需要一个字节,因此该列最多可以存储65,535个字符。
如果将列转换为
utf8
,则每个字符最多可能需要三个字节,最大可能长度为3×65,535 = 196,605字节。
该长度不适合
TEXT
列的长度字节,因此MySQL将数据类型转换为
MEDIUMTEXT
,这是长度字节可以记录值196,605的最小字符串类型。
同样,
VARCHAR
列可能会转换为
MEDIUMTEXT
。
要避免更改刚才描述的类型的数据类型,请不要使用
CONVERT TO CHARACTER SET
。
相反,用于
MODIFY
更改单个列。
例如:
ALTER TABLE t MODIFY latin1_text_col文本字符集utf8;
ALTER TABLE t MODIFY latin1_varchar_col VARCHAR(M
)CHARACTER SET utf8;
如果您指定
CONVERT TO CHARACTER SET binary
的
CHAR
,
VARCHAR
和
TEXT
列转换为它们相应的二进制字符串类型(
BINARY
,
VARBINARY
,
BLOB
)。
这意味着列不再具有字符集,后续
CONVERT TO
操作将不适用于它们。
如果
charset_name
是
DEFAULT
在一个
CONVERT TO CHARACTER
SET
操作中,由命名的字符集
character_set_database
被用于系统变量。
该
CONVERT TO
操作转换原始字符集和命名字符集之间的列值。
如果你在一个字符集中有一个列(如
),
那么
这
不是
你想要的,
latin1
但存储的值实际上使用了一些其他不兼容的字符集(如
utf8
)。
在这种情况下,您必须为每个此类列执行以下操作:
ALTER TABLE t1 CHANGE c1 c1 BLOB; ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
这样做的原因是当您转换为
BLOB
列
或从
列
转换时没有转换
。
要仅更改 表 的 默认 字符集,请使用以下语句:
ALTER TABLEtbl_name
DEFAULT CHARACTER SETcharset_name
;
这个词
DEFAULT
是可选的。
如果未指定稍后添加到表中的列的字符集(例如,with
ALTER TABLE ... ADD
column
)
,则默认字符集是使用的字符集
。
当
foreign_key_checks
系统变量启用,这是默认设置,字符集转换是不允许的,其中包括在一个外键约束使用的字符串列的表。
解决方法是
foreign_key_checks
在执行字符集转换之前
禁用
。
在重新启用之前,必须对外键约束中涉及的两个表执行转换
foreign_key_checks
。
如果
foreign_key_checks
在仅转换其中一个表后
重新启用
,则
由于在这些操作期间发生的隐式转换,
ON DELETE
CASCADE
或
ON UPDATE CASCADE
操作可能会破坏引用表中的数据(Bug#45290,Bug#74816)。
一个
InnoDB
在自己创建的表
文件的每个表的
表空间可以被丢弃,并使用进口
DISCARD TABLESPACE
和
IMPORT
TABLESPACE
选项。
这些选项可用于从备份导入每个表的文件表空间,或者将每个表的文件表空间从一个数据库服务器复制到另一个数据库服务器。
请参见
第15.6.3.7节“将表空间复制到另一个实例”
。
ORDER BY
使您能够以特定顺序创建包含行的新表。
当您知道在大多数时间以特定顺序查询行时,此选项很有用。
通过在对表进行重大更改后使用此选项,您可以获得更高的性能。
在某些情况下,如果表格由您想要稍后订购的列按顺序排列,则可能会使MySQL更容易排序。
插入和删除后,表不会保持指定的顺序。
ORDER BY
语法允许为排序指定一个或多个列名,每个列名可选地可以分别跟随
ASC
或
DESC
指示升序或降序排序。
默认为升序。
只允许列名作为排序标准;
不允许使用任意表达式。
该条款应在任何其他条款之后最后给出。
ORDER BY
对
InnoDB
表
没有意义,
因为
InnoDB
总是根据
聚簇索引
对表行进行排序
。
在分区表上使用时,
ALTER TABLE ... ORDER
BY
仅对每个分区中的行进行排序。
partition_options
表示可以与分区表一起使用的选项,用于重新分区,添加,删除,丢弃,导入,合并和拆分分区,以及执行分区维护。
这是可能的
ALTER
TABLE
语句包含一个
PARTITION BY
或
REMOVE PARTITIONING
子句中,除其他更改规格,但
PARTITION
BY
还是
REMOVE PARTITIONING
子句必须最后任何其他规格后指定。
的
ADD
PARTITION
,
DROP PARTITION
,
DISCARD PARTITION
,
IMPORT
PARTITION
,
COALESCE PARTITION
,
REORGANIZE PARTITION
,
EXCHANGE
PARTITION
,
ANALYZE PARTITION
,
CHECK PARTITION
,和
REPAIR
PARTITION
选项不能与其他单一更改规格组合
ALTER TABLE
,因为选择刚上市就单个分区的行为。
有关分区选项的更多信息,请参见
第13.1.20节“CREATE TABLE语法”
和
第13.1.9.1节“ALTER TABLE分区操作”
。
有关
ALTER TABLE ...
EXCHANGE PARTITION
语句的
信息和示例
,请参见
第23.3.3节“使用表交换分区和子分区”
。
与分区相关的子句
ALTER
TABLE
可以与分区表一起用于重新分区,添加,删除,丢弃,导入,合并和拆分分区,以及执行分区维护。
只需
在分区表上
使用
partition_options
子句,
ALTER
TABLE
就可以根据定义的分区方案对表进行重新分区
partition_options
。
此子句始终
PARTITION BY
以及适用于该
partition_options
子句
的相同语法和其他规则
开始
CREATE
TABLE
(有关更多详细信息,请参见
第13.1.20节“CREATE TABLE语法”
),并且还可用于对现有表进行分区。尚未分区。
例如,考虑如下所示定义的(非分区)表:
CREATE TABLE t1( id INT, year_col INT );
通过此语句
HASH
,可以使用
id
列作为分区键
将此表分区
为8个分区:
改编表t1 哈希分区(id) PARTITIONS 8;
MySQL支持一个
ALGORITHM
选项
[SUB]PARTITION BY [LINEAR] KEY
。
ALGORITHM=1
在计算分区中行的位置时,服务器使用与MySQL 5.1相同的密钥散列函数;
ALGORITHM=2
表示服务器使用默认为
KEY
MySQL 5.5及更高版本中的
新
分区表
实现和使用的密钥散列函数
。
(使用MySQL 5.5及更高版本中使用的密钥散列函数创建的分区表不能由MySQL 5.1服务器使用。)不指定该选项与使用具有相同的效果
ALGORITHM=2
。
此选项主要用于升级或降级时
[LINEAR] KEY
MySQL 5.1和更高版本MySQL版本之间的分区表,或者用于创建
可在MySQL 5.1服务器上使用的MySQL 5.5或更高版本服务器上
KEY
或
LINEAR KEY
之上
分区的表
。
使用
ALTER TABLE
... PARTITION BY
语句
产生的
表必须遵循与
使用
语句创建的规则相同的规则
CREATE TABLE ...
PARTITION BY
。
这包括管理表可能具有的任何唯一键(包括任何主键)与分区表达式中使用的列之间的关系的规则,如
第23.6.1节“分区键,主键和独特的钥匙“
。
CREATE TABLE ... PARTITION BY
指定分区数
的
规则也适用于
ALTER TABLE ... PARTITION BY
。
该
partition_definition
子句
ALTER TABLE ADD PARTITION
支持与语句的同名子句相同的选项
CREATE
TABLE
。
(有关
语法和说明,
请参见
第13.1.20节“CREATE TABLE语法”
。)假设您创建了分区表,如下所示:
CREATE TABLE t1( id INT, year_col INT ) 按范围划分(year_col)( 分数p0值低于(1991), 分区p1值低于(1995), 分区p2值低于(1999) );
您可以
p3
向此表
添加新分区
,以存储小于以下值的值
2002
:
更改表t1添加分区(分区p3值小于(2002));
DROP PARTITION
可用于删除一个或多个
RANGE
或
LIST
分区。
这种说法不能使用
HASH
或
KEY
分区;
相反,使用
COALESCE
PARTITION
(见本节后面部分)。
存储在
partition_names
列表中
指定的已删除分区中的任何数据都将被
丢弃。
例如,根据
t1
先前定义
的表
,您可以删除命名的分区
p0
,
p1
如下所示:
ALTER TABLE t1 DROP PARTITION p0,p1;
DROP PARTITION
不适用于使用
NDB
存储引擎的
表
。
请参见
第23.3.1节“RANGE和LIST分区的管理”
和
第22.1.7节“NDB集群的已知限制”
。
ADD PARTITION
并且
DROP
PARTITION
目前不支持
IF
[NOT] EXISTS
。
在
DISCARD
PARTITION ... TABLESPACE
和
IMPORT
PARTITION ... TABLESPACE
选项延长
传输表空间
功能个别
InnoDB
表分区。
每个
InnoDB
表分区都有自己的表空间文件(
.ibd
文件)。
可
传输表空间
功能可以轻松地将表空间从正在运行的MySQL服务器实例复制到另一个正在运行的实例,或者在同一实例上执行还原。
这两个选项都使用逗号分隔的一个或多个分区名称列表。
例如:
更改表t1 DISCARD PARTITION p2,p3 TABLESPACE;
更改表t1导入分区p2,p3 TABLESPACE;
在子分区表上
运行时
DISCARD
PARTITION ... TABLESPACE
,
IMPORT
PARTITION ... TABLESPACE
允许分区和子分区名称。
指定分区名称时,将包括该分区的子分区。
可
传输表空间
功能还支持复制或还原分区
InnoDB
表(所有分区一次)。
有关其他信息,请参见
第15.6.3.7节“将表空间复制到另一个实例”
,以及
第15.6.3.7.1节“可传输表空间示例”
。
支持分区表的重命名。
您可以使用间接重命名单个分区
ALTER TABLE
... REORGANIZE PARTITION
;
但是,此操作会复制分区的数据。
要从选定分区中删除行,请使用该
TRUNCATE PARTITION
选项。
此选项采用一个或多个逗号分隔的分区名称列表。
考虑一下
t1
这个语句创建的表:
CREATE TABLE t1( id INT, year_col INT ) 按范围划分(year_col)( 分数p0值低于(1991), 分区p1值低于(1995), 分区p2值低于(1999), 分区p3的价值低于(2003年), 分区p4价值低于(2007年) );
要从分区中删除所有行
p0
,请使用以下语句:
ALTER TABLE t1 TRUNCATE PARTITION p0;
刚才显示的语句与以下
DELETE
语句
具有相同的效果
:
DELETE FROM t1 WHERE year_col <1991;
截断多个分区时,分区不必是连续的:这可以大大简化分区表上的删除操作,否则
WHERE
如果使用
DELETE
语句
,则需要非常复杂的
条件
。
例如,此语句删除分区中的所有行,
p1
并且
p3
:
ALTER TABLE t1 TRUNCATE PARTITION p1,p3;
DELETE
这里显示了
一个等效
语句:
从t1 WHERE中删除 (year_col> = 1991 AND year_col <1995) 要么 (year_col> = 2003 AND year_col <2007);
如果使用
ALL
关键字代替分区名称列表,则该语句将作用于所有表分区。
TRUNCATE PARTITION
只是删除行;
它不会改变表本身或其任何分区的定义。
要验证行是否已删除,请
INFORMATION_SCHEMA.PARTITIONS
使用以下查询
检查
表:
SELECT PARTITION_NAME,TABLE_ROWS 来自INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME ='t1';
COALESCE PARTITION
可以与分区的表一起使用,
HASH
或者
KEY
减少分区数
number
。
假设您已创建表
t2
,如下所示:
创建表t2( 名称VARCHAR(30), 开始日期 ) 哈希分区(年(开始)) 分数6;
要将使用的分区数
t2
从6减少到4,请使用以下语句:
更改表t2 COALESCE PARTITION 2;
最后一个
number
分区中
包含的数据
将合并到其余分区中。
在这种情况下,分区4和5将合并到前4个分区(编号为0,1,2和3的分区)中。
要更改分区表使用的部分但不是全部分区,可以使用
REORGANIZE
PARTITION
。
可以通过以下几种方式使用此语句:
将一组分区合并到一个分区中。
这是通过在
partition_names
列表中
命名多个分区
并为其提供单个定义来完成的
partition_definition
。
将现有分区拆分为多个分区。
通过为单个分区命名
partition_names
并提供多个
分区来完成此任务
partition_definitions
。
更改使用定义的分区子集的范围
VALUES LESS THAN
或
使用定义的分区子集
的值列表
VALUES IN
。
对于没有明确命名的分区,MySQL的自动提供的默认名称
p0
,
p1
,
p2
,等等。
对于子分区也是如此。
有关
ALTER TABLE ... REORGANIZE PARTITION
语句的
更多详细信息和示例
,请参见
第23.3.1节“RANGE和LIST分区的管理”
。
要使用表交换表分区或子分区,请使用该
ALTER
TABLE ... EXCHANGE PARTITION
语句,即将分区或子分区中的任何现有行移动到非分区表,将非分区表中的任何现有行移动到表分区或子分区。
有关用法信息和示例,请参见 第23.3.3节“使用表交换分区和子分区” 。
有几个选项提供分区维护和修复功能,类似于通过诸如
CHECK
TABLE
和
REPAIR
TABLE
(以及分区表也支持的
语句
)
为非
分区表实现的功能;有关更多信息,请参见
第13.7.3节“表维护语句”
)。
这些措施包括
ANALYZE PARTITION
,
CHECK
PARTITION
,
OPTIMIZE PARTITION
,
REBUILD PARTITION
,和
REPAIR
PARTITION
。
这些选项中的每一个都采用
partition_names
由一个或多个分区名称组成的子句,以逗号分隔。
分区必须已存在于目标表中。
您也可以使用
ALL
关键字代替
partition_names
在这种情况下,该语句作用于所有表分区。
有关更多信息和示例,请参见
第23.3.4节“分区维护”
。
InnoDB
目前不支持按分区优化;
ALTER TABLE ...
OPTIMIZE PARTITION
导致整个表重建和分析,并发出适当的警告。
(Bug#11751825,Bug#42822)要解决此问题,请使用
ALTER TABLE ... REBUILD
PARTITION
而
ALTER TABLE ... ANALYZE
PARTITION
不是。
在
ANALYZE PARTITION
,
CHECK
PARTITION
,
OPTIMIZE PARTITION
,和
REPAIR PARTITION
选项不支持未分区表。
REMOVE PARTITIONING
使您可以删除表的分区,而不会影响表或其数据。
此选项可以与其他
ALTER
TABLE
选项
结合使用,
例如用于添加,删除或重命名列或索引的选项。
使用该
ENGINE
选项
ALTER
TABLE
可更改表使用的存储引擎,而不会影响分区。
目标存储引擎必须提供自己的分区处理程序。
只有
InnoDB
和
NDB
存储引擎有本机分区处理程序;
NDB
MySQL 8.0目前不支持。
这是可能的
ALTER
TABLE
语句包含一个
PARTITION BY
或
REMOVE PARTITIONING
子句中,除其他更改规格,但
PARTITION
BY
还是
REMOVE PARTITIONING
子句必须最后任何其他规格后指定。
的
ADD PARTITION
,
DROP
PARTITION
,
COALESCE PARTITION
,
REORGANIZE PARTITION
,
ANALYZE
PARTITION
,
CHECK PARTITION
,和
REPAIR PARTITION
选项不能与其他单一更改规格组合
ALTER
TABLE
,因为选择刚上市就单个分区的行为。
有关更多信息,请参见
第13.1.9.1节“ALTER TABLE分区操作”
。
只有以下任一选项的单个实例可以在给定的使用
ALTER
TABLE
声明:
PARTITION BY
,
ADD
PARTITION
,
DROP PARTITION
,
TRUNCATE PARTITION
,
EXCHANGE
PARTITION
,
REORGANIZE PARTITION
,或
COALESCE PARTITION
,
ANALYZE
PARTITION
,
CHECK PARTITION
,
OPTIMIZE PARTITION
,
REBUILD
PARTITION
,
REMOVE PARTITIONING
。
例如,以下两个语句无效:
ALTER TABLE t1 ANALYZE PARTITION p1,ANALYZE PARTITION p2; ALTER TABLE t1 ANALYZE PARTITION p1,CHECK PARTITION p2;
在第一种情况下,您可以
使用单个语句同时
分析分区
p1
和
p2
表,
t1
并使用单个
ANALYZE PARTITION
选项列出要分析的两个分区,如下所示:
ALTER TABLE t1 ANALYZE PARTITION p1,p2;
在第二种情况下,不可能
同时在同一个表的不同分区上
执行
ANALYZE
和
CHECK
操作。
相反,您必须发出两个单独的语句,如下所示:
ALTER TABLE t1 ANALYZE PARTITION p1; ALTER TABLE t1检查分区p2;
REBUILD
子分区目前不支持操作。
所述
REBUILD
关键字被明确地与子分区不允许,并且使得
ALTER TABLE
如果这样用失败,错误。
CHECK PARTITION
REPAIR
PARTITION
当要检查或修复的分区包含任何重复的键错误时
,
操作失败。
有关这些语句的更多信息,请参见 第23.3.4节“分区维护” 。
ALTER TABLE
允许生成的列操作是
ADD
,
MODIFY
,和
CHANGE
。
可以添加生成的列。
CREATE TABLE t1(c1 INT); 更改表t1添加列c2 INT始终作为(c1 + 1)存储;
可以修改生成列的数据类型和表达式。
创建表t1(c1 INT,c2 INT始终作为(c1 + 1)存储); 更改表t1修改栏c2 TINYINT始终作为(c1 + 5)存储;
如果没有其他列引用它们,则可以重命名或删除生成的列。
创建表t1(c1 INT,c2 INT始终作为(c1 + 1)存储); 更改表t1更改c2 c3 INT始终作为(c1 + 1)存储; ALTER TABLE t1 DROP COLUMN c3;
虚拟生成的列不能更改为存储的生成列,反之亦然。 要解决此问题,请删除该列,然后使用新定义添加该列。
创建表t1(c1 INT,c2 INT始终为(c1 + 1)VIRTUAL); ALTER TABLE t1 DROP COLUMN c2; 更改表t1添加列c2 INT始终作为(c1 + 1)存储;
非生成列可以更改为已存储但不是虚拟生成列。
CREATE TABLE t1(c1 INT,c2 INT); 更改表t1修改栏c2 INT始终作为(c1 + 1)存储;
存储但不是虚拟生成的列可以更改为非生成列。 存储的生成值将成为非生成列的值。
创建表t1(c1 INT,c2 INT始终作为(c1 + 1)存储); ALTER TABLE t1 MODIFY COLUMN c2 INT;
ADD COLUMN
不是存储列的就地操作(不使用临时表),因为表达式必须由服务器评估。
对于存储的列,索引更改将在适当的位置完成,并且表达式更改不会就位。
列注释的更改已就位。
对于非分区表,
ADD COLUMN
以及
DROP COLUMN
虚拟列的就地操作。
但是,无法在与其他
ALTER
TABLE
操作
组合的情况下执行添加或删除虚拟列
。
对于分区表,
ADD COLUMN
并且
DROP COLUMN
不是虚拟列的就地操作。
InnoDB
支持虚拟生成列上的二级索引。
在虚拟生成列上添加或删除辅助索引是就地操作。
有关更多信息,请参见
第13.1.20.10节“二级索引和生成的列”
。
将
VIRTUAL
生成的列添加到表中或进行修改时,无法确保生成的列表达式计算的数据不会超出列的范围。
这可能导致返回不一致的数据和意外失败的语句。
允许控制是否对此类列,
ALTER TABLE
支持
WITHOUT VALIDATION
和
WITH
VALIDATION
子句
进行验证
:
使用
WITHOUT VALIDATION
(默认情况下,如果未指定none子句),将执行就地操作(如果可能),不检查数据完整性,并且语句更快完成。
但是,如果值超出范围,稍后从表中读取可能会报告列的警告或错误。
用
WITH VALIDATION
,
ALTER
TABLE
复制表。
如果发生超出范围或任何其他错误,则语句失败。
由于执行了表副本,因此语句需要更长时间。
WITHOUT VALIDATION
并且
WITH
VALIDATION
只有被允许
ADD
COLUMN
,
CHANGE COLUMN
和
MODIFY COLUMN
操作。
否则,
ER_WRONG_USAGE
会发生错误。
如果表达式求值导致截断或向函数提供不正确的输入,则
ALTER
TABLE
语句将终止并显示错误,并拒绝DDL操作。
ALTER TABLE
更改列的默认值
的
语句
col_name
还可能更改引用列使用
col_name
的生成列表达式的值,这可能会更改引用该列的生成列表达式的值
。
因此,
如果任何生成的列表达式使用,则更改列定义的操作会导致表重建
。
DEFAULT(
col_name
)ALTER TABLE
DEFAULT()
从
t1
如下所示创建
的表开始
:
CREATE TABLE t1(INTEGER,b CHAR(10));
要将表重命名
t1
为
t2
:
ALTER TABLE t1 RENAME t2;
若要更改列
a
从
INTEGER
给
TINYINT NOT
NULL
(名字一样),并更改列
b
从
CHAR(10)
到
CHAR(20)
以及来自重命名
b
到
c
:
ALTER TABLE t2修改TINYINT NOT NULL,更改bc CHAR(20);
要添加
TIMESTAMP
名为
的新
列
d
:
ALTER TABLE t2 ADD d TIMESTAMP;
要添加对列的索引
d
和
UNIQUE
对列索引
a
:
ALTER TABLE t2 ADD INDEX(d),ADD UNIQUE(a);
要删除列
c
:
ALTER TABLE t2 DROP COLUMN c;
要添加
AUTO_INCREMENT
名为
的新
整数列
c
:
ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT, 添加主要密钥(c);
我们索引
c
(作为a
PRIMARY
KEY
)因为
AUTO_INCREMENT
列必须被索引,并且我们声明
c
为
NOT NULL
因为主键列不能
NULL
。
对于
NDB
表,还可以更改用于表或列的存储类型。
例如,考虑
NDB
如下所示创建
的
表:
MySQL的> CREATE TABLE t1 (c1 INT) TABLESPACE ts_1 ENGINE NDB;
查询OK,0行受影响(1.27秒)
要将此表转换为基于磁盘的存储,可以使用以下
ALTER
TABLE
语句:
MySQL的>ALTER TABLE t1 TABLESPACE ts_1 STORAGE DISK;
查询正常,0行受影响(2.99秒) 记录:0重复:0警告:0 MySQL的>SHOW CREATE TABLE t1\G
*************************** 1。排******************** ******* 表:t1 创建表:CREATE TABLE`t1`( `c1` int(11)DEFAULT NULL )/ *!50100 TABLESPACE ts_1存储盘* / ENGINE = ndbcluster DEFAULT CHARSET = latin1 1排(0.01秒)
最初创建表时,没有必要引用表空间;
但是,表空间必须由以下引用
ALTER
TABLE
:
MySQL的>CREATE TABLE t2 (c1 INT) ts_1 ENGINE NDB;
查询正常,0行受影响(1.00秒) mysql> ERROR 1005(HY000):无法创建表'c。#sql-1750_3'(错误号:140) mysql>ALTER TABLE t2 STORAGE DISK;
ALTER TABLE t2 TABLESPACE ts_1 STORAGE DISK;
查询OK,0行受影响(3.42秒) 记录:0重复:0警告:0 MySQL的>SHOW CREATE TABLE t2\G
*************************** 1。排******************** ******* 表:t1 创建表:CREATE TABLE`t2`( `c1` int(11)DEFAULT NULL )/ *!50100 TABLESPACE ts_1存储盘* / ENGINE = ndbcluster DEFAULT CHARSET = latin1 1排(0.01秒)
要更改单个列的存储类型,您可以使用
ALTER TABLE ... MODIFY [COLUMN]
。
例如,假设您使用以下
CREATE
TABLE
语句
创建具有两列的NDB Cluster Disk Data表
:
mysql>CREATE TABLE t3 (c1 INT, c2 INT)
- >TABLESPACE ts_1 STORAGE DISK ENGINE NDB;
查询OK,0行受影响(1.34秒)
要将列
c2
从基于磁盘的存储
更改
为内存存储,请在ALTER TABLE语句使用的列定义中包含STORAGE MEMORY子句,如下所示:
MySQL的> ALTER TABLE t3 MODIFY c2 INT STORAGE MEMORY;
查询正常,0行受影响(3.14秒)
记录:0重复:0警告:0
您可以通过
STORAGE DISK
类似的方式
使用内存中的列到基于磁盘的列
。
列
c1
使用基于磁盘的存储,因为这是表的缺省值(由
STORAGE DISK
语句中的
表级
子句
确定
CREATE
TABLE
)。
但是,列
c2
使用内存存储,这可以在SHOW的输出中看到
CREATE
TABLE
:
MySQL的> SHOW CREATE TABLE t3\G
*************************** 1。排******************** *******
表:t3
创建表:CREATE TABLE`t3`(
`c1` int(11)DEFAULT NULL,
`c2` int(11)/ *!50120 STORAGE MEMORY * / DEFAULT NULL
)/ *!50100 TABLESPACE ts_1存储磁盘* / ENGINE = ndbcluster DEFAULT CHARSET = latin1
1排(0.02秒)
添加
AUTO_INCREMENT
列时,列值将自动填入序列号。
对于
MyISAM
表,您可以通过执行
之前
或使用
表选项
来设置第一个序列号
。
SET
INSERT_ID=
value
ALTER TABLE
AUTO_INCREMENT=
value
对于
MyISAM
表,如果不更改
AUTO_INCREMENT
列,则序列号不受影响。
如果删除
AUTO_INCREMENT
列然后添加另一
AUTO_INCREMENT
列,则从1开始重新排序数字。
使用复制时,向
AUTO_INCREMENT
表中
添加
列可能不会在从属和主服务器上生成相同的行顺序。
发生这种情况是因为行的编号顺序取决于用于表的特定存储引擎以及插入行的顺序。
如果在主站和从站上具有相同的顺序很重要,则必须在分配
AUTO_INCREMENT
号码
之前对行进行排序
。
假设您要向
AUTO_INCREMENT
表中
添加一
列
t1
,以下语句将生成一个
与
列
t2
相同
t1
但具有
AUTO_INCREMENT
列
的新表
:
CREATE TABLE t2(id INT AUTO_INCREMENT PRIMARY KEY) SELECT * FROM t1 ORDER BY col1,col2;
这假设表
t1
有列
col1
和
col2
。
这组语句还将生成一个
与添加
列
t2
相同
的新表
:
t1
AUTO_INCREMENT
CREATE TABLE t2 LIKE t1; ALTER TABLE t2 ADD id INT AUTO_INCREMENT PRIMARY KEY; INSERT INTO t2 SELECT * FROM t1 ORDER BY col1,col2;
为了保证主服务器和从服务器上的相同顺序
,
必须在
子句中
引用
所有
列
。
t1
ORDER BY
无论用于创建和填充具有
AUTO_INCREMENT
列
的副本的方法如何
,最后一步是删除原始表,然后重命名副本:
DROP TABLE t1; ALTER TABLE t2 RENAME t1;
仅ALTER [UNDO] TABLESPACE NDB: {ADD | DROP} DATAFILE' 'tablespace_name
file_name
[INITIAL_SIZE [=]尺寸] [等待] InnoDB和NDB: [仅限 RENAME TOtablespace_name
] InnoDB: [SET {ACTIVE | INACTIVE}] [ENCRYPTION [=] {'Y'| 'N'}] InnoDB和NDB: [ENGINE [=]engine_name
]
此语句与
NDB
和
InnoDB
表空间一起使用。
它可用于向
NDB
表空间
添加新数据文件或从
表空间
删除数据文件
。
它还可用于重命名NDB Cluster Disk Data表空间,重命名
InnoDB
常规表空间,加密
InnoDB
常规表空间或将
InnoDB
undo表空间
标记
为活动或非活动。
UNDO
MySQL 8.0.14中引入
的
关键字与该
SET {ACTIVE|INACTIVE}
子句一起
使用,
以将
InnoDB
撤消表空间
标记
为活动或非活动。
有关更多信息,请参见
第15.6.3.4节“撤消表空间”
。
该
ADD DATAFILE
变量使您可以
NDB
使用
INITIAL_SIZE
子句
指定
磁盘数据表空间
的初始大小
,其中
size
以字节为单位进行测量;
默认值为134217728(128 MB)。
您可以选择
size
使用一个字母的缩写,一个数量级,类似于中使用的那些
my.cnf
。
通常,这是字母
M
(兆字节)或
G
(千兆字节)之一。
在32位系统上,支持的最大值为
INITIAL_SIZE
4294967296(4 GB)。
(Bug#29186)
INITIAL_SIZE
是明确的四舍五入的
CREATE
TABLESPACE
。
创建数据文件后,其大小无法更改;
但是,您可以使用其他
ALTER TABLESPACE ... ADD DATAFILE
语句
将更多数据文件添加到NDB表空间
。
当
ALTER TABLESPACE ... ADD DATAFILE
与使用
ENGINE = NDB
中,每个群集的数据节点上创建的数据文件,但在仅生成一个行
INFORMATION_SCHEMA.FILES
表。
有关详细信息,请参阅此表的说明以及
第22.5.13.1节“NDB集群磁盘数据对象”
。
表空间
ADD DATAFILE
不支持
InnoDB
。
使用
DROP DATAFILE
与
ALTER
TABLESPACE
下降的数据文件“
file_name
从NDB表”。
您不能从任何表正在使用的表空间中删除数据文件;
换句话说,数据文件必须为空(不使用扩展数据块)。
请参见
第22.5.13.1节“NDB集群磁盘数据对象”
。
此外,要删除的任何数据文件必须先前已使用
CREATE
TABLESPACE
或
添加到表空间
ALTER
TABLESPACE
。
表空间
DROP
DATAFILE
不支持
InnoDB
。
WAIT
被解析但被忽略。
它旨在用于未来的扩展。
该
ENGINE
子句指定了表空间使用的存储引擎,已弃用,将在以后的版本中删除。
表空间存储引擎是数据字典已知的,使该
ENGINE
子句过时。
如果指定了存储引擎,则它必须与数据字典中定义的表空间存储引擎匹配。
engine_name
与
NDB
表空间
兼容
的唯一值
是
NDB
和
NDBCLUSTER
。
RENAME TO
autocommit
无论
autocommit
设置
如何,
都以
模式
隐式执行操作
。
甲
RENAME TO
操作不能同时被执行
LOCK
TABLES
或者
FLUSH TABLES
WITH READ
LOCK
是在驻留在表空间的表的效果。
在重命名表空间时,驻留在通用表空间中的表采用 独占 元数据锁 ,这可防止并发DDL。 支持并发DML。
CREATE TABLESPACE
需要
该
权限才能重命名
InnoDB
常规表空间。
该
ENCRYPTION
子句启用或禁用
InnoDB
常规表空间或
mysql
系统表空间的
页级数据加密
。
MySQL 8.0.13中引入了对通用表空间的加密支持。
mysql
MySQL 8.0.16中引入
了对
系统表空间的
加密支持
。
必须先安装并配置密钥环插件,然后才能启用加密。
从MySQL 8.0.16开始,如果
table_encryption_privilege_check
启用了
该
变量,
TABLE_ENCRYPTION_ADMIN
则需要
使用
权限来更改具有与
ENCRYPTION
设置不同
的
子句设置
的常规表空间
default_table_encryption
。
如果表空间中的任何表属于使用定义的模式,则对通用表空间启用加密会失败
DEFAULT
ENCRYPTION='N'
。
同样,如果通用表空间中的任何表属于定义的模式,则禁用加密会失败
DEFAULT
ENCRYPTION='Y'
。
该
DEFAULT
ENCRYPTION
模式选项在MySQL 8.0.16介绍。
如果
ALTER
TABLESPACE
在通用表空间上执行
的
语句不包含
ENCRYPTION
子句,则表空间将保留其当前加密状态,而不管
default_table_encryption
设置
如何
。
对通用表空间或
mysql
系统表空间进行加密时,驻留在表空间中的所有表都将被加密。
同样,在加密表空间中创建的表也是加密的。
INPLACE
在更改
ENCRYPTION
通用表空间或
mysql
系统表空间
的
属性
时使用
该
算法
。
该
INPLACE
算法允许驻留在表空间中的表上的并发DML。
并发DDL被阻止。
有关更多信息,请参见 第15.6.3.9节“InnoDB静态数据加密” 。
改变 [ALGORITHM = {UNDEFINED | MERGE | 不是Temptable}] [DEFINER =user
] [SQL SECURITY {DEFINER | INVOKER}] 查看view_name
[(column_list
)] 如select_statement
[WITH [CASCADED | 本地]检查选项]
此语句更改必须存在的视图的定义。
语法是类似于对
CREATE
VIEW
见
第13.1.23,“CREATE VIEW语法”
)。
此语句需要
视图的权限
CREATE VIEW
和
DROP
特权,以及
SELECT
语句中
引用的每个列的某些特权
。
ALTER
VIEW
仅允许定义者或用户提供
SET_USER_ID
或
SUPER
特权。
创建{数据库| SCHEMA} [如果不存在]db_name
[create_specification
] ......create_specification
: [DEFAULT] CHARACTER SET [=]charset_name
| [DEFAULT] COLLATE [=]collation_name
| DEFAULT ENCRYPTION [=] {'Y'| 'N'}
CREATE
DATABASE
创建具有给定名称的数据库。
要使用此语句,您需要
CREATE
数据库
的
权限。
CREATE
SCHEMA
是...的同义词
CREATE
DATABASE
。
如果数据库存在且您未指定,则会发生错误
IF NOT EXISTS
。
CREATE
DATABASE
在具有活动
LOCK
TABLES
语句
的会话中不允许
。
create_specification
options指定数据库特征。
数据库特征存储在数据字典中。
该
CHARACTER SET
子句指定默认数据库字符集。
该
COLLATE
子句指定默认的数据库排序规则。
第10章,
字符集,排序规则,Unicode
,讨论字符集和排序规则名称。
DEFAULT ENCRYPTION
MySQL 8.0.16中引入的
该
子句定义了默认数据库加密,该加密由数据库中创建的表继承。
如果
DEFAULT ENCRYPTION
未指定
该
子句,则该
default_table_encryption
设置将定义默认数据库加密。
如果
table_encryption_privilege_check
启用
该
变量,
TABLE_ENCRYPTION_ADMIN
则需要
该
权限才能指定与设置不同的默认加密
default_table_encryption
设置。
有关更多信息,请参阅
为架构和常规表空间定义加密默认值
。
MySQL中的数据库实现为包含与数据库中的表对应的文件的目录。
由于最初创建数据库时没有表,因此该
CREATE
DATABASE
语句仅在MySQL数据目录下创建一个目录。
第9.2节“模式对象名称”
中给出了允许的数据库名称的规则
。
如果数据库名称包含特殊字符,则数据库目录的名称包含这些字符的编码版本,如
第9.2.3节“标识符到文件名的映射”中所述
。
在MySQL 8.0中不支持通过在 数据目录下手动创建目录(例如,使用 mkdir )来 创建数据库目录 。
您还可以使用 mysqladmin 程序创建数据库。 请参见 第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端” 。
创建 [DEFINER =user
] 事件 [IF NOT EXISTS]event_name
按照时间表schedule
[完成[NOT] PRESERVE] [ENABLE | 禁用| 禁止在[SLAVE] [评论'string
'] 做event_body
;schedule
: ATtimestamp
[+ INTERVALinterval
] ...... | 每个interval
[开始timestamp
[+间隔interval
] ...] [结束timestamp
[+ INTERVALinterval
] ...]interval
:quantity
{年| QUARTER | 月| 一天| 小时| 分钟| 周| 第二| YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
此语句创建并计划新事件。 除非启用了事件计划程序,否则该事件将不会运行。 有关检查事件调度程序状态并在必要时启用它的信息,请参见 第24.4.2节“事件调度程序配置” 。
CREATE
EVENT
需要对
EVENT
要在其中创建事件的模式
的
权限。
如果该
DEFINER
子句存在,则所需的权限取决于
user
值,如
第24.6节“存储对象访问控制”中所述
。
有效
CREATE
EVENT
声明
的最低要求
如下:
关键字
CREATE EVENT
加上事件名称,它唯一标识数据库模式中的事件。
一个
ON SCHEDULE
子句,用于确定事件执行的时间和频率。
一个
DO
子句,包含要由事件执行的SQL语句。
这是最小
CREATE
EVENT
语句
的示例
:
创造事件myevent 在CURRENT_TIMESTAMP + INTERVAL 1小时的时间表 做 更新myschema.mytable SET mycol = mycol + 1;
前一个语句创建一个名为的事件
myevent
。
此事件在创建后执行一次 - 通过运行SQL语句,该语句将
myschema.mytable
表的
mycol
列
的值递增
1。
在
event_name
必须与64个字符的最大长度一个有效的MySQL标识符。
事件名称是不区分大小写,所以你不能有两个名为事件
myevent
,并
MyEvent
在同一个模式。
通常,管理事件名称的规则与存储例程的名称相同。
请参见
第9.2节“架构对象名称”
。
事件与架构相关联。
如果没有指示模式作为其一部分
event_name
,则假定默认(当前)模式。
要在特定模式中创建事件,请使用
语法
使用模式限定事件名称
。
schema_name
.event_name
该
DEFINER
子句指定在事件执行时检查访问权限时要使用的MySQL帐户。
如果
DEFINER
子句,该
user
值应被指定为一个MySQL帐户
,
或
。
允许的
值取决于您拥有的权限,如
第24.6节“存储对象访问控制”中所述
。
有关事件安全性的其他信息,另请参阅该部分。
'
user_name
'@'host_name
'CURRENT_USER
CURRENT_USER()
user
如果
DEFINER
省略
该
子句,则默认定义者是执行该
CREATE
EVENT
语句
的用户
。
这与
DEFINER = CURRENT_USER
明确
指定相同
。
在事件正文中,该
CURRENT_USER
函数返回用于在事件执行时检查权限的帐户,即
DEFINER
用户。
有关事件中用户审计的信息,请参见
第6.2.22节“基于SQL的帐户活动审计”
。
IF NOT EXISTS
具有相同的含义为
CREATE
EVENT
为
CREATE
TABLE
:如果命名的事件
event_name
已经在相同的模式存在,不采取任何行动,而不会出现错误。
(但是,在这种情况下会产生警告。)
该
ON SCHEDULE
子句确定
event_body
事件
的
定义
时间,频率和持续时间
。
该子句采用以下两种形式之一:
AT
用于一次性事件。
它指定事件仅在给定的日期和时间执行一次,该日期和时间
timestamp
timestamp
必须包括日期和时间,或者必须是解析为datetime值的表达式。
您可以
为此目的
使用
DATETIME
或
TIMESTAMP
类型
的值
。
如果日期是过去的,则会发出警告,如下所示:
MySQL的>SELECT NOW();
+ --------------------- + | 现在()| + --------------------- + | 2006-02-10 23:59:01 | + --------------------- + 1排(0.04秒) mysql>CREATE EVENT e_totals
- >ON SCHEDULE AT '2006-02-10 23:59:00'
- >DO INSERT INTO test.totals VALUES (NOW());
查询正常,0行受影响,1警告(0.00秒) MySQL的>SHOW WARNINGS\G
*************************** 1。排******************** ******* 等级:注意 代码:1588 消息:事件执行时间是过去而完全没有 PRESERVE已经确定。事件在此之后立即被删除 创建。
CREATE
EVENT
无论出于何种原因本身无效的语句 - 失败并出现错误。
您可以使用
CURRENT_TIMESTAMP
指定当前日期和时间。
在这种情况下,事件一旦创建就会起作用。
要创建一个相对于当前日期和时间在某个时间点发生的事件 - 例如短语
“
从现在起三周
”所表达的事件
- 您可以使用optional子句
。
该
部分由两部分组成,即数量和时间单位,并遵循
时间间隔中
描述的语法规则
,但在定义事件时不能使用任何涉及微秒的单位关键字。
对于一些间隔类型,可以使用复杂的时间单位。
例如,
“
两分十秒
”
可以表示为
。
+
INTERVAL
interval
interval
+
INTERVAL '2:10' MINUTE_SECOND
您还可以组合间隔。
例如,
AT
CURRENT_TIMESTAMP + INTERVAL 3 WEEK + INTERVAL 2 DAY
相当于
“
从现在开始的三周和两天
”
。
这样一个条款的每一部分都必须以
+ INTERVAL
。
要定期重复操作,请使用
EVERY
子句。
该
EVERY
关键字后跟一个关键字
interval
的前一个讨论中所描述的
AT
关键字。
(
+ INTERVAL
是
不
与所用
EVERY
。)例如,
EVERY 6
WEEK
是指
“
每六周
”
。
虽然
+ INTERVAL
条款中不允许使用
EVERY
条款,但您可以使用相同的复杂时间单位
+
INTERVAL
。
一个
EVERY
子句可以包含一个可选的
STARTS
条款。
STARTS
后跟一个
timestamp
值,
该
值指示动作应该何时开始重复,并且还可以
用于指定
“
从现在起
”
的时间量
。
例如,
意思是
“
每三个月,从现在开始一周
”
。
同样,你可以表达
“
每两个星期,开始6小时15分钟从现在开始
”
的
。
未指定
与使用相同
+ INTERVAL
interval
EVERY 3 MONTH STARTS CURRENT_TIMESTAMP +
INTERVAL 1
WEEK
EVERY 2 WEEK STARTS CURRENT_TIMESTAMP
+ INTERVAL '6:15' HOUR_MINUTE
STARTS
STARTS
CURRENT_TIMESTAMP
- 也就是说,为事件指定的操作在创建事件后立即开始重复。
一个
EVERY
子句可以包含一个可选的
ENDS
条款。
该
ENDS
关键字后跟
timestamp
告诉MySQL时,该事件应停止重复值。
你也可以
用
;
例如,
相当于
“
每十二小时,从现在开始三十分钟,从现在开始四周后
”
。
不使用
意味着事件继续无限期执行。
+ INTERVAL
interval
ENDS
EVERY 12 HOUR
STARTS CURRENT_TIMESTAMP + INTERVAL 30 MINUTE ENDS
CURRENT_TIMESTAMP + INTERVAL 4 WEEK
ENDS
ENDS
支持与复杂时间单位相同的语法
STARTS
。
您可以
在
条款中
使用
STARTS
,
ENDS
或两者都使用
EVERY
。
如果重复事件未在其调度间隔内终止,则结果可能是同时执行事件的多个实例。
如果这是不合需要的,您应该建立一个机制来防止同时发生。
例如,您可以使用
GET_LOCK()
函数,或行或表锁定。
该
ON SCHEDULE
子句可以使用涉及内置MySQL函数和用户变量的表达式来获取
它包含的
任何
timestamp
或
interval
值。
您不能在此类表达式中使用存储函数或用户定义函数,也不能使用任何表引用;
但是,你可以使用
SELECT FROM DUAL
。
对于这两个
CREATE
EVENT
和
ALTER
EVENT
陈述
都是如此
。
在这种情况下,特别不允许引用存储函数,用户定义函数和表,并且失败并出现错误(参见Bug#22830)。
在时代
ON SCHEDULE
条款使用当前会话解释
time_zone
值。
这成为事件时区;
也就是说,用于事件调度的时区,它在执行时在事件中生效。
这些时间将转换为UTC并与
mysql.event
表中
的事件时区一起存储
。
这使得事件执行能够按照定义继续执行,而不管服务器时区或夏令时效果的任何后续更改。
有关事件时间表示的其他信息,请参见
第24.4.4节“事件元数据”
。
另请参见
第13.7.6.18节“显示事件语法”
和
第25.10节“INFORMATION_SCHEMA事件表”
。
通常,一旦事件过期,它会立即被删除。
您可以通过指定来覆盖此行为
ON
COMPLETION PRESERVE
。
使用
ON COMPLETION NOT
PRESERVE
仅仅使默认的非持久行为显式化。
您可以创建一个事件,但使用该
DISABLE
关键字
阻止它处于活动状态
。
或者,您可以使用
ENABLE
显式默认状态,该状态是活动的。
这最有用
ALTER
EVENT
(参见
第13.1.3节“ALTER EVENT语法”
)。
第三个值也可能代替
ENABLE
或
出现
DISABLE
;
DISABLE ON SLAVE
设置为复制从站上事件的状态,以指示事件是在主服务器上创建并复制到从服务器,但不在从服务器上执行。
请参见
第17.4.1.16节“调用调用的功能”
。
您可以使用
COMMENT
子句
为事件提供注释
。
comment
可以是您希望用于描述事件的任何最多64个字符的字符串。
注释文本是字符串文字,必须用引号括起来。
该
DO
子句指定事件携带的操作,并由SQL语句组成。
几乎任何可以在存储例程中使用的有效MySQL语句也可以用作已调度事件的操作语句。
(请参见
第C.1节“存储程序的限制”
。)例如,以下事件
每小时
e_hourly
删除
sessions
一次表中的
所有行
,其中此表是
site_activity
模式的
一部分
:
e_hourly创造活动 按照时间表 每一个小时 评论'每小时清理一次会议表。' 做 从site_activity.sessions中删除;
MySQL存储在
sql_mode
创建或更改事件时生效
的
系统变量设置,并始终使用此设置执行事件,
而不管事件开始执行时当前服务器SQL模式如何
。
一个
CREATE
EVENT
包含一个声明
ALTER
EVENT
它在声明中
DO
条款似乎是成功的;
但是,当服务器尝试执行生成的预定事件时,执行将失败并显示错误。
在事件中使用时,
诸如
SELECT
或
SHOW
仅返回结果集的
语句
不起作用;
这些输出不会发送到MySQL监视器,也不会存储在任何地方。
但是,你可以使用语句,如
SELECT
...
INTO
与
INSERT INTO ...
SELECT
该商店的结果。
(有关后者的实例,请参阅本节中的下一个示例。)
事件所属的模式是
DO
子句
中表引用的默认模式
。
必须使用正确的模式名称限定对其他模式中的表的任何引用。
与存储例程一样,您可以使用
和
关键字
在
DO
子句中
使用复合语句语法
,如下所示:
BEGIN
END
分隔符| 创造事件e_daily 按照时间表 每一天 评论'保存会话总数,然后每天清理表' 做 开始 INSERT INTO site_activity.totals(时间,总计) SELECT CURRENT_TIMESTAMP,COUNT(*) 来自site_activity.sessions; 从site_activity.sessions中删除; 结束| 分隔符;
此示例使用该
delimiter
命令更改语句分隔符。
请参见
第24.1节“定义存储的程序”
。
在事件中,可以使用更复杂的复合语句,例如存储例程中使用的语句。 此示例使用局部变量,错误处理程序和流控制构造:
分隔符| 创造事件e 按照时间表 每隔5秒 做 开始 DECLARE v INTEGER; DECLARE CONTINUE HANDLER开始SQLEXCEPTION开始; SET v = 0; WHILE v <5 DO 插入t1值(0); 更新t2 SET s1 = s1 + 1; SET v = v + 1; 结束时间; 结束| 分隔符;
无法直接将参数传递给事件或从事件传递参数; 但是,可以使用事件中的参数调用存储的例程:
创建事件e_call_myproc 按照时间表 在CURRENT_TIMESTAMP + INTERVAL 1天 请致电myproc(5,27);
如果事件的定义者具有足以设置全局系统变量的特权(请参见 第5.1.9.1节“系统变量特权” ),则事件可以读取和写入全局变量。 由于授予此类特权可能会导致滥用,因此必须特别注意这样做。
通常,在存储例程中有效的任何语句都可以用于事件执行的操作语句。 有关存储例程中允许的语句的更多信息,请参见 第24.2.1节“存储的例程语法” 。 您可以将事件创建为存储例程的一部分,但事件不能由另一个事件创建。
该
CREATE FUNCTION
语句用于创建存储函数和用户定义函数(UDF):
有关创建存储函数的信息,请参见 第13.1.17节“创建过程和创建函数语法” 。
有关创建用户定义函数的信息,请参见 第13.7.4.1节“用户定义函数的CREATE FUNCTION语法” 。
创建[UNIQUE | FULLTEXT | 空间]索引index_name
[index_type
] ONtbl_name
(key_part
,...) [index_option
] [algorithm_option
|lock_option
] ......key_part
:{col_name
[(length
)] | (expr
)} [ASC | DESC]index_option
: KEY_BLOCK_SIZE [=]value
|index_type
| 与PARSERparser_name
| 评论'string
' | {VISIBLE | 无形}index_type
: 使用{BTREE | HASH}algorithm_option
: ALGORITHM [=] {DEFAULT | INPLACE | 复制}lock_option
: LOCK [=] {DEFAULT | 没有| 共享| 独家}
通常,您在创建表本身时在表上创建所有索引
CREATE
TABLE
。
请参见
第13.1.20节“CREATE TABLE语法”
。
对于
InnoDB
表,其中主键确定数据文件中行的物理布局,
此指南尤其重要
。
CREATE
INDEX
使您可以向现有表添加索引。
CREATE
INDEX
映射到一个
ALTER
TABLE
语句来创建索引。
请参见
第13.1.9节“ALTER TABLE语法”
。
CREATE
INDEX
不能用来创造
PRIMARY KEY
;
使用
ALTER
TABLE
来代替。
有关索引的更多信息,请参见
第8.3.1节“MySQL如何使用索引”
。
InnoDB
支持虚拟列上的二级索引。
有关更多信息,请参见
第13.1.20.10节“二级索引和生成的列”
。
innodb_stats_persistent
启用
该
设置
后,在该表上创建索引后
运行
表
的
ANALYZE
TABLE
语句
InnoDB
。
表单的索引规范
创建具有多个关键部分的索引。
索引键值是通过连接给定关键部分的值而形成的。
例如
指定与由索引关键字值从多列索引
,
和
。
(
key_part1
,
key_part2
, ...)(col1, col2, col3)
col1
col2
col3
甲
key_part
规格可以与结束
ASC
或
DESC
以指定的索引值是否被存储在升序或降序。
如果未给出订单说明符,则默认值为升序。
ASC
并且
DESC
不允许
HASH
索引。
在MySQL 8.0.12的,
ASC
而
DESC
不是允许
SPATIAL
索引。
以下部分描述了该
CREATE
INDEX
语句的
不同方面
:
对于字符串列,可以创建仅使用列值的前导部分
的索引
,使用
语法指定索引前缀长度:
col_name
(length
)
前缀
必须
用于指定
BLOB
和
TEXT
关键零部件。
此外,
BLOB
和
TEXT
列可以只对索引
InnoDB
,
MyISAM
和
BLACKHOLE
表。
前缀
限制
以字节为单位。
然而,前缀
长度
在索引规范
CREATE
TABLE
,
ALTER
TABLE
和
CREATE INDEX
语句解释为非二进制串类型的字符数(
CHAR
,
VARCHAR
,
TEXT
)和二进制串类型的字节数(
BINARY
,
VARBINARY
,
BLOB
)。
在为使用多字节字符集的非二进制字符串列指定前缀长度时,请考虑这一点。
前缀支持和前缀长度(支持的位置)取决于存储引擎。
例如,对于
InnoDB
使用
REDUNDANT
或
COMPACT
行格式的
表,
前缀最长可达767字节
。
对于
InnoDB
使用
DYNAMIC
或
COMPRESSED
行格式的
表,
前缀长度限制为3072字节
。
对于
MyISAM
表,前缀长度限制为1000个字节。
该
NDB
存储引擎不支持前缀(见
第22.1.7.6,“在NDB簇不支持或缺失的功能”
)。
如果指定的索引前缀超过最大列数据类型大小,
CREATE
INDEX
则按如下方式处理索引:
对于非唯一索引,要么发生错误(如果启用了严格的SQL模式),要么索引长度减少到最大列数据类型大小,并产生警告(如果未启用严格SQL模式)。
对于唯一索引,无论SQL模式如何都会发生错误,因为减少索引长度可能会导致插入不符合指定唯一性要求的非唯一条目。
此处显示的语句使用列的前10个字符创建索引
name
(假设它
name
具有非二进制字符串类型):
CREATE INDEX part_of_name ON customer(name(10));
如果列中的名称通常在前10个字符中不同,则使用此索引执行的查找不应比使用从整个
name
列
创建的索引慢得多
。
此外,使用索引的列前缀可以使索引文件更小,这可以节省大量磁盘空间并且还可以加快
INSERT
操作。
阿
“
正常
”
索引索引列值或者列值的前缀。
例如,在下表中,给定
t1
行
的索引条目
包括完整
col1
值和
col2
由前10个字符组成的
值的前缀
:
CREATE TABLE t1( col1 VARCHAR(10), col2 VARCHAR(20), INDEX(col1,col2(10)) );
MySQL 8.0.13及更高版本支持索引表达式值而不是列或列前缀值的功能键部分。 使用功能键部件可以索引未直接存储在表中的值。 例子:
CREATE TABLE t1(col1 INT,col2 INT,INDEX func_index((ABS(col1)))); CREATE INDEX idx1 ON t1((col1 + col2)); CREATE INDEX idx2 ON t1((col1 + col2),(col1-col2),col1); ALTER TABLE t1 ADD INDEX((col1 * 40)DESC);
具有多个关键部分的索引可以混合非功能和功能关键部分。
ASC
并
DESC
支持功能关键部件。
功能关键部件必须遵守以下规则。 如果关键部件定义包含不允许的构造,则会发生错误。
在索引定义中,将表达式括在括号内,以将它们与列或列前缀区分开来。 例如,这是允许的; 表达式括在括号内:
INDEX((col1 + col2),(col3-col4))
这会产生错误; 表达式不包含在括号内:
INDEX(col1 + col2,col3 - col4)
功能键部分不能仅由列名组成。 例如,这是不允许的:
INDEX((col1),(col2))
相反,将关键部分写为非功能性关键部分,不带括号:
INDEX(col1,col2)
功能键部分表达式不能引用列前缀。
有关解决方法,请参阅的讨论
SUBSTRING()
,并
CAST()
在本节后面。
外键规范中不允许使用功能关键部件。
对于
CREATE
TABLE ... LIKE
,目标表保留原始表中的功能键部分。
功能索引实现为隐藏的虚拟生成列,具有以下含义:
每个功能键部分都计入表列总数的限制; 请参见 第C.10.4节“表列数和行大小的限制” 。
功能键部件继承适用于生成列的所有限制。 例子:
对于功能关键部件,仅允许生成列允许的功能。
不允许使用子查询,参数,变量,存储函数和用户定义的函数。
有关适用限制的更多信息,请参见 第13.1.20.9节“创建表和生成的列” 和 第13.1.9.2节“更改表和生成的列” 。
虚拟生成列本身不需要存储。 索引本身占用的存储空间与任何其他索引一样。
UNIQUE
支持包含功能键部分的索引。
但是,主键不能包含功能键部分。
主键需要存储生成的列,但功能键部分实现为虚拟生成列,而不是存储生成列。
SPATIAL
和
FULLTEXT
索引不能有功能关键部分。
如果表中不包含主键,
InnoDB
则会自动将第一个
UNIQUE NOT
NULL
索引提升为主键。
UNIQUE NOT NULL
具有功能键部分的索引
不支持此
功能。
如果存在重复索引,则非功能性索引会发出警告。 包含功能键部件的索引没有此功能。
要删除功能键部件引用的列,必须首先删除索引。 否则,会发生错误。
虽然非功能性关键部件支持前缀长度规范,但这对于功能关键部件是不可能的。
解决方案是使用
SUBSTRING()
(或
CAST()
,如本节后面所述)。
对于包含
SUBSTRING()
要在查询中使用
的
函数
的功能键部分
,该
WHERE
子句必须包含
SUBSTRING()
相同的参数。
在以下示例中,只有第二个
SELECT
能够使用索引,因为这是
SUBSTRING()
与索引规范匹配的
参数的唯一查询
:
CREATE TABLE tbl( col1 LONGTEXT, INDEX idx1((SUBSTRING(col1,1,10))) ); SELECT * FROM tbl WHERE SUBSTRING(col1,1,9)='123456789'; SELECT * FROM tbl WHERE SUBSTRING(col1,1,10)='1234567890';
功能键部件支持索引无法索引的值,例如
JSON
值。
但是,必须正确地完成这一操作才能达到预期的效果。
例如,此语法不起作用:
CREATE TABLE员工( 数据JSON, INDEX((data - >>'$。name')) );
语法失败,因为:
该
->>
运营商转变成
JSON_UNQUOTE(JSON_EXTRACT(...))
。
JSON_UNQUOTE()
返回数据类型为的值,
LONGTEXT
因此为隐藏生成的列分配相同的数据类型。
MySQL不能
LONGTEXT
在关键部分
索引
没有前缀长度的列,并且在功能键部分中不允许使用前缀长度。
要索引
JSON
列,您可以尝试使用以下
CAST()
函数:
CREATE TABLE员工( 数据JSON, INDEX((CAST(data - >>'$。name'AS CHAR(30)))) );
为隐藏的生成列分配
VARCHAR(30)
数据类型,可以对其进行索引。
但是这种方法在尝试使用索引时会产生一个新问题:
CAST()
返回带有排序规则的字符串
utf8mb4_0900_ai_ci
(服务器默认排序规则)。
JSON_UNQUOTE()
返回带有排序规则的字符串
utf8mb4_bin
(硬编码)。
因此,前面的表定义中的索引表达式
WHERE
与以下查询中
的
子句表达式
之间存在排序规则不匹配
:
SELECT * FROM employees WHERE data - >>'$。name'='James';
不使用索引,因为查询中的表达式和索引不同。
为了支持这种方案的功能键部分,优化自动去除
CAST()
寻找一个指数时使用,但
只有
当索引表达式的排序规则匹配查询表达式。
对于具有要使用的功能键部分的索引,以下两个解决方案中的任何一个都有效(尽管它们在某种程度上有所不同):
解决方案1.为索引表达式分配相同的排序规则
JSON_UNQUOTE()
:
CREATE TABLE员工( 数据JSON, INDEX idx((CAST(data - >>“$。name”AS CHAR(30))COLLATE utf8mb4_bin)) ); 插入员工价值观 ('{“name”:“james”,“salary”:9000}'), ('{“name”:“詹姆斯”,“薪水”:10000}'), ('{“name”:“Mary”,“salary”:12000}'), ('{“name”:“Peter”,“salary”:8000}'); SELECT * FROM employees WHERE data - >>'$。name'='James';
该
->>
操作是一样的
JSON_UNQUOTE(JSON_EXTRACT(...))
,并
JSON_UNQUOTE()
返回与归类的字符串
utf8mb4_bin
。
因此,比较区分大小写,只有一行匹配:
+ ------------------------------------ + | 数据| + ------------------------------------ + | {“name”:“James”,“薪水”:10000} | + ------------------------------------ +
解决方案2.在查询中指定完整表达式:
CREATE TABLE员工( 数据JSON, INDEX idx((CAST(data - >>“$。name”AS CHAR(30)))) ); 插入员工价值观 ('{“name”:“james”,“salary”:9000}'), ('{“name”:“詹姆斯”,“薪水”:10000}'), ('{“name”:“Mary”,“salary”:12000}'), ('{“name”:“Peter”,“salary”:8000}'); SELECT * FROM employees WHERE CAST(data - >>'$。name'AS CHAR(30))='James';
CAST()
返回带有排序规则的字符串
utf8mb4_0900_ai_ci
,因此比较不区分大小写且两行匹配:
+ ------------------------------------ + | 数据| + ------------------------------------ + | {“name”:“james”,“salary”:9000} | | {“name”:“James”,“薪水”:10000} | + ------------------------------------ +
请注意,尽管优化程序支持
CAST()
使用索引生成的列
自动剥离
,但以下方法不起作用,因为它会生成带有和不带索引的不同结果(Bug#27337092):
MySQL的>CREATE TABLE employees (
data JSON,
generated_col VARCHAR(30) AS (CAST(data->>'$.name' AS CHAR(30)))
);
查询正常,0行受影响,1警告(0.03秒) MySQL的>INSERT INTO employees (data)
VALUES ('{"name": "james"}'), ('{"name": "James"}');
查询正常,2行受影响,1警告(0.01秒) 记录:2个重复:0警告:1 MySQL的>SELECT * FROM employees WHERE data->>'$.name' = 'James';
+ ------------------- + --------------- + | 数据| generated_col | + ------------------- + --------------- + | {“name”:“James”} | 詹姆斯| + ------------------- + --------------- + 1排(0.00秒) MySQL的>ALTER TABLE employees ADD INDEX idx (generated_col);
查询正常,0行受影响,1警告(0.03秒) 记录:0重复:0警告:1 MySQL的>SELECT * FROM employees WHERE data->>'$.name' = 'James';
+ ------------------- + --------------- + | 数据| generated_col | + ------------------- + --------------- + | {“name”:“james”} | 詹姆斯| | {“name”:“James”} | 詹姆斯| + ------------------- + --------------- + 2行(0.01秒)
一个
UNIQUE
索引创建的约束,使得该指数的所有值必须是不同的。
如果您尝试添加具有与现有行匹配的键值的新行,则会发生错误。
如果为
UNIQUE
索引中的列
指定前缀值
,则列值必须在前缀长度内是唯一的。
一个
UNIQUE
索引,可以多次
NULL
进行,可以包含列的值
NULL
。
如果表具有
由具有整数类型的单个列组成的索引
PRIMARY KEY
或
UNIQUE NOT NULL
索引,则可以使用它
_rowid
来引用
SELECT
语句中
的索引列
,如下所示:
_rowid
PRIMARY
KEY
如果存在
PRIMARY
KEY
由单个整数列组成
的
列,则
引用该
列。
如果有,
PRIMARY KEY
但它不包含单个整数列,
_rowid
则不能使用。
否则,
如果该索引由单个整数列组成
,则
_rowid
引用第一个
UNIQUE NOT NULL
索引中的列。
如果第一个
UNIQUE NOT NULL
索引不包含单个整数列,
_rowid
则不能使用。
FULLTEXT
索引仅支持
InnoDB
和
MyISAM
表格,并且可以只包括
CHAR
,
VARCHAR
和
TEXT
列。
索引总是发生在整个列上;
不支持列前缀索引,如果指定,则忽略任何前缀长度。
有关
操作的详细信息,
请参见
第12.9节“全文搜索功能”
。
在
MyISAM
,
InnoDB
,
NDB
,和
ARCHIVE
存储引擎支持空间列,比如
POINT
和
GEOMETRY
。
(
第11.5节“空间数据类型”
描述了空间数据类型。)但是,空间列索引的支持因引擎而异。
根据以下规则,空间列上的空间和非空间索引可用。
空间列上的空间索引具有以下特征:
在空间列非空间索引(与创建
INDEX
,
UNIQUE
或
PRIMARY KEY
)具有以下特征:
在关键部件列表之后,可以给出索引选项。
的
index_option
值可以是任何以下的:
KEY_BLOCK_SIZE [=]
value
对于
MyISAM
表,
KEY_BLOCK_SIZE
可以选择指定用于索引键块的大小(以字节为单位)。
该值被视为提示;
如有必要,可以使用不同的尺寸。
KEY_BLOCK_SIZE
为单个索引定义指定
的
值将覆盖表级
KEY_BLOCK_SIZE
值。
KEY_BLOCK_SIZE
InnoDB
表
的索引级别不支持
。
请参见
第13.1.20节“CREATE TABLE语法”
。
index_type
某些存储引擎允许您在创建索引时指定索引类型。 例如:
CREATE TABLE查找(id INT)ENGINE = MEMORY; CREATE INDEX id_index ON lookup(id)USING BTREE;
表13.1“每个存储引擎的索引类型”
显示了不同存储引擎支持的允许索引类型值。
如果列出了多个索引类型,则在没有给出索引类型说明符时,第一个是缺省值。
表中未列出的存储引擎不支持
index_type
索引定义中
的
子句。
该
index_type
子句不能用于
FULLTEXT INDEX
或(在MySQL 8.0.12之前)
SPATIAL INDEX
规范。
全文索引实现依赖于存储引擎。
空间索引实现为R树索引。
如果指定的索引类型对于给定的存储引擎无效,但引擎可以使用另一种索引类型而不影响查询结果,则引擎将使用可用类型。
解析器识别
RTREE
为类型名称。
从MySQL 8.0.12开始,仅允许
SPATIAL
索引使用。
在8.0.12之前,
RTREE
无法为任何存储引擎指定。
BTREE
索引由
NDB
存储引擎实现为T树索引。
对于
NDB
表列的
索引
,
USING
只能为唯一索引或主键指定
该
选项。
USING HASH
阻止创建有序索引;
否则,在
NDB
表
上创建唯一索引或主键会
自动导致创建有序索引和散列索引,每个索引都对同一列索引进行索引。
对于包含
NULL
表的一列
或多
列的
唯一索引,
NDB
哈希索引只能用于查找文字值,这意味着
IS [NOT] NULL
条件需要对表进行完整扫描。
一种解决方法是确保
NULL
在这样的表上
使用一个或多个
列
的唯一索引
始终以包含有序索引的方式创建;
也就是说,避免
USING HASH
在创建索引时使用。
如果指定的索引类型对于给定的存储引擎无效,但引擎可以使用另一种索引类型而不影响查询结果,则引擎将使用可用类型。
解析器识别
RTREE
为类型名称,但目前无法为任何存储引擎指定。
index_type
在
不推荐使用
该
子句
之前
使用该
选项
;
在将来的MySQL版本中将删除对此位置中选项的使用的支持。
如果
在较早和较晚的位置都给出了
一个
选项,则最终选项适用。
ON
tbl_name
index_type
TYPE
被认为是的同义词
。
但是,
是首选形式。
type_name
USING
type_name
USING
下表显示了支持该
index_type
选项
的存储引擎的索引特征
。
表13.2 InnoDB存储引擎索引特征
指数类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
---|---|---|---|---|---|
首要的关键 | BTREE |
没有 | 没有 | N / A | N / A |
独特 | BTREE |
是 | 是 | 指数 | 指数 |
键 | BTREE |
是 | 是 | 指数 | 指数 |
FULLTEXT |
N / A | 是 | 是 | 表 | 表 |
SPATIAL |
N / A | 没有 | 没有 | N / A | N / A |
表13.3 MyISAM存储引擎索引特征
指数类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
---|---|---|---|---|---|
首要的关键 | BTREE |
没有 | 没有 | N / A | N / A |
独特 | BTREE |
是 | 是 | 指数 | 指数 |
键 | BTREE |
是 | 是 | 指数 | 指数 |
FULLTEXT |
N / A | 是 | 是 | 表 | 表 |
SPATIAL |
N / A | 没有 | 没有 | N / A | N / A |
表13.4 MEMORY存储引擎索引特征
指数类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
---|---|---|---|---|---|
首要的关键 | BTREE |
没有 | 没有 | N / A | N / A |
独特 | BTREE |
是 | 是 | 指数 | 指数 |
键 | BTREE |
是 | 是 | 指数 | 指数 |
首要的关键 | HASH |
没有 | 没有 | N / A | N / A |
独特 | HASH |
是 | 是 | 指数 | 指数 |
键 | HASH |
是 | 是 | 指数 | 指数 |
表13.5 NDB存储引擎索引特征
指数类 | 索引类型 | 存储NULL值 | 允许多个NULL值 | IS NULL扫描类型 | IS NOT NULL扫描类型 |
---|---|---|---|---|---|
首要的关键 | BTREE |
没有 | 没有 | 指数 | 指数 |
独特 | BTREE |
是 | 是 | 指数 | 指数 |
键 | BTREE |
是 | 是 | 指数 | 指数 |
首要的关键 | HASH |
没有 | 没有 | 表(见注1) | 表(见注1) |
独特 | HASH |
是 | 是 | 表(见注1) | 表(见注1) |
键 | HASH |
是 | 是 | 表(见注1) | 表(见注1) |
表注意:
1.
USING HASH
阻止创建隐式有序索引。
WITH PARSER
parser_name
此选项只能用于
FULLTEXT
索引。
如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引相关联。
InnoDB
并
MyISAM
支持全文解析器插件。
有关详细信息,请参阅
全文分析器插件
和
第29.2.4.4节“编写全文分析器插件”
。
COMMENT
'
string
'
索引定义可以包含最多1024个字符的可选注释。
该
MERGE_THRESHOLD
索引页面可以被配置为使用单独的索引
中的条款
声明。
例如:
index_option
COMMENT
CREATE INDEX
CREATE TABLE t1(id INT); CREATE INDEX id_index ON t1(id)COMMENT'MERGE_THRESHOLD = 40';
如果索引页的页面满百分比低于
MERGE_THRESHOLD
删除行时或更新操作缩短行时
的
值,则
InnoDB
尝试将索引页与相邻索引页合并。
默认
MERGE_THRESHOLD
值为50,这是以前的硬编码值。
MERGE_THRESHOLD
也可以使用
CREATE TABLE
和
ALTER
TABLE
语句
在索引级别和表级别定义
。
有关更多信息,请参见
第15.8.11节“配置索引页的合并阈值”
。
VISIBLE
,
INVISIBLE
指定索引可见性。 默认情况下,索引是可见的。 优化程序不使用不可见索引。 索引可见性的规范适用于除主键之外的索引(显式或隐式)。 有关更多信息,请参见 第8.3.12节“不可见索引” 。
ALGORITHM
并且
LOCK
可以赋予子句以影响表复制方法和在修改索引时读写表的并发级别。
它们与
ALTER
TABLE
声明
具有相同的含义
。
有关更多信息,请参见
第13.1.9节“ALTER TABLE语法”
NDB Cluster
ALGORITHM=INPLACE
使用与标准MySQL服务器
相同的
语法
支持在线操作
。
有关
更多信息
,
请参见
第22.5.14节“使用NDB簇中的ALTER TABLE进行联机操作”
。
CREATE LOGFILE GROUPlogfile_group
ADD UNDOFILE'undo_file
' [INITIAL_SIZE [=]initial_size
] [UNDO_BUFFER_SIZE [=]undo_buffer_size
] [REDO_BUFFER_SIZE [=]redo_buffer_size
] [NODEGROUP [=]nodegroup_id
] [等待] [评论[=]'string
'] 发动机[=]engine_name
此语句创建一个
名为“
”
logfile_group
的单个
UNDO
文件
的新日志文件组
undo_file
。
一个
CREATE LOGFILE GROUP
语句有一个且只有一个
ADD UNDOFILE
条款。
有关日志文件组命名的规则,请参见
第9.2节“架构对象名称”
。
所有NDB Cluster Disk Data对象共享相同的命名空间。 这意味着 必须唯一地命名 每个磁盘数据对象 (而不仅仅是给定类型的每个磁盘数据对象)。 例如,您不能拥有具有相同名称的表空间和日志文件组,或者具有相同名称的表空间和数据文件。
在任何给定时间,每个NDB群集实例只能有一个日志文件组。
可选
INITIAL_SIZE
参数设置
UNDO
文件的初始大小;
如果未指定,则默认为
128M
(128兆字节)。
可选
UNDO_BUFFER_SIZE
参数设置
UNDO
缓冲区用于日志文件组的大小;
其缺省值
UNDO_BUFFER_SIZE
是
8M
(8兆字节);
此值不能超过可用的系统内存量。
这两个参数都以字节为单位指定。
您可以选择使用一个字母的缩写来跟随其中一个或两个,其数量级类似于
my.cnf
。
通常,这是字母之一
M
(兆字节)或
G
(千兆字节)。
用于的内存
UNDO_BUFFER_SIZE
来自全局池,其大小由
SharedGlobalMemory
数据节点配置参数
的值确定
。
这包括通过设置
InitialLogFileGroup
数据节点配置参数
对此选项隐含的任何默认值
。
允许的最大值为
UNDO_BUFFER_SIZE
629145600(600 MB)。
在32位系统上,支持的最大值为
INITIAL_SIZE
4294967296(4 GB)。
(Bug#29186)
允许的最小值为
INITIAL_SIZE
1048576(1 MB)。
该
ENGINE
选项确定此日志文件组要使用
engine_name
的存储引擎,该存储引擎是存储引擎的名称。
在MySQL 8.0中,这必须是
NDB
(或
NDBCLUSTER
)。
如果
ENGINE
未设置,MySQL将尝试使用
default_storage_engine
服务器系统变量(以前
storage_engine
)
指定的引擎
。
在任何情况下,如果引擎未指定为
NDB
or
NDBCLUSTER
,则该
CREATE
LOGFILE GROUP
语句似乎成功但实际上无法创建日志文件组,如下所示:
mysql>CREATE LOGFILE GROUP lg1
- >ADD UNDOFILE 'undo.dat' INITIAL_SIZE = 10M;
查询正常,0行受影响,1警告(0.00秒) MySQL的>SHOW WARNINGS;
+ ------- + ------ + ---------------------------------- -------------------------------------------------- ------------ + | 等级| 代码| 消息| + ------- + ------ + ---------------------------------- -------------------------------------------------- ------------ + | 错误| 1478 | 表存储引擎'InnoDB'不支持创建选项'TABLESPACE或LOGFILE GROUP' | + ------- + ------ + ---------------------------------- -------------------------------------------------- ------------ + 1排(0.00秒) mysql> ERROR 1529(HY000):无法删除LOGFILE GROUPDROP LOGFILE GROUP lg1 ENGINE = NDB;
mysql>CREATE LOGFILE GROUP lg1
- >ADD UNDOFILE 'undo.dat' INITIAL_SIZE = 10M
- >ENGINE = NDB;
查询OK,0行受影响(2.97秒)
CREATE LOGFILE GROUP
当一个非
NDB
存储引擎被命名,但似乎成功
时
,该
语句实际上没有返回错误
这一事实
是我们希望在未来的NDB Cluster版本中解决的一个已知问题。
REDO_BUFFER_SIZE
,
NODEGROUP
,
WAIT
,和
COMMENT
被分析,但是被忽略,所以有在MySQL 8.0没有影响。
这些选项旨在用于将来的扩展。
使用时
ENGINE [=] NDB
,
UNDO
会在每个群集数据节点上创建
日志文件组和关联的
日志文件。
您可以
UNDO
通过查询
INFORMATION_SCHEMA.FILES
表
来验证
文件是否已创建并获取有关它们的信息
。
例如:
mysql>SELECT LOGFILE_GROUP_NAME, LOGFILE_GROUP_NUMBER, EXTRA
- >FROM INFORMATION_SCHEMA.FILES
- >WHERE FILE_NAME = 'undo_10.dat';
+ -------------------- + ---------------------- + ----- ----------- + | LOGFILE_GROUP_NAME | LOGFILE_GROUP_NUMBER | 额外| + -------------------- + ---------------------- + ----- ----------- + | lg_3 | 11 | CLUSTER_NODE = 3 | | lg_3 | 11 | CLUSTER_NODE = 4 | + -------------------- + ---------------------- + ----- ----------- + 2行(0.06秒)
CREATE LOGFILE GROUP
仅适用于NDB Cluster的磁盘数据存储。
请参见
第22.5.13节“NDB集群磁盘数据表”
。
创建 [DEFINER =user
] 程序sp_name
([proc_parameter
[,...]]) [characteristic
...]routine_body
创建 [DEFINER =user
] 功能sp_name
([func_parameter
[,...]]) 退货type
[characteristic
...]routine_body
proc_parameter
: [IN | OUT | 进出 ]param_name
type
func_parameter
:param_name
type
type
:Any valid MySQL data type
characteristic
: 评论'string
' | 语言SQL | [NOT]决定因素 | {包含SQL | 没有SQL | 读取SQL数据| 修改SQL DATA} | SQL SECURITY {DEFINER | INVOKER}routine_body
:Valid SQL routine statement
这些语句创建存储的例程。
默认情况下,例程与默认数据库关联。
要将例程与给定数据库显式关联,请
db_name.sp_name
在创建时
指定名称
。
该
CREATE FUNCTION
语句还在MySQL中用于支持UDF(用户定义的函数)。
请参见
第29.4节“向MySQL添加新函数”
。
UDF可以被视为外部存储功能。
存储函数与UDF共享其命名空间。
有关
描述服务器如何解释对不同类型函数的引用的规则
,
请参见
第9.2.4节“函数名称解析和解析”
。
要调用存储过程,请使用该
CALL
语句(请参见
第13.2.1节“CALL语法”
)。
要调用存储的函数,请在表达式中引用它。
该函数在表达式求值期间返回一个值。
CREATE PROCEDURE
并
CREATE FUNCTION
要求
CREATE ROUTINE
特权。
如果该
DEFINER
子句存在,则所需的权限取决于
user
值,如
第24.6节“存储对象访问控制”中所述
。
如果启用了二进制日志记录,则
CREATE FUNCTION
可能需要该
SUPER
特权,如
第24.7节“存储程序二进制日志记录”中所述
。
默认情况下,MySQL的自动授权
ALTER ROUTINE
和
EXECUTE
权限,以常规的创造者。
可以通过禁用
automatic_sp_privileges
系统变量
来更改此行为
。
请参见
第24.2.2节“存储例程和MySQL特权”
。
的
DEFINER
和
SQL SECURITY
子句指定的安全上下文,在程序执行时检查访问权限的情况下,如在本节后面所述使用。
如果例程名称与内置SQL函数的名称相同,则会发生语法错误,除非在定义例程或稍后调用例程时在名称和以下括号之间使用空格。 因此,请避免将现有SQL函数的名称用于您自己的存储例程。
在
IGNORE_SPACE
SQL模式适用于内置的功能,而不是保存的程序。
无论是否
IGNORE_SPACE
启用
,始终允许在存储的例程名称后面有空格
。
括号内的参数列表必须始终存在。
如果没有参数,
()
则应使用
空参数列表
。
参数名称不区分大小写。
IN
默认情况下,
每个参数都是
参数。
要为参数指定其他方式,请使用关键字
OUT
或
INOUT
参数名称之前。
将参数指定为
IN
,
OUT
或
INOUT
仅对a有效
PROCEDURE
。
对于a
FUNCTION
,参数始终被视为
IN
参数。
一个
IN
参数传送一个值的过程。
该过程可能会修改该值,但过程返回时调用程序看不到修改。
一个
OUT
参数传送从过程返回给调用者的值。
它的初始值
NULL
在过程中,当过程返回时,调用者可以看到它的值。
一个
INOUT
参数是由呼叫者初始化,可以由程序进行修改,并且由所述方法制备的任何变化是可见的呼叫者时,过程返回。
对于每个
OUT
或
INOUT
参数,在
CALL
调用过程
的
语句中
传递用户定义的变量,
以便在过程返回时获取其值。
如果要调用从另一个存储过程或函数内的过程中,你也可以通过常规的参数或局部常规变量作为
OUT
或
INOUT
参数。
如果要调用从一个触发器中的过程中,你也可以通过
作为
或
参数。
NEW.
col_name
OUT
INOUT
有关未处理条件对过程参数的影响的信息,请参见 第13.6.7.8节“条件处理和OUT或INOUT参数” 。
在例程中准备的语句中不能引用例程参数; 请参见 第C.1节“存储程序的限制” 。
以下示例显示了一个使用
OUT
参数
的简单存储过程
:
MySQL的>delimiter //
mysql>CREATE PROCEDURE simpleproc (OUT param1 INT)
- >BEGIN
- >SELECT COUNT(*) INTO param1 FROM t;
- >END//
查询正常,0行受影响(0.00秒) MySQL的>delimiter ;
MySQL的>CALL simpleproc(@a);
查询正常,0行受影响(0.00秒) MySQL的>SELECT @a;
+ ------ + | @a | + ------ + | 3 | + ------ + 1排(0.00秒)
该示例使用
MySQL的
客户机
delimiter
命令语句从定界符改变
;
到
//
当正在定义的过程。
这使得
;
过程体中使用
的
分隔符能够传递到服务器,而不是由
mysql
本身
解释
。
请参见
第24.1节“定义存储的程序”
。
该
RETURNS
条款只能为a
FUNCTION
强制规定。
它表示函数的返回类型,函数体必须包含一个
语句。
如果
语句返回不同类型的值,则将该值强制转换为正确的类型。
例如,如果函数
在
子句中
指定了一个
或
值
,但该
语句返回一个整数,则该函数返回的值是
成员集
的相应
成员
的字符串
。
RETURN
value
RETURN
ENUM
SET
RETURNS
RETURN
ENUM
SET
以下示例函数接受一个参数,使用SQL函数执行操作,并返回结果。
在这种情况下,不必使用,
delimiter
因为函数定义不包含内部
;
语句分隔符:
mysql>CREATE FUNCTION hello (s CHAR(20))
mysql>RETURNS CHAR(50) DETERMINISTIC
- >RETURN CONCAT('Hello, ',s,'!');
查询正常,0行受影响(0.00秒) MySQL的>SELECT hello('world');
+ ---------------- + | 你好('世界')| + ---------------- + | 你好,世界!| + ---------------- + 1排(0.00秒)
可以声明参数类型和函数返回类型以使用任何有效的数据类型。
COLLATE
如果前面有
CHARACTER SET
规范,
则可以使用
该
属性
。
它
routine_body
由一个有效的SQL例程语句组成。
这可以是一个简单的语句,如
SELECT
or
INSERT
,或者是使用
BEGIN
和
编写的复合语句
END
。
复合语句可以包含声明,循环和其他控制结构语句。
第13.6节“复合语句语法”中
描述了这些语句的
语法
。
实际上,存储函数倾向于使用复合语句,除非正文包含单个
RETURN
语句。
MySQL允许例程包含DDL语句,例如
CREATE
和
DROP
。
MySQL还允许存储过程(但不是存储函数)包含SQL事务语句,如
COMMIT
。
存储的函数可能不包含执行显式或隐式提交或回滚的语句。
SQL标准不要求支持这些语句,该标准规定每个DBMS供应商可以决定是否允许它们。
返回结果集的语句可以在存储过程中使用,但不能在存储的函数中使用。
这项禁令包括
SELECT
不具有的声明
条款等语句,如
,
和
。
对于可以在函数定义时确定以返回结果集的语句,会
发生错误(
)。
对于只能在运行时确定以返回结果集的语句,会
发生错误(
)。
INTO
var_list
SHOW
EXPLAIN
CHECK TABLE
Not allowed to return a result set from a
function
ER_SP_NO_RETSET
PROCEDURE %s can't return a result set in the
given
context
ER_SP_BADSELECT
USE
不允许存储例程中的语句。
调用例程时,将
执行
隐式
(并在例程终止时撤消)。
导致例程在执行时具有给定的默认数据库。
应使用适当的数据库名称限定对除例程缺省数据库之外的数据库中的对象的引用。
USE
db_name
有关存储例程中不允许的语句的其他信息,请参见 第C.1节“存储程序的限制” 。
有关从具有MySQL接口的语言编写的程序中调用存储过程的信息,请参见 第13.2.1节“CALL语法” 。
MySQL
sql_mode
在创建或更改例程时
存储有效的
系统变量设置,并始终使用此设置执行例程,
而不管例程开始执行时当前服务器SQL模式如何
。
在评估参数并将结果值分配给例程参数之后,将从调用者的SQL模式切换到例程的SQL模式。 如果在严格SQL模式下定义例程但在非严格模式下调用它,则不会在严格模式下为常规参数分配参数。 如果要求在严格SQL模式下分配传递给例程的表达式,则应调用具有严格模式的例程。
该
COMMENT
特性是MySQL扩展,可用于描述存储的例程。
此信息由
SHOW CREATE
PROCEDURE
和
SHOW CREATE
FUNCTION
语句
显示
。
该
LANGUAGE
特性表示其中例行程序语言编写。
服务器忽略了这个特性;
仅支持SQL例程。
的例程被认为是
“
确定性的
”
,如果它总是产生相同的结果对于相同的输入参数,并且
“
不确定性
”
否则。
如果
例程定义中
既未
给出
也
DETERMINISTIC
未
NOT
DETERMINISTIC
给出,则默认为
NOT DETERMINISTIC
。
要声明函数是确定性的,必须
DETERMINISTIC
明确
指定
。
对例程性质的评估基于
创建者
的
“
诚实
”
:MySQL不会检查声明的例程
DETERMINISTIC
是否没有产生非确定性结果的语句。
但是,错误地说明例程可能会影响结果或影响性能。
声明非确定性例程
DETERMINISTIC
可能会导致优化程序选择错误的执行计划,从而导致意外结果。
声明确定性例程
NONDETERMINISTIC
可能会导致不使用可用的优化,从而降低性能。
如果启用了二进制日志记录,则该
DETERMINISTIC
特性会影响MySQL接受的例程定义。
请参见
第24.7节“存储程序二进制日志记录”
。
包含
NOW()
函数(或其同义词)或
RAND()
不确定
的例程
,但它可能仍然是复制安全的。
对于
NOW()
,二进制日志包括时间戳并正确复制。
RAND()
只要在执行例程期间只调用一次,也可以正确复制。
(您可以将例程执行时间戳和随机数种子视为主服务器和从服务器上相同的隐式输入。)
几个特征提供了关于例程使用数据的性质的信息。 在MySQL中,这些特征仅供参考。 服务器不使用它们来约束允许例程执行的语句类型。
所述
SQL SECURITY
特性可以是
DEFINER
或
INVOKER
以指定的安全上下文;
也就是说,例程是使用例程
DEFINER
子句中
指定的帐户的权限
还是使用调用它的用户执行。
此帐户必须具有访问与例程关联的数据库的权限。
默认值为
DEFINER
。
调用例程的用户必须拥有该
EXECUTE
特权,
DEFINER
如果例程在definer安全上下文中执行,则
必须具有该
帐户
的
特权
。
该
DEFINER
子句指定在常规执行时检查具有该
SQL SECURITY
DEFINER
特征的
例程的访问权限时要使用的MySQL帐户
。
如果
DEFINER
子句,该
user
值应被指定为一个MySQL帐户
,
或
。
允许的
值取决于您拥有的权限,如
第24.6节“存储对象访问控制”中所述
。
有关存储的例程安全性的其他信息,另请参阅该部分。
'
user_name
'@'host_name
'CURRENT_USER
CURRENT_USER()
user
如果
DEFINER
省略
该
子句,则默认定义者是执行
CREATE
PROCEDURE
or
CREATE
FUNCTION
语句
的用户
。
这与
DEFINER = CURRENT_USER
明确
指定相同
。
在使用
SQL SECURITY DEFINER
特征
定义的存储例程的主体内
,该
CURRENT_USER
函数返回例程的
DEFINER
值。
有关存储例程中的用户审计的信息,请参见
第6.2.22节“基于SQL的帐户活动审计”
。
请考虑以下过程,该过程显示
mysql.user
系统表中
列出的MySQL帐户数量的计数
:
CREATE DEFINER ='admin'@'localhost'PROCEDURE account_count() 开始 SELECT'帐号数:',COUNT(*)FROM mysql.user; 结束;
无论哪个用户定义
该过程,都会为该过程分配
DEFINER
帐户
'admin'@'localhost'
。
无论哪个用户调用它,它都以该帐户的权限执行(因为默认的安全特性是
DEFINER
)。
该过程成功或失败取决于调用者是否具有该
EXECUTE
特权并
'admin'@'localhost'
具有
SELECT
该
mysql.user
表
的
特权
。
现在假设该过程是使用以下
SQL
SECURITY INVOKER
特征
定义的
:
CREATE DEFINER ='admin'@'localhost'PROCEDURE account_count() SQL安全调查员 开始 SELECT'帐号数:',COUNT(*)FROM mysql.user; 结束;
该过程仍具有
DEFINER
的
'admin'@'localhost'
,但在这种情况下,它与调用用户的权限执行。
因此,该过程成功或失败取决于调用者是否具有该
EXECUTE
特权以及
SELECT
该
mysql.user
表
的
特权
。
服务器处理例程参数的数据类型,使用
DECLARE
或函数返回值
创建的本地例程变量
,如下所示:
检查分配的数据类型不匹配和溢出。 转换和溢出问题会导致警告或严格SQL模式中的错误。
只能分配标量值。
例如,诸如
SET x = (SELECT 1, 2)
无效
的陈述
。
对于字符数据类型,if
CHARACTER SET
包含在声明中,使用指定的字符集及其默认排序规则。
如果该
COLLATE
属性也存在,则使用该排序规则而不是默认排序规则。
如果
CHARACTER SET
和
COLLATE
不存在,则使用在例程创建时有效的数据库字符集和排序规则。
为避免服务器使用数据库字符集和排序规则,请
为字符数据参数
提供显式
CHARACTER SET
和
COLLATE
属性。
如果更改数据库缺省字符集或排序规则,则必须删除并重新创建使用数据库缺省值的存储例程,以便它们使用新的缺省值。
该数据库字符集和校对规则由的值给出
character_set_database
和
collation_database
系统变量。
有关更多信息,请参见
第10.3.3节“数据库字符集和排序规则”
。
创建服务器server_name
外部数据包装wrapper_name
选项(option
[,option
] ...)option
: {主持人character-literal
| 数据库character-literal
| 用户character-literal
| 密码character-literal
| SOCKETcharacter-literal
| 所有者character-literal
| PORTnumeric-literal
}
此语句创建用于
FEDERATED
存储引擎
的服务器的定义
。
该
CREATE
SERVER
语句
servers
在
mysql
数据库
的
表中
创建一个新行
。
此声明需要该
SUPER
权限。
本
应该是唯一的参考服务器。
服务器定义在服务器范围内是全局的,无法将服务器定义限定为特定数据库。
server_name
最大长度为64个字符(超过64个字符的名称被静默截断),并且不区分大小写。
您可以将名称指定为带引号的字符串。
server_name
它
是一个标识符,可以用单引号引用。
wrapper_name
对于每个,
您必须指定字符文字或数字文字。
字符文字是UTF-8,最大长度为64个字符,默认为空(空)字符串。
字符串文字被静默截断为64个字符。
数字文字必须是0到9999之间的数字,默认值为0。
option
该
OWNER
选项当前未应用,并且对创建的服务器连接的所有权或操作没有影响。
该
CREATE SERVER
语句在
mysql.servers
表中
创建一个条目,
以后可以
CREATE
TABLE
在创建
FEDERATED
表
时
与
语句
一起使用
。
您指定的选项将用于填充表中的
mysql.servers
列。
该表包括
Server_name
,
Host
,
Db
,
Username
,
Password
,
Port
和
Socket
。
例如:
创建服务器 FOREIGN DATA WRAPPER mysql 选项(用户'远程',主机'198.51.100.106',数据库'测试');
请务必指定与服务器建立连接所需的所有选项。 用户名,主机名和数据库名是必需的。 也可能需要其他选项,例如密码。
创建与
FEDERATED
表
的连接时,可以使用存储在表中的数据
:
CREATE TABLE t(s1 INT)ENGINE = FEDERATED CONNECTION ='s';
有关更多信息,请参见 第16.8节“FEDERATED存储引擎” 。
CREATE SERVER
导致隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
CREATE SERVER
无论正在使用的日志记录格式如何,都不会写入二进制日志。
创建或替换空间参考系统 ......srid
srs_attribute
创建空间参考系统 [IF NOT EXISTS]srid
srs_attribute
...srs_attribute
:{ 名称 'srs_name
' | 定义'definition
' | 组织org_name
'IDENTIFIED BYorg_id
| 说明'description
' }srid
,org_id
:32-bit unsigned integer
此语句创建
空间参照系
(SRS)定义并将其存储在数据字典中。
可以使用该
INFORMATION_SCHEMA
ST_SPATIAL_REFERENCE_SYSTEMS
表
检查定义
。
此声明需要该
SUPER
权限。
如果既未
指定
也
OR REPLACE
未
IF NOT
EXISTS
指定,则如果已存在具有SRID值的SRS定义,则会发生错误。
使用
CREATE OR REPLACE
语法,将替换具有相同SRID值的任何现有SRS定义,除非现有表中的某些列使用SRID值。
在这种情况下,会发生错误。
例如:
MySQL的> CREATE OR REPLACE SPATIAL REFERENCE SYSTEM 4326 ...;
ERROR 3716(SR005):无法修改SRID 4326。有
至少有一列取决于它。
要标识哪个或哪些列使用SRID,请使用以下查询:
SELECT * FROM INFORMATION_SCHEMA.ST_GEOMETRY_COLUMNS WHERE SRS_ID = 4326;
使用
CREATE ... IF NOT EXISTS
语法,任何具有相同SRID值的现有SRS定义都会导致忽略新定义并发出警告。
SRID值必须在32位无符号整数的范围内,具有以下限制:
SRID 0是有效的SRID,但不能与之一起使用
CREATE SPATIAL REFERENCE
SYSTEM
。
如果该值在保留的SRID范围内,则会发出警告。 保留范围为[0,32767](由EPSG保留),[60,000,000,69,999,999](由EPSG保留)和[2,000,000,000,2,147,483,647](由MySQL保留)。 EPSG代表 欧洲石油调查组 。
用户不应在保留范围内创建具有SRID的SRS。 这样做可能会导致SRID与MySQL分发的未来SRS定义冲突,从而导致新系统提供的SRS未安装用于MySQL升级或用户定义的SRS被覆盖。
语句的属性必须满足以下条件:
属性可以按任何顺序给出,但不能多次给出属性。
在
NAME
和
DEFINITION
属性是强制性的。
该
NAME
srs_name
属性值必须是唯一的。
ORGANIZATION
org_name
和
org_id
属性值
的组合
必须是唯一的。
的
NAME
srs_name
属性值和
ORGANIZATION
org_name
属性值不能为空或开始或空白结束。
属性规范中的字符串值不能包含控制字符,包括换行符。
下表显示了字符串属性值的最大长度。
这是一个示例
CREATE SPATIAL REFERENCE
SYSTEM
声明。
为了
DEFINITION
便于阅读,
该
值在多行中重新格式化。
(对于合法的陈述,实际上必须在一行上给出该值。)
创建空间参考系统4120 姓名'希腊' 组织'EPSG'由4120识别 定义 'GEOGCS [“希腊语”,DATUM [“希腊语”,SPHEROID [“Bessel 1841”, 6377397.155,299.1528128,AUTHORITY [ “EPSG”, “7004”]], AUTHORITY [ “EPSG”, “6120”]],PRIMEM [ “格林威治”,0, AUTHORITY [ “EPSG”, “8901”]],单位[ “度”,0.017453292519943278, AUTHORITY [ “EPSG”, “9122”]],AXIS [ “纬度”,NORTH],AXIS [ “经度”,EAST] AUTHORITY [ “EPSG”, “4120”]]“;
SRS定义的语法基于 OpenGIS Implementation Specification:Coordinate Transformation Services ,Revision 1.00,OGC 01-009,2001年1月12日,第7.2节中 定义的语法 。 该规范可从 http://www.opengeospatial.org/standards/ct获得 。
MySQL将这些更改合并到规范中:
仅实施
<horz cs>
生产规则(即,地理和预计的SRS)。
有一个可选的非标准
<authority>
条款
<parameter>
。
这使得可以通过权限而不是名称来识别投影参数。
规范没有
AXIS
在
GEOGCS
空间参考系统定义中
强制
使用
子句
。
但是,如果没有
AXIS
子句,MySQL无法确定定义是否具有纬度 - 经度顺序或经度 - 纬度顺序的轴。
MySQL强制执行非标准要求,即每个
GEOGCS
定义必须包含两个
AXIS
子句。
一个必须是,
NORTH
或
SOUTH
另一个
EAST
或
WEST
。
该
AXIS
子句顺序决定的定义是否在纬度-经度顺序或经纬度顺序轴。
SRS定义可能不包含换行符。
如果SRS定义指定了投影的权限代码(建议使用),则如果定义缺少必需参数,则会发生错误。 在这种情况下,错误消息表明问题是什么。 MySQL支持的投影方法和强制参数如 表13.7“支持的空间参考系统投影方法” 和 表13.8“空间参考系统投影参数”所示 。
有关编写SRS定义为MySQL的更多信息,请参见 在MySQL 8.0地理空间参考系统 和 投影空间参照系在MySQL 8.0
下表显示了MySQL支持的投影方法。 MySQL允许未知的投影方法,但无法检查强制参数的定义,也无法将空间数据转换为未知投影或从未知投影转换空间数据。 有关每个投影如何工作的详细说明,包括公式,请参阅 EPSG指导说明7-2 。
表13.7支持的空间参考系统投影方法
EPSG代码 | 投影名称 | 强制参数(EPSG代码) |
---|---|---|
1024 | 流行的可视化伪墨卡托 | 8801,8802,8806,8807 |
1027 | Lambert Azimuthal等面积(球面) | 8801,8802,8806,8807 |
1028 | 等距圆柱形 | 8823,8802,8806,8807 |
1029 | 等距圆柱(球面) | 8823,8802,8806,8807 |
1041 | Krovak(朝北) | 8811,8833,1036,8818,8819,8806,8807 |
1042 | Krovak修改 | 8811,8833,1036,8818,8819,8806,8807,8617,8618,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035 |
1043 | Krovak改装(朝北) | 8811,8833,1036,8818,8819,8806,8807,8617,8618,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035 |
1051 | Lambert Conic Conformal(密歇根州2SP) | 8821,8822,8823,8824,8826,8827,1038 |
1052 | 哥伦比亚城市 | 8801,8802,8806,8807,1039 |
9801 | Lambert Conic Conformal(1SP) | 8801,8802,8805,8806,8807 |
9802 | Lambert Conic Conformal(2SP) | 8821,8822,8823,8824,8826,8827 |
9803 | Lambert Conic Conformal(2SP比利时) | 8821,8822,8823,8824,8826,8827 |
9804 | 墨卡托(变种A) | 8801,8802,8805,8806,8807 |
9805 | 墨卡托(变种B) | 8823,8802,8806,8807 |
9806 | 卡西尼 - 雇佣兵 | 8801,8802,8806,8807 |
9807 | 横向墨卡托 | 8801,8802,8805,8806,8807 |
9808 | 横向墨卡托(南方定向) | 8801,8802,8805,8806,8807 |
9809 | 倾斜立体 | 8801,8802,8805,8806,8807 |
9810 | 极地立体(变体A) | 8801,8802,8805,8806,8807 |
9811 | 新西兰地图网格 | 8801,8802,8806,8807 |
9812 | Hotine Oblique Mercator(变体A) | 8811,8812,8813,8814,8815,8806,8807 |
9813 | Laborde Oblique Mercator | 8811,8812,8813,8815,8806,8807 |
9815 | Hotine Oblique Mercator(变体B) | 8811,8812,8813,8814,8815,8816,8817 |
9816 | 突尼斯矿业网 | 8821,8822,8826,8827 |
9817 | Lambert Conic近共形 | 8801,8802,8805,8806,8807 |
9818 | 美国的Polyconic | 8801,8802,8806,8807 |
9819 | Krovak | 8811,8833,1036,8818,8819,8806,8807 |
9820 | Lambert Azimuthal平等区域 | 8801,8802,8806,8807 |
9822 | Albers Equal Area | 8821,8822,8823,8824,8826,8827 |
9824 | 横向墨卡托分区网格系统 | 8801,8830,8831,8805,8806,8807 |
9826 | Lambert Conic Conformal(西方定向) | 8801,8802,8805,8806,8807 |
9828 | Bonne(南方定位) | 8801,8802,8806,8807 |
9829 | 极地立体图(变体B) | 8832,8833,8806,8807 |
9830 | 极地立体(变体C) | 8832,8833,8826,8827 |
9831 | 关岛投射 | 8801,8802,8806,8807 |
9832 | 改进的Azimuthal等距离 | 8801,8802,8806,8807 |
9833 | 双曲卡西尼号战士 | 8801,8802,8806,8807 |
9834 | 朗伯圆柱等面积(球面) | 8823,8802,8806,8807 |
9835 | 朗伯圆柱面积等面积 | 8823,8802,8806,8807 |
下表显示了MySQL识别的投影参数。 识别主要由权威代码发生。 如果没有权限代码,MySQL将回退到参数名称上不区分大小写的字符串匹配。 有关每个参数的详细信息,请通过 EPSG Online Registry 中的代码进行查找 。
表13.8空间参考系统投影参数
EPSG代码 | 后备名称(由MySQL认可) | EPSG名称 |
---|---|---|
1026 | C1 | C1 |
1027 | C2 | C2 |
1028 | C3 | C3 |
1029 | C4 | C4 |
1030 | C5 | C5 |
1031 | C6 | C6 |
1032 | C7 | C7 |
1033 | C8 | C8 |
1034 | C9 | C9 |
1035 | C10 | C10 |
1036 | 方位 | 锥轴的共同纬度 |
1038 | ellipsoid_scale_factor | 椭球比例因子 |
1039 | projection_plane_height_at_origin | 投影平面原点高度 |
8617 | evaluation_point_ordinate_1 | 纵坐标1评价点 |
8618 | evaluation_point_ordinate_2 | 纵坐标评价点2 |
8801 | latitude_of_origin | 纬度自然来源 |
8802 | central_meridian | 经度来源于自然 |
8805 | 比例因子 | 天然来源的比例因子 |
8806 | false_easting | 虚假的东方 |
8807 | false_northing | 假北上 |
8811 | latitude_of_center | 投影中心的纬度 |
8812 | longitude_of_center | 投影中心的经度 |
8813 | 方位 | 初始线的方位角 |
8814 | rectified_grid_angle | 从整流到偏斜网格的角度 |
8815 | 比例因子 | 初始线上的比例因子 |
8816 | false_easting | 在投影中心东边 |
8817 | false_northing | 北投影中心 |
8818 | pseudo_standard_parallel_1 | 纬度的标准并行 |
8819 | 比例因子 | 伪标准并行的比例因子 |
8821 | latitude_of_origin | 虚假来源的纬度 |
8822 | central_meridian | 虚假出身的经度 |
8823 | standard_parallel_1,standard_parallel1 | 第一标准平行纬度 |
8824 | standard_parallel_2,standard_parallel2 | 纬度为第二标准平行 |
8826 | false_easting | 东方是错误的起源 |
8827 | false_northing | 北方在虚假的起源 |
8830 | initial_longitude | 初始经度 |
8831 | zone_width | 区域宽度 |
8832 | standard_parallel | 纬度标准平行 |
8833 | longitude_of_center | 经度 |
CREATE [TEMPORARY] TABLE [IF NOT EXISTS]tbl_name
(create_definition
,...) [table_options
] [partition_options
] CREATE [TEMPORARY] TABLE [IF NOT EXISTS]tbl_name
[(create_definition
,...)] [table_options
] [partition_options
] [IGNORE | 更换] [如]query_expression
CREATE [TEMPORARY] TABLE [IF NOT EXISTS]tbl_name
{LIKEold_tbl_name
| (LIKEold_tbl_name
)}create_definition
: | {INDEX | KEY} [ ] [ ](,...)col_name
column_definition
index_name
index_type
key_part
[index_option
] ...... | {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name
](key_part
,...) [index_option
] ...... | [CONSTRAINT [symbol
]] PRIMARY KEY [index_type
](key_part
,...) [index_option
] ...... | [CONSTRAINT [symbol
]] UNIQUE [INDEX | KEY] [index_name
] [index_type
](key_part
,...) [index_option
] ...... | [CONSTRAINT [symbol
]]外键 [index_name
](col_name
,...)reference_definition
|check_constraint_definition
column_definition
:data_type
[NOT NULL | NULL] [DEFAULT {literal
| (expr
)}] [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY] [评论'string
'] [收集collation_name
] [COLUMN_FORMAT {FIXED | DYNAMIC | DEFAULT}] [STORAGE {DISK | MEMORY}] [reference_definition
] [check_constraint_definition
] |data_type
[收集collation_name
] [GENERATED ALWAYS] AS(expr
) [VIRTUAL | 存储] [NOT NULL | 空值] [UNIQUE [KEY]] [[PRIMARY] KEY] [评论'string
'] [reference_definition
] [check_constraint_definition
]data_type
: (见第11章,数据类型)key_part
:{col_name
[(length
)] | (expr
)} [ASC | DESC]index_type
: 使用{BTREE | HASH}index_option
: KEY_BLOCK_SIZE [=]value
|index_type
| 与PARSERparser_name
| 评论'string
' | {VISIBLE | 无形}check_constraint_definition
: [CONSTRAINT [symbol
]] CHECK(expr
)[[NOT] ENFORCED]reference_definition
: 参考文献tbl_name
(key_part
,...) [匹配完整| 匹配部分| 匹配简单] [ON DELETEreference_option
] [ON UPDATEreference_option
]reference_option
: 限制| CASCADE | SET NULL | 没有动作| 默认设置table_options
:table_option
[[,]table_option
] ......table_option
: AUTO_INCREMENT [=]value
| AVG_ROW_LENGTH [=]value
| [DEFAULT] CHARACTER SET [=]charset_name
| CHECKSUM [=] {0 | 1} | [DEFAULT] COLLATE [=]collation_name
| 评论[=]'string
' | COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'} | 连接[=]'connect_string
' | {DATA | INDEX} DIRECTORY [=]'absolute path to directory
' | DELAY_KEY_WRITE [=] {0 | 1} | ENCRYPTION [=] {'Y'| 'N'} | 发动机[=]engine_name
| INSERT_METHOD [=] {NO | 第一个| 最后} | KEY_BLOCK_SIZE [=]value
| MAX_ROWS [=]value
| MIN_ROWS [=]value
| PACK_KEYS [=] {0 | 1 | 默认} | 密码[=]'string
' | ROW_FORMAT [=] {DEFAULT | DYNAMIC | FIXED | COMPRESSED | REDUNDANT | COMPACT} | STATS_AUTO_RECALC [=] {DEFAULT | 0 | 1} | STATS_PERSISTENT [=] {DEFAULT | 0 | 1} | STATS_SAMPLE_PAGES [=]value
| TABLESPACEtablespace_name
[STORAGE {DISK | MEMORY}] | UNION [=](tbl_name
[,tbl_name
] ......)partition_options
: 分区 {[LINEAR] HASH(expr
) | [LINEAR] KEY [ALGORITHM = {1 | 2}](column_list
) | 范围{(expr
)| COLUMNS(column_list
)} | 列表{(expr
)| COLUMNS(column_list
)}} [PARTITIONSnum
] [SUBPARTITION BY {[LINEAR] HASH(expr
) | [LINEAR] KEY [ALGORITHM = {1 | 2}](column_list
)} [SUBPARTITIONSnum
] ] [(partition_definition
[,partition_definition
] ......)]partition_definition
: 划分partition_name
[VALUES {不到{(expr
|value_list
)| MAXVALUE} | IN(value_list
)}] [[STORAGE] ENGINE [=]engine_name
] [评论[=]'string
'] [DATA DIRECTORY [=]''] [INDEX DIRECTORY [=]'
data_dir
'] [MAX_ROWS [=]
index_dir
max_number_of_rows
] [MIN_ROWS [=]min_number_of_rows
] [TABLESPACE [=] tablespace_name] [(subpartition_definition
[,subpartition_definition
] ......)]subpartition_definition
: SUBPARTITIONlogical_name
[[STORAGE] ENGINE [=]engine_name
] [评论[=]'string
'] [DATA DIRECTORY [=]''] [INDEX DIRECTORY [=]'
data_dir
'] [MAX_ROWS [=]
index_dir
max_number_of_rows
] [MIN_ROWS [=]min_number_of_rows
] [TABLESPACE [=] tablespace_name]query_expression:
选择......(Some valid select or union statement
)
CREATE
TABLE
创建一个具有给定名称的表。
您必须拥有
CREATE
该表
的
权限。
默认情况下,使用
InnoDB
存储引擎
在默认数据库中创建表
。
如果表存在,如果没有默认数据库,或者数据库不存在,则会发生错误。
有关表的物理表示的信息,请参见 第13.1.20.2节“由CREATE TABLE创建的文件” 。
CREATE TABLE
创建表时,MySQL将存储
原始
语句,包括所有规范和表选项。
有关更多信息,请参见
第13.1.20.1节“CREATE TABLE语句保留”
。
CREATE
TABLE
声明
有几个方面
,在本节的以下主题中描述:
tbl_name
可以指定表名
db_name.tbl_name
以在特定数据库中创建表。
假设数据库存在,无论是否存在默认数据库,这都有效。
如果使用带引号的标识符,请分别引用数据库和表名。
例如,写
`mydb`.`mytbl`
,不
`mydb.mytbl`
。
第9.2节“模式对象名称” 中给出了允许的表名称的规则 。
IF NOT EXISTS
如果表存在,则防止发生错误。
但是,没有验证现有表的结构与
CREATE TABLE
语句
指示的结构相同
。
您可以
TEMPORARY
在创建表时
使用该
关键字。
一个
TEMPORARY
表只在当前会话中可见,而当会话关闭时自动删除。
有关更多信息,请参见
第13.1.20.3节“CREATE TEMPORARY TABLE语法”
。
LIKE
用于
CREATE TABLE ... LIKE
根据另一个表的定义创建一个空表,包括原始表中定义的任何列属性和索引:
new_tbl
像表格一样orig_tbl
;
有关更多信息,请参见 第13.1.20.4节“CREATE TABLE ... LIKE语法” 。
[AS]
query_expression
要从另一个表创建一个表,请在
SELECT
语句末尾
添加一个
CREATE TABLE
语句:
CREATE TABLEnew_tbl
AS SELECT * FROMorig_tbl
;
有关更多信息,请参见 第13.1.20.5节“CREATE TABLE ... SELECT语法” 。
IGNORE|REPLACE
在
IGNORE
和
REPLACE
选项指示如何处理使用复制表时复制唯一键值的行
SELECT
声明。
有关更多信息,请参见 第13.1.20.5节“CREATE TABLE ... SELECT语法” 。
每个表的硬限制为4096列,但给定表的有效最大值可能更小,并取决于 第C.10.4节“表列计数和行大小限制”中 讨论的因素 。
data_type
data_type
表示列定义中的数据类型。
有关可用于指定列数据类型的语法的完整说明,以及有关每种类型的属性的信息,请参见
第11章,
数据类型
。
某些属性不适用于所有数据类型。
AUTO_INCREMENT
仅适用于整数和浮点类型。
在此之前的MySQL 8.0.13,
DEFAULT
并不适用于
BLOB
,
TEXT
,
GEOMETRY
,和
JSON
类型。
字符数据类型(
CHAR
,
VARCHAR
,的
TEXT
类型,
ENUM
,
SET
,和任何同义词)同义词)可以包括
CHARACTER SET
指定的字符的列设置。
CHARSET
是...的同义词
CHARACTER SET
。
可以使用
COLLATE
属性以及任何其他属性
指定字符集的排序规则
。
有关详细信息,请参见
第10章,
字符集,排序规则,Unicode
。
例:
CREATE TABLE t(c CHAR(20)CHARACTER SET utf8 COLLATE utf8_bin);
MySQL 8.0以字符形式解释字符列定义中的长度规范。
长度为
BINARY
和
VARBINARY
以字节
为
单位。
为
CHAR
,
VARCHAR
,
BINARY
,和
VARBINARY
列,索引可以创建仅使用列值的前导部分,使用
语法来指定一个索引前缀长度。
和
列也可以编入索引,但
必须
给出
前缀长度
。
对于非二进制字符串类型,前缀长度以字符给出,对于二进制字符串类型,以字节为单位给出。
即,索引项由所述第一的
每个列的值的字符
,
和
col_name
(length
)BLOB
TEXT
length
CHAR
VARCHAR
TEXT
列,并且所述第一
length
对每个列的值的字节
BINARY
,
VARBINARY
和
BLOB
列。
仅索引像这样的列值的前缀可以使索引文件更小。
有关索引前缀的其他信息,请参见
第13.1.15节“CREATE INDEX语法”
。
只有
InnoDB
和
MyISAM
存储引擎支持索引
BLOB
和
TEXT
列。
例如:
CREATE TABLE test(blob_col BLOB,INDEX(blob_col(10)));
如果指定的索引前缀超过最大列数据类型大小,
CREATE
TABLE
则按如下方式处理索引:
对于非唯一索引,要么发生错误(如果启用了严格的SQL模式),要么索引长度减少到最大列数据类型大小,并产生警告(如果未启用严格SQL模式)。
对于唯一索引,无论SQL模式如何都会发生错误,因为减少索引长度可能会导致插入不符合指定唯一性要求的非唯一条目。
JSON
列无法编入索引。
您可以通过在生成的列上创建索引来解决此限制,该
JSON
列
从列中提取标量值
。
有关
详细示例,
请参阅
索引生成的列以提供JSON列索引
。
NOT NULL | NULL
如果既未
指定
也
NULL
未
NOT
NULL
指定,则将列视为
NULL
已指定。
在MySQL 8.0中,只有
InnoDB
,
MyISAM
以及
MEMORY
在可以有列存储引擎支持索引
NULL
值。
在其他情况下,您必须将索引列声明为
NOT NULL
错误结果。
DEFAULT
指定列的默认值。
有关默认值处理的更多信息,包括列定义不包含显式
DEFAULT
值的情况,请参见
第11.7节“数据类型默认值”
。
如果
启用
了
NO_ZERO_DATE
或
NO_ZERO_IN_DATE
SQL模式并且根据该模式的日期值默认值不正确,
CREATE TABLE
则在未启用严格SQL模式时生成警告,如果启用了严格模式则生成错误。
例如,
NO_ZERO_IN_DATE
启用后,
c1 DATE DEFAULT '2010-00-00'
会生成警告。
AUTO_INCREMENT
整数或浮点列可以具有附加属性
AUTO_INCREMENT
。
当您插入值
NULL
(推荐)或
0
索引
AUTO_INCREMENT
列时,该列将设置为下一个序列值。
通常,这是
,这里
value
+1value
是目前在表中的列的最大值。
AUTO_INCREMENT
序列开头
1
。
要
AUTO_INCREMENT
在插入行后
检索
值,请使用
LAST_INSERT_ID()
SQL函数或
mysql_insert_id()
C API函数。
请参见
第12.15节“信息函数”
和
第28.7.7.38节“mysql_insert_id()”
。
如果
NO_AUTO_VALUE_ON_ZERO
启用
了
SQL模式,则可以
0
在
AUTO_INCREMENT
列中
存储
0
而不生成新的序列值。
请参见
第5.1.11节“服务器SQL模式”
。
AUTO_INCREMENT
每个表
只能有一
列,必须编制索引,并且不能有
DEFAULT
值。
一
AUTO_INCREMENT
列正常工作,只有当它仅包含正值。
插入负数被视为插入一个非常大的正数。
这样做是为了避免数字
从正到负
“
包裹
”
时的精度问题,
并确保您不会意外地获得
AUTO_INCREMENT
包含
的
列
0
。
对于
MyISAM
表,您可以
AUTO_INCREMENT
在多列键中
指定
辅助列。
请参见
第3.6.9节“使用AUTO_INCREMENT”
。
要使MySQL与某些ODBC应用程序兼容,您可以
AUTO_INCREMENT
使用以下查询
找到
最后插入行
的
值:
SELECT * FROMtbl_name
WHERE为auto_col
NULL
此方法要求
sql_auto_is_null
变量未设置为0.请参见
第5.1.8节“服务器系统变量”
。
有关信息
InnoDB
,并
AUTO_INCREMENT
请参见
第15.6.1.4,“AUTO_INCREMENT InnoDB的处理”
。
有关
AUTO_INCREMENT
和MySQL Replication的信息,请参见
第17.4.1.1节“Replication和AUTO_INCREMENT”
。
COMMENT
可以使用
COMMENT
选项
指定列的注释
,最多1024个字符。
注释由
SHOW
CREATE TABLE
和
SHOW FULL
COLUMNS
语句
显示
。
COLUMN_FORMAT
在NDB簇,它也可以指定的各个列的数据存储格式
NDB
使用表
COLUMN_FORMAT
。
允许列格式
FIXED
,
DYNAMIC
以及
DEFAULT
。
FIXED
用于指定固定宽度存储,
DYNAMIC
允许
DEFAULT
列为
可变宽度,
并使列使用由列的数据类型确定的固定宽度或可变宽度存储(可能由
ROW_FORMAT
说明符
覆盖
)。
对于
NDB
表,
COLUMN_FORMAT
is
的默认值
FIXED
。
在NDB Cluster中,定义的列的最大可能偏移量为
COLUMN_FORMAT=FIXED
8188字节。
有关更多信息和可能的解决方法,请参见
第22.1.7.5节“与NDB集群中的数据库对象关联的限制”
。
COLUMN_FORMAT
目前对使用除存储引擎之外的表的列没有影响
NDB
。
MySQL 8.0默默地忽略
COLUMN_FORMAT
。
STORAGE
对于
NDB
表,可以使用
STORAGE
子句
指定列是存储在磁盘上还是存储在内存中
。
STORAGE
DISK
导致列存储在磁盘上,并
STORAGE MEMORY
导致使用内存存储。
使用的
CREATE TABLE
声明必须包括一个
TABLESPACE
条款:
mysql>CREATE TABLE t1 (
- >c1 INT STORAGE DISK,
- >c2 INT STORAGE MEMORY
- > ERROR 1005(HY000):无法创建表'c.t1'(错误号:140)) ENGINE NDB;
mysql>CREATE TABLE t1 (
- >c1 INT STORAGE DISK,
- >c2 INT STORAGE MEMORY
- >) TABLESPACE ts_1 ENGINE NDB;
查询OK,0行受影响(1.06秒)
对于
NDB
表,
STORAGE
DEFAULT
相当于
STORAGE
MEMORY
。
该
STORAGE
子句对使用除以外的存储引擎的表没有影响
NDB
。
STORAGE
仅在
与NDB Cluster一起提供
的
mysqld
的构建中支持
该
关键字
;
在任何其他版本的MySQL中都无法识别,任何尝试使用该
STORAGE
关键字都会导致语法错误。
GENERATED ALWAYS
用于指定生成的列表达式。 有关 生成的列的 信息 ,请参见 第13.1.20.9节“创建表和生成的列” 。
存储生成的列
可以编制索引。
InnoDB
支持
虚拟生成列
上的二级索引
。
请参见
第13.1.20.10节“二级索引和生成的列”
。
有几个关键字适用于索引,外键和
CHECK
约束的创建。
除了以下描述之外,还有一般背景知识,请参见
第13.1.15节“CREATE INDEX语法”
,
第13.1.20.6节“使用FOREIGN KEY约束”
和
第13.1.20.7节“检查约束”
。
CONSTRAINT
symbol
可以给出
该
子句来命名约束。
如果未给出该子句,或者
在
关键字
后面不包含
a
,则MySQL会自动生成约束名称,但下面会有例外情况。
对于
每个约束类型,
该
值(如果使用)对于每个模式(数据库)必须是唯一的。
重复会
导致错误。
CONSTRAINT
symbol
symbol
CONSTRAINT
symbol
symbol
如果
在外键定义中没有给出
该
子句,或者
在
关键字
后面不包含
a
,则MySQL使用外键索引名称直到MySQL 8.0.15,并在此后自动生成约束名称。
CONSTRAINT
symbol
symbol
CONSTRAINT
SQL标准指定所有类型的约束(主键,唯一索引,外键,检查)属于同一名称空间。 在MySQL中,每个约束类型都有自己的每个模式的命名空间。 因此,每种类型的约束的名称对于每个模式必须是唯一的。
PRIMARY KEY
唯一索引,其中必须将所有键列定义为
NOT NULL
。
如果没有明确
NOT NULL
声明它们,MySQL就会隐式声明(并且默默地)。
一张桌子只能有一张
PRIMARY KEY
。
a的名称
PRIMARY
KEY
始终为
PRIMARY
,因此不能用作任何其他类型索引的名称。
如果你没有a
PRIMARY KEY
和应用程序要求
PRIMARY KEY
你的表,MySQL将返回第一个
UNIQUE
没有
NULL
列的
索引
PRIMARY KEY
。
在
InnoDB
表中,保留
PRIMARY
KEY
short以最小化二级索引的存储开销。
每个辅助索引条目都包含相应行的主键列的副本。
(参见
第15.6.2.1节“聚集和二级索引”
。)
在创建的表中,
PRIMARY KEY
首先放置
a
,然后放置所有
UNIQUE
索引,然后
放置
非唯一索引。
这有助于MySQL优化器确定要使用哪个索引的优先级,并且还可以更快地检测重复的
UNIQUE
密钥。
A
PRIMARY KEY
可以是多列索引。
但是,您无法使用
PRIMARY KEY
列规范中
的
键属性
创建多列索引
。
这样做只会将单列标记为主列。
您必须使用单独的
条款。
PRIMARY
KEY(
key_part
, ...)
如果表具有
由具有整数类型的单个列组成的索引
PRIMARY KEY
或
UNIQUE NOT NULL
索引,则可以用于
_rowid
引用
SELECT
语句中
的索引列
,如
唯一索引中所述
。
在MySQL中,a的名称
PRIMARY KEY
是
PRIMARY
。
对于其他指标,如果不指定一个名称,该指数被分配相同的名称作为第一个索引列,有一个可选的后缀(
_2
,
_3
,
...
),以使其独特。
您可以使用查看表的索引名称
。
请参见
第13.7.6.22节“SHOW INDEX语法”
。
SHOW INDEX FROM
tbl_name
KEY | INDEX
KEY
通常是...的同义词
INDEX
。
键属性
PRIMARY
KEY
也可以
KEY
在列定义中
指定
时指定。
这是为了与其他数据库系统兼容而实现的。
UNIQUE
一个
UNIQUE
索引创建的约束,使得该指数的所有值必须是不同的。
如果您尝试添加具有与现有行匹配的键值的新行,则会发生错误。
对于所有引擎,
UNIQUE
索引允许
NULL
包含的列的
多个
值
NULL
。
如果为
UNIQUE
索引中的列
指定前缀值
,则列值必须在前缀长度内是唯一的。
如果表具有
由具有整数类型的单个列组成的索引
PRIMARY KEY
或
UNIQUE NOT NULL
索引,则可以用于
_rowid
引用
SELECT
语句中
的索引列
,如
唯一索引中所述
。
FULLTEXT
一个
FULLTEXT
指标是用于全文搜索索引的一种特殊类型。
只有
InnoDB
和
MyISAM
存储引擎支持
FULLTEXT
索引。
他们只能从创建
CHAR
,
VARCHAR
和
TEXT
列。
索引总是发生在整个列上;
不支持列前缀索引,如果指定,则忽略任何前缀长度。
有关
操作的详细信息,
请参见
第12.9节“全文搜索功能”
。
甲
WITH PARSER
子句可以被指定为一个
index_option
如果全文索引和搜索操作需要特殊处理,则将解析器插件与索引相关联的值。
该子句仅对
FULLTEXT
索引
有效
。
InnoDB
并
MyISAM
支持全文解析器插件。
有关详细信息,请参阅
全文分析器插件
和
第29.2.4.4节“编写全文分析器插件”
。
SPATIAL
您可以
SPATIAL
在空间数据类型上
创建
索引。
仅支持
InnoDB
和
MyISAM
表的
空间类型
,并且必须将索引列声明为
NOT
NULL
。
请参见
第11.5节“空间数据类型”
。
FOREIGN KEY
MySQL支持外键,它允许您跨表交叉引用相关数据,以及外键约束,这有助于保持这种展开数据的一致性。
有关定义和选项信息,请参阅
reference_definition
和
reference_option
。
使用
InnoDB
存储引擎的
分区表
不支持外键。
有关
更多信息
,
请参见
第23.6节“分区的限制和限制”
。
CHECK
该
CHECK
子句允许创建要检查表行中数据值的约束。
请参见
第13.1.20.7节“检查约束”
。
key_part
甲
key_part
规格可以与结束
ASC
或
DESC
以指定的索引值是否被存储在升序或降序。
如果未给出订单说明符,则默认值为升序。
由
length
属性
定义的前缀
最长可达767个字节
InnoDB
使用
REDUNDANT
或
COMPACT
行格式的
表,
。
对于
InnoDB
使用
DYNAMIC
或
COMPRESSED
行格式的
表,
前缀长度限制为3072字节
。
对于
MyISAM
表,前缀长度限制为1000个字节。
前缀
限制
以字节为单位。
然而,前缀
长度
为索引规范
CREATE
TABLE
,
ALTER
TABLE
和
CREATE
INDEX
语句解释为非二进制字符串类型(字符数
CHAR
,
VARCHAR
,
TEXT
)和字节数为二进制串类型(
BINARY
,
VARBINARY
,
BLOB
)。
在为使用多字节字符集的非二进制字符串列指定前缀长度时,请考虑这一点。
index_type
某些存储引擎允许您在创建索引时指定索引类型。
index_type
说明符
的语法
是
。
USING
type_name
例:
CREATE TABLE查找 (id INT,索引使用BTREE(id)) ENGINE = MEMORY;
首选位置
USING
位于索引列列表之后。
它可以在列列表之前给出,但不支持在该位置使用该选项,并且将在以后的MySQL版本中删除。
index_option
index_option
values指定索引的其他选项。
KEY_BLOCK_SIZE
对于
MyISAM
表,
KEY_BLOCK_SIZE
可以选择指定用于索引键块的大小(以字节为单位)。
该值被视为提示;
如有必要,可以使用不同的尺寸。
KEY_BLOCK_SIZE
为单个索引定义指定
的
值将覆盖表级
KEY_BLOCK_SIZE
值。
有关表级
KEY_BLOCK_SIZE
属性的信息,请参阅
表选项
。
WITH PARSER
该
WITH PARSER
选项只能与
FULLTEXT
索引
一起使用
。
如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引相关联。
InnoDB
并
MyISAM
支持全文解析器插件。
如果您的
MyISAM
表具有关联的全文解析器插件,则可以将表转换为
InnoDB
使用
ALTER
TABLE
。
COMMENT
在MySQL 8.0中,索引定义可以包含最多1024个字符的可选注释。
您可以
InnoDB
MERGE_THRESHOLD
使用该
index_option
COMMENT
子句
设置
单个索引
的
值
。
请参见
第15.8.11节“配置索引页的合并阈值”
。
有关允许
index_option
值的
更多信息
,请参见
第13.1.15节“CREATE INDEX语法”
。
有关索引的更多信息,请参见
第8.3.1节“MySQL如何使用索引”
。
有关
reference_definition
语法详细信息和示例,请参见
第13.1.20.6节“使用FOREIGN KEY约束”
。
有关外键的特定信息
InnoDB
,请参见
第15.6.1.5节“InnoDB和FOREIGN KEY约束”
。
InnoDB
和
NDB
表支持检查外键约束。
必须始终明确命名引用表的列。
无论
ON
DELETE
和
ON UPDATE
外键的行动的支持。
有关更多详细信息和示例,请参见
第13.1.20.6节“使用FOREIGN KEY约束”
。
有关外键的特定信息
InnoDB
,请参见
第15.6.1.5节“InnoDB和FOREIGN KEY约束”
。
对于其它存储引擎,MySQL服务器解析,而忽略
FOREIGN KEY
和
REFERENCES
语法的
CREATE TABLE
语句。
请参见
第1.8.2.3节“外键差异”
。
对于熟悉ANSI / ISO SQL标准的用户,请注意,没有存储引擎,包括
InnoDB
,识别或强制执行
MATCH
参照完整性约束定义中使用
的
子句。
使用explicit
MATCH
子句不会产生指定的效果,也会
忽略
cause
ON DELETE
和
ON UPDATE
子句。
出于这些原因,
MATCH
应该避免
指定
。
MATCH
SQL标准中
的
子句控制
NULL
在与主键进行比较时如何处理复合(多列)外键中的值。
InnoDB
本质上实现了定义的语义
MATCH
SIMPLE
,允许外键全部或部分
NULL
。
在这种情况下,允许插入包含此类外键的(子表)行,并且与引用的(父)表中的任何行都不匹配。
可以使用触发器实现其他语义。
此外,MySQL要求为引用的列编制索引以提高性能。
但是,
InnoDB
不强制要求声明引用的列
UNIQUE
或
NOT
NULL
。
对包含
NULL
值的
非唯一键或键的外键引用的处理
没有为诸如
UPDATE
或之类的
操作定义
DELETE
CASCADE
。
建议您使用只引用
UNIQUE
(或
PRIMARY
)和的
键的外键
NOT
NULL
。
MySQL解析但忽略了
“
内联
REFERENCES
规范
”
(在SQL标准中定义),其中引用被定义为列规范的一部分。
MySQL
REFERENCES
仅在指定为单独
FOREIGN KEY
规范的
一部分时才
接受
子句
。
有关信息
RESTRICT
,
CASCADE
,
SET NULL
,
NO ACTION
,和
SET
DEFAULT
选项,请参阅
第13.1.20.6,“使用外键约束”
。
表选项用于优化表的行为。
在大多数情况下,您不必指定其中任何一个。
除非另有说明,否则这些选项适用于所有存储引擎
可以接受并记住不适用于给定存储引擎的选项作为表定义的一部分。
如果您稍后使用
ALTER
TABLE
转换表以使用其他存储引擎,
则此类选项适用
。
ENGINE
使用下表中显示的名称之一指定表的存储引擎。
引擎名称可以不加引号或引用。
引用的名称
'DEFAULT'
被识别但被忽略。
存储引擎 | 描述 |
---|---|
InnoDB |
具有行锁定和外键的事务安全表。
新表的默认存储引擎。
如果你有MySQL经验但是很新的话
,
请参见
第15章,
InnoDB存储引擎
,特别是
第15.1节“InnoDB简介”
InnoDB
。
|
MyISAM |
二进制便携式存储引擎,主要用于只读或大部分读取工作负载。 请参见 第16.2节“MyISAM存储引擎” 。 |
MEMORY |
此存储引擎的数据仅存储在内存中。 请参见 第16.3节“MEMORY存储引擎” 。 |
CSV |
以逗号分隔值格式存储行的表。 请参见 第16.4节“CSV存储引擎” 。 |
ARCHIVE |
归档存储引擎。 请参见 第16.5节“ARCHIVE存储引擎” 。 |
EXAMPLE |
一个示例引擎。 请参见 第16.9节“示例存储引擎” 。 |
FEDERATED |
访问远程表的存储引擎。 请参见 第16.8节“FEDERATED存储引擎” 。 |
HEAP |
这是一个同义词
MEMORY
。
|
MERGE |
MyISAM
用作一个表
的
表
的集合
。
也称为
MRG_MyISAM
。
请参见
第16.7节“MERGE存储引擎”
。
|
NDB |
集群,容错,基于内存的表,支持事务和外键。
也称为
NDBCLUSTER
。
请参见
第22章,
MySQL NDB Cluster 8.0
。
|
默认情况下,如果指定的存储引擎不可用,则该语句将失败并显示错误。
您可以通过
NO_ENGINE_SUBSTITUTION
从服务器SQL模式中
删除来覆盖此行为
(请参见
第5.1.11节“服务器SQL模式”
),以便MySQL允许使用默认存储引擎替换指定的引擎。
通常在这种情况下,这是
系统变量
InnoDB
的默认值
default_storage_engine
。
当
NO_ENGINE_SUBSTITUTION
被禁用,如果存储引擎规格不兑现出现警告。
AUTO_INCREMENT
AUTO_INCREMENT
表
的初始
值。
在MySQL 8.0,这个工程的
MyISAM
,
MEMORY
,
InnoDB
,和
ARCHIVE
表格。
要为不支持
AUTO_INCREMENT
表选项的
引擎设置第一个自动增量值,请
在创建表后
插入
一个值小于所需值
的
“
虚拟
”
行,然后删除虚拟行。
对于支持
语句中
的
AUTO_INCREMENT
表选项的
引擎
CREATE TABLE
,您还可以使用
重置
值。
该值不能设置为低于列中当前的最大值。
ALTER TABLE
tbl_name
AUTO_INCREMENT =
N
AUTO_INCREMENT
AVG_ROW_LENGTH
表格的平均行长度的近似值。 您只需为具有可变大小行的大型表设置此项。
当您创建
MyISAM
表时,MySQL使用
MAX_ROWS
和
AVG_ROW_LENGTH
选项
的乘积
来确定结果表的大小。
如果未指定任一选项,则
MyISAM
默认情况下数据和索引文件
的最大大小为
256 TB。
(如果您的操作系统不支持较大的文件,则表大小受文件大小限制的限制。)如果您想要保持指针大小以使索引更小更快而且您不需要大文件,那么可以通过设置
myisam_data_pointer_size
系统变量
来减少默认指针大小
。
(看到
第5.1.8节“服务器系统变量”
。)如果您希望所有表都能够超过默认限制并且愿意让您的表稍微慢一些并且大于必要的值,则可以通过设置此变量来增加默认指针大小。
将值设置为7允许表格大小高达65,536TB。
[DEFAULT] CHARACTER SET
指定表的默认字符集。
CHARSET
是...的同义词
CHARACTER
SET
。
如果字符集名称是
DEFAULT
,则使用数据库字符集。
CHECKSUM
如果希望MySQL为所有行维护实时校验和(即,当表更改时MySQL会自动更新的校验和),请将此值设置为1。
这使得表更新速度稍慢,但也可以更容易地找到损坏的表。
该
CHECKSUM
TABLE
声明报告了校验和。
(
MyISAM
仅限。)
[DEFAULT] COLLATE
指定表的默认排序规则。
COMMENT
该表的注释,最多2048个字符。
您可以
InnoDB
MERGE_THRESHOLD
使用该
table_option
COMMENT
子句
设置
表
的
值
。
请参见
第15.8.11节“配置索引页的合并阈值”
。
设置NDB_TABLE选项。
在该表注释
CREATE TABLE
创建一个
NDB
表或
ALTER
TABLE
这会改变一个也可以用于指定一到四个声明
NDB_TABLE
选项
NOLOGGING
,
READ_BACKUP
,
PARTITION_BALANCE
,或
FULLY_REPLICATED
为一组名称-值对,用逗号隔开如果需要的话,紧跟着
NDB_TABLE=
以引用的注释文本开头的
字符串
。
此处显示了使用此语法的示例语句(强调文本):
CREATE TABLE t1(
c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
c2 VARCHAR(100),
c3 VARCHAR(100))
ENGINE = NDB
COMMENT =“NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RP_BY_NODE” ;
引用的字符串中不允许使用空格。 该字符串不区分大小写。
评论显示为输出的一部分
SHOW CREATE TABLE
。
注释的文本也可以作为MySQL Information Schema
TABLES
表
的TABLE_COMMENT列
。
表的
ALTER
TABLE
语句
也支持此注释语法
NDB
。
请记住,使用的表注释
ALTER TABLE
替换了表可能具有的任何现有注释。
MERGE_THRESHOLD
表格不支持在表注释中
设置
选项
NDB
(忽略它)。
有关完整的语法信息和示例,请参见 第13.1.20.11节“设置NDB_TABLE选项” 。
COMPRESSION
用于
InnoDB
表的
页面级压缩的压缩算法
。
支持的值包括
Zlib
,
LZ4
,和
None
。
该
COMPRESSION
属性是通过透明页面压缩功能引入的。
页面压缩仅支持
InnoDB
驻留在
每个表文件表
空间中的表,并且仅在支持稀疏文件和打孔的Linux和Windows平台上可用。
有关更多信息,请参见
第15.9.2节“InnoDB页面压缩”
。
CONNECTION
FEDERATED
表
的连接字符串
。
旧版本的MySQL使用
COMMENT
连接字符串
的
选项。
DATA DIRECTORY
,
INDEX
DIRECTORY
对于
InnoDB
,该
子句允许在数据目录之外创建每个表的文件表空间。
表空间数据文件在指定目录中创建,该子目录位于与模式同名的子目录中。
必须启用
该
变量才能使用该
子句。
必须指定完整目录路径。
有关更多信息,请参见
第15.6.3.6节“在数据目录外创建表空间”
。
DATA
DIRECTORY='
directory
'innodb_file_per_table
DATA
DIRECTORY
创建
MyISAM
表时,可以使用
子句,
子句或两者。
它们分别指定放置
表的数据文件和索引文件的位置。
与
表
不同
,MySQL在创建
带有
或
选项
的
表
时不会创建与数据库名对应的子目录
。
文件在指定的目录中创建。
DATA
DIRECTORY='
directory
'INDEX
DIRECTORY='
directory
'MyISAM
InnoDB
MyISAM
DATA DIRECTORY
INDEX
DIRECTORY
您必须有权
FILE
使用
DATA DIRECTORY
或
INDEX DIRECTORY
表选项。
分区表将忽略
表级别
DATA DIRECTORY
和
INDEX DIRECTORY
选项。
(Bug#32091)
这些选项仅在您不使用该
--skip-symbolic-links
选项时有效。
您的操作系统还必须具有可正常工作的线程安全
realpath()
呼叫。
有关
更多完整信息,
请参见
第8.12.2.2节“在Unix上使用MyISAM表的符号链接”
。
如果
MyISAM
创建
的
表没有
DATA DIRECTORY
选项,
.MYD
则在数据库目录中创建
该
文件。
默认情况下,如果
在这种情况下
MyISAM
找到现有
.MYD
文件,则会覆盖它。
这同样适用于
.MYI
没有
INDEX
DIRECTORY
选项
创建的表的文件
。
要禁止此行为,请使用
--keep_files_on_create
选项
启动服务器
,在这种情况下,
MyISAM
不会覆盖现有文件并返回错误。
如果
MyISAM
使用
DATA DIRECTORY
或
INDEX
DIRECTORY
选项
创建表
并且
找到
现有
.MYD
或
.MYI
文件,则MyISAM始终返回错误。
它不会覆盖指定目录中的文件。
您不能使用包含MySQL数据目录的路径名
DATA DIRECTORY
或
INDEX DIRECTORY
。
这包括分区表和单个表分区。
(参见Bug#32167。)
DELAY_KEY_WRITE
如果要在表关闭之前延迟表的密钥更新,请将此值设置为1。
见的描述
delay_key_write
在系统变量
第5.1.8节,“服务器系统变量”
。
(
MyISAM
仅限。)
ENCRYPTION
该
ENCRYPTION
子句启用或禁用表的页级数据加密
InnoDB
。
必须先安装并配置密钥环插件,然后才能启用加密。
在MySQL 8.0.16之前,
ENCRYPTION
只能在每个表文件表空间中创建表时指定
该
子句。
从MySQL 8.0.16开始,
ENCRYPTION
在通用表空间中创建表时也可以指定
该
子句。
从MySQL 8.0.16开始,如果
ENCRYPTION
未指定子句
,表将继承默认模式加密
。
如果
table_encryption_privilege_check
启用了
该
变量,
TABLE_ENCRYPTION_ADMIN
则需要
该
权限才能创建一个子表
ENCRYPTION
设置与默认架构加密不同
的表
。
在通用表空间中创建表时,表和表空间加密必须匹配。
从MySQL 8.0.16开始,
在使用不支持加密的存储引擎时
,指定
ENCRYPTION
一个值不同于
'N'
或
''
不允许
的
子句
。
此前,该条款被接受。
有关更多信息,请参见 第15.6.3.9节“InnoDB静态数据加密” 。
INSERT_METHOD
如果要将数据插入
MERGE
表中,则必须指定
INSERT_METHOD
应插入行的表。
INSERT_METHOD
是一个
MERGE
仅对表
有用的选项
。
使用值
FIRST
或
LAST
将
值
插入第一个或最后一个表,或使用值
NO
来防止插入。
请参见
第16.7节“MERGE存储引擎”
。
KEY_BLOCK_SIZE
对于
MyISAM
表,
KEY_BLOCK_SIZE
可以选择指定用于索引键块的大小(以字节为单位)。
该值被视为提示;
如有必要,可以使用不同的尺寸。
KEY_BLOCK_SIZE
为单个索引定义指定
的
值将覆盖表级
KEY_BLOCK_SIZE
值。
对于
InnoDB
表,
KEY_BLOCK_SIZE
指定
用于
压缩
表
的
页面
大小(以KB为单位)
。
该
值被视为提示;
如有必要,
可以使用不同的尺寸
。
只能小于或等于该
值。
值0表示默认的压缩页面大小,它是该
值的
一半
。
根据具体情况
,可能的
值包括
0,1,2,4,8
和16.有关
更多信息
,
请参见
第15.9.1节“InnoDB表压缩”
。
InnoDB
KEY_BLOCK_SIZE
InnoDB
KEY_BLOCK_SIZE
innodb_page_size
innodb_page_size
innodb_page_size
KEY_BLOCK_SIZE
Oracle建议使
innodb_strict_mode
指定时
KEY_BLOCK_SIZE
为
InnoDB
表。
当
innodb_strict_mode
被启用,指定一个无效的
KEY_BLOCK_SIZE
值返回一个错误。
如果
innodb_strict_mode
禁用,则无效
KEY_BLOCK_SIZE
值将导致警告,并
KEY_BLOCK_SIZE
忽略
该
选项。
该
Create_options
列响应
SHOW TABLE STATUS
报告
KEY_BLOCK_SIZE
表所使用
的实际
情况
SHOW CREATE TABLE
。
InnoDB
只支持
KEY_BLOCK_SIZE
表级。
KEY_BLOCK_SIZE
不支持32KB和64KB
innodb_page_size
值。
InnoDB
表压缩不支持这些页面大小。
InnoDB
KEY_BLOCK_SIZE
在创建临时表时
不支持该
选项。
MAX_ROWS
您计划在表中存储的最大行数。 这不是硬限制,而是存储引擎的提示,表必须能够存储至少这么多行。
不推荐
使用
MAX_ROWS
with
NDB
表来控制表分区的数量。
它在以后的版本中仍然受支持以实现向后兼容性,但在将来的版本中可能会被删除。
请改用PARTITION_BALANCE;
请参阅
设置NDB_TABLE选项
。
该
NDB
存储引擎将这个值作为最大。
如果您打算创建非常大的NDB簇表(含数百万行),你应该使用这个选项,以确保
NDB
分配在用于通过设置存储表的主键的哈希值的哈希表足够数量的指数中的时隙的
,这里
是您希望插入表中的行数。
MAX_ROWS = 2 *
rows
rows
最大值
MAX_ROWS
为4294967295;
较大的值被截断为此限制。
MIN_ROWS
您计划在表中存储的最小行数。
该
MEMORY
存储引擎使用此选项,因为一个关于内存使用提示。
PACK_KEYS
仅对
MyISAM
表有效。
如果要使用较小的索引,请将此选项设置为1。
这通常会使更新变慢并且读取速度更快。
将该选项设置为0将禁用所有键的打包。
将其设置为
DEFAULT
告诉存储引擎只封装长
CHAR
,
VARCHAR
,
BINARY
,或
VARBINARY
列。
如果不使用
PACK_KEYS
,则默认为打包字符串,而不是数字。
如果您使用
PACK_KEYS=1
,也会打包数字。
在打包二进制数字键时,MySQL使用前缀压缩:
每个密钥都需要一个额外的字节来指示前一个密钥的字节数对于下一个密钥是相同的。
指向该行的指针直接以密钥后的高字节优先顺序存储,以改善压缩。
这意味着如果在两个连续的行上有许多相等的键,则所有后面的
“
相同
”
键通常只占用两个字节(包括指向该行的指针)。
将此与以下键所采用的普通情况
storage_size_for_key + pointer_size
(指针大小通常为4)进行比较。
相反,只有当您有许多相同的数字时,才能从前缀压缩中获得显着的好处。
如果所有键完全不同,则每个键使用一个字节,如果键不是可以具有
NULL
值
的键
。
(在这种情况下,打包密钥长度存储在用于标记密钥的相同字节中
NULL
。)
PASSWORD
此选项未使用。
ROW_FORMAT
定义存储行的物理格式。
执行
禁用
严格模式
的
CREATE TABLE
语句时
,如果指定了用于表的存储引擎不支持的行格式,则使用该存储引擎的默认行格式创建表。
表的实际行格式在
和
响应的列中
报告
。
还会报告表的实际行格式。
Row_format
Create_options
SHOW TABLE STATUS
SHOW CREATE TABLE
行格式选择因表格使用的存储引擎而异。
对于
InnoDB
表格:
默认行格式由
innodb_default_row_format
,其默认设置为
DYNAMIC
。
ROW_FORMAT
未定义选项或
使用时使用默认行格式
ROW_FORMAT=DEFAULT
。
如果
ROW_FORMAT
未定义
该
选项,或者
ROW_FORMAT=DEFAULT
使用
了该
选项,则
重建表的操作也会以静默方式将表的行格式更改为默认定义的
innodb_default_row_format
。
有关更多信息,请参阅
定义表的行格式
。
为了更有效地
InnoDB
存储数据类型,尤其是
BLOB
类型,请使用
DYNAMIC
。
有关
与
行格式
关联的要求,
请参阅
DYNAMIC
DYNAMIC
行格式。
要为
InnoDB
表
启用压缩
,请指定
ROW_FORMAT=COMPRESSED
。
ROW_FORMAT=COMPRESSED
创建临时表时不支持
该
选项。
有关
行格式的
要求
,
请参见
第15.9节“InnoDB表和页面压缩”
COMPRESSED
。
仍然可以通过指定
REDUNDANT
行格式
来请求旧版MySQL中使用的
行格式。
指定非默认
ROW_FORMAT
子句时,请考虑启用
innodb_strict_mode
配置选项。
ROW_FORMAT=FIXED
不受支持。
如果
ROW_FORMAT=FIXED
在
innodb_strict_mode
禁用时
指定,
则
InnoDB
发出警告并假定
ROW_FORMAT=DYNAMIC
。
如果
ROW_FORMAT=FIXED
在
innodb_strict_mode
启用时
指定
(默认值),则
InnoDB
返回错误。
有关
InnoDB
行格式的
其他信息
,请参见
第15.10节“InnoDB行格式”
。
为
MyISAM
表,该选项值可以是
FIXED
或
DYNAMIC
为静态的或可变长度的行格式。
myisampack
将类型设置为
COMPRESSED
。
请参见
第16.2.3节“MyISAM表存储格式”
。
对于
NDB
表,默认
ROW_FORMAT
为
DYNAMIC
。
STATS_AUTO_RECALC
指定是否自动重新计算
持续的统计数据
为
InnoDB
表。
该值
DEFAULT
导致表的持久统计信息设置由
innodb_stats_auto_recalc
配置选项
确定
。
1
当表中10%的数据发生更改时,
该值
会导致重新计算统计信息。
该值
0
可防止自动重新计算此表;
使用此设置,发出
ANALYZE TABLE
声明以在对表进行实质性更改后重新计算统计信息。
有关持久性统计信息功能的详细信息,请参阅
第15.8.10.1节“配置持久优化器统计信息参数”
。
STATS_PERSISTENT
指定是否
为
表
启用
持久统计信息
InnoDB
。
该值
DEFAULT
导致表的持久统计信息设置由
innodb_stats_persistent
配置选项
确定
。
该值
1
启用表的持久统计信息,而值
0
将关闭此功能。
通过
CREATE
TABLE
or
ALTER TABLE
语句
启用持久统计信息后
,请发出
第15.8.10.1节“配置持久优化器统计信息参数”
。
ANALYZE TABLE
信息后,在将代表性数据加载到表中后
语句来计算统计信息。
有关持久性统计信息功能的详细信息,请参阅
STATS_SAMPLE_PAGES
估计索引列的基数和其他统计信息时要采样的索引页数,例如计算的列
ANALYZE
TABLE
。
有关更多信息,请参见
第15.8.10.1节“配置持久优化器统计信息参数”
。
TABLESPACE
该
TABLESPACE
子句可用于在现有通用表空间,每表文件表空间或系统表空间中创建表。
CREATE TABLEtbl_name
... TABLESPACE [=]tablespace_name
您指定的常规表空间必须在使用该
TABLESPACE
子句
之前存在
。
有关常规表空间的信息,请参见
第15.6.3.3节“常规表空间”
。
这
是一个区分大小写的标识符。
它可能是引用或不引用的。
不允许
使用正斜杠字符(
“
/
”
)。
名称以
“
innodb_
”
开头
保留用于特殊用途。
tablespace_name
要在系统表空间中创建表,请指定
innodb_system
为表空间名称。
CREATE TABLE tbl_name
... TABLESPACE [=] innodb_system
使用时
TABLESPACE [=] innodb_system
,无论
innodb_file_per_table
设置
如何,都可以在系统表空间中放置任何未压缩行格式的表
。
例如,您可以使用添加表
ROW_FORMAT=DYNAMIC
到系统表空间
TABLESPACE [=] innodb_system
。
要在每个表的文件表空间中创建一个表,请指定
innodb_file_per_table
为表空间名称。
CREATE TABLE tbl_name
... TABLESPACE [=] innodb_file_per_table
如果
innodb_file_per_table
已启用,则无需指定
TABLESPACE=innodb_file_per_table
创建
InnoDB
每个表
的
文件表空间。
启用
InnoDB
时,默认情况下,在每个表的表空间中创建表
innodb_file_per_table
。
该
DATA DIRECTORY
条款是允许的,
CREATE TABLE ...
TABLESPACE=innodb_file_per_table
但不支持与该
TABLESPACE
条款
结合使用
。
自MySQL 8.0.13起,不推荐使用对
支持
TABLESPACE =
innodb_file_per_table
和
TABLESPACE =
innodb_temporary
子句的
支持,
并将
CREATE
TEMPORARY TABLE
在未来的MySQL版本中删除。
该
STORAGE
表选项仅采用了与
NDB
表。
STORAGE
确定使用的存储类型(磁盘或内存),可以是
DISK
或
MEMORY
。
TABLESPACE ... STORAGE DISK
将表分配给NDB Cluster Disk Data表空间。
必须已使用创建表空间
CREATE
TABLESPACE
。
有关
更多信息
,
请参见
第22.5.13节“NDB集群磁盘数据表”
。
一个
STORAGE
子句不能被用在
CREATE TABLE
声明中没有
TABLESPACE
从句。
用于访问一组相同的
MyISAM
表。
这仅适用于
MERGE
表格。
请参见
第16.7节“MERGE存储引擎”
。
你必须有
SELECT
,
UPDATE
以及
DELETE
对表的权限您映射到一个
MERGE
表。
以前,所有使用的表必须与
MERGE
表本身
在同一个数据库中
。
此限制不再适用。
partition_options
可用于控制创建的表的分区
CREATE
TABLE
。
并非所有
partition_options
分区类型都可以使用本节开头
语法中显示的所有选项
。
有关每种类型的信息,请参阅以下各个类型的列表,
有关MySQL中分区的工作和使用的更完整信息,以及有关表创建和其他相关语句的其他示例,
请参见
第23章
分区
。到MySQL分区。
可以修改,合并,添加到表以及从表中删除分区。 有关完成这些任务的MySQL语句的基本信息,请参见 第13.1.9节“ALTER TABLE语法” 。 有关更多详细说明和示例,请参见 第23.3节“分区管理” 。
PARTITION BY
如果使用,
partition_options
则以子句开头
PARTITION BY
。
该子句包含用于确定分区的函数;
该函数返回一个从1到1的整数值
num
,其中
num
是分区数。
(表可能包含的最大用户定义分区数为1024;子区域的数量 - 本节稍后讨论 - 包含在此最大值中。)
子句中
expr
使用
的表达式(
)
PARTITION BY
不能引用不在正在创建的表中的任何列;
此类引用是特别不允许的,并导致语句失败并出现错误。
(缺陷#29444)
HASH(
expr
)
散列一列或多列以创建用于放置和定位行的键。
expr
是使用一个或多个表列的表达式。
这可以是产生单个整数值的任何有效的MySQL表达式(包括MySQL函数)。
例如,这些都是有效的
CREATE TABLE
语句使用
PARTITION BY HASH
:
CREATE TABLE t1(col1 INT,col2 CHAR(5)) HASH分区(col1); CREATE TABLE t1(col1 INT,col2 CHAR(5),col3 DATETIME) 哈希分区(年(col3));
您不能使用其中任何一个
VALUES LESS THAN
或
VALUES IN
子句
PARTITION
BY HASH
。
PARTITION BY HASH
使用余数
expr
除以分区数(即模数)。
有关示例和其他信息,请参见
第23.2.4节“HASH分区”
。
的
LINEAR
关键字需要稍微不同的算法。
在这种情况下,计算存储行的分区的编号作为一个或多个逻辑
AND
操作的结果。
有关线性散列的讨论和示例,请参见
第23.2.4.1节“
线性散列
分区”
。
KEY(
column_list
)
这类似于
HASH
,除了MySQL提供散列函数以保证均匀的数据分布。
的
column_list
参数是简单的1个或多个表列(最大:16)的列表。
此示例显示了一个按键分区的简单表,包含4个分区:
CREATE TABLE tk(col1 INT,col2 CHAR(5),col3 DATE) PARTITION BY KEY(col3) PARTITIONS 4;
对于按键分区的表,可以使用
LINEAR
关键字进行
线性分区
。
这与分区的表具有相同的效果
HASH
。
也就是说,使用
&
运算符而不是模
数找到分区号
(有关
详细信息,
请参见
第23.2.4.1节“线性哈希分区”
和
第23.2.5节“键分区”
)。
此示例使用按键的线性分区在5个分区之间分配数据:
CREATE TABLE tk(col1 INT,col2 CHAR(5),col3 DATE) 线性键分区(col3) PARTITIONS 5;
该
ALGORITHM={1|2}
选项受支持
[SUB]PARTITION BY [LINEAR] KEY
。
ALGORITHM=1
使服务器使用与MySQL 5.1相同的密钥散列函数;
ALGORITHM=2
表示服务器使用默认为
KEY
MySQL 5.5及更高版本中的
新
分区表
实现和使用的密钥散列函数
。
(使用MySQL 5.5及更高版本中使用的密钥散列函数创建的分区表不能由MySQL 5.1服务器使用。)不指定该选项与使用具有相同的效果
ALGORITHM=2
。
此选项主要用于升级或降级
或
[LINEAR] KEY
在MySQL 5.1和更高版本的MySQL版本之间
分区表,或用于创建分区的表时
KEY
LINEAR
KEY
在MySQL 5.5或更高版本的服务器上,可以在MySQL 5.1服务器上使用。
有关更多信息,请参见
第13.1.9.1节“ALTER TABLE分区操作”
。
MySQL 5.7(及更高版本)中的 mysqldump 将此选项写入版本化注释中,如下所示:
CREATE TABLE t1(INT)
/ *!50100 PARTITION BY KEY * / / *!50611 ALGORITHM = 1 * / / *!50100()
PARTITIONS 3 * /
这会导致MySQL 5.6.10和更早版本的服务器忽略该选项,否则会导致这些版本中的语法错误。
如果您计划在MySQL 5.7服务器上加载转储,在该服务器中使用分区或子分区的表
KEY
到5.6.11之前的MySQL 5.6服务器,请务必
在继续之前
查阅
MySQL 5.6中的更改
。
(如果您正在将包含
KEY
由MySQL 5.7实际5.6.11或更高版本服务器组成的分区或子分区表
的转储加载
到MySQL 5.5.30或更早版本的服务器中,
那么此处找到的信息也适用
。)
同样在MySQL 5.6.11及更高版本中,
ALGORITHM=1
必要时在
SHOW CREATE TABLE
使用版本化注释
的输出中
以与
mysqldump
相同的方式显示
。
即使在创建原始表时指定了此选项,也
ALGORITHM=2
始终从
SHOW CREATE TABLE
输出中
省略
。
您不能使用其中任何一个
VALUES LESS THAN
或
VALUES IN
子句
PARTITION
BY KEY
。
RANGE(
expr
)
在这种情况下,
expr
使用一组
VALUES LESS THAN
运算符
显示一系列值
。
使用范围分区时,必须使用定义至少一个分区
VALUES LESS THAN
。
您不能使用
VALUES IN
范围分区。
对于分区的表
RANGE
,
VALUES LESS THAN
必须与整数文字值或计算结果为单个整数值的表达式一起使用。
在MySQL 8.0中,您可以在使用
PARTITION BY RANGE COLUMNS
本节
定义的表中克服此限制
,如本节后面所述。
假设您有一个表,您希望在包含年份值的列上进行分区,根据以下方案。
分区号码: | 年份范围: |
---|---|
0 | 1990年及早些时候 |
1 | 1991年至1994年 |
2 | 1995年至1998年 |
3 | 1999年至2002年 |
4 | 2003年至2005年 |
五 | 2006年及以后 |
实现这种分区方案的表可以通过
CREATE TABLE
此处显示
的
语句
实现
:
CREATE TABLE t1( year_col INT, some_data INT ) 按范围划分(year_col)( 分数p0值低于(1991), 分区p1值低于(1995), 分区p2值低于(1999), 分区p3价值低于(2002年), 分区p4价值低于(2006年), 分区p5的值低于MAXVALUE );
PARTITION ... VALUES LESS THAN ...
陈述以连续的方式起作用。
VALUES LESS
THAN MAXVALUE
用于指定
大于另外指定的最大值的
“
剩余
”
值。
VALUES LESS THAN
子句以类似于
块
的
case
部分的
方式顺序工作
switch ... case
(如在许多编程语言中找到的那样,如C,Java和PHP)。
也就是说,条款必须以这样的方式排列,即每个连续中指定的上限
VALUES LESS
THAN
大于前一个的
上限
,其中一个引用
MAXVALUE
最后列在列表中。
RANGE
COLUMNS(
column_list
)
此变体
RANGE
有助于使用多列上的范围条件(即具有诸如
WHERE a = 1 AND b
< 10
或的
条件
WHERE a = 1 AND b = 10 AND c
< 10
)
对查询进行分区修剪
。
它允许您通过使用
COLUMNS
子句
中的列列表
和每个
分区定义子句中的
一组列值
来指定多列中的值范围
。
(在最简单的情况下,此集合由单个列组成。)可以在
和中
引用的最大列数
为16。
PARTITION ... VALUES LESS THAN
(
value_list
)column_list
value_list
该
column_list
中使用的
COLUMNS
条款可能只包含列的名称;
列表中的每一列必须是以下MySQL数据类型之一:整数类型;
字符串类型;
和时间或日期列类型。
使用列
BLOB
,
TEXT
,
SET
,
ENUM
,
BIT
,或空间数据类型不允许;
也不允许使用浮点数类型的列。
您也可以不在
COLUMNS
子句中
使用函数或算术表达式
。
VALUES LESS THAN
分区定义中使用
的
子句必须为
COLUMNS()
子句
中出现的每个列指定文字值
;
也就是说,用于每个
VALUES LESS THAN
子句
的值列表
必须包含与
COLUMNS
子句中
列出的列相同数量的值
。
尝试到在使用更多或更少的值
VALUES LESS THAN
以外还有的条款
COLUMNS
条款会导致失败,错误的语句
在列列表的使用不一致的分区...
。
您不能使用
NULL
任何出现的值
VALUES LESS THAN
。
可以使用
MAXVALUE
对于除第一列之外的给定列,不止一次,如下例所示:
CREATE TABLE rc( INT NOT NULL, b INT NOT NULL ) 按范围栏划分(a,b)( 分区p0值小于(10,5), 分区p1值小于(20,10), 分区p2值小于(50,MAXVALUE), 分区p3值低于(65,MAXVALUE), PARTITION p4值小于(MAXVALUE,MAXVALUE) );
VALUES LESS THAN
值列表中
使用的每个值
必须与相应列的类型完全匹配;
没有转换。
例如,您不能将字符串
'1'
用于与使用整数类型的列匹配的值(您必须使用数字
1
),也不能将数字
1
用于与使用字符串类型的列匹配的值(在此类中)一个案例,你必须使用带引号的字符串:)
'1'
。
有关更多信息,请参见 第23.2.1节“RANGE分区” 和 第23.4节“分区修剪” 。
LIST(
expr
)
在基于具有一组受限值的可能值(例如州或国家/地区代码)的表列分配分区时,这非常有用。
在这种情况下,可以将属于某个州或国家的所有行分配给单个分区,或者可以为某组州或国家保留分区。
它类似于
RANGE
,除了可以仅
VALUES
IN
用于指定每个分区的允许值。
VALUES IN
与要匹配的值列表一起使用。
例如,您可以创建一个分区方案,如下所示:
CREATE TABLE client_firms( id INT, 名称VARCHAR(35) ) 按名单划分(id)( 分区r0值((1,5,9,13,17,21), 分区r1值(2,6,10,14,18,22), 分区r2值(3,7,11,15,19,23), 分区r3值(4,8,12,16,20,24) );
使用列表分区时,必须使用定义至少一个分区
VALUES IN
。
您不能使用
VALUES LESS THAN
与
PARTITION BY
LIST
。
对于分区的表
LIST
,使用的值列表
VALUES IN
必须仅包含整数值。
在MySQL 8.0中,您可以使用分区来克服此限制
LIST
COLUMNS
,本节稍后将对此进行介绍。
LIST
COLUMNS(
column_list
)
此变体
LIST
有助于使用多列上的比较条件(即具有诸如
WHERE a =
5 AND b = 5
或的
条件
WHERE a = 1 AND b = 10 AND c
= 5
)
对查询进行分区修剪
。
它允许您通过使用
COLUMNS
子句
中的列列表
和每个
分区定义子句中的
一组列值
来指定多列中的
值
。
PARTITION ... VALUES IN
(
value_list
)
管理有关数据类型中使用的列列表中的规则
和使用值列表
是相同的那些在使用的列清单
,并在使用值列表
分别,只是在
条款,
是不允许的,和你可能会用
。
LIST
COLUMNS(
column_list
)VALUES
IN(
value_list
)RANGE
COLUMNS(
column_list
)VALUES LESS
THAN(
value_list
)VALUES IN
MAXVALUE
NULL
有用于值列表之间的一个重要区别
VALUES IN
有
PARTITION
BY LIST COLUMNS
,而不是当它与使用
PARTITION BY LIST
。
与之一起使用时
PARTITION BY LIST COLUMNS
,
VALUES IN
子句中的
每个元素都
必须是一
组
列值;
每个集合中的值的数量必须与
COLUMNS
子句中
使用的列数相同
,并且这些值的数据类型必须与列的数据类型匹配(并以相同的顺序出现)。
在最简单的情况下,该集合由一列组成。
可以
column_list
在构成元素的元素中
使用的最大列数
value_list
为16。
由以下
CREATE
TABLE
语句
定义的表
提供了使用
LIST COLUMNS
分区
的表的示例
:
创建表lc( 一个INT NULL, b INT NULL ) 列表栏分区(a,b)( PARTITION p0 VALUES IN((0,0),(NULL,NULL)), 分区p1值((0,1),(0,2),(0,3),(1,1),(1,2)), 分区p2值((1,0),(2,0),(2,1),(3,0),(3,1)), ((1,3),(2,2),(2,3),(3,2),(3,3)中的分区p3值) );
PARTITIONS
num
可以选择使用
子句
指定
分区数
,其中
是分区数。
如果同时使用此子句
和
任何
子句,则
必须等于使用
子句
声明的任何分区的总数
。
PARTITIONS
num
num
PARTITION
num
PARTITION
无论是否
PARTITIONS
在创建由
RANGE
or
分区的表中
使用
子句
LIST
,您仍必须
PARTITION
VALUES
在表定义中
包含至少一个
子句(参见下文)。
SUBPARTITION BY
可以可选地将分区划分为多个子分区。
这可以通过使用optional
SUBPARTITION BY
子句
来指示
。
子分区可以通过
HASH
或
完成
KEY
。
这些都可能是
LINEAR
。
这些工作方式与先前针对等效分区类型所述的方式相同。
(不可能通过
LIST
或
分区
RANGE
。)
可以使用
SUBPARTITIONS
关键字后跟整数值
来指示子分区的数量
。
严格检查使用
PARTITIONS
或
SUBPARTITIONS
子句中使用的值,该值必须符合以下规则:
该值必须是正的非零整数。
不允许前导零。
该值必须是整数文字,并且不能是表达式。
例如,
PARTITIONS
0.2E+01
即使
0.2E+01
评估为
,也不允许
2
。
(缺陷#15890)
partition_definition
可以使用
partition_definition
子句
单独定义每个分区
。
构成本条款的各个部分如下:
PARTITION
partition_name
指定分区的逻辑名称。
VALUES
对于范围分区,每个分区必须包含一个
VALUES LESS THAN
子句;
对于列表分区,您必须
VALUES
IN
为每个分区
指定一个
子句。
这用于确定要在此分区中存储哪些行。
见分区类型的讨论
第23章,
分区
,语法的例子。
[STORAGE] ENGINE
MySQL的接受
[STORAGE] ENGINE
了这两个选项
PARTITION
和
SUBPARTITION
。
目前,可以使用此选项的唯一方法是将所有分区或所有子分区设置为同一存储引擎,并且尝试为同一表中的分区或子分区设置不同的存储引擎将导致错误
ERROR 1469 (HY000):在此版本的MySQL中不允许分区中的处理程序组合
。
COMMENT
可选
COMMENT
子句可用于指定描述分区的字符串。
例:
评论='1999年之前的数据'
分区注释的最大长度为1024个字符。
DATA DIRECTORY
和
INDEX
DIRECTORY
DATA DIRECTORY
并且
INDEX
DIRECTORY
可以用于指示分别存储该分区的数据和索引的目录。
无论是
和
data_dir
必须是绝对系统路径名。
index_dir
您必须有权
FILE
使用
DATA DIRECTORY
或
INDEX DIRECTORY
分区选项。
例:
CREATE TABLE th(id INT,名称VARCHAR(30),adate DATE) 按名单划分(年份(adate)) ( 分区p1999价值观(1995年,1999年,2003年) DATA DIRECTORY ='/var/appdata/95/data
' INDEX DIRECTORY ='/var/appdata/95/idx
', 分区p2000价值观(1996年,2000年,2004年) DATA DIRECTORY ='/var/appdata/96/data
' INDEX DIRECTORY ='/var/appdata/96/idx
', 分区p2001价值观(1997年,2001年,2005年) DATA DIRECTORY ='/var/appdata/97/data
' INDEX DIRECTORY ='/var/appdata/97/idx
', 分区p2002价值观(1998年,2002年,2006年) DATA DIRECTORY ='/var/appdata/98/data
' INDEX DIRECTORY ='/var/appdata/98/idx
' );
DATA DIRECTORY
并且
与用于
表
INDEX
DIRECTORY
的
CREATE TABLE
语句
table_option
子句
中的行为相同
MyISAM
。
每个分区可以指定一个数据目录和一个索引目录。 如果未指定,则数据和索引默认存储在表的数据库目录中。
在
DATA DIRECTORY
和
INDEX
DIRECTORY
选项将被忽略创建分区表是否
NO_DIR_IN_CREATE
有效。
MAX_ROWS
和
MIN_ROWS
可用于分别指定要在分区中存储的最大和最小行数。
为价值观
max_number_of_rows
和
min_number_of_rows
必须为正整数。
与具有相同名称的表级选项一样,这些选项仅作为
服务器的
“
建议
”
而不是硬限制。
TABLESPACE
可用于通过指定
InnoDB
为分区指定每个表
的
文件表空间
TABLESPACE `innodb_file_per_table`
。
所有分区必须属于同一存储引擎。
不支持
将
InnoDB
表分区放在共享
InnoDB
表空间中。
共享表空间包括
InnoDB
系统表空间和通用表空间。
subpartition_definition
分区定义可以可选地包含一个或多个
subpartition_definition
子句。
这些中的每一个至少包含
,其中
是子分区的标识符。
除了替换
关键字with外
,子分区定义的语法与分区定义的语法相同。
SUBPARTITION
name
name
PARTITION
SUBPARTITION
子分区必须完成
HASH
或
KEY
,并且只能在完成
RANGE
或
LIST
分区。
请参见
第23.2.6节“子分区”
。
按生成的列进行分区
允许按生成的列进行分区。 例如:
CREATE TABLE t1( s1 INT, s2 INT AS(EXP(s1))已存储 ) 按名单划分(第2条)( 分区p1值(1) );
分区将生成的列视为常规列,这使得可以对不允许进行分区的函数进行限制(请参见
第23.6.3节“对函数相关的分区限制”
)。
上面的示例演示了此技术:
EXP()
不能直接在
PARTITION BY
子句中使用,但
EXP()
允许
使用定义的生成列
。
CREATE TABLE
创建表时,MySQL将存储
原始
语句,包括所有规范和表选项。
保留信息,以便在使用
ALTER
TABLE
语句
更改存储引擎,排序规则或其他设置时
,将保留指定的原始表选项。
这使您可以在
表
InnoDB
和
MyISAM
类型
之间进行更改,
即使两个引擎支持的行格式不同。
因为保留了原始语句的文本,但是由于某些值和选项可以以静默方式重新配置的方式,活动表定义(可通过
DESCRIBE
或使用
SHOW TABLE STATUS
)和表创建字符串(可通过
SHOW
CREATE TABLE
)可以报告不同的值。
对于
InnoDB
表,
SHOW
CREATE TABLE
以及
Create_options
报告
的
列
SHOW TABLE
STATUS
显示
表使用
的实际
ROW_FORMAT
和
KEY_BLOCK_SIZE
属性。
在以前的MySQL版本中,报告了这些属性的最初指定值。
对于
InnoDB
在每个表文件表空间或通用表空间中创建的表,表数据和关联索引存储在
数据库目录
中的
ibd文件
中。
当
InnoDB
在系统表空间中创建表,表数据和索引存储在
ibdata *文件
表示系统表空间。
该
innodb_file_per_table
选项控制是否默认情况下在每个表的文件表空间或系统表空间中创建表。
TABLESPACE
无论
innodb_file_per_table
设置
如何,
该
选项都可用于将表放在每个表的文件表空间,通用表空间或系统表空间中
。
对于
MyISAM
表,存储引擎会创建数据和索引文件。
因此,对于每个
MyISAM
表
tbl_name
,有两个磁盘文件。
文件 | 目的 |
---|---|
|
数据文件 |
|
索引文件 |
第16章, 备用存储引擎 ,描述了每个存储引擎为表示表而创建的文件。 如果表名包含特殊字符,则表文件的名称包含这些字符的编码版本,如 第9.2.3节“标识符到文件名的映射”中所述 。
您可以
TEMPORARY
在创建表时
使用该
关键字。
一个
TEMPORARY
表只在当前会话中可见,而当会话关闭时自动删除。
这意味着两个不同的会话可以使用相同的临时表名,而不会相互冲突或与现有
TEMPORARY
的同名
非
表
冲突
。
(在删除临时表之前,将隐藏现有表。)
InnoDB
不支持压缩的临时表。
当
innodb_strict_mode
启用(默认值),
CREATE
TEMPORARY
TABLE
如果返回错误
ROW_FORMAT=COMPRESSED
或
KEY_BLOCK_SIZE
指定的。
如果
innodb_strict_mode
禁用,则发出警告,并使用非压缩行格式创建临时表。
该
innodb_file_per-table
选项不会影响
InnoDB
临时表
的创建
。
CREATE
TABLE
导致隐式提交,除非与
TEMPORARY
关键字一起使用。
请参见
第13.3.3节“导致隐式提交的语句”
。
TEMPORARY
表与数据库(模式)的关系非常松散。
删除数据库不会自动删除
TEMPORARY
在该数据库中创建的
任何
表。
此外,
TEMPORARY
如果使用
CREATE TABLE
语句中
的数据库名限定表名,则
可以
在不存在的数据库中
创建
表
。
在这种情况下,必须使用数据库名称限定对表的所有后续引用。
要创建临时表,您必须具有该
CREATE TEMPORARY
TABLES
权限。
会话创建临时表后,服务器不会对表执行进一步的权限检查。
所述创建会话可以在桌子上进行任何操作,例如
DROP
TABLE
,
INSERT
,
UPDATE
,或
SELECT
。
这种行为的一个含义是,即使当前用户没有创建它们的权限,会话也可以操纵其临时表。
假设当前用户没有
CREATE TEMPORARY
TABLES
权限,但能够执行定义者上下文存储过程,该过程以具有
CREATE TEMPORARY
TABLES
创建临时表
的用户的权限执行
。
该过程执行时,会话使用定义用户的权限。
该过程返回后,有效权限将恢复为当前用户的权限,该权限仍然可以查看临时表并对其执行任何操作。
您不能使用
CREATE TEMPORY TABLE ... LIKE
基于表
mysql
空间,
InnoDB
system tablespace(
innodb_system
)或常规表空间
中的
表
的定义来创建空表
。
此类表的表空间定义包括一个
TABLESPACE
属性,
该
属性定义表所在的表空间,并且上述表空间不支持临时表。
要根据此类表的定义创建临时表,请改用以下语法:
CREATE TEMPORARY TABLEnew_tbl
SELECT * FROMorig_tbl
LIMIT 0;
自MySQL 8.0.13起,不推荐使用对
支持
TABLESPACE =
innodb_file_per_table
和
TABLESPACE =
innodb_temporary
子句的
支持,
并将
CREATE
TEMPORARY
TABLE
在未来的MySQL版本中删除。
用于
CREATE TABLE ... LIKE
根据另一个表的定义创建一个空表,包括原始表中定义的任何列属性和索引:
new_tbl
像表格一样orig_tbl
;
使用与原始表相同的表存储格式版本创建副本。
SELECT
原始表上需要
该
权限。
LIKE
仅适用于基表,不适用于视图。
您无法执行
CREATE TABLE
或
CREATE TABLE ... LIKE
在
LOCK TABLES
语句生效时执行。
CREATE
TABLE ...
LIKE
进行相同的检查
CREATE
TABLE
。
这意味着如果当前SQL模式与创建原始表时生效的模式不同,则对于新模式,表定义可能被视为无效,并且语句将失败。
对于
CREATE TABLE ... LIKE
,目标表保留原始表中生成的列信息。
对于
CREATE TABLE ... LIKE
,目标表保留原始表中的表达式默认值。
对于
CREATE TABLE ... LIKE
,目标表保留
CHECK
原始表中的约束,但生成所有约束名称除外。
CREATE TABLE ... LIKE
不保留
为原始表或任何外键定义指定的
任何
DATA DIRECTORY
或
INDEX
DIRECTORY
表选项。
如果原始表是
TEMPORARY
表,
CREATE TABLE ... LIKE
则不保留
TEMPORARY
。
要创建
TEMPORARY
目标表,请使用
CREATE TEMPORARY TABLE ... LIKE
。
在
mysql
表空间,
InnoDB
系统表空间(
innodb_system
)或通用表空间中创建的表包含
TABLESPACE
表定义中
的
属性,该属性定义表所在的表空间。
由于临时回归,
CREATE TABLE
... LIKE
保留
TABLESPACE
属性并在定义的表空间中创建表,而不管
innodb_file_per_table
设置
如何
。
要在
TABLESPACE
基于此类表的定义创建空表时
避免该
属性,请使用以下语法:
CREATE TABLEnew_tbl
SELECT * FROMorig_tbl
LIMIT 0;
您可以通过在
SELECT
语句末尾
添加
语句
来创建另一个表
CREATE
TABLE
:
CREATE TABLEnew_tbl
[AS] SELECT * FROMorig_tbl
;
MySQL为其中的所有元素创建新列
SELECT
。
例如:
mysql>CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
- >PRIMARY KEY (a), KEY(b))
- >ENGINE=MyISAM SELECT b,c FROM test2;
这将创建一个
MyISAM
表有三列,
a
,
b
,和
c
。
该
ENGINE
选项是
CREATE
TABLE
声明的
一部分
,不应使用
SELECT
;
这会导致语法错误。
对于其他
CREATE
TABLE
选项
也是如此
CHARSET
。
请注意,
SELECT
语句中
的列
会附加到表的右侧,而不会重叠到表的右侧。
请看以下示例:
MySQL的>SELECT * FROM foo;
+ --- + | n | + --- + | 1 | + --- + MySQL的>CREATE TABLE bar (m INT) SELECT n FROM foo;
查询OK,1行受影响(0.02秒) 记录:1个重复:0警告:0 MySQL的>SELECT * FROM bar;
+ ------ + --- + | m | n | + ------ + --- + | NULL | 1 | + ------ + --- + 1排(0.00秒)
对于表中的每一行
foo
,将插入一行,
bar
其中
foo
包含新列
的值
和默认值。
在由此产生的表中
CREATE
TABLE ...
SELECT
,仅在
CREATE
TABLE
部件中
命名的列
首先出现。
在两个部分中或仅在部件中命名的列在此
SELECT
之后。
SELECT
可以通过指定
CREATE
TABLE
零件中
的
列来覆盖列
的数据类型
。
如果在将数据复制到表时发生任何错误,则会自动删除它而不会创建。
您可以在
SELECT
by
之前
IGNORE
或
REPLACE
指示如何处理复制唯一键值的行。
使用
IGNORE
,复制唯一键值上现有行的行将被丢弃。
使用
REPLACE
新行替换具有相同唯一键值的行。
如果既未
指定
也
IGNORE
未
REPLACE
指定,则重复的唯一键值会导致错误。
有关更多信息,请参阅
IGNORE关键字和严格SQL模式的比较
。
因为
SELECT
无法始终确定
基础
语句
中行的顺序
,
CREATE TABLE ... IGNORE SELECT
并且
CREATE TABLE ... REPLACE SELECT
语句被标记为基于语句的复制不安全。
当使用基于语句的模式时,此类语句在错误日志中生成警告,并在使用
MIXED
模式
时使用基于行的格式写入二进制日志
。
另请参见
第17.2.1.1节“基于语句和基于行的复制的优点和缺点”
。
CREATE
TABLE ...
SELECT
不会自动为您创建任何索引。
这样做是为了使声明尽可能灵活。
如果要在创建的表中包含索引,则应在
SELECT
语句
之前指定这些索引
:
MySQL的> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
对于
CREATE TABLE ... SELECT
,目标表不保留有关selected-from表中的列是否为生成列的信息。
SELECT
语句
的
一部分无法为目标表中的生成列分配值。
对于
CREATE TABLE ... SELECT
,目标表确实保留原始表中的表达式默认值。
可能会发生某些数据类型转换。
例如,
AUTO_INCREMENT
不保留
该
属性,
VARCHAR
列可以成为
CHAR
列。
再培训属性是
NULL
(或
NOT
NULL
),对于有他们这些列,
CHARACTER SET
,
COLLATION
,
COMMENT
,和
DEFAULT
条款。
使用时创建表
CREATE
TABLE ... SELECT
,请确保在查询中为任何函数调用或表达式设置别名。
如果不这样做,则该
CREATE
语句可能会失败或导致不合需要的列名。
CREATE TABLE artists_and_works SELECT artist.name,COUNT(work.artist_id)AS number_of_works 来自艺术家LEFT JOIN的作品在artist.id = work.artist_id上 GROUP BY artist.id;
您还可以在创建的表中显式指定列的数据类型:
CREATE TABLE foo(TINYINT NOT NULL)SELECT b + 1 AS FROM BAR;
因为
CREATE
TABLE
... SELECT
,如果
IF NOT EXISTS
给定并且目标表存在,则不会向目标表中插入任何内容,并且不会记录该语句。
为确保二进制日志可用于重新创建原始表,MySQL不允许在此期间进行并发插入
CREATE
TABLE ...
SELECT
。
您不能将其
FOR UPDATE
用作
SELECT
声明中的
一部分
。
如果您尝试这样做,则该语句将失败。
CREATE
TABLE
new_table
SELECT ... FROM
old_table
...
MySQL支持外键,它允许您跨表交叉引用相关数据,以及
外键约束
,这有助于保持这种展开数据的一致性。
CREATE
TABLE
or
ALTER
TABLE
语句
中外键约束定义的基本语法
如下所示:
[CONSTRAINT [symbol
]]外键 [index_name
](col_name
,...) 参考文献tbl_name
(col_name
,...) [ON DELETEreference_option
] [ON UPDATEreference_option
]reference_option
: 限制| CASCADE | SET NULL | 没有动作| 默认设置
index_name
表示外键ID。
index_name
如果子表上已经显式定义了可以支持外键的索引,则忽略
该
值。
否则,MySQL会隐式创建一个根据以下规则命名的外键索引:
如果已定义,
CONSTRAINT
symbol
则使用
该
值。
否则,使用该
FOREIGN KEY
index_name
值。
如果既没有
CONSTRAINT
symbol
或
FOREIGN
KEY
index_name
定义,使用引用外键列的名称所产生的外键索引名。
外键定义符合以下条件:
外键关系涉及
保存中心数据值
的
父表
,以及具有
指向其父级的相同值
的
子表
。
该
FOREIGN KEY
子句在子表中指定。
父表和子表必须使用相同的存储引擎。
他们不能是
TEMPORARY
桌子。
在MySQL 8.0中,创建外键约束需要
REFERENCES
父表
的
特权。
外键和引用键中的相应列必须具有相似的数据类型。 整数类型的大小和符号必须相同 。 字符串类型的长度不必相同。 对于非二进制(字符)字符串列,字符集和排序规则必须相同。
如果
foreign_key_checks
启用(默认设置),则在包含外键约束中使用的字符串列的表上不允许进行字符集转换。
第13.1.9节“ALTER TABLE语法”中
介绍了解决方法
。
MySQL需要外键和引用键的索引,以便外键检查可以快速,不需要表扫描。
在引用表中,必须有一个索引,其中外键列
以相同的顺序
列为
第一
列。
如果引用表不存在,则会自动在引用表上创建此索引。
如果您创建另一个可用于强制执行外键约束的索引,则可以稍后以静默方式删除此索引。
index_name
如果给出,则如前所述使用。
InnoDB
允许外键引用任何索引列或列组。
但是,在引用的表中,必须有一个索引,其中引用的列是
同一顺序
中的
第一
列。
InnoDB
还会考虑添加到索引的
隐藏列
(请参见
第15.6.2.1节“聚簇和二级索引”
)。
NDB
要求在作为外键引用的任何列上使用显式唯一键(或主键)。
不支持外键列上的索引前缀。
这样做的一个结果是,
BLOB
并且
TEXT
列不能包含在外键中,因为这些列上的索引必须始终包含前缀长度。
如果
给出了
该
子句,则该
值(如果使用)在数据库中必须是唯一的。
重复
将导致类似于以下的
错误
:
ERROR 1022(2300):无法写入;
表'#sql-464_1'中的重复键
。
如果未给出该子句,或者
关键字
后面没有包含
a
,则MySQL使用外键索引名称直到MySQL 8.0.15,并在此后自动生成约束名称。
CONSTRAINT
symbol
symbol
symbol
symbol
CONSTRAINT
InnoDB
当前不支持具有用户定义分区的表的外键。
这包括父表和子表。
此限制不适用于
NDB
由
(
KEY
或
存储引擎
LINEAR KEY
支持的唯一用户分区类型)
分区的表
NDB
;
这些可能具有外键引用或是这些引用的目标。
对于
NDB
表,
ON
UPDATE CASCADE
不支持引用父表的主键的位置。
FOREIGN KEY
本节中的以下主题描述
了
约束使用的
其他方面
:
本节介绍外键如何帮助保证 参照完整性 。
对于支持外键的存储引擎,
如果父表中没有匹配的候选
键值,则MySQL拒绝任何
尝试在子表中创建外键值的操作
INSERT
或
UPDATE
操作。
当
UPDATE
或
DELETE
操作影响父表中具有子表中匹配行的键值时,结果取决于
使用
子句
和
子
句子
指定
的
引用操作
。
MySQL支持关于要采取的操作的五个选项,如下所示:
ON UPDATE
ON DELETE
FOREIGN KEY
CASCADE
:从父表中删除或更新行,并自动删除或更新子表中的匹配行。
这两个
ON DELETE
CASCADE
和
ON UPDATE CASCADE
支持。
在两个表之间,不要定义多个
ON UPDATE CASCADE
子句,
这些
子句作用于父表或子表中的同一列。
如果
FOREIGN KEY
在外键关系中的两个表上
定义了一个
子句
,使两个表都成为父和子,则
必须
为另一个
子句
定义为一个
子句
定义的
子句
ON UPDATE
CASCADE
或
子句,以便级联操作成功。
如果
仅为一个
子句
定义了一个
或
子
子句,则级联操作将失败并显示错误。
ON DELETE CASCADE
FOREIGN KEY
ON UPDATE
CASCADE
ON DELETE CASCADE
FOREIGN
KEY
级联外键操作不会激活触发器。
SET NULL
:从父表中删除或更新行,并将子表中的外键列设置为
NULL
。
支持
两个
ON DELETE SET NULL
和
ON
UPDATE SET NULL
子句。
如果指定
SET NULL
操作,请
确保未将子表中的列声明为
NOT
NULL
。
RESTRICT
:拒绝父表的删除或更新操作。
指定
RESTRICT
(或
NO
ACTION
)与省略
ON
DELETE
or
ON UPDATE
子句
相同
。
NO ACTION
:标准SQL中的关键字。
在MySQL中,相当于
RESTRICT
。
如果引用的表中存在相关的外键值,则MySQL服务器拒绝父表的删除或更新操作。
某些数据库系统具有延迟检查,并且
NO ACTION
是延迟检查。
在MySQL中,立即检查外键约束,因此
NO ACTION
也是
如此
RESTRICT
。
SET DEFAULT
:这个动作由MySQL解析器认可,但两者
InnoDB
并
NDB
拒绝包含表定义
ON DELETE SET DEFAULT
或
ON UPDATE SET DEFAULT
条款。
对于
未指定
的
ON DELETE
或未
ON
UPDATE
指定的,默认操作始终为
RESTRICT
。
MySQL支持表中一列与另一列之间的外键引用。 (列不能有自己的外键引用。)在这些情况下, “ 子表记录 ” 实际上是指同一个表中的依赖记录。
在存储生成列外键约束不能使用
CASCADE
,
SET NULL
或
SET DEFAULT
作为
ON
UPDATE
参照动作,也不能使用
SET NULL
或
SET DEFAULT
作为
ON DELETE
参照动作。
在存储生成列的基本列外键约束不能使用
CASCADE
,
SET NULL
或
SET DEFAULT
作为
ON UPDATE
或
ON
DELETE
引用操作。
外键约束不能引用虚拟生成的列。
有关
InnoDB
外键和生成列的限制,请参见
第15.6.1.5节“InnoDB和FOREIGN KEY约束”
。
这是一个
通过单列外键
关联
parent
和
child
表
的简单示例
:
CREATE TABLE父级( id INT NOT NULL, PRIMARY KEY(id) )ENGINE = INNODB; CREATE TABLE子( id INT, parent_id INT, INDEX par_ind(parent_id), FOREIGN KEY(parent_id) REFERENCES parent(id) ON DELETE CASCADE )ENGINE = INNODB;
一个更复杂的示例,其中
product_order
表具有两个其他表的外键。
一个外键引用表中的两列索引
product
。
另一个引用表中的单列索引
customer
:
CREATE TABLE产品( category INT NOT NULL,id INT NOT NULL, 价格DECIMAL, PRIMARY KEY(类别,id) )ENGINE = INNODB; CREATE TABLE客户( id INT NOT NULL, PRIMARY KEY(id) )ENGINE = INNODB; CREATE TABLE product_order( 没有INT NOT NULL AUTO_INCREMENT, product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, PRIMARY KEY(不), INDEX(product_category,product_id), INDEX(customer_id), FOREIGN KEY(product_category,product_id) REFERENCES产品(类别,ID) 在DELETE RESTRICT上更新级联, FOREIGN KEY(customer_id) 参考客户(id) )ENGINE = INNODB;
您可以使用添加新的外键约束到现有表
ALTER
TABLE
。
此语句显示与此语句的外键相关的语法:
ALTER TABLEtbl_name
ADD [CONSTRAINT [symbol
]] FOREIGN KEY [index_name
](col_name
,...) 参考文献tbl_name
(col_name
,...) [ON DELETEreference_option
] [ON UPDATEreference_option
]
外键可以是自引用的(参考同一个表)。
使用时向表中添加外键约束时
ALTER
TABLE
,
请记住首先创建所需的索引。
您还可以使用
ALTER
TABLE
此处显示的语法来删除外键:
ALTER TABLEtbl_name
DROP FOREIGN KEYfk_symbol
;
如果
FOREIGN KEY
子句
CONSTRAINT
在创建外键时
包含
名称,则可以引用该名称以删除外键。
否则,在
fk_symbol
创建外键时在内部生成
该
值。
要在删除外键时找出符号值,请使用
SHOW CREATE TABLE
语句,如下所示:
MySQL的>SHOW CREATE TABLE ibtest11c\G
*************************** 1。排******************** ******* 表:ibtest11c 创建表:CREATE TABLE`ibtest11c`( `A`int(11)NOT NULL auto_increment, `D` int(11)NOT NULL默认'0', `B` varchar(200)NOT NULL default'', `C` varchar(175)默认为NULL, PRIMARY KEY(`A`,`D`,`B`), KEY`B`(`B`,`C`), KEY`C`(`C`), CONSTRAINT`0_38775` FOREIGN KEY(`A`,`D`) 参考文献`ibtest11a`(`A`,`D`) 在更新级联上删除级联, CONSTRAINT`0_38776` FOREIGN KEY(`B`,`C`) 参考文献`ibtest11a`(`B`,`C`) ON UPATE CASCADE ON UPDATE CASCADE )ENGINE = INNODB CHARSET = utf8mb4 1排(0.01秒) MySQL的>ALTER TABLE ibtest11c DROP FOREIGN KEY `0_38775`;
ALTER TABLE
支持
在同一
语句中
添加和删除外键
ALTER
TABLE ...
ALGORITHM=INPLACE
但不支持
ALTER
TABLE ...
ALGORITHM=COPY
。
FOREIGN KEY ...
REFERENCES ...
子句中的
表和列标识符
可以在反引号(
`
)中
引用
。
或者,
"
如果
ANSI_QUOTES
启用
了
SQL模式,则
可以使用
双引号(
)
。
lower_case_table_names
还考虑
了
系统变量
的设置
。
您可以查看子表的外键定义作为
SHOW CREATE
TABLE
语句
输出的一部分
:
SHOW CREATE TABLE tbl_name
;
您还可以通过查询
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
表
获取有关外键的信息
。
您可以
在
数据库中
找到有关
InnoDB
表
INNODB_FOREIGN
和
INNODB_FOREIGN_COLS
表中
使用的外键
的
INFORMATION_SCHEMA
信息。
mysqldump 在转储文件中生成正确的表定义,包括子表的外键。
为了更容易为具有外键关系的表重新加载转储文件,
mysqldump会
自动在转储输出中包含一个语句,设置
foreign_key_checks
为0.这样可以避免在重新加载转储时必须按特定顺序重新加载表的问题。
也可以手动设置此变量:
mysql>SET foreign_key_checks = 0;
mysql> mysql>SOURCE
dump_file_name
;SET foreign_key_checks = 1;
这使您可以按任何顺序导入表,如果转储文件包含未正确为外键订购的表。
它还加快了进口操作。
设置
foreign_key_checks
为0,也可以是在忽略外键约束有用
LOAD
DATA
和
ALTER
TABLE
操作。
但是,即使
foreign_key_checks
=
0
MySQL不允许创建外键约束,其中列引用不匹配的列类型。
此外,如果表具有外键约束,
ALTER
TABLE
则不能用于更改表以使用其他存储引擎。
要更改存储引擎,必须先删除任何外键约束。
除非您这样做,否则不能
DROP
TABLE
为
FOREIGN KEY
约束
引用的表
发出
SET foreign_key_checks =
0
。
删除表时,也会删除用于创建该表的语句中定义的任何约束。
如果重新创建已删除的表,则它必须具有符合引用它的外键约束的定义。
它必须具有正确的列名和类型,并且必须在引用的键上具有索引,如前所述。
如果不满足这些,MySQL将返回错误1005并在错误消息中引用错误150,这意味着未正确形成外键约束。
类似地,如果
ALTER
TABLE
由于错误150而失败,则意味着对于更改的表将错误地形成外键定义。
对于
InnoDB
表,您可以
InnoDB
通过检查输出来获得MySQL服务器中
最新
外键错误
的详细说明
SHOW
ENGINE
INNODB STATUS
。
MySQL根据需要将元数据锁扩展到由外键约束相关的表。 扩展元数据锁可防止冲突的DML和DDL操作在相关表上并发执行。 此功能还允许在修改父表时更新外键元数据。 在早期的MySQL版本中,子表所拥有的外键元数据无法安全更新。
如果显式锁定
LOCK
TABLES
表,则会打开并隐式锁定由外键约束关联的任何表。
对于外键检查,
LOCK TABLES
READ
对相关表
执行共享只读锁(
)。
对于级联更新,
LOCK TABLES
WRITE
对操作中涉及的相关表
采用无共享写锁(
)。
对于熟悉ANSI / ISO SQL标准的用户,请注意,没有存储引擎,包括
InnoDB
,识别或强制执行
MATCH
参照完整性约束定义中使用
的
子句。
使用explicit
MATCH
子句不会产生指定的效果,也会
忽略
cause
ON DELETE
和
ON UPDATE
子句。
出于这些原因,
MATCH
应该避免
指定
。
MATCH
SQL标准中
的
子句控制
NULL
在与主键进行比较时如何处理复合(多列)外键中的值。
MySQL本质上实现了定义的语义
MATCH SIMPLE
,允许外键全部或部分
NULL
。
在这种情况下,允许插入包含此类外键的(子表)行,并且与引用的(父)表中的任何行都不匹配。
可以使用触发器实现其他语义。
此外,由于性能原因,MySQL要求对引用的列进行索引。
然而,该系统并不强制所引用的列是一个要求
UNIQUE
或声明
NOT
NULL
。
对包含
NULL
值的
非唯一键或键的外键引用的处理
没有为诸如
UPDATE
或之类的
操作定义
DELETE
CASCADE
。
建议您使用仅引用
UNIQUE
(包括
PRIMARY
)和
NOT NULL
键的外键。
此外,MySQL解析但忽略了
“
内联
REFERENCES
规范
”
(如SQL标准中所定义),其中引用被定义为列规范的一部分。
MySQL
REFERENCES
仅在指定为单独
FOREIGN KEY
规范的
一部分时才
接受
子句
。
对于不支持外键(例如
MyISAM
)的
存储引擎
,MySQL Server会解析并忽略外键规范。
该
INFORMATION_SCHEMA.KEY_COLUMN_USAGE
表标识了具有约束的键列。
InnoDB
在
INNODB_SYS_FOREIGN
和
INNODB_SYS_FOREIGN_COLS
表中
可以找到
特定于
外键的
元数据
。
如果涉及
InnoDB
表
的外键错误
(通常是MySQL服务器中的错误150),
InnoDB
可以通过检查
SHOW
ENGINE INNODB STATUS
输出
获得
有关最新
外键错误的
信息
。
如果用户拥有所有父表的表级的特权,
ER_NO_REFERENCED_ROW_2
并
ER_ROW_IS_REFERENCED_2
为外键操作错误信息公开有关父表的信息。
如果用户没有所有父表的表级权限,则会显示更多通用错误消息(
ER_NO_REFERENCED_ROW
和
ER_ROW_IS_REFERENCED
)。
例外情况是,对于定义为使用
DEFINER
特权
执行的存储程序
,评估特权的用户是程序
DEFINER
子句中
的用户
,而不是调用用户。
如果该用户具有表级父表权限,则仍会显示父表信息。
在这种情况下,存储的程序创建者有责任通过包括适当的条件处理程序来隐藏信息。
在MySQL 8.0.16之前,
CREATE
TABLE
只允许以下限制版本的表
CHECK
约束语法,该语法被解析并被忽略:
检查(expr
)
从MySQL 8.0.16开始,
CREATE
TABLE
允许
CHECK
所有存储引擎
的表和列
约束
的核心功能
。
对于表约束和列约束,
CREATE
TABLE
允许以下
CHECK
约束语法:
[CONSTRAINT [symbol
]] CHECK(expr
)[[NOT] ENFORCED]
optional
symbol
指定约束的名称。
如果省略,MySQL将根据表名,文字
_chk_
和序号(1,2,3,...)生成名称。
约束名称的最大长度为64个字符。
它们区分大小写,但不区分重音。
expr
将约束条件指定为布尔表达式,该表达式必须
为表的每一行
计算
TRUE
或
UNKNOWN
(对于
NULL
值)。
如果条件求值为
FALSE
,则失败并发生约束违规。
违规的影响取决于正在执行的语句,如本节后面所述。
可选的强制子句指示是否强制执行约束:
如果省略或指定为
ENFORCED
,则创建并强制执行约束。
如果指定为
NOT ENFORCED
,则创建约束但不强制执行。
甲
CHECK
约束被指定为任一表约束或列约束:
表约束不会出现在列定义中,并且可以引用任何表列或列。 允许前向引用到表定义中稍后出现的列。
列约束出现在列定义中,并且只能引用该列。
考虑这个表定义:
CREATE TABLE t1 ( 检查(c1 <> c2), c1 INT CHECK(c1> 10), c2 INT CONSTRAINT c2_positive CHECK(c2> 0), c3 INT CHECK(c3 <100), CONSTRAINT c1_nonzero CHECK(c1 <> 0), 检查(c1> c3) );
该定义包括命名和未命名格式的表约束和列约束:
第一个约束是表约束:它发生在任何列定义之外,因此它可以(并且确实)引用多个表列。 此约束包含对尚未定义的列的前向引用。 没有指定约束名称,因此MySQL生成一个名称。
接下来的三个约束是列约束:每个约束都出现在列定义中,因此只能引用要定义的列。 其中一个约束是明确命名的。 MySQL为其他两个中的每一个生成一个名称。
最后两个约束是表约束。 其中一个是明确命名的。 MySQL为另一个生成一个名称。
如上所述,MySQL为没有
CHECK
指定的
任何
约束
生成一个名称
。
要查看为上一个表定义生成的名称,请使用
SHOW CREATE TABLE
:
MySQL的> SHOW CREATE TABLE t1\G
*************************** 1。排******************** *******
表:t1
创建表:CREATE TABLE`t1`(
`c1` int(11)DEFAULT NULL,
`c2` int(11)DEFAULT NULL,
`c3` int(11)DEFAULT NULL,
CONSTRAINT`c1_nonzero` CHECK((``c1` <> 0)),
CONSTRAINT`c2_positive`检查((``c2`> 0)),
约束`t1_chk_1`检查((``c1` <>`c2`)),
约束`t1_chk_2`检查((``c1`> 10)),
CONSTRAINT`t1_chk_3`检查((``c3` <100)),
CONSTRAINT`t1_chk_4`检查((``c1`>`c3`))
)ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci
SQL标准指定所有类型的约束(主键,唯一索引,外键,检查)属于同一名称空间。
在MySQL中,每个约束类型每个模式(数据库)都有自己的命名空间。
因此,
CHECK
每个模式的约束名称必须是唯一的;
同一模式中没有两个表可以共享
CHECK
约束名称。
(例外:
TEMPORARY
表隐藏了一个
TEMPORARY
同名
的非
表,因此它也可以具有相同的
CHECK
约束名。)
使用表名开始生成约束名称有助于确保模式唯一性,因为表名在模式中也必须是唯一的。
CHECK
条件表达式必须遵守以下规则。
如果表达式包含不允许的构造,则会发生错误。
允许使用非生成和生成的列,但具有
AUTO_INCREMENT
其他表中
的
属性和列的列
除外
。
允许使用文字,确定性内置函数和运算符。
如果给定表中的相同数据,则多个调用产生相同的结果,而不是连接的用户,则函数是确定性的。
:那是不确定性和失败,这个定义功能的例子
CONNECTION_ID()
,
CURRENT_USER()
,
NOW()
。
不允许存储函数和用户定义的函数。
不允许存储过程和函数参数。
不允许使用变量(系统变量,用户定义的变量和存储的程序局部变量)。
不允许子查询。
对
约束中
使用的列禁止
外键引用操作(
ON UPDATE
,
ON DELETE
)
CHECK
。
同样,
CHECK
对外键引用操作中使用的列禁止约束。
CHECK
约束评估
INSERT
,
UPDATE
,
REPLACE
,
LOAD
DATA
,和
LOAD
XML
语句并且如果约束评估为发生错误
FALSE
。
如果发生错误,则已应用的更改的处理因事务和非事务存储引擎而异,并且还取决于严格的SQL模式是否有效,如
严格SQL模式中所述
。
CHECK
约束评估
INSERT
IGNORE
,
UPDATE
IGNORE
,
LOAD
DATA ...
IGNORE
,和
LOAD
XML ...
IGNORE
语句,如果一个约束评估为出现警告
FALSE
。
将跳过任何违规行的插入或更新。
如果约束表达式求值为与声明的列类型不同的数据类型,则根据通常的MySQL类型转换规则对声明的类型进行隐式强制。 请参见 第12.2节“表达式评估中的类型转换” 。 如果类型转换失败或导致精度损失,则会发生错误。
约束表达式评估使用在评估时生效的SQL模式。 如果表达式的任何组件依赖于SQL模式,则表的不同用法可能会出现不同的结果,除非在所有使用过程中SQL模式都相同。
在某些情况下,MySQL会默认地更改列规范
CREATE
TABLE
或在
ALTER
TABLE
语句中
给出的规范
。
这些可能是对数据类型,与数据类型关联的属性或索引规范的更改。
所有更改都受内部行大小限制65,535字节的限制,这可能会导致某些数据类型更改尝试失败。 请参见 第C.10.4节“表列数和行大小的限制” 。
列,其一部分
PRIMARY KEY
是由
NOT NULL
即使没有声明的方式。
MySQL将其他SQL数据库供应商使用的某些数据类型映射到MySQL类型。 请参见 第11.10节“使用其他数据库引擎中的数据类型” 。
如果包含一个
USING
子句来指定给定存储引擎不允许的索引类型,但引擎可以使用另一种可用的索引类型而不影响查询结果,则引擎使用可用类型。
如果未启用严格SQL模式,则会
VARCHAR
将长度指定大于65535
TEXT
的
VARBINARY
列
转换为
,并将
长度指定大于65535
的
列转换为
BLOB
。
否则,在这两种情况下都会发生错误。
指定
CHARACTER SET binary
字符数据类型
的
属性会导致将列创建为相应的二进制数据类型:
CHAR
变为
BINARY
,
VARCHAR
变为
VARBINARY
和
TEXT
变为
BLOB
。
对于
ENUM
和
SET
数据类型,不会发生这种情况;
它们是按声明创建的。
假设您使用此定义指定表:
创建表t ( c1 VARCHAR(10)CHARACTER SET二进制, c2 TEXT CHARACTER SET二进制, c3 ENUM('a','b','c')CHARACTER SET二进制 );
结果表具有以下定义:
创建表t ( c1 VARBINARY(10), c2 BLOB, c3 ENUM('a','b','c')CHARACTER SET二进制 );
要查看MySQL是否使用了您指定的数据类型以外的数据类型,请
在创建或更改表后
发出
DESCRIBE
或
SHOW CREATE TABLE
声明。
如果使用 myisampack 压缩表, 则 可能会发生某些其他数据类型更改 。 请参见 第16.2.3.3节“压缩表特性” 。
CREATE
TABLE
支持生成列的规范。
生成列的值是根据列定义中包含的表达式计算的。
NDB
存储引擎
也支持生成的列
。
下面的简单示例显示了一个表,该表存储了
sidea
和
三角形中
sideb
的直角三角形的长度,并计算了斜边的长度
sidec
(其他边的平方和的平方根):
CREATE TABLE三角形( sidea DOUBLE, sideb DOUBLE, sidec DOUBLE AS(SQRT(sidea * sidea + sideb * sideb)) ); 插入三角形(sidea,sideb)VALUES(1,1),(3,4),(6,8);
从表中选择会产生以下结果:
MySQL的> SELECT * FROM triangle;
+ ------- ------- + + -------------------- +
| sidea | sideb | sidec |
+ ------- ------- + + -------------------- +
| 1 | 1 | 1.4142135623730951 |
| 3 | 4 | 5 |
| 6 | 8 | 10 |
+ ------- ------- + + -------------------- +
使用该
triangle
表的
任何应用程序
都可以访问斜边值,而无需指定计算它们的表达式。
生成的列定义具有以下语法:
col_name
data_type
[GENERATED ALWAYS] AS(expr
) [VIRTUAL | 存储] [NOT NULL | 空值] [UNIQUE [KEY]] [[PRIMARY] KEY] [评论'string
']
AS (
表示生成列并定义用于计算列值的表达式。
expr
)AS
之前
GENERATED ALWAYS
可以使列的生成性质更明确。
表达式中允许或禁止的构造将在后面讨论。
的
VIRTUAL
或
STORED
关键字表示列的值的存储方式,其具有用于使用列含义:
VIRTUAL
:不存储列值,但在任何
BEFORE
触发器
之后立即读取行时计算列值
。
虚拟列不占用存储空间。
InnoDB
支持虚拟列上的二级索引。
请参见
第13.1.20.10节“二级索引和生成的列”
。
STORED
:插入或更新行时,将评估和存储列值。
存储的列确实需要存储空间并且可以编制索引。
VIRTUAL
如果两个关键字都未指定,则
默认为
。
允许
在表格中
混合
VIRTUAL
和
STORED
列。
可以给出其他属性以指示列是否被索引或可以是
NULL
,或者提供评论。
生成的列表达式必须遵守以下规则。 如果表达式包含不允许的构造,则会发生错误。
允许使用文字,确定性内置函数和运算符。
如果给定表中的相同数据,则多个调用产生相同的结果,而不是连接的用户,则函数是确定性的。
:那是不确定性和失败,这个定义功能的例子
CONNECTION_ID()
,
CURRENT_USER()
,
NOW()
。
不允许存储函数和用户定义的函数。
不允许存储过程和函数参数。
不允许使用变量(系统变量,用户定义的变量和存储的程序局部变量)。
不允许子查询。
生成的列定义可以引用其他生成的列,但只能引用表定义中较早出现的列。 生成的列定义可以引用表中的任何基本(非生成)列,无论其定义是早期还是稍后发生。
该
AUTO_INCREMENT
属性不能用于生成的列定义。
一个
AUTO_INCREMENT
列不能用作在生成的列定义的基柱。
如果表达式求值导致截断或向函数提供不正确的输入,则
CREATE TABLE
语句将终止并显示错误,并拒绝DDL操作。
如果表达式求值为与声明的列类型不同的数据类型,则根据通常的MySQL类型转换规则对声明的类型进行隐式强制。 请参见 第12.2节“表达式评估中的类型转换” 。
表达式评估使用SQL模式在评估时生效。 如果表达式的任何组件依赖于SQL模式,则表的不同用法可能会出现不同的结果,除非在所有使用过程中SQL模式都相同。
对于
CREATE
TABLE ... LIKE
,目标表保留原始表中生成的列信息。
对于
CREATE
TABLE ... SELECT
,目标表不保留有关selected-from表中的列是否为生成列的信息。
SELECT
语句
的
一部分无法为目标表中的生成列分配值。
允许按生成的列进行分区。 请参阅 表分区 。
在存储生成列外键约束不能使用
CASCADE
,
SET NULL
或
SET DEFAULT
作为
ON UPDATE
参照动作,也不能使用
SET NULL
或
SET DEFAULT
作为
ON
DELETE
参照动作。
在存储生成列的基本列外键约束不能使用
CASCADE
,
SET NULL
或
SET DEFAULT
作为
ON UPDATE
或
ON DELETE
引用操作。
外键约束不能引用虚拟生成的列。
有关
InnoDB
外键和生成列的限制,请参见
第15.6.1.5节“InnoDB和FOREIGN KEY约束”
。
触发器不能用于
或用于
引用生成的列。
NEW.
col_name
OLD.
col_name
对于
INSERT
,,
REPLACE
和
UPDATE
,如果生成的列明确插入,替换或更新,则唯一允许的值为
DEFAULT
。
视图中生成的列被视为可更新,因为可以为其分配。
但是,如果明确更新此类列,则唯一允许的值为
DEFAULT
。
生成的列有几个用例,例如:
虚拟生成的列可用作简化和统一查询的方法。 可以将复杂条件定义为生成列,并从表上的多个查询引用,以确保它们全部使用完全相同的条件。
存储生成的列可以用作物化缓存,用于复杂的条件,这些条件在运行中计算成本很高。
生成的列可以模拟功能索引:使用生成的列定义功能表达式并对其进行索引。
这对于处理无法直接索引的类型列(例如
JSON
列)
非常有用
;
有关详细示例,
请参阅
索引生成的列以提供JSON列索引
。
对于存储的生成列,这种方法的缺点是值存储两次; 一次作为生成列的值,一次作为索引。
如果生成的列已建立索引,则优化程序将识别与列定义匹配的查询表达式,并在查询执行期间根据需要使用列中的索引,即使查询未按名称直接引用该列也是如此。 有关详细信息,请参见 第8.3.11节“生成列索引的优化程序使用” 。
例:
假设一个表
t1
包含
first_name
和
last_name
列,并且该应用程序经常使用如下表达式构造全名:
SELECT CONCAT(first_name,'',last_name)AS full_name FROM t1;
避免编写出表达的一种方法是创建一个视图
v1
上
t1
,其通过使它们简化的应用程序来选择
full_name
的情况下直接使用的表达式:
创建视图v1 AS SELECT *,CONCAT(first_name,'',last_name)AS full_name FROM t1; SELECT full_name FROM v1;
生成的列还使应用程序可以
full_name
直接
选择
,而无需定义视图:
CREATE TABLE t1( first_name VARCHAR(10), last_name VARCHAR(10), full_name VARCHAR(255)AS(CONCAT(first_name,'',last_name)) ); SELECT full_name FROM t1;
InnoDB
支持虚拟生成列上的二级索引。
不支持其他索引类型。
在虚拟列上定义的辅助索引有时被称为
“
虚拟索引
”
。
可以在一个或多个虚拟列上或在虚拟列和常规列或存储的生成列的组合上创建二级索引。
包含虚拟列的二级索引可以定义为
UNIQUE
。
在虚拟生成列上创建辅助索引时,生成的列值将在索引的记录中实现。 如果索引是 覆盖索引 (包括查询检索的所有列的 索引 ),则从索引结构中的具体化值中检索生成的列值,而不是 “ 在运行中 ” 计算 。
有额外的费用写入使用辅助索引时,在虚拟列,由于在计算过程中物化辅助索引记录虚拟列值时,进行考虑
INSERT
和
UPDATE
操作。
即使有额外的写入成本,虚拟列上的二级索引可能优于生成的
存储
列,这些列在聚簇索引中具体化,从而导致需要更多磁盘空间和内存的更大表。
如果未在虚拟列上定义辅助索引,则会有额外的读取成本,因为每次检查列的行时都必须计算虚拟列值。
索引虚拟列的值是MVCC记录的,以避免在回滚期间或清除操作期间对生成的列值进行不必要的重新计算。
记录的值的数据长度是由767个字节的索引关键字限制的限制
COMPACT
和
REDUNDANT
排格式,并为3072个字节
DYNAMIC
和
COMPRESSED
列格式。
在虚拟列上添加或删除辅助索引是就地操作。
如其他地方所述,
JSON
列不能直接索引。
要创建间接引用此类列的索引,可以定义生成的列以提取应编制索引的信息,然后在生成的列上创建索引,如以下示例所示:
mysql>CREATE TABLE jemp (
- >c JSON,
- >g INT GENERATED ALWAYS AS (c->"$.id")),
- >INDEX i (g)
- >);
查询OK,0行受影响(0.28秒) MySQL的>INSERT INTO jemp (c) VALUES
>('{"id": "1", "name": "Fred"}'), ('{"id": "2", "name": "Wilma"}'),
>('{"id": "3", "name": "Barney"}'), ('{"id": "4", "name": "Betty"}');
查询OK,4行受影响(0.04秒) 记录:4个重复:0警告:0 mysqlSELECT c->>"$.name" AS name
>>FROM jemp WHERE g > 2;
+ -------- + | 名字| + -------- + | 巴尼| | 贝蒂| + -------- + 2行(0.00秒) mysqlEXPLAIN SELECT c->>"$.name" AS name
>>FROM jemp WHERE g > 2\G
*************************** 1。排******************** ******* id:1 select_type:SIMPLE 桌子:jemp 分区:NULL 类型:范围 possible_keys:i 关键:我 key_len:5 ref:NULL 行:2 过滤:100.00 额外:使用在哪里 1排,1警告(0.00秒) MySQL的>SHOW WARNINGS\G
*************************** 1。排******************** ******* 等级:注意 代码:1003 消息:/ * select#1 * / select json_unquote(json_extract(`test` .jemp``c`,'$。name')) AS`name`来自`test` .jemp` where(`test` .jemp``g`> 2) 1排(0.00秒)
(我们已经包装了此示例中最后一个语句的输出以适合查看区域。)
当您
EXPLAIN
在
SELECT
包含一个或多个使用
->
or
->>
运算符的
表达式的其他SQL语句上使用时
,这些表达式将使用
JSON_EXTRACT()
和(如果需要)
转换为其等效项
JSON_UNQUOTE()
,如此处
SHOW
WARNINGS
紧接此
EXPLAIN
语句
后面
的输出中所示
:
mysqlEXPLAIN SELECT c->>"$.name"
>>FROM jemp WHERE g > 2 ORDER BY c->"$.name"\G
*************************** 1。排******************** ******* id:1 select_type:SIMPLE 桌子:jemp 分区:NULL 类型:范围 possible_keys:i 关键:我 key_len:5 ref:NULL 行:2 过滤:100.00 额外:使用在哪里; 使用filesort 1排,1警告(0.00秒) MySQL的>SHOW WARNINGS\G
*************************** 1。排******************** ******* 等级:注意 代码:1003 消息:/ * select#1 * / select json_unquote(json_extract(`test` .jemp``c`,'$。name'))AS `c - >>“$。name”`来自`test` .jemp` where(`test` .jemp``g`> 2)order by json_extract(`test`.`jemp`.`c`, '$。名称') 1排(0.00秒)
有关
其他信息和示例,
请参阅
->
和
->>
运算符
的说明
JSON_EXTRACT()
以及
JSON_UNQUOTE()
函数
和
函数的说明。
此技术还可用于提供间接引用无法直接索引的其他类型列的索引,例如
GEOMETRY
列。
根据以下条件,还可以在MySQL NDB Cluster中使用JSON列的间接索引:
CREATE TABLE
用于创建
jempn
此处所示
表格
的
语句
是
jemp
前面显示
的
表格的
一个版本
,其修改使其与
NDB
以下
内容兼容
:
CREATE TABLE jempn( a BIGINT(20)NOT NULL AUTO_INCREMENT PRIMARY KEY, c JSON DEFAULT NULL, g INT GENERATED ALWAYS AS(c - >“$。name”)STORED, INDEX i(g) )ENGINE = NDB;
我们可以使用以下
INSERT
语句
填充此表
:
插入jempn(a,c)VALUES (NULL,'{“id”:“1”,“name”:“Fred”}'), (NULL,'{“id”:“2”,“name”:“Wilma”}'), (NULL,'{“id”:“3”,“name”:“Barney”}'), (NULL,'{“id”:“4”,“name”:“Betty”}');
现在
NDB
可以使用索引
i
,如下所示:
MySQL的>EXPLAIN SELECT c->>"$.name" AS name FROM jempn WHERE g > 2\G
*************************** 1。排******************** ******* id:1 select_type:SIMPLE 桌子:jempn 分区:p0,p1 类型:范围 possible_keys:i 关键:我 key_len:5 ref:NULL 行:3 过滤:100.00 额外:使用推送条件的地方(`test` .jempn``g`> 2) 1排,1警告(0.00秒) MySQL的>SHOW WARNINGS\G
*************************** 1。排******************** ******* 等级:注意 代码:1003 消息:/ *选择#1 * /选择 json_unquote(json_extract(`test` .jempn``c`,'$。name'))AS`name`来自 `test``jempn` where(`test` .jempn``g`> 2) 1排(0.00秒)
您应该记住,存储的生成列使用
DataMemory
,并且此
列
上的索引使用
IndexMemory
。
在MySQL NDB Cluster中,
CREATE
TABLE
或者
ALTER
TABLE
语句中
的表注释
也可以用于指定一个
NDB_TABLE
选项,该选项由一个或多个名称 - 值对组成,如果需要,在字符串后面用逗号分隔
NDB_TABLE=
。
此处显示了名称和值语法的完整语法:
COMMENT =“NDB_TABLE =ndb_table_option
[,ndb_table_option
[,...]]”ndb_table_option
: NOLOGGING = {1 | 0} | READ_BACKUP = {1 | 0} | PARTITION_BALANCE = {FOR_RP_BY_NODE | FOR_RA_BY_NODE | FOR_RP_BY_LDM | FOR_RA_BY_LDM | FOR_RA_BY_LDM_X_2 | FOR_RA_BY_LDM_X_3 | FOR_RA_BY_LDM_X_4} | FULLY_REPLICATED = {1 | 0}
引用的字符串中不允许使用空格。 该字符串不区分大小写。
NDB
可以在这几个段落中更详细地描述以这种方式设置为注释的一部分
的四个
表选项。
NOLOGGING
:使用1对应已
ndb_table_no_logging
启用,但没有实际效果。
作为占位符提供,主要是为了完整的
ALTER
TABLE
陈述。
READ_BACKUP
:将此选项设置为1与
ndb_read_backup
启用时
具有相同的效果
;
可以从任何副本中读取。
您可以
READ_BACKUP
使用
ALTER TABLE
类似于以下所示
的
语句
在线
设置
现有表
:
ALTER TABLE ... ALGORITHM = INPLACE,COMMENT =“NDB_TABLE = READ_BACKUP = 1”; ALTER TABLE ... ALGORITHM = INPLACE,COMMENT =“NDB_TABLE = READ_BACKUP = 0”;
有关该
ALGORITHM
选项的
更多信息
ALTER TABLE
,请参见
第22.5.14节“使用NDB簇中的ALTER TABLE进行联机操作”
。
PARTITION_BALANCE
:提供对分区的分配和放置的额外控制。
支持以下四种方案:
FOR_RP_BY_NODE
:每个节点一个分区。
每个节点上只有一个LDM存储主分区。 每个分区都存储在所有节点上的相同LDM(相同ID)中。
FOR_RA_BY_NODE
:每个节点组一个分区。
每个节点都存储一个分区,可以是主副本,也可以是备份副本。 每个分区都存储在所有节点上的相同LDM中。
FOR_RP_BY_LDM
:每个节点上每个LDM的一个分区;
默认。
这与MySQL NDB Cluster 7.5.2之前的行为相同,除了稍微不同的分区到LDM的映射,从LDM 0开始并为每个节点组放置一个分区,然后转到下一个LDM。
如果
READ_BACKUP
设置为1,则
使用此设置
。
FOR_RA_BY_LDM
:每个节点组中每个LDM一个分区。
这些分区可以是主分区或备份分区。
FOR_RA_BY_LDM_X_2
:每个节点组中每个LDM有两个分区。
这些分区可以是主分区或备份分区。
FOR_RA_BY_LDM_X_3
:每个节点组中每个LDM有三个分区。
这些分区可以是主分区或备份分区。
FOR_RA_BY_LDM_X_4
:每个节点组中每个LDM有四个分区。
这些分区可以是主分区或备份分区。
PARTITION_BALANCE
是用于设置每个表的分区数的首选接口。
MAX_ROWS
不推荐
使用
强制分区数,但继续支持向后兼容;
它将在MySQL NDB Cluster的未来版本中删除。
(Bug#81759,Bug#23544301)
FULLY_REPLICATED
控制表是否完全复制,即每个数据节点是否具有表的完整副本。
要启用表的完全复制,请使用
FULLY_REPLICATED=1
。
也可以使用
ndb_fully_replicated
系统变量
控制此设置
。
将其设置为
ON
默认情况下为所有新
NDB
表
启用该选项
;
默认是
OFF
。
该
ndb_data_node_neighbour
系统变量也可用于完全复制表,以确保当被访问的完全复制表中,我们访问的是本地本MySQL服务器的数据节点。
此处显示了在
CREATE TABLE
创建
NDB
表
时使用此类注释
的
语句
示例
:
的MySQL>CREATE TABLE t1 (
>c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
>c2 VARCHAR(100),
>c3 VARCHAR(100) )
>ENGINE=NDB
>COMMENT="NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RP_BY_NODE";
评论显示为输出的一部分
SHOW CREATE TABLE
。
查询文本也可以从查询MySQL信息模式
TABLES
表中获得,如下例所示:
mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";
+ ------------ + -------------- + --------------------- ------------------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ------------------------------------- + | t1 | c | NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RP_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ------------------------------------- + 2行(0.00秒)
表的
ALTER
TABLE
语句
也支持此注释语法
NDB
。
请记住,使用的表注释
ALTER TABLE
替换了表可能具有的任何现有注释。
MySQL的>ALTER TABLE t1 COMMENT="NDB_TABLE=PARTITION_BALANCE=FOR_RA_BY_NODE";
查询OK,0行受影响(0.40秒) 记录:0重复:0警告:0 mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";
+ ------------ + -------------- + --------------------- ----------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ----------------------------- + | t1 | c | NDB_TABLE = PARTITION_BALANCE = FOR_RA_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ----------------------------- + 2行(0.01秒)
您还
PARTITION_BALANCE
可以在
ndb_desc
的输出中
看到该
选项
的值
。
ndb_desc
还显示是否
为表设置
了
READ_BACKUP
和
FULLY_REPLICATED
选项。
有关更多信息,请参阅此程序的说明。
因为该
READ_BACKUP
值未被转移到
ALTER
TABLE
语句
设置的新注释
,所以不再使用SQL来检索先前为其设置的值。
为防止这种情况发生,建议您保留现有注释字符串中的任何此类值,如下所示:
mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";
+ ------------ + -------------- + --------------------- ------------------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ------------------------------------- + | t1 | c | NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RP_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ------------------------------------- + 2行(0.00秒) MySQL的>ALTER TABLE t1 COMMENT="NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RA_BY_NODE";
查询OK,0行受影响(1.56秒) 记录:0重复:0警告:0 mysqlSELECT TABLE_NAME, TABLE_SCHEMA, TABLE_COMMENT
>>FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="t1";
+ ------------ + -------------- + --------------------- ------------------------------------------- + | TABLE_NAME | TABLE_SCHEMA | TABLE_COMMENT | + ------------ + -------------- + --------------------- ------------------------------------------- + | t1 | c | NDB_TABLE = READ_BACKUP = 0,PARTITION_BALANCE = FOR_RA_BY_NODE | | t1 | d | | + ------------ + -------------- + --------------------- ------------------------------------------- + 2行(0.01秒)
创建[UNDO] TABLESPACEtablespace_name
InnoDB和NDB: [添加数据文件'file_name
'] 仅限InnoDB: [FILE_BLOCK_SIZE =值] [ENCRYPTION [=] {'Y'| 'N'}] 仅限NDB: 使用LOGFILE GROUPlogfile_group
[EXTENT_SIZE [=]extent_size
] [INITIAL_SIZE [=]initial_size
] [AUTOEXTEND_SIZE [=]autoextend_size
] [MAX_SIZE [=]max_size
] [NODEGROUP [=]nodegroup_id
] [等待] [评论[=]'string
'] InnoDB和NDB: [ENGINE [=]engine_name
]
该语句用于创建表空间。
精确的语法和语义取决于所使用的存储引擎。
在标准MySQL版本中,这始终是一个
InnoDB
表空间。
MySQL NDB Cluster还支持使用
NDB
存储引擎的
表空间
。
CREATE TABLESPACE
语法用于创建常规表空间或撤消表空间。
UNDO
必须指定MySQL 8.0.14中引入
的
关键字以创建撤消表空间。
通用表空间是共享表空间。 它可以容纳多个表,并支持所有表行格式。 可以在相对于或独立于数据目录的位置创建常规表空间。
创建
InnoDB
通用表空间后,使用
或
将表添加到表空间。
有关更多信息,请参见
第15.6.3.3节“常规表空间”
。
CREATE
TABLE
tbl_name
... TABLESPACE [=]
tablespace_name
ALTER TABLE
tbl_name
TABLESPACE [=]
tablespace_name
撤消表空间包含撤消日志。 通过指定完全限定的数据文件路径,可以在选定的位置创建撤消表空间。 有关更多信息,请参见 第15.6.3.4节“撤消表空间” 。
此语句用于创建表空间,该表空间可包含一个或多个数据文件,为NDB集群磁盘数据表提供存储空间(请参见
第22.5.13节“NDB集群磁盘数据表”
)。
使用此语句创建一个数据文件并将其添加到表空间。
可以使用该
ALTER TABLESPACE
语句
将其他数据文件添加到表空间
(请参见
第13.1.10节“ALTER TABLESPACE语法”
)。
所有NDB Cluster Disk Data对象共享相同的命名空间。 这意味着 必须唯一地命名 每个磁盘数据对象 (而不仅仅是给定类型的每个磁盘数据对象)。 例如,您不能拥有具有相同名称的表空间和日志文件组,或者具有相同名称的表空间和数据文件。
UNDO
必须将
一个或多个
日志文件
的日志文件组
分配给要使用该
USE LOGFILE GROUP
子句
创建的表空间
。
logfile_group
必须是使用创建的现有日志文件组
CREATE LOGFILE
GROUP
(请参见
第13.1.16节“CREATE LOGFILE GROUP语法”
)。
多个表空间可能使用相同的日志文件组进行
UNDO
日志记录。
设置
EXTENT_SIZE
或时
INITIAL_SIZE
,您可以选择使用一个字母的缩写来表示一个数量级的数字,类似于中使用的那些
my.cnf
。
通常,这是字母之一
M
(兆字节)或
G
(千兆字节)。
INITIAL_SIZE
并按
EXTENT_SIZE
以下方式进行四舍五入:
EXTENT_SIZE
向上舍入到最近的32K的整数倍。
INITIAL_SIZE
向下
舍入
到最近的32K的整数倍;
此结果向上舍入到最接近的整数倍
EXTENT_SIZE
(在任何舍入后)。
刚才描述的舍入是明确完成的,当执行任何这样的舍入时,MySQL服务器会发出警告。
NDB内核还使用舍入值来计算
INFORMATION_SCHEMA.FILES
列值和其他用途。
但是,为避免出现意外结果,我们建议您在指定这些选项时始终使用32K的整数倍。
当
CREATE TABLESPACE
与使用
ENGINE [=] NDB
,表空间和相关联的数据文件的每一个数据群集节点上创建。
您可以通过查询
INFORMATION_SCHEMA.FILES
表
来验证数据文件是否已创建并获取有关它们的信息
。
(请参阅本节后面的示例。)
(参见 第25.11节“INFORMATION_SCHEMA文件表” 。)
ADD DATAFILE
:定义表空间数据文件的名称。
ADD DATAFILE
创建撤消表空间时需要
该
子句。
否则,从MySQL 8.0.14开始它是可选的。
一个
InnoDB
表空间仅支持单个数据文件,其名称必须包括
.ibd
扩展名。
NDB Cluster表空间支持多个数据文件,这些文件可以包含任何合法的文件名;
通过使用
ALTER TABLESPACE
语句
创建NDB Cluster表空间后,可以将更多数据文件添加到NDB Cluster表空间
。
要将常规表空间数据文件放在数据目录之外的位置,请包括完全限定的路径或相对于数据目录的路径。
撤消表空间只允许使用完全限定的路径。
如果未指定路径,则会在数据目录中创建常规表空间。
在未指定路径的情况下创建的撤消表空间将在
innodb_undo_directory
变量
定义的目录中创建
。
如果
innodb_undo_directory
变量未定义,则在数据目录中创建撤消表空间。
不支持在数据目录下的子目录中创建通用表空间,以避免与隐式创建的每表文件表空间冲突。
在数据目录之外创建通用表空间或撤消表空间时,该目录必须存在,并且必须
InnoDB
在创建表空间之前
知道
。
要使目录已知
InnoDB
,请将其添加到
innodb_directories
值或其值附加到
innodb_directories
值
的变量之一
。
innodb_directories
是一个只读变量。
配置它需要重新启动服务器。
的
,包括任何指定的路径,必须是单或双引号引起来。
文件名(不包括文件扩展名)和目录名的长度必须至少为一个字节。
不支持零长度文件名和目录名。
file_name
如果
ADD DATAFILE
在创建表空间时未指定子句,则会隐式创建具有唯一文件名的表空间数据文件。
唯一文件名是128位UUID,格式化为由破折号(
aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
)
分隔的五组十六进制数字
。
如果存储引擎需要,则添加文件扩展名。
一个
.ibd
文件的扩展名被添加为
InnoDB
一般的表空间的数据文件。
在复制环境中,在主服务器上创建的数据文件名与在从服务器上创建的数据文件名不同。
从MySQL 8.0.17开始,该
ADD DATAFILE
子句在创建
InnoDB
表空间
时不允许循环目录引用
。
例如,
/../
不允许以下语句中
的循环目录reference(
):
CREATE TABLESPACE ts1添加DATAFILE ts1.ibd' any_directory
/../ts1.ibd';
Linux上存在此限制的例外情况,如果前面的目录是符号链接,则允许使用循环目录引用。
例如,如果
any_directory
是符号链接
,则允许上述示例中的数据文件路径
。
(仍然允许数据文件路径以'
../
'
开头
。)
FILE_BLOCK_SIZE
:此选项 - 特定于
InnoDB
常规表空间,并由
NDB
-defines表空间数据文件的块大小
忽略
。
值可以以字节或千字节为单位指定。
例如,一个8千字节的文件块大小可以指定为8192或8K。
如果未指定此选项,则
FILE_BLOCK_SIZE
默认为该
innodb_page_size
值。
FILE_BLOCK_SIZE
当您打算使用表空间存储压缩
InnoDB
表(
ROW_FORMAT=COMPRESSED
)
时,是必需的
。
在这种情况下,您必须
FILE_BLOCK_SIZE
在创建表
空间
时
定义表
空间。
如果
FILE_BLOCK_SIZE
是相等的
innodb_page_size
值,则表可以含有具有未压缩的行格式仅表(
COMPACT
,
REDUNDANT
,和
DYNAMIC
)。
具有
COMPRESSED
行格式的
表具有与
未压缩表不同的物理页大小。
因此,压缩表不能与未压缩表共存于同一表空间中。
要使通用表空间包含压缩表,
FILE_BLOCK_SIZE
必须指定该
FILE_BLOCK_SIZE
值
,并且该
值必须是
与该
值相关的有效压缩页大小
innodb_page_size
。
此外,压缩表(
KEY_BLOCK_SIZE
)
的物理页面大小
必须等于
FILE_BLOCK_SIZE/1024
。
例如,如果
innodb_page_size=16K
和
FILE_BLOCK_SIZE=8K
,该
KEY_BLOCK_SIZE
表必须为8欲了解更多信息,请参见
第15.6.3.3,“一般的表空间”
。
USE LOGFILE GROUP
:必需
NDB
,这是以前使用创建的日志文件组的名称
CREATE LOGFILE
GROUP
。
不支持
InnoDB
,失败并出错。
EXTENT_SIZE
:此选项特定于NDB,并且InnoDB不支持该选项,因为它失败并出现错误。
EXTENT_SIZE
设置属于表空间的任何文件使用的范围的大小(以字节为单位)。
默认值为1M。
最小尺寸为32K,理论最大值为2G,但实际最大尺寸取决于许多因素。
在大多数情况下,更改范围大小对性能没有任何可测量的影响,建议除了最不寻常的情况之外的所有情况都使用默认值。
的
程度
是磁盘空间分配的单位。
在使用另一个范围之前,一个范围充满了该范围可以包含的数据。
理论上,每个数据文件最多可使用65,535(64K)个扩展区;
但是,建议的最大值是32,768(32K)。
单个数据文件的建议最大大小为32G,即32K范围×每个范围1 MB。
此外,一旦将范围分配给给定分区,它就不能用于存储来自不同分区的数据;
范围无法存储来自多个分区的数据。
这意味着,例如,具有单个数据文件的表空间
INITIAL_SIZE
(在下面的项目中描述)是256 MB并且其中
EXTENT_SIZE
128M只有两个扩展区,因此可用于存储来自最多两个不同磁盘数据表分区的数据。
您可以通过查询
INFORMATION_SCHEMA.FILES
表
来查看给定数据文件中有多少个扩展区可用
,因此可以估算文件中剩余的空间大小。
有关进一步的讨论和示例,请参见
第25.11节“INFORMATION_SCHEMA文件表”
。
INITIAL_SIZE
:此选项特定于
失败并且出现错误的情况下
NDB
不受支持
InnoDB
。
该
INITIAL_SIZE
参数设置特定使用的数据文件的总大小(以字节为单位)
ADD DATATFILE
。
创建此文件后,其大小无法更改;
但是,您可以使用添加更多数据文件到表空间
ALTER
TABLESPACE ... ADD DATAFILE
。
INITIAL_SIZE
是可选的;
其默认值为134217728(128 MB)。
在32位系统上,支持的最大值为
INITIAL_SIZE
4294967296(4 GB)。
AUTOEXTEND_SIZE
:目前被MySQL忽略;
保留供将来使用。
无论使用何种存储引擎,在MySQL 8.0或MySQL NDB Cluster 8.0的任何版本中都不起作用。
MAX_SIZE
:目前被MySQL忽略;
保留供将来使用。
无论使用何种存储引擎,在MySQL 8.0或MySQL NDB Cluster 8.0的任何版本中都不起作用。
NODEGROUP
:目前被MySQL忽略;
保留供将来使用。
无论使用何种存储引擎,在MySQL 8.0或MySQL NDB Cluster 8.0的任何版本中都不起作用。
WAIT
:目前被MySQL忽略;
保留供将来使用。
无论使用何种存储引擎,在MySQL 8.0或MySQL NDB Cluster 8.0的任何版本中都不起作用。
COMMENT
:目前被MySQL忽略;
保留供将来使用。
无论使用何种存储引擎,在MySQL 8.0或MySQL NDB Cluster 8.0的任何版本中都不起作用。
该
ENCRYPTION
子句启用或禁用
InnoDB
常规表空间的
页级数据加密
。
MySQL 8.0.13中引入了对通用表空间的加密支持。
从MySQL 8.0.16开始,如果
ENCRYPTION
未指定
该
子句,则该
default_table_encryption
设置控制是否启用加密。
该
ENCRYPTION
子句覆盖该
default_table_encryption
设置。
但是,如果
table_encryption_privilege_check
启用
该
变量,
TABLE_ENCRYPTION_ADMIN
则需要使用与
ENCRYPTION
设置不同
的
子句设置
的
权限
default_table_encryption
。
必须先安装和配置密钥环插件,然后才能创建启用加密的表空间。
对通用表空间进行加密时,驻留在表空间中的所有表都将被加密。 同样,在加密表空间中创建的表也是加密的。
有关更多信息,请参见 第15.6.3.9节“InnoDB静态数据加密”
ENGINE
:定义使用表空间的存储引擎,其中
engine_name
是存储引擎的名称。
目前,
InnoDB
标准MySQL 8.0版本
仅
支持存储引擎。
MySQL NDB Cluster支持两者
NDB
和
InnoDB
表空间。
如果未指定选项,则
default_storage_engine
使用系统变量
的值
ENGINE
。
有关MySQL表空间命名的规则,请参见
第9.2节“模式对象名称”
。
除了这些规则之外,
不允许使用
斜杠字符(
“
/
”
),也不能使用以?开头的名称
innodb_
,因为此前缀保留供系统使用。
不支持创建临时通用表空间。
常规表空间不支持临时表。
该
TABLESPACE
选项可以与
表分区或子分区一起
使用
CREATE TABLE
或
ALTER
TABLE
分配给每个
InnoDB
表的文件表空间。
所有分区必须属于同一存储引擎。
InnoDB
不支持
将表分区分配给共享
表空间。
共享表空间包括
InnoDB
系统表空间和通用表空间。
常规表空间支持使用任何行格式添加表
CREATE TABLE ...
TABLESPACE
。
innodb_file_per_table
不需要启用。
innodb_strict_mode
不适用于一般表空间。
表空间管理规则严格执行
innodb_strict_mode
。
如果
CREATE TABLESPACE
参数不正确或不兼容,则无论
innodb_strict_mode
设置
如何,操作都将失败
。
使用
CREATE TABLE ...
TABLESPACE
或
将表添加到常规表空间时
ALTER
TABLE ...
TABLESPACE
,
innodb_strict_mode
将忽略该
表
,
但会将该语句评估为
innodb_strict_mode
启用。
使用
DROP TABLESPACE
删除表空间。
在删除表空间
DROP
TABLE
之前,
必须从表空间
中删除所有表。
在删除NDB Cluster表空间之前,还必须使用一个或多个
ALTER
TABLESPACE ... DROP DATATFILE
语句
删除其所有数据文件
。
请参见
第22.5.13.1节“NDB集群磁盘数据对象”
。
InnoDB
添加到
InnoDB
通用表空间
的
表的
所有部分
都驻留在通用表空间中,包括索引和
BLOB
页面。
对于
NDB
分配给表空间的表,只有那些未编制索引的列存储在磁盘上,并实际使用表空间数据文件。
所有
NDB
表的
索引和索引列
始终保留在内存中。
与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间
.ibd数据文件
内部创建可用空间,该
文件
只能用于新
InnoDB
数据。
空间不会像文件每表表空间一样释放回操作系统。
通用表空间不与任何数据库或模式关联。
ALTER
TABLE ...
DISCARD TABLESPACE
并且
ALTER
TABLE
...IMPORT TABLESPACE
不支持属于常规表空间的表。
服务器对引用常规表空间的DDL使用表空间级元数据锁定。 相比之下,服务器对引用每表文件表空间的DDL使用表级元数据锁定。
生成的或现有的表空间不能更改为常规表空间。
通用表空间名称和每个表文件表空间名称之间没有冲突。 一般表空间名称中不允许 使用 “ / ” 字符,该字符存在于每个表的表空间名称中。
mysqldump
和
mysqlpump
不转储
InnoDB
CREATE TABLESPACE
语句。
此示例演示如何创建常规表空间并添加三个不同行格式的未压缩表。
MySQL的>CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' ENGINE=INNODB;
MySQL的>CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=REDUNDANT;
MySQL的>CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=COMPACT;
MySQL的>CREATE TABLE t3 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=DYNAMIC;
此示例演示如何创建常规表空间并添加压缩表。
该示例假定默认
innodb_page_size
值为16K。
在
FILE_BLOCK_SIZE
8192要求压缩表有
KEY_BLOCK_SIZE
8个。
MySQL的>CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
MySQL的>CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
此示例演示如何创建通用表空间而不指定
ADD DATAFILE
子句,从MySQL 8.0.14开始,该子句是可选的。
MySQL的> CREATE TABLESPACE `ts3` ENGINE=INNODB;
此示例演示如何创建撤消表空间。
MySQL的> CREATE UNDO TABLESPACE undo_003
ADD DATAFILE 'undo_003
.ibu';
假设您希望创建一个
myts
使用
名为
的数据文件命名
的NDB Cluster Disk Data表空间
mydata-1.dat
。
一个
NDB
表空间总是需要使用由一个或多个撤消日志文件,日志文件组。
对于此示例,我们首先
使用
此处显示
的
语句
创建一个名为的日志文件组
mylg
,其中包含一个名为的undo long文件
:
myundo-1.dat
CREATE LOGFILE GROUP
mysql>CREATE LOGFILE GROUP myg1
- >ADD UNDOFILE 'myundo-1.dat'
- >ENGINE=NDB;
查询OK,0行受影响(3.29秒)
现在,您可以使用以下语句创建先前描述的表空间:
mysql>CREATE TABLESPACE myts
- >ADD DATAFILE 'mydata-1.dat'
- >USE LOGFILE GROUP mylg
- >ENGINE=NDB;
查询OK,0行受影响(2.98秒)
您现在可以使用
CREATE
TABLE
带有
TABLESPACE
和
STORAGE DISK
选项
的
语句
创建磁盘数据表
,类似于此处显示的内容:
mysql>CREATE TABLE mytable (
- >id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
- >lname VARCHAR(50) NOT NULL,
- >fname VARCHAR(50) NOT NULL,
- >dob DATE NOT NULL,
- >joined DATE NOT NULL,
- >INDEX(last_name, first_name)
- >)
- >TABLESPACE myts STORAGE DISK
- >ENGINE=NDB;
查询OK,0行受影响(1.41秒)
需要注意的是只有这一点非常重要
dob
和
joined
列从
mytable
实际存储在磁盘上,由于事实
id
,
lname
和
fname
列所有索引。
如前所述,在
CREATE TABLESPACE
使用时
ENGINE [=] NDB
,会在每个NDB Cluster数据节点上创建表空间和关联的数据文件。
您可以通过查询
INFORMATION_SCHEMA.FILES
表
来验证数据文件是否已创建并获取有关它们的信息
,如下所示:
mysql>SELECT FILE_NAME, FILE_TYPE, LOGFILE_GROUP_NAME, STATUS, EXTRA
- >FROM INFORMATION_SCHEMA.FILES
- >WHERE TABLESPACE_NAME = 'myts';
+ -------------- + ------------ + -------------------- + -------- + ---------------- + | file_name | file_type | logfile_group_name | 状态| 额外的| + -------------- + ------------ + -------------------- + -------- + ---------------- + | mydata-1.dat | DATAFILE | mylg | 正常| CLUSTER_NODE = 5 | | mydata-1.dat | DATAFILE | mylg | 正常| CLUSTER_NODE = 6 | | NULL | TABLESPACE | mylg | 正常| NULL | + -------------- + ------------ + -------------------- + -------- + ---------------- + 3行(0.01秒)
有关其他信息和示例,请参见 第22.5.13.1节“NDB集群磁盘数据对象” 。
创建 [DEFINER =user
] TRIGGER ON FOR EACH ROWtrigger_name
trigger_time
trigger_event
tbl_name
[trigger_order
]trigger_body
trigger_time
:{BEFORE | 之后}trigger_event
:{INSERT | 更新| 删除}trigger_order
:{跟进| PRECEDES}other_trigger_name
此语句创建一个新触发器。
触发器是与表关联的命名数据库对象,并在表发生特定事件时激活。
触发器与名为table的表相关联,该表
tbl_name
必须引用永久表。
您无法将触发器与
TEMPORARY
表或视图
相关联
。
模式名称空间中存在触发器名称,这意味着所有触发器必须在模式中具有唯一名称。 不同模式中的触发器可以具有相同的名称。
本节介绍
CREATE
TRIGGER
语法。
有关其他讨论,请参见
第24.3.1节“触发器语法和示例”
。
CREATE
TRIGGER
需要
TRIGGER
与触发器关联的表
的
权限。
如果该
DEFINER
子句存在,则所需的权限取决于
user
值,如
第24.6节“存储对象访问控制”中所述
。
如果启用了二进制日志记录,则
CREATE TRIGGER
可能需要该
SUPER
特权,如
第24.7节“存储程序二进制日志记录”中所述
。
该
DEFINER
子句确定在触发器激活时检查访问权限时要使用的安全上下文,如本节后面所述。
trigger_time
是触发动作时间。
它可以是
BEFORE
或
AFTER
表示触发器在每行要修改之前或之后激活。
基本列值检查在触发器激活之前发生,因此您无法使用
BEFORE
触发器将不适合列类型的值转换为有效值。
trigger_event
表示激活触发器的操作类型。
trigger_event
允许
这些
值:
它
trigger_event
不代表激活触发器的文字类型的SQL语句,因为它表示一种表操作。
例如,
INSERT
触发器不仅激活
INSERT
语句而且
激活
LOAD
DATA
语句,因为两个语句都将行插入表中。
一个可能令人困惑的例子是
INSERT
INTO ... ON DUPLICATE KEY UPDATE ...
语法:
BEFORE INSERT
触发器为每一行激活,后跟
AFTER INSERT
触发器或两者
BEFORE UPDATE
和
AFTER
UPDATE
触发器,具体取决于行是否有重复的键。
级联外键操作不会激活触发器。
可以为具有相同触发事件和操作时间的给定表定义多个触发器。
例如,您可以
BEFORE UPDATE
为表创建
两个
触发器。
默认情况下,具有相同触发事件和操作时间的触发器按创建顺序激活。
要影响触发器顺序,请指定一个
trigger_order
子句,
该
子句指示
FOLLOWS
或者
PRECEDES
具有相同触发事件和操作时间的现有触发器的名称。
使用时
FOLLOWS
,新触发器在现有触发器之后激活。
使用时
PRECEDES
,新触发器在现有触发器之前激活。
trigger_body
是触发器激活时要执行的语句。
要执行多个语句,请使用
BEGIN ... END
复合语句构造。
这也使您可以使用存储例程中允许的相同语句。
请参见
第13.6.1节“BEGIN ... END复合语句语法”
。
触发器中不允许使用某些语句;
请参见
第C.1节“存储程序的限制”
。
在触发器主体中,您可以使用别名
OLD
和
引用主题表(与触发器关联的表)中的列
NEW
。
在更新或删除之前,它指的是现有行的列。
指的是要插入的新行的列或更新后的现有行。
OLD.
col_name
NEW.
col_name
触发器不能用于
或用于
引用生成的列。
有关生成的列的信息,请参见
第13.1.20.9节“创建表和生成的列”
。
NEW.
col_name
OLD.
col_name
MySQL
sql_mode
在创建触发器时
存储有效的
系统变量设置,并始终使用此设置执行触发器主体,
而不管触发器开始执行时当前服务器SQL模式如何
。
该
DEFINER
子句指定在触发器激活时检查访问权限时要使用的MySQL帐户。
如果
DEFINER
子句,该
user
值应被指定为一个MySQL帐户
,
或
。
允许的
值取决于您拥有的权限,如
第24.6节“存储对象访问控制”中所述
。
有关触发器安全性的其他信息,另请参阅该部分。
'
user_name
'@'host_name
'CURRENT_USER
CURRENT_USER()
user
如果
DEFINER
省略
该
子句,则默认定义者是执行该
CREATE
TRIGGER
语句
的用户
。
这与
DEFINER = CURRENT_USER
明确
指定相同
。
DEFINER
在检查触发权限时,
MySQL会将
用户考虑在内,如下所示:
在
CREATE TRIGGER
时间,谁发出语句的用户必须有
TRIGGER
特权。
在触发器激活时,将针对
DEFINER
用户
检查权限
。
该用户必须具有以下权限:
在触发器主体内,该
CURRENT_USER
函数返回用于在触发器激活时检查权限的帐户。
这是
DEFINER
用户,而不是其操作导致触发器被激活的用户。
有关触发器内用户审核的信息,请参见
第6.2.22节“基于SQL的帐户活动审核”
。
如果您使用
LOCK TABLES
锁定具有触发器的表,则触发器中使用的表也会被锁定,如
LOCK TABLES和Triggers中所述
。
有关触发器使用的其他讨论,请参见 第24.3.1节“触发器语法和示例” 。
创建 [或更换] [ALGORITHM = {UNDEFINED | MERGE | 不是Temptable}] [DEFINER =user
] [SQL SECURITY {DEFINER | INVOKER}] 查看view_name
[(column_list
)] 如select_statement
[WITH [CASCADED | 本地]检查选项]
该
CREATE
VIEW
语句创建一个新视图,或者如果
OR
REPLACE
给出
该
子句则
替换现有视图
。
如果视图不存在,
CREATE
OR REPLACE
VIEW
则相同
CREATE
VIEW
。
如果视图确实存在,则
CREATE
OR REPLACE
VIEW
替换它。
有关视图使用限制的信息,请参见 第C.5节“视图限制” 。
这
select_statement
是一个
SELECT
提供视图定义的语句。
(从视图中选择实际上是使用
SELECT
语句
select_statement
选择
。)
可以从基表或其他视图中进行选择。
视图定义
在创建时
“
冻结
”
,不受后续表对基础表定义的更改的影响。
例如,如果视图定义为
SELECT *
在表上,则稍后添加到表中的新列不会成为视图的一部分,从表中删除的列将从视图中进行选择时导致错误。
该
ALGORITHM
子句影响MySQL处理视图的方式。
在
DEFINER
与
SQL SECURITY
子句指定的安全上下文在查看调用时检查访问权限时使用。
该
WITH CHECK OPTION
子句可用于约束对视图引用的表中的行的插入或更新。
这些条款将在本节后面介绍。
该
CREATE
VIEW
语句需要
CREATE VIEW
视图
的
特权,以及该
SELECT
语句
选择的每个列的一些特权
。
对于
SELECT
语句中
其他位置使用的列
,您必须具有该
SELECT
权限。
如果该
OR REPLACE
子句存在,您还必须具有
DROP
该视图
的
权限。
如果该
DEFINER
子句存在,则所需的权限取决于
user
值,如
第24.6节“存储对象访问控制”中所述
。
引用视图时,将执行权限检查,如本节后面所述。
视图属于数据库。
默认情况下,在默认数据库中创建新视图。
要在给定数据库中显式创建视图,请使用
db_name.view_name
语法
使用
数据库名称限定视图名称:
CREATE VIEW test.v AS SELECT * FROM t;
SELECT
语句中的
非限定表或视图名称
也是针对默认数据库进行解释的。
视图可以通过使用适当的数据库名称限定表或视图名称来引用其他数据库中的表或视图。
在数据库中,基表和视图共享相同的命名空间,因此基表和视图不能具有相同的名称。
由
SELECT
语句
检索的列
可以是对表列的简单引用,也可以是使用函数,常量值,运算符等的表达式。
视图必须具有唯一的列名,没有重复项,就像基表一样。
默认情况下,
SELECT
语句
检索的
列的名称将用于视图列名称。
要为视图列定义显式名称,请将可选
column_list
子句
指定
为逗号分隔标识符的列表。
名称的数量
column_list
必须与
SELECT
语句
检索的列数相同
。
可以从多种
SELECT
语句
创建视图
。
它可以引用基表或其他视图。
它可以使用连接
UNION
和子查询。
该
SELECT
甚至不需要引用任何表:
创建视图v_today(今天)AS SELECT CURRENT_DATE;
以下示例定义了一个视图,该视图从另一个表中选择两列以及从这些列计算的表达式:
mysql>CREATE TABLE t (qty INT, price INT);
mysql>INSERT INTO t VALUES(3, 50);
mysql>CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql>SELECT * FROM v;
+ ------ + ------- ------- + + | 数量| 价格| 价值| + ------ + ------- ------- + + | 3 | 50 | 150 | + ------ + ------- ------- + +
视图定义受以下限制:
该
SELECT
语句不能引用系统变量或用户定义的变量。
在存储的程序中,
SELECT
语句不能引用程序参数或局部变量。
该
SELECT
语句不能引用预处理语句参数。
定义中引用的任何表或视图都必须存在。
如果在创建视图后,删除了定义引用的表或视图,则使用该视图会导致错误。
要检查此类问题的视图定义,请使用该
CHECK
TABLE
语句。
该定义不能引用
TEMPORARY
表,也不能创建
TEMPORARY
视图。
您无法将触发器与视图相关联。
将
SELECT
根据最大列长度64个字符(不是最大别名长度为256个字符)检查语句中
列名的
别名。
ORDER BY
在视图定义中是允许的,但如果使用具有自己的语句从视图中进行选择,则会忽略它
ORDER BY
。
对于定义中的其他选项或子句,它们将添加到引用视图的语句的选项或子句中,但效果未定义。
例如,如果视图定义包含
LIMIT
子句,并且您使用具有其自己的
LIMIT
子句
的语句从视图中进行选择
,则未定义哪个限制适用。
这个道理同样适用于选项,例如
ALL
,
DISTINCT
或者
SQL_SMALL_RESULT
后面的
SELECT
关键字,并以条款,例如
INTO
,
FOR UPDATE
,
FOR SHARE
,
LOCK IN SHARE
MODE
,和
PROCEDURE
。
如果通过更改系统变量更改查询处理环境,则视图中获得的结果可能会受到影响:
MySQL的>CREATE VIEW v (mycol) AS SELECT 'abc';
查询OK,0行受影响(0.01秒) MySQL的>SET sql_mode = '';
查询正常,0行受影响(0.00秒) MySQL的>SELECT "mycol" FROM v;
+ ------- + | mycol | + ------- + | mycol | + ------- + 1排(0.01秒) MySQL的>SET sql_mode = 'ANSI_QUOTES';
查询正常,0行受影响(0.00秒) MySQL的>SELECT "mycol" FROM v;
+ ------- + | mycol | + ------- + | abc | + ------- + 1排(0.00秒)
在
DEFINER
和
SQL SECURITY
条款确定哪个MySQL账户时,执行语句引用视图的视图检查访问权限时使用。
有效的
SQL SECURITY
特征值是
DEFINER
(默认值)和
INVOKER
。
这些表明必须由分别定义或调用视图的用户持有所需的权限。
如果
DEFINER
子句,该
user
值应被指定为一个MySQL帐户
,
或
。
允许的
值取决于您拥有的权限,如
第24.6节“存储对象访问控制”中所述
。
有关视图安全性的其他信息,另请参阅该部分。
'
user_name
'@'host_name
'CURRENT_USER
CURRENT_USER()
user
如果
DEFINER
省略
该
子句,则默认定义者是执行该
CREATE
VIEW
语句
的用户
。
这与
DEFINER = CURRENT_USER
明确
指定相同
。
在视图定义中,该
CURRENT_USER
函数
DEFINER
默认
返回视图的
值。
对于使用
SQL SECURITY INVOKER
特征
定义
CURRENT_USER
的视图
,
返回视图调用者的帐户。
有关视图中的用户审核的信息,请参见
第6.2.22节“基于SQL的帐户活动审核”
。
在使用
SQL
SECURITY DEFINER
特性
定义的存储例程中
,
CURRENT_USER
返回例程的
DEFINER
值。
如果视图定义包含
DEFINER
值
,则这也会影响在此例程中定义的视图
CURRENT_USER
。
MySQL检查查看权限,如下所示:
在视图定义时,视图创建者必须具有使用视图访问的顶级对象所需的权限。
例如,如果视图定义引用表列,则创建者必须对定义的选择列表中的每个列具有一些特权,并且
SELECT
对定义中其他位置使用的每个列
具有
特权。
如果定义引用存储的函数,则只能检查调用该函数所需的权限。
函数调用时所需的权限只能在执行时检查:对于不同的调用,可能会采用函数内的不同执行路径。
引用视图时
DEFINER
,将根据
视图
帐户或调用者所
拥有的权限检查视图访问的对象的权限
,具体取决于
SQL SECURITY
特征
是否
为
DEFINER
或
INVOKER
。
如果对视图的引用导致执行存储的函数,则对函数内执行的语句的特权检查取决于函数
SQL SECURITY
特征
是否
为
DEFINER
或
INVOKER
。
如果安全特性是
DEFINER
,则该功能以
DEFINER
帐户
的权限运行
。
如果特征是
INVOKER
,则该函数以视图
SQL
SECURITY
特征
确定的特权运行
。
示例:视图可能依赖于存储的函数,该函数可能会调用其他存储的例程。
例如,以下视图调用存储的函数
f()
:
创建视图v SELECT SELECT * FROM t WHERE t.id = f(t.name);
假设
f()
包含如下语句:
如果名称IS为NULL CALL p1(); 其他 CALL p2(); 万一;
执行时
f()
需要检查
执行语句所需的权限
f()
。
这可能意味着需要特权,
p1()
或者
p2()
取决于其中的执行路径
f()
。
必须在运行时检查这些权限,并且必须拥有权限的用户由
SQL
SECURITY
视图
v
和函数
的
值
确定
f()
。
视图
的
DEFINER
和
SQL SECURITY
子句是标准SQL的扩展。
在标准SQL中,使用规则处理视图
SQL SECURITY
DEFINER
。
该标准表示视图的定义者(与视图模式的所有者相同)在视图上获得适用的权限(例如,
SELECT
)并且可以授予它们。
MySQL没有架构
“
所有者
”的
概念
,因此MySQL添加了一个子句来识别定义器。
该
DEFINER
条款是一个扩展,其目的是具有标准所具有的内容;
也就是说,谁定义了视图的永久记录。
这就是默认
DEFINER
值是视图创建者的帐户的原因。
optional
ALGORITHM
子句是标准SQL的MySQL扩展。
它会影响MySQL处理视图的方式。
ALGORITHM
三个值:
MERGE
,
TEMPTABLE
或
UNDEFINED
。
有关更多信息,请参见
第24.5.2节“视图处理算法”
,以及
第8.2.2.4节“使用合并或实现优化派生表,视图引用和公用表表达式”
。
有些视图是可更新的。
也就是说,你可以在语句,如使用它们
UPDATE
,
DELETE
或
INSERT
更新基础表的内容。
要使视图可更新,视图中的行与基础表中的行之间必须存在一对一的关系。
还有一些其他构造使视图不可更新。
视图中生成的列被视为可更新,因为可以为其分配。
但是,如果明确更新此类列,则唯一允许的值为
DEFAULT
。
有关生成的列的信息,请参见
第13.1.20.9节“创建表和生成的列”
。
WITH CHECK OPTION
可以为可更新视图提供
该
子句,以防止对行的插入或更新,除了其中的
WHERE
子句
select_statement
为true的行。
在
WITH CHECK OPTION
可更新视图
的
子句中,
LOCAL
和
CASCADED
关键字确定在根据另一个视图定义视图时检查测试的范围。
的
LOCAL
关键字限制
CHECK OPTION
只向视图限定。
CASCADED
还会导致对基础视图的检查进行评估。
如果没有给出关键字,则默认为
CASCADED
。
有关可更新视图和
WITH
CHECK OPTION
子句的
更多信息
,请参见
第24.5.3节“可更新和可插入视图”
和
第24.5.4节“视图WITH CHECK OPTION子句”
。
DROP {DATABASE | SCHEMA} [如果存在]db_name
DROP
DATABASE
删除数据库中的所有表并删除数据库。
对此声明
要
非常
小心!
要使用
DROP
DATABASE
,您需要
DROP
数据库
的
权限。
DROP
SCHEMA
是...的同义词
DROP
DATABASE
。
删除数据库时, 不会 自动删除 专门为数据库授予的权限 。 必须手动删除它们。 请参见 第13.7.1.6节“GRANT语法” 。
IF EXISTS
用于防止在数据库不存在时发生错误。
如果删除默认数据库,则取消设置默认数据库(
DATABASE()
函数返回
NULL
)。
如果
DROP
DATABASE
在符号链接的数据库上使用,则链接和原始数据库都将被删除。
DROP
DATABASE
返回已删除的表的数量。
该
DROP
DATABASE
语句从给定的数据库目录中删除MySQL本身在正常操作期间可能创建的文件和目录。
这包括具有以下列表中显示的扩展名的所有文件:
.BAK
.DAT
.HSH
.MRG
.MYD
.MYI
.cfg
.db
.ibd
.ndb
如果在MySQL删除刚刚列出的文件或目录后,其他文件或目录仍保留在数据库目录中,则无法删除数据库目录。
在这种情况下,您必须手动删除任何剩余的文件或目录并
DROP
DATABASE
再次
发出该
语句。
删除数据库不会删除
TEMPORARY
在该数据库中创建的
任何
表。
TEMPORARY
当创建它们的会话结束时,会自动删除这些表。
请参见
第13.1.20.3节“CREATE TEMPORARY TABLE语法”
。
您也可以使用 mysqladmin 删除数据库 。 请参见 第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端” 。
DROP EVENT [如果存在] event_name
此语句将删除名为的事件
event_name
。
该事件立即停止活动,并从服务器中完全删除。
如果事件不存在,
则会
出现错误
ERROR 1517(HY000):未知事件'
event_name
'
。
您可以覆盖它并使该语句为不存在的事件生成警告,而不是使用
IF EXISTS
。
此语句需要
EVENT
要删除事件所属的架构
的
权限。
该
DROP
FUNCTION
语句用于删除存储的函数和用户定义的函数(UDF):
有关删除存储函数的信息,请参见 第13.1.29节“DROP PROCEDURE和DROP FUNCTION语法” 。
有关删除用户定义函数的信息,请参见 第13.7.4.2节“DROP FUNCTION语法” 。
DROP INDEXindex_name
ONtbl_name
[algorithm_option
|lock_option
] ......algorithm_option
: 算法[=] {DEFAULT | INPLACE | COPY}lock_option
: LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
DROP
INDEX
删除
index_name
从表中
命名的索引
tbl_name
。
此语句映射
ALTER
TABLE
到删除索引
的
语句。
请参见
第13.1.9节“ALTER TABLE语法”
。
要删除主键,索引名称始终
PRIMARY
为必须指定为带引号的标识符,因为
PRIMARY
它是保留字:
DROP INDEX`PRIMARY`ON;
NDB
表格的
可变宽度列的索引
在线删除;
也就是说,没有任何表复制。
该表未被锁定以防止来自其他NDB Cluster API节点的访问,尽管在操作期间它被锁定在
同一
API节点
上的其他
操作。
这是由服务器在确定可以这样做时自动完成的;
您不必使用任何特殊的SQL语法或服务器选项来导致它发生。
ALGORITHM
并且
LOCK
可以赋予子句以影响表复制方法和在修改索引时读写表的并发级别。
它们与
ALTER
TABLE
声明
具有相同的含义
。
有关更多信息,请参见
第13.1.9节“ALTER TABLE语法”
MySQL NDB Cluster使用
ALGORITHM=INPLACE
标准MySQL服务器支持
的相同
语法
支持在线操作
。
有关
更多信息
,
请参见
第22.5.14节“使用NDB簇中的ALTER TABLE进行联机操作”
。
DROP LOGFILE GROUPlogfile_group
ENGINE [=]engine_name
此语句删除名为的日志文件组
logfile_group
。
日志文件组必须已存在或导致错误。
(有关创建日志文件组的信息,请参见
第13.1.16节“CREATE LOGFILE GROUP语法”
。)
在删除日志文件组之前,必须删除使用该日志文件组进行
UNDO
日志记录的
所有表空间
。
required
ENGINE
子句提供要删除的日志文件组使用的存储引擎的名称。
目前,唯一允许的值
engine_name
是
NDB
和
NDBCLUSTER
。
DROP LOGFILE GROUP
仅适用于NDB Cluster的磁盘数据存储。
请参见
第22.5.13节“NDB集群磁盘数据表”
。
DROP {PROCEDURE | 功能} [如果存在]sp_name
此语句用于删除存储过程或函数。
也就是说,从服务器中删除指定的例程。
你必须拥有
ALTER ROUTINE
例行公事
的
特权。
(如果
automatic_sp_privileges
启用
了
系统变量,
EXECUTE
则在创建例程时将该
特权
自动授予例程创建者,并在例程被删除时从创建者中删除该
特权
。请参见
第24.2.2节“存储的例程和MySQL特权”
。)
该
IF EXISTS
子句是MySQL扩展。
如果过程或函数不存在,它可以防止发生错误。
生成可以查看的警告
SHOW WARNINGS
。
DROP
FUNCTION
也用于删除用户定义的函数(请参见
第13.7.4.2节“DROP FUNCTION语法”
)。
DROP SERVER [如果存在] server_name
删除名为的服务器的服务器定义
。
server_name
mysql.servers
表中
的相应行将
被删除。
此声明需要该
SUPER
权限。
删除表的服务器不会影响
FEDERATED
在创建表时使用此连接信息的
任何
表。
请参见
第13.1.18节“创建服务器语法”
。
DROP SERVER
导致隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
DROP SERVER
无论正在使用的日志记录格式如何,都不会写入二进制日志。
DROP空间参考系统 [如果存在]srid
srid
:32-bit unsigned integer
此语句
从数据字典中
删除
空间参照系
(SRS)定义。
它需要
SUPER
特权。
例:
DROP空间参考系统4120;
如果不存在具有SRID值的SRS定义,则除非
IF EXISTS
指定
,否则
将
发生错误
。
在这种情况下,会发出警告而不是错误。
如果现有表中的某些列使用SRID值,则会发生错误。 例如:
MySQL的> DROP SPATIAL REFERENCE SYSTEM 4326;
ERROR 3716(SR005):无法修改SRID 4326。有
至少有一列取决于它。
要标识哪个或哪些列使用SRID,请使用以下查询:
SELECT * FROM INFORMATION_SCHEMA.ST_GEOMETRY_COLUMNS WHERE SRS_ID = 4326;
SRID值必须在32位无符号整数的范围内,具有以下限制:
SRID 0是有效的SRID,但不能与之一起使用
DROP SPATIAL REFERENCE SYSTEM
。
如果该值在保留的SRID范围内,则会发出警告。 保留范围为[0,32767](由EPSG保留),[60,000,000,69,999,999](由EPSG保留)和[2,000,000,000,2,147,483,647](由MySQL保留)。 EPSG代表 欧洲石油调查组 。
用户不应丢弃具有保留范围中的SRID的SRS。 如果删除了系统安装的SRS,则可以为MySQL升级重新创建SRS定义。
DROP [TEMPORARY] TABLE [IF EXISTS]tbl_name
[,tbl_name
] ...... [限制| 级联]
DROP
TABLE
删除一个或多个表。
您必须拥有
DROP
每个表
的
权限。
小心 这个说法! 对于每个表,它将删除表定义和所有表数据。 如果表已分区,则该语句将删除表定义,其所有分区,存储在这些分区中的所有数据以及与已删除表关联的所有分区定义。
删除表也会删除表的任何触发器。
DROP
TABLE
导致隐式提交,除非与
TEMPORARY
关键字一起使用。
请参见
第13.3.3节“导致隐式提交的语句”
。
删除表时, 不会 自动删除 专门为该表授予的权限 。 必须手动删除它们。 请参见 第13.7.1.6节“GRANT语法” 。
如果参数列表中指定的任何表不存在,则
DROP
TABLE
行为取决于是否
IF EXISTS
给出
了该
子句:
如果没有
IF EXISTS
,则语句失败并显示错误,指示无法删除哪些不存在的表,并且不进行任何更改。
使用
IF EXISTS
时,不存在的表不会发生错误。
该语句将删除所有存在的命名表,并
NOTE
为每个不存在的表
生成
诊断。
这些注释可以显示
SHOW WARNINGS
。
请参见
第13.7.6.40节“显示警告语法”
。
IF EXISTS
对于在特殊情况下删除表也很有用,在这种情况下,数据字典中有条目但没有存储引擎管理的表。
(例如,如果在从存储引擎中删除表之后但在删除数据字典条目之前发生异常服务器退出。)
该
TEMPORARY
关键字具有以下效果:
该声明仅删除
TEMPORARY
表格。
该语句不会导致隐式提交。
没有检查访问权限。
一个
TEMPORARY
表可见只与创建它的会话,所以没有检查是必要的。
包含
TEMPORARY
关键字是防止意外丢弃非
TEMPORARY
表
的好方法
。
在
RESTRICT
和
CASCADE
关键字无能为力。
允许它们从其他数据库系统中轻松移植。
DROP
TABLE
并非所有
innodb_force_recovery
设置
都支持
。
请参见
第15.20.2节“强制InnoDB恢复”
。
DROP [UNDO] TABLESPACEtablespace_name
[ENGINE [=]engine_name
]
此语句删除以前使用创建的表空间
CREATE TABLESPACE
。
它是由支持
NDB
和
InnoDB
存储引擎。
UNDO
必须指定在MySQL 8.0.14中引入
的
关键字以删除撤消表空间。
只能
CREATE UNDO
TABLESPACE
删除
使用
语法
创建的撤消表空间
。
撤消表空间必须处于
empty
可以删除之前
的
状态。
有关更多信息,请参见
第15.6.3.4节“撤消表空间”
。
ENGINE
设置使用表空间的存储引擎,其中
engine_name
是存储引擎的名称。
目前,值
InnoDB
和
NDB
支持。
如果未设置,
default_storage_engine
则使用
值
。
如果它与用于创建表空间的存储引擎不同,则该
DROP TABLESPACE
语句将失败。
是MySQL中区分大小写的标识符。
tablespace_name
对于
InnoDB
通用表空间,必须在
DROP
TABLESPACE
操作
之前从表空间中删除所有表
。
如果表空间不为空,则
DROP TABLESPACE
返回错误。
NDB
要删除
的
表空间不得包含任何数据文件;
换句话说,在删除
NDB
表空间之前,必须先使用删除每个数据文件
ALTER TABLESPACE
... DROP DATAFILE
。
InnoDB
删除表空间中的最后一个表时,不会自动删除
常规
表空间。
必须使用显式删除表空间
。
DROP TABLESPACE
tablespace_name
一个
DROP DATABASE
操作可以丢弃属于一般的表空间的表,但它不能删除表空间,即使操作下降属于表空间中的所有表。
必须使用显式删除表空间
。
DROP TABLESPACE
tablespace_name
与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间
.ibd数据文件
内部创建可用空间,该
文件
只能用于新
InnoDB
数据。
空间不会像文件每表表空间一样释放回操作系统。
此示例演示如何删除
InnoDB
常规表空间。
ts1
使用单个表创建
常规表空间
。
在删除表空间之前,必须删除该表。
MySQL的>CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
MySQL的>CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts10 Engine=InnoDB;
MySQL的>DROP TABLE t1;
MySQL的>DROP TABLESPACE ts1;
此示例演示了删除撤消表空间。
撤消表空间必须处于
empty
可以删除之前
的
状态。
有关更多信息,请参见
第15.6.3.4节“撤消表空间”
。
MySQL的> DROP UNDO TABLESPACE undo_003
;
这个例子展示了如何删除一个
NDB
表
myts
具有命名的数据文件
mydata-1.dat
之后首先创建表,并假定命名一个日志文件组的存在
mylg
(见
章节13.1.16,“CREATE LOGFILE GROUP语法”
)。
mysql>CREATE TABLESPACE myts
- >ADD DATAFILE 'mydata-1.dat'
- >USE LOGFILE GROUP mylg
- >ENGINE=NDB;
ALTER TABLESPACE
如下所示,
必须先删除表空间中的所有数据文件
,然后才能删除它们:
mysql>ALTER TABLESPACE myts
- >DROP DATAFILE 'mydata-1.dat'
- >ENGINE=NDB;
MySQL的>DROP TABLESPACE myts;
DROP TRIGGER [IF EXISTS] [schema_name
。]trigger_name
此语句删除触发器。
模式(数据库)名称是可选的。
如果省略了架构,则会从默认架构中删除触发器。
DROP
TRIGGER
需要
TRIGGER
与触发器关联的表
的
权限。
使用
IF EXISTS
以防止发生错误,从一个不存在的触发器发生。
甲
NOTE
使用时不存在的触发产生
IF EXISTS
。
请参见
第13.7.6.40节“显示警告语法”
。
如果删除表,也会删除表的触发器。
DROP VIEW [IF EXISTS]view_name
[,view_name
] ...... [限制| 级联]
DROP
VIEW
删除一个或多个视图。
您必须拥有
DROP
每个视图
的
权限。
如果参数列表中指定的任何视图不存在,则该语句将失败,并显示一个错误,该错误按名称指示它无法删除的不存在的视图,并且不进行任何更改。
在MySQL 5.7及更早版本中,
DROP
VIEW
如果参数列表中指定的任何视图不存在,则返回错误,但也会丢弃列表中存在的所有视图。
由于MySQL 8.0中的行为发生了变化,
DROP
VIEW
MySQL 5.7主服务器上的
部分完成
操作在MySQL 8.0从服务器上复制时失败。
要避免此故障情形,请
IF EXISTS
在
DROP
VIEW
语句中
使用
语法
以防止对不存在的视图发生错误。
有关更多信息,请参见
第13.1.1节“原子数据定义语句支持”
。
该
IF EXISTS
子句可防止对不存在的视图发生错误。
给出此子句时,
NOTE
将为每个不存在的视图生成
a
。
请参见
第13.7.6.40节“显示警告语法”
。
RESTRICT
并且
CASCADE
,如果给定,则被解析并被忽略。
RENAME TABLEtbl_name
TOnew_tbl_name
[,tbl_name2
TOnew_tbl_name2
] ......
RENAME
TABLE
重命名一个或多个表。
您必须具有
ALTER
与
DROP
原始表的权限,以及
CREATE
与
INSERT
新表的权限。
例如,重命名一个指定的表
old_table
来
new_table
,用这个语句:
RENAME TABLE old_table TO new_table;
该声明等同于以下
ALTER
TABLE
声明:
ALTER TABLE old_table RENAME new_table;
RENAME TABLE
与之不同
ALTER
TABLE
,可以在一个语句中重命名多个表:
RENAME TABLE old_table1到new_table1, old_table2到new_table2, old_table3 TO new_table3;
重命名操作从左到右执行。
因此,要交换两个表名,请执行此操作(假设具有中间名称的表
tmp_table
尚不存在):
RENAME TABLE old_table TO tmp_table, new_table TO old_table, tmp_table TO new_table;
表上的元数据锁是按名称顺序获取的,在某些情况下,当多个事务并发执行时,这会对操作结果产生影响。 请参见 第8.11.4节“元数据锁定” 。
从MySQL 8.0.13开始,您可以重命名用
LOCK TABLES
语句
锁定的
表,前提是它们是使用锁定锁定的,
WRITE
或者是
WRITE
多表重命名操作中前面步骤中
重命名
锁定表
的产物
。
例如,允许这样做:
LOCK TABLE old_table1 WRITE; RENAME TABLE old_table1到new_table1, new_table1 TO new_table2;
这是不允许的:
LOCK TABLE old_table1 READ; RENAME TABLE old_table1到new_table1, new_table1 TO new_table2;
在MySQL 8.0.13之前,要执行
RENAME TABLE
,必须没有锁定表
LOCK
TABLES
。
在满足事务表锁定条件的情况下,重命名操作以原子方式完成; 在重命名正在进行时,没有其他会话可以访问任何表。
如果在a期间发生任何错误
RENAME TABLE
,则语句将失败并且不会进行任何更改。
您可以使用
RENAME TABLE
将表从一个数据库移动到另一个数据库:
重命名表current_db.tbl_name
TOother_db.tbl_name;
使用此方法将所有表从一个数据库移动到另一个数据库实际上重命名数据库(MySQL没有单个语句的操作),除了原始数据库继续存在,尽管没有表。
喜欢
RENAME TABLE
,
ALTER TABLE ...
RENAME
也可以用来将表移动到不同的数据库。
无论使用何种语句,如果重命名操作将表移动到位于不同文件系统上的数据库,则结果的成功是特定于平台的,并且取决于用于移动表文件的基础操作系统调用。
如果表具有触发器,则尝试将表重命名为其他数据库会
因错误的schema
(
ER_TRG_IN_WRONG_SCHEMA
)错误
触发器而
失败
。
未加密的表可以移动到启用加密的数据库,反之亦然。
但是,如果
table_encryption_privilege_check
启用了
该
变量,
TABLE_ENCRYPTION_ADMIN
则如果表加密设置与默认数据库加密不同,则需要
该
权限。
要重命名
TEMPORARY
表,
RENAME
TABLE
不起作用。
请
ALTER
TABLE
改用。
RENAME TABLE
适用于视图,但视图无法重命名为其他数据库。
专门为重命名的表或视图授予的任何权限都不会迁移到新名称。 必须手动更改它们。
RENAME TABLE
更改内部生成的外键约束名称和以字符串
“
tbl_name
TO
new_tbl_name
tbl_name
_ibfk_
”
开头
以反映新表名称的
用户定义的外键约束名称
。
InnoDB
将以字符串
“
tbl_name
_ibfk_
”
开头的外键约束名称解释
为内部生成的名称。
除非存在冲突,否则指向重命名表的外键约束名称将自动更新,在这种情况下,语句将失败并显示错误。 如果重命名的约束名称已存在,则会发生冲突。 在这种情况下,您必须删除并重新创建外键才能使其正常运行。
RENAME TABLE
更改内部生成的和用户定义的
tbl_name
TO
new_tbl_name
CHECK
约束名称,以字符串
“
tbl_name
_chk_
”
开头
以反映新的表名。
MySQL
CHECK
将以字符串
“
tbl_name
_chk_
”
开头的约束名称
解释
为内部生成的名称。
例:
MySQL的>SHOW CREATE TABLE t1\G
*************************** 1。排******************** ******* 表:t1 创建表:CREATE TABLE`t1`( `i1` int(11)DEFAULT NULL, `i2` int(11)DEFAULT NULL, 约束`t1_chk_1`检查((``i1`> 0)), 约束`t1_chk_2`检查((``i2` <0)) )ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci 1排(0.02秒) MySQL的>RENAME TABLE t1 TO t3;
查询正常,0行受影响(0.03秒) MySQL的>SHOW CREATE TABLE t3\G
*************************** 1。排******************** ******* 表:t3 创建表:CREATE TABLE`t3`( `i1` int(11)DEFAULT NULL, `i2` int(11)DEFAULT NULL, 约束`t3_chk_1`检查((``i1`> 0)), 约束`t3_chk_2`检查((``i2` <0)) )ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci 1排(0.01秒)
TRUNCATE [表] tbl_name
TRUNCATE
TABLE
完全清空一张桌子。
它需要
DROP
特权。
从逻辑上讲,
TRUNCATE
TABLE
类似于一个
DELETE
一个删除所有行,或序列声明
DROP
TABLE
和
CREATE
TABLE
陈述。
要实现高性能,请
TRUNCATE
TABLE
绕过删除数据的DML方法。
因此,它不会导致
ON DELETE
触发器触发,它不能对
InnoDB
具有父子外键关系的表
执行
,并且不能像DML操作那样回滚。
但是,
TRUNCATE
TABLE
如果服务器在运行期间暂停,则对使用原子DDL支持的存储引擎的表的操作要么完全提交,要么回滚。
有关更多信息,请参见
第13.1.1节“原子数据定义语句支持”
。
虽然
TRUNCATE TABLE
类似
DELETE
,但它被归类为DDL语句而不是DML语句。
它与
DELETE
以下方式不同:
截断操作会删除并重新创建表,这比逐个删除行要快得多,特别是对于大型表。
截断操作会导致隐式提交,因此无法回滚。 请参见 第13.3.3节“导致隐式提交的语句” 。
如果会话持有活动表锁,则无法执行截断操作。
TRUNCATE
TABLE
如果
引用该表的其他表
有任何
约束,
则
InnoDB
表或
NDB
表
失败
FOREIGN KEY
。
允许同一表的列之间的外键约束。
截断操作不会为已删除的行数返回有意义的值。 通常的结果是 “ 0行受影响 ” ,应该被解释为 “ 没有信息。 ”
只要表定义有效,
TRUNCATE TABLE
即使数据或索引文件已损坏,也
可以将表重新创建为空表
。
任何
AUTO_INCREMENT
值都将重置为其起始值。
即使对于
MyISAM
并且
InnoDB
通常不重用序列值也是如此。
与分区表一起使用时,
TRUNCATE TABLE
保留分区;
也就是说,数据和索引文件被删除并重新创建,而分区定义不受影响。
该
TRUNCATE TABLE
语句不会调用
ON DELETE
触发器。
InnoDB
支持
截断损坏的
表。
TRUNCATE
TABLE
对于表关闭所有打开的表的处理程序
HANDLER
OPEN
。
TRUNCATE
TABLE
被处理用于二进制日志记录和复制的目的,
DROP
TABLE
后面是
CREATE
TABLE
-dhat,而不是DML。
这是因为,当使用
InnoDB
事务隔离级别不允许基于语句的日志记录(
READ
COMMITTED
或
READ
UNCOMMITTED
)的
事务存储引擎
时,使用
STATEMENT
或
MIXED
记录模式
时不会记录和复制该语句
。
(缺陷号36763)但是,它仍然
InnoDB
以前面描述的方式
应用于复制从属设备
。
在MySQL 5.7及更早版本中,在具有大缓冲池并
innodb_adaptive_hash_index
启用的
TRUNCATE TABLE
系统上,由于在删除表的自适应哈希索引条目时发生LRU扫描,操作可能导致系统性能暂时下降(Bug#68184)。
重新映射
TRUNCATE
TABLE
到
MySQL 8.0
DROP
TABLE
和
CREATE
TABLE
在MySQL 8.0中避免了有问题的LRU扫描。
TRUNCATE
TABLE
可以与性能架构摘要表一起使用,但效果是将摘要列重置为0,或者
NULL
不删除行。
请参见
第26.12.16节“性能模式摘要表”
。
CALLsp_name
([parameter
[,...]]) CALLsp_name
[()]
该
CALL
语句调用先前定义的存储过程
CREATE PROCEDURE
。
不带括号的存储过程可以在没有括号的情况下调用。
也就是说,
CALL p()
而且
CALL p
是等价的。
CALL
可以使用声明为
OUT
或
INOUT
参数的
参数将值传回给调用者
。
当过程返回时,客户端程序还可以获取在例程中执行的最终语句受影响的行数:在SQL级别,调用该
ROW_COUNT()
函数;
从C API,调用该
mysql_affected_rows()
函数。
有关未处理条件对过程参数的影响的信息,请参见 第13.6.7.8节“条件处理和OUT或INOUT参数” 。
要使用
OUT
or
INOUT
参数
从过程中获取值
,请通过用户变量传递参数,然后在过程返回后检查变量的值。
(如果要调用从另一个存储过程或函数内的程序,也可以通过常规参数或局部例程变量作为
IN
或
INOUT
参数)。对于一个
INOUT
参数,它传递给过程之前初始化它的值。
以下过程具有
OUT
过程设置为当前服务器版本的
INOUT
参数,以及过程从其当前值开始递增的值:
CREATE PROCEDURE p(OUT ver_param VARCHAR(25),INOUT incr_param INT) 开始 #设置OUT参数的值 SELECT VERSION()INTO ver_param; #INOUT参数的增量值 SET incr_param = incr_param + 1; 结束;
在调用该过程之前,初始化要作为
INOUT
参数
传递的变量
。
调用该过程后,将设置或修改两个变量的值:
mysql>SET @increment = 10;
mysql>CALL p(@version, @increment);
mysql>SELECT @version, @increment;
+ -------------------- + ------------ + | @version | @increment | + -------------------- + ------------ + | 8.0.3-rc-debug-log | 11 | + -------------------- + ------------ +
在
CALL
使用
PREPARE
和的
EXECUTE
预
准备
语句中
,占位符可用于
IN
参数
OUT
和
INOUT
参数。
这些类型的参数可以使用如下:
mysql>SET @increment = 10;
mysql>PREPARE s FROM 'CALL p(?, ?)';
mysql>EXECUTE s USING @version, @increment;
mysql>SELECT @version, @increment;
+ -------------------- + ------------ + | @version | @increment | + -------------------- + ------------ + | 8.0.3-rc-debug-log | 11 | + -------------------- + ------------ +
要编写使用
CALL
SQL语句执行生成结果集的存储过程的
C程序,
CLIENT_MULTI_RESULTS
必须启用
该
标志。
这是因为
CALL
除了过程中执行的语句可能返回的任何结果集之外,
每个都
返回一个结果来指示调用状态。
CLIENT_MULTI_RESULTS
如果
CALL
用于执行包含预准备语句的任何存储过程,
则还必须启用
。
无论何时加载这样的过程都无法确定这些语句是否会产生结果集,因此有必要假设它们会产生结果集。
CLIENT_MULTI_RESULTS
可以在调用时启用
mysql_real_connect()
,可以通过传递
CLIENT_MULTI_RESULTS
标志本身
显式
启用
,也可以通过传递
隐式
CLIENT_MULTI_STATEMENTS
启用(也可以启用
CLIENT_MULTI_RESULTS
)。
CLIENT_MULTI_RESULTS
默认情况下启用。
要处理
CALL
使用
mysql_query()
or
执行
的
语句
的结果
mysql_real_query()
,请使用调用的循环
mysql_next_result()
来确定是否有更多结果。
有关示例,请参见
第28.7.23节“C API多语句执行支持”
。
C程序可以使用prepared-statement接口来执行
CALL
语句,访问
OUT
和
INOUT
参数。
这是通过
CALL
使用循环
处理
语句
的结果来完成的,该
循环调用
mysql_stmt_next_result()
以确定是否有更多结果。
有关示例,请参见
第28.7.25节“C API准备的CALL语句支持”
。
提供MySQL接口的语言可以使用预准备
CALL
语句直接检索
OUT
和
INOUT
过程参数。
检测到存储程序引用的对象的元数据更改,并在下次执行程序时自动重新分析受影响的语句。 有关更多信息,请参见 第8.10.3节“准备语句和存储程序的缓存” 。
DELETE
是一个从表中删除行的DML语句。
一个
DELETE
语句可以用开始
WITH
子句来定义内访问的公共表表达式
DELETE
。
请参见
第13.2.13节“WITH语法(公用表表达式)”
。
从tbl_name
[[AS]tbl_alias
] 删除[LOW_PRIORITY] [QUICK] [IGNORE ] [PARTITION(partition_name
[,partition_name
] ...)] [在哪里where_condition
] [订购...] [限制row_count
]
该
DELETE
语句从中删除行
tbl_name
并返回已删除行的数量。
要检查已删除行的数量,请调用
第12.15节“信息功能”中
ROW_COUNT()
所述的
功能
。
optional
WHERE
子句中
的条件
标识要删除的行。
如果没有
WHERE
子句,则删除所有行。
where_condition
是一个表达式,对于要删除的每一行,计算结果为true。
它的规定如
第13.2.10节“SELECT语法”中所述
。
如果
ORDER BY
指定了
该
子句,则按指定的顺序删除行。
该
LIMIT
子句限制了可以删除的行数。
这些子句适用于单表删除,但不适用于多表删除。
删除[LOW_PRIORITY] [QUICK] [IGNORE]tbl_name
[。*] [,tbl_name
[。*]] ... 来自table_references
[地点where_condition
] 删除[LOW_PRIORITY] [QUICK] [IGNORE] FROMtbl_name
[。*] [,tbl_name
[。*]] ...... 使用table_references
[在哪里where_condition
]
您需要
DELETE
表上
的
权限才能从中删除行。
您只需要
SELECT
对只读取的任何列
的
权限,例如在
WHERE
子句中指定的列。
当您不需要知道已删除行的数量时,该
TRUNCATE TABLE
语句是一种更快的方式来清空表而不是
DELETE
没有
WHERE
子句的语句。
不同的是
DELETE
,
TRUNCATE TABLE
不能在事务中使用或者如果您对表有锁定。
请参见
第13.1.37节“TRUNCATE TABLE语法”
和
第13.3.6节“LOCK TABLES和UNLOCK TABLES语法”
。
删除操作的速度也可能受 第8.2.5.3节“优化DELETE语句”中 讨论的因素的影响 。
为确保给定
DELETE
语句不占用太多时间,特定于MySQL的
子句
指定要删除的最大行数。
如果要删除的行数大于限制,请重复该
语句,直到受影响的行数小于该
值。
LIMIT
row_count
DELETE
DELETE
LIMIT
您无法从表中删除并从子查询中的同一表中进行选择。
DELETE
支持使用
PARTITION
选项
显式分区选择,该
选项获取一个或多个分区或子分区(或两者)的逗号分隔名称列表,从中选择要删除的行。
未包含在列表中的分区将被忽略。
由于分区表
t
有一个名为分区
p0
,执行该语句
DELETE
FROM t PARTITION (p0)
对表作为执行相同的效果
ALTER
TABLE t TRUNCATE PARTITION (p0)
;
在这两种情况下,分区
p0
中的
所有行都将
被删除。
PARTITION
可以与
WHERE
条件
一起使用
,在这种情况下,仅对列出的分区中的行测试条件。
例如,
DELETE FROM t PARTITION (p0) WHERE c < 5
仅从
p0
条件
c < 5
为true的
分区中删除行
;
不检查任何其他分区中的行,因此不受其影响
DELETE
。
该
PARTITION
选项也可用于多表
DELETE
语句。
您可以在
FROM
选项
中指定的每个表中使用最多一个此类
选项。
有关更多信息和示例,请参见 第23.5节“分区选择” 。
如果删除包含列的最大值的行
AUTO_INCREMENT
,则不会对该
表
MyISAM
或
InnoDB
表
重用该值
。
如果
在
模式下
删除表中的所有行
(没有
子句)
,则除了
和
之外
,
所有存储引擎的序列都将重新开始
。
表的
这种行为有一些例外
,如
第15.6.1.4节“InnoDB中的AUTO_INCREMENT处理”中所述
。
DELETE
FROM
tbl_name
WHERE
autocommit
InnoDB
MyISAM
InnoDB
对于
MyISAM
表,您可以
AUTO_INCREMENT
在多列键中
指定
辅助列。
在这种情况下,即使对于
MyISAM
表,
也会重复使用从序列顶部删除的值
。
请参见
第3.6.9节“使用AUTO_INCREMENT”
。
该
DELETE
语句支持以下修饰符:
如果指定
LOW_PRIORITY
修饰符,则服务器会延迟执行,
DELETE
直到没有其他客户端从表中读取。
这会影响只使用表级锁只存储引擎(例如
MyISAM
,
MEMORY
和
MERGE
)。
对于
MyISAM
表,如果使用
QUICK
修饰符,则存储引擎在删除期间不会合并索引叶,这可能会加速某些类型的删除操作。
该
IGNORE
修改导致MySQL删除行的过程中忽略的错误。
(解析阶段遇到的错误以常规方式处理。)由于使用而
IGNORE
被
忽略的错误
将作为警告返回。
有关更多信息,请参阅
IGNORE关键字和严格SQL模式的比较
。
如果
DELETE
语句包含
ORDER BY
子句,则按照子句指定的顺序删除行。
这主要与结合使用有用
LIMIT
。
例如,以下语句查找与
WHERE
子句
匹配的行
,对其进行排序
timestamp_column
,并删除第一个(最旧的):
从somelog中删除WHERE user ='jcole' ORDER BY timestamp_column LIMIT 1;
ORDER BY
还有助于删除所需的顺序中的行以避免参照完整性违规。
如果要从大表中删除许多行,则可能会超出表的锁定表大小
InnoDB
。
要避免此问题,或者只是为了最小化表保持锁定的时间,以下策略(根本不使用
DELETE
)可能会有所帮助:
选择 不要 删除 的行 到与原始表具有相同结构的空表中:
INSERT INTO t_copy SELECT * FROM t WHERE ...;
使用
RENAME TABLE
以原子移动原始表的方式进行,并重新命名拷贝到原来的名称:
RENAME TABLE t TO t_old,t_copy TO t;
删除原始表:
DROP TABLE t_old;
没有其他会话可以在
RENAME
TABLE
执行时
访问所涉及的表
,因此重命名操作不受并发问题的影响。
请参见
第13.1.36节“RENAME TABLE语法”
。
在
MyISAM
表中,已删除的行在链表中维护,后续
INSERT
操作重用旧的行位置。
要回收未使用的空间并减小文件大小,请使用
OPTIMIZE TABLE
语句或
myisamchk
实用程序重新组织表。
OPTIMIZE TABLE
更容易使用,但
myisamchk
更快。
请参见
第13.7.3.4节“OPTIMIZE TABLE语法”
和
第4.6.4节“
myisamchk
- MyISAM表维护实用程序”
。
该
QUICK
修改会影响指数的叶子是否合并的删除操作。
DELETE QUICK
对于已删除行的索引值被稍后插入的行中的类似索引值替换的应用程序最有用。
在这种情况下,将重复使用已删除值留下的孔。
DELETE QUICK
当删除的值导致未满填充的索引块跨越一系列索引值时,这些索引块将再次出现新的插入值,因此无效。
在这种情况下,使用
QUICK
会导致索引中浪费的空间仍然无法回收。
以下是此类场景的示例:
创建一个包含索引
AUTO_INCREMENT
列
的表
。
在表中插入许多行。 每个插入都会生成一个索引值,该值将添加到索引的高端。
使用删除列范围低端的行块
DELETE QUICK
。
在这种情况下,与已删除的索引值关联的索引块变为未填充但由于使用而未与其他索引块合并
QUICK
。
当新插入发生时,它们仍然未充满,因为新行在已删除范围内没有索引值。
此外,即使您稍后
DELETE
不
使用它们,它们仍然未充满
QUICK
,除非一些已删除的索引值恰好位于未充满的块内或附近的索引块中。
要在这些情况下回收未使用的索引空间,请使用
OPTIMIZE TABLE
。
如果要从表中删除许多行,则
DELETE QUICK
后续
使用可能会更快
OPTIMIZE TABLE
。
这会重建索引,而不是执行许多索引块合并操作。
您可以在
DELETE
语句中
指定多个表,以
根据
WHERE
子句中
的条件从一个或多个表中删除行
。
您不能使用
ORDER
BY
或
LIMIT
在多表中
DELETE
。
该
table_references
子句列出了连接中涉及的表,如
第13.2.10.2节“JOIN语法”中所述
。
对于第一个多表语法,仅
FROM
删除子句
之前列出的表中的匹配行
。
对于第二个多表语法,仅
删除
FROM
子句(在
USING
子句
之前
)中
列出的表中的匹配行
。
结果是您可以同时从多个表中删除行,并具有仅用于搜索的其他表:
删除t1,t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE_1.id = t2.id AND t2.id = t3.id;
要么:
从t1,t2删除使用t1 INNER JOIN t2 INNER JOIN t3 WHERE_1.id = t2.id AND t2.id = t3.id;
这些语句查找的行删除的时候,但仅删除表的匹配行使用所有三个表
t1
和
t2
。
前面的示例使用
INNER JOIN
,但多表
DELETE
语句可以使用语句中允许的其他类型的连接
SELECT
,例如
LEFT JOIN
。
例如,要删除不存在
t1
匹配项的行
t2
,请使用
LEFT JOIN
:
删除t1 FROM t1 LEFT JOIN t2 ON t1.id = t2.id WHERE t2.id IS NULL;
语法允许
.*
在每个
语句
之后
tbl_name
与
Access
兼容
。
如果您使用
DELETE
涉及
InnoDB
具有外键约束
的表的多表
语句
,则MySQL优化器可能会按照与其父/子关系不同的顺序处理表。
在这种情况下,语句失败并回滚。
相反,您应该从单个表中删除并依赖于
提供
的
ON DELETE
功能,
InnoDB
以便相应地修改其他表。
如果声明表的别名,则在引用表时必须使用别名:
删除t1 FROM测试AS t1,test2 WHERE ...
多表中的表别名
DELETE
只应
table_references
在语句
的
部分声明。
在其他地方,允许别名引用但不允许别名声明。
正确:
删除a1,a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id = a2.id; 从a1,a2删除使用t1作为a1 INNER JOIN t2作为a2 WHERE a1.id = a2.id;
不正确:
删除t1 AS a1,t2 AS a2 FROM t1 INNER JOIN t2 WHERE a1.id = a2.id; 从t1 AS a1删除,t2 AS a2使用t1 INNER JOIN t2 WHERE a1.id = a2.id;
DELETE
从MySQL 8.0.16开始,
单表
语句
也支持表别名
。
(Bug#89410,Bug#27455809)
DOexpr
[,expr
] ......
DO
执行表达式但不返回任何结果。
在大多数方面,它
DO
是简写
,但有一个优点,当你不关心结果时,它会稍微快一些。
SELECT
expr
, ...
DO
主要用于具有副作用的函数,例如
RELEASE_LOCK()
。
示例:此
SELECT
语句暂停,但也生成结果集:
MySQL的> SELECT SLEEP(5);
+ ---------- +
| 睡觉(5)|
+ ---------- +
| 0 |
+ ---------- +
1排(5.02秒)
DO
另一方面,暂停而不产生结果集:
MySQL的> DO SLEEP(5);
查询OK,0行受影响(4.99秒)
这可能很有用,例如在存储函数或触发器中,它禁止生成结果集的语句。
DO
只执行表达式。
它不能用于所有
SELECT
可以使用的情况。
例如,
DO id FROM t1
无效,因为它引用了一个表。
HANDLERtbl_name
OPEN [[AS]alias
] HANDLERtbl_name
READindex_name
{= | <= | > = | <| >}(value1
,value2
,...) [在哪里where_condition
] [限制...] HANDLERtbl_name
READindex_name
{FIRST | 下一步| 上一个| 最后} [在哪里where_condition
] [限制...] HANDLERtbl_name
READ {FIRST | 下一个 } [在哪里where_condition
] [限制...] HANDLERtbl_name
关闭
该
HANDLER
语句提供对表存储引擎接口的直接访问。
它适用于
InnoDB
和
MyISAM
表。
该
HANDLER ... OPEN
语句打开一个表,使用后续
HANDLER ...
READ
语句
可以访问它
。
此表对象不会被其他会话共享,并且在会话调用
HANDLER ... CLOSE
或会话终止
之前不会关闭
。
如果使用别名打开表,则对包含其他
HANDLER
语句
的open表的进一步引用
必须使用别名而不是表名。
如果不使用别名,但使用由数据库名称限定的表名打开表,则进一步的引用必须使用非限定表名。
例如,对于使用的表
mydb.mytable
,必须使用进一步的引用
mytable
。
第一个
HANDLER ... READ
语法获取指定索引满足给定值并满足
WHERE
条件的行。
如果您有多列索引,请将索引列值指定为逗号分隔列表。
指定索引中所有列的值,或指定索引列的最左前缀的值。
假设一个索引
my_idx
包括三个名为列
col_a
,
col_b
以及
col_c
以该顺序。
该
HANDLER
语句可以指定索引中所有三列的值,也可以指定最左侧前缀中的列。
例如:
HANDLER ...阅读my_idx =(col_a_val,col_b_val,col_c_val)...... HANDLER ...阅读my_idx =(col_a_val,col_b_val)...... HANDLER ...阅读my_idx =(col_a_val)......
要使用
HANDLER
接口来引用表
PRIMARY KEY
,请使用带引号的标识符
`PRIMARY`
:
HANDLER tbl_name
阅读`PRIMARY` ...
第二种
HANDLER ... READ
语法以与
WHERE
条件
匹配的索引顺序从表中获取一行
。
第三种
HANDLER ... READ
语法以自然行顺序从表中获取与
WHERE
条件
匹配的行
。
它比
需要全表扫描时
更快
。
自然行顺序是行存储在
表数据文件中
的顺序
。
此语句也适用于
表,但没有这样的概念,因为没有单独的数据文件。
HANDLER
tbl_name
READ
index_name
MyISAM
InnoDB
如果没有
LIMIT
子句,所有形式的
HANDLER ... READ
获取单行(如果有)。
要返回特定数量的行,请包含
LIMIT
子句。
它具有与
SELECT
语句
相同的语法
。
请参见
第13.2.10节“SELECT语法”
。
HANDLER ... CLOSE
关闭一个打开的表
HANDLER ... OPEN
。
使用
HANDLER
接口而不是普通
SELECT
语句
有几个原因
:
HANDLER
比
SELECT
以下
更快
:
HANDLER
可以更轻松地移植到使用类似低级
ISAM
接口的
MySQL应用程序
。
(有关
调整使用键值存储范例的应用程序的替代方法,
请参见
第15.19节“InnoDB memcached插件”
。)
HANDLER
使您能够以难以(甚至不可能)完成的方式遍历数据库
SELECT
。
该
HANDLER
接口是与提供的交互式用户界面到数据库的应用程序时,看数据更自然的方式。
HANDLER
是一个有点低级的声明。
例如,它不提供一致性。
也就是说,
HANDLER ... OPEN
它
不
走表的快照,并
不能
锁定表。
这意味着在发出
HANDLER ...
OPEN
语句
后
,可以修改表数据(通过当前会话或其他会话),并且这些修改可能仅部分可见
HANDLER ...
NEXT
或
HANDLER ... PREV
扫描。
打开处理程序可以关闭并标记为重新打开,在这种情况下,处理程序将丢失其在表中的位置。 当以下两种情况都成立时会发生这种情况:
任何会话
FLUSH
TABLES
在处理程序表上
执行
或DDL语句。
处理程序处于打开状态的会话执行
HANDLER
使用表的
非
语句。
TRUNCATE
TABLE
对于表关闭所有打开的表的处理程序
HANDLER
OPEN
。
如果使用
打开
的表刷新表
,则会隐式刷新处理程序并丢失其位置。
FLUSH
TABLES
tbl_name
WITH READ
LOCKHANDLER
进口表来自sdi_file
[,sdi_file
] ......
该
IMPORT
TABLE
语句
MyISAM
根据
.sdi
(序列化字典信息)元数据文件中
包含的信息
导入
表
。
IMPORT
TABLE
需要
FILE
权限来读取
.sdi
和表内容文件,以及
CREATE
要创建的表
特权。
可以使用
mysqldump
从一个服务器导出表
以编写SQL语句文件,并使用
mysql
导入到另一个服务器
以处理转储文件。
IMPORT
TABLE
使用
“
原始
”
表文件
提供更快的替代方案
。
在导入之前,提供表内容的文件必须放在导入服务器的相应模式目录中,并且该
.sdi
文件必须位于服务器可访问的目录中。
例如,
.sdi
文件可以放在
secure_file_priv
系统变量
指定的目录中
,或者(如果
secure_file_priv
为空)放在服务器数据目录下的目录中。
以下示例描述如何
从
一个服务器
的
模式
导出已
MyISAM
命名的表
employees
,
并将其导入
另一个服务器
的
模式。
该示例使用这些假设(在您自己的系统上执行类似的操作,根据需要修改路径名称):
managers
hr
hr
对于导出服务器,
export_basedir
表示其基本目录,其数据目录为
。
export_basedir
/data
对于导入服务器,
import_basedir
表示其基本目录,其数据目录为
。
import_basedir
/data
表文件从导出服务器导出到
/tmp/export
目录中,并且此目录是安全的(其他用户无法访问)。
导入服务器
/tmp/mysql-files
用作其
secure_file_priv
系统变量
命名的目录
。
要从导出服务器导出表,请使用以下过程:
通过执行此语句来锁定表以确保在导出期间无法修改表,从而确保一致的快照:
MySQL的> FLUSH TABLES hr.employees, hr.managers WITH READ LOCK;
锁定有效时,表仍然可以使用,但仅用于读取访问。
在文件系统级别,将
schema
.sdi
和table内容文件从
hr
schema目录
复制
到安全导出目录:
该
.sdi
文件位于
hr
架构目录中,但可能与表名称的基本名称不完全相同。
例如,
.sdi
对于文件
employees
和
managers
表可能被命名为
employees_125.sdi
和
managers_238.sdi
。
对于
MyISAM
表,内容文件是其
.MYD
数据文件和
.MYI
索引文件。
给定这些文件名,复制命令如下所示:
shell> shell> shell> shell> shell>cd
export_basedir
/data/hrcp employees_125.sdi /tmp/export
cp managers_238.sdi /tmp/export
cp employees.{MYD,MYI} /tmp/export
cp managers.{MYD,MYI} /tmp/export
解锁桌子:
MySQL的> UNLOCK TABLES;
要将表导入导入服务器,请使用以下过程:
导入架构必须存在。 如有必要,执行此语句以创建它:
MySQL的> CREATE SCHEMA hr;
在文件系统级别,将
.sdi
文件
复制
到导入服务器
secure_file_priv
目录,
/tmp/mysql-files
。
另外,将表内容文件复制到
hr
架构目录:
shell>cd /tmp/export
shell>cp employees_125.sdi /tmp/mysql-files
shell>cp managers_238.sdi /tmp/mysql-files
shell> shell>cp employees.{MYD,MYI}
import_basedir
/data/hrcp managers.{MYD,MYI}
import_basedir
/data/hr
通过执行
IMPORT
TABLE
命名的语句来
导入表
.sdi
文件
:
MySQL的>IMPORT TABLE FROM
'/tmp/mysql-files/employees.sdi',
'/tmp/mysql-files/managers.sdi';
如果该变量为空,则
.sdi
不需要
将该
文件放在
secure_file_priv
系统变量
指定的导入服务器目录中
;
它可以位于服务器可访问的任何目录中,包括导入表的架构目录。
.sdi
但是,
如果
文件放在该目录中,则可以重写;
导入操作会
.sdi
为表
创建一个新
文件,
.sdi
如果操作对新文件使用相同的文件名
,则会覆盖旧
文件。
每个
sdi_file
值必须是一个字符串文字,
.sdi
用于为表
命名
文件或者是与
.sdi
文件
匹配的模式
。
如果字符串是模式,则
.sdi
必须按字面指定
任何前导目录路径和
文件名后缀。
仅在文件名的基本名称部分允许使用模式字符:
?
匹配任何单个字符
*
匹配任何字符序列,包括没有字符
使用模式,前面的
IMPORT
TABLE
语句可能是这样编写的(假设该
/tmp/mysql-files
目录不包含其他
语句)
.sdi
与模式匹配的
文件):
IMPORT TABLE FROM'/ tmp / mysql-files / *。sdi';
要解释
.sdi
文件路径名
的位置
,服务器将使用与
IMPORT
TABLE
服务器端规则
相同的规则
LOAD
DATA
(即非
LOCAL
规则)。
请参见
第13.2.7节“LOAD DATA语法”
,特别注意用于解释相对路径名的规则。
IMPORT
TABLE
如果无法找到
.sdi
或表文件,则会
失败
。
导入表后,服务器会尝试打开它,并在检测到任何问题时报告为警告。
要尝试修复以更正任何报告的问题,请使用
REPAIR
TABLE
。
IMPORT
TABLE
没有写入二进制日志。
IMPORT
TABLE
仅适用于非
TEMPORARY
MyISAM
表格。
它不适用于使用事务存储引擎创建的表,使用创建的表
CREATE
TEMPORARY
TABLE
或视图。
除非导出服务器上定义的表使用
DATA DIRECTORY
或
INDEX
DIRECTORY
表选项
,否则必须在导入操作之前将表数据和索引文件放在导入服务器的模式目录中
。
在这种情况下,在执行
IMPORT
TABLE
语句
之前使用以下备选方案之一修改导入过程
:
将数据和索引文件放在导入服务器主机上与导出服务器主机上相同的目录中,并在导入服务器模式目录中为这些文件创建符号链接。
将数据和索引文件放入与导出服务器主机上的导入服务器主机目录不同的导入服务器主机目录中,并在导入服务器模式目录中为这些文件创建符号链接。
此外,修改
.sdi
文件以反映不同的文件位置。
将数据和索引文件放入导入服务器主机上的架构目录中,并修改该
.sdi
文件以删除数据和索引目录表选项。
存储在
.sdi
文件
中的任何归类ID
必须引用导出和导入服务器上的相同归类。
表的触发器信息未序列化到表
.sdi
文件中,因此导入操作不会还原触发器。
.sdi
在执行
IMPORT
TABLE
语句
之前允许
对
文件进行
一些编辑
,而其他文件是有问题的,甚至可能导致导入操作失败:
如果导出和导入服务器之间的数据和索引文件的位置不同,则需要更改数据目录和索引目录表选项。
需要更改模式名称才能将表导入导入服务器上的不同模式,而不是导出服务器上。
可能需要更改模式和表名称以适应导出和导入服务器上的文件系统区分大小写语义之间的差异或
lower_case_table_names
设置的
差异
。
更改
.sdi
文件中
的表名
可能也需要重命名表文件。
在某些情况下,允许更改列定义。 更改数据类型可能会导致问题。
INSERT [LOW_PRIORITY | 延迟| HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
[PARTITION(partition_name
[,partition_name
] ...)] [(col_name
[,col_name
] ......)] {VALUES | VALUE}(value_list
)[,(value_list
)] ...... [ON DUPLICATE KEY UPDATEassignment_list
] INSERT [LOW_PRIORITY | 延迟| HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
[PARTITION(partition_name
[,partition_name
] ...)] SETassignment_list
[ON DUPLICATE KEY UPDATEassignment_list
] INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
[PARTITION(partition_name
[,partition_name
] ...)] [(col_name
[,col_name
] ......)] 选择 ... [ON DUPLICATE KEY UPDATEassignment_list
]value
: {expr
| 默认}value_list
:value
[,value
] ......assignment
:col_name
=value
assignment_list
:assignment
[,assignment
] ......
INSERT
将新行插入现有表中。
该
INSERT
... VALUES
和
INSERT
... SET
语句的形式插入基于明确指定的值的行。
的
INSERT
... SELECT
形式插入从另一个或多个表中选择行。
如果要插入的行会导致
索引中
的重复值,则
INSERT
使用
ON DUPLICATE KEY UPDATE
子句可以更新现有行
。
UNIQUE
PRIMARY
KEY
有关更多信息
INSERT ...
SELECT
,并
INSERT ... ON
DUPLICATE KEY UPDATE
请参见
第13.2.6.1,“INSERT ... SELECT语法”
和
第13.2.6.2,“插入...对重复密钥更新语法”
。
在MySQL 8.0中,
DELAYED
关键字被接受但被服务器忽略。
有关此原因,请参见
第13.2.6.3节“INSERT DELAYED语法”
,
插入表需要表的
INSERT
权限。
如果使用该
ON DUPLICATE KEY UPDATE
子句并且重复键导致
UPDATE
执行,则该语句需要
UPDATE
更新列
的
权限。
对于已读但未修改的列,您只需要该
SELECT
权限(例如,对于仅在
子句中
col_name
=
expr
赋值
的右侧引用的列
ON DUPLICATE KEY UPDATE
)。
插入分区表时,可以控制哪些分区和子分区接受新行。
该
PARTITION
选项获取表的一个或多个分区或子分区(或两者)的逗号分隔名称列表。
如果给定
INSERT
语句
要插入的任何行与
列出的其中一个分区不匹配,则该
INSERT
语句将失败,并显示错误“
找到与给定分区集不匹配的行”
。
有关更多信息和示例,请参见
第23.5节“分区选择”
。
您可以使用
REPLACE
而不是
INSERT
覆盖旧行。
REPLACE
是
INSERT
IGNORE
处理包含复制旧行的唯一键值的新行
的对应物
:新行替换旧行而不是丢弃。
请参见
第13.2.9节“REPLACE语法”
。
tbl_name
是应该插入行的表。
指定语句提供值的列,如下所示:
在表名后面提供以逗号分隔的列名的括号列表。
在这种情况下,每个命名列的值必须由
VALUES
列表或
SELECT
语句提供。
如果没有为
INSERT
...
VALUES
or
指定列名列表,
INSERT ...
SELECT
则表中每列的值必须由
VALUES
列表或
SELECT
语句提供。
如果您不知道表中列的顺序,请使用
以查找。
DESCRIBE
tbl_name
甲
SET
子句表示列明确地通过名称,与分配每一个的值一起。
列值可以通过多种方式给出:
如果未启用严格SQL模式,则任何未显式赋值的列都将设置为其默认值(显式或隐式)。 例如,如果指定的列列表未指定表中的所有列,则将未命名的列设置为其默认值。 第11.7节“数据类型默认值”中 描述了默认值分配 。 另请参见 第1.8.3.3节“无效数据的约束” 。
如果启用了严格SQL模式,则如果
INSERT
语句没有为没有默认值的每个列指定显式值
,则会
生成错误。
请参见
第5.1.11节“服务器SQL模式”
。
如果列列表和
VALUES
列表都为空,
INSERT
创建一行,并将每列设置为其默认值:
插入 tbl_name
()VALUES();
如果未启用严格模式,则MySQL会对没有显式定义的默认值的任何列使用隐式默认值。 如果启用了严格模式,则如果任何列没有默认值,则会发生错误。
使用关键字
DEFAULT
将列显式设置为其默认值。
这使得编写
INSERT
为除了几列之外的所有列分配值的语句
变得更容易
,因为它使您能够避免编写
VALUES
不包含表中每列的值
的不完整
列表。
否则,您必须提供与列表中每个值对应的列名
VALUES
列表。
如果显式插入生成的列,则唯一允许的值为
DEFAULT
。
有关生成的列的信息,请参见
第13.1.20.9节“创建表和生成的列”
。
在表达式中,您可以使用它
来生成列的默认值
。
DEFAULT(
col_name
)col_name
expr
如果表达式数据类型与列数据类型不匹配,则可能会发生提供列值
的表达式的类型转换
。
转换给定值可能会导致不同的插入值,具体取决于列类型。
例如,将所述字符串
'1999.0e-2'
成
INT
,
FLOAT
,
DECIMAL(10,6)
,或
YEAR
列中的值插入
1999
,
19.9921
,
19.992100
,或
1999
,分别。
存储在
INT
和
YEAR
列中
的值
是
1999
因为字符串到数字的转换只能看到字符串的初始部分,因为它可能被视为有效的整数或年份。
对于
FLOAT
和
DECIMAL
列,字符串到数字的转换将整个字符串视为有效的数值。
表达式
expr
可以引用先前在值列表中设置的任何列。
例如,您可以执行此操作,因为
之前已分配的
col2
引用
值
col1
:
INSERT INTO tbl_name
(col1,col2)VALUES(15,col1 * 2);
但以下是不合法的,因为参考的值是
col1
指
col2
之后的
col1
:
INSERT INTO tbl_name
(col1,col2)VALUES(col2 * 2,15);
包含
AUTO_INCREMENT
值的
列发生异常
。
由于
AUTO_INCREMENT
值是在其他值赋值之后生成的
AUTO_INCREMENT
,因此对赋值中
的
列的
任何引用都会
返回a
0
。
INSERT
使用的陈述
VALUES
语法的语句可以插入多行。
为此,请包含多个以逗号分隔的列值列表,其中列表括在括号中并用逗号分隔。
例:
插入 tbl_name
(a,b,c)值(1,2,3),(4,5,6),(7,8,9);
每个值列表必须包含与每行插入的值完全相同的值。 以下语句无效,因为它包含一个包含九个值的列表,而不是三个包含三个值的列表:
插入tbl_name
(a,b,c)价值观(1,2,3,4,5,6,7,8,9);
VALUE
是
VALUES
这种情况下
的同义词
。
既不会暗示值列表的数量,也不暗示每个列表的值的数量。
无论是单个值列表还是多个列表,都可以使用,无论每个列表的值的数量是多少。
INSERT
可以使用
ROW_COUNT()
SQL函数或
mysql_affected_rows()
C API函数
获取
an的affected-rows值
。
请参见
第12.15节“信息函数”
和
第28.7.7.1节“mysql_affected_rows()”
。
如果使用
INSERT
...
VALUES
带有多个值列表
INSERT ...
SELECT
的语句,则该语句将返回以下格式的信息字符串:
记录:N1
重复:N2
警告:N3
如果您使用的是C API,则可以通过调用该
mysql_info()
函数
来获取信息字符串
。
请参见
第28.7.7.36节“mysql_info()”
。
Records
表示语句处理的行数。
(这不一定是实际插入的行数,因为
Duplicates
它可能非零。)
Duplicates
表示无法插入的行数,因为它们会复制某些现有的唯一索引值。
Warnings
表示以某种方式插入有问题的列值的尝试次数。
在以下任何条件下都可能发生警告:
插入
NULL
已声明的列
NOT NULL
。
对于多行
INSERT
语句或
INSERT INTO ...
SELECT
语句,该列设置为列数据类型的隐式默认值。
这适用
0
于数字类型,字符串类型为空字符串(
''
)
,日期和时间类型为
“
零
”
值。
INSERT INTO ...
SELECT
语句的处理方式与多行插入的处理方式相同,因为服务器不检查结果集
SELECT
以查看它是否返回单行。
(对于单行
INSERT
,
NULL
插入
时不会发出警告
NOT
NULL
柱。
相反,该语句失败并出现错误。)
将数字列设置为位于列范围之外的值。 该值将剪切到范围的最近端点。
将值分配
'10.34 a'
给数字列。
将删除尾随的非数字文本,并插入剩余的数字部分。
如果字符串值没有前导数字部分,则列设置为
0
。
插入一个字符串转换成一个字符串柱(
CHAR
,
VARCHAR
,
TEXT
,或
BLOB
),其超过了列的最大长度。
该值将截断为列的最大长度。
将值插入对数据类型不合法的日期或时间列。 该列设置为该类型的适当零值。
有关
列值的
INSERT
示例
AUTO_INCREMET
,请参见
第3.6.9节“使用AUTO_INCREMENT”
。
如果
INSERT
将行插入到具有
AUTO_INCREMENT
列
的表中,则
可以使用
LAST_INSERT_ID()
SQL函数或
mysql_insert_id()
C API函数
找到用于该列的值
。
这两个函数的行为并不总是相同。
第12.15节“信息函数”
和
第28.7.7.38节“mysql_insert_id()”中
进一步讨论了有关列
的
INSERT
语句
行为
。
AUTO_INCREMENT
该
INSERT
语句支持以下修饰符:
如果使用
LOW_PRIORITY
修饰符,
INSERT
则会延迟
执行,
直到没有其他客户端从表中读取。
这包括在现有客户端正在阅读时开始阅读的其他客户端,以及
INSERT
LOW_PRIORITY
语句等待时。
因此,发布
INSERT
LOW_PRIORITY
语句
的客户端可能
需要等待很长时间。
LOW_PRIORITY
影响使用仅表级锁定仅存储引擎(如
MyISAM
,
MEMORY
,和
MERGE
)。
LOW_PRIORITY
通常不应该与
MyISAM
表
一起使用,
因为这样做会禁用并发插入。
请参见
第8.11.3节“并发插入”
。
如果指定
HIGH_PRIORITY
,则在
--low-priority-updates
使用该选项启动服务器时
,它将覆盖该
选项
的效果
。
它还会导致不使用并发插入。
请参见
第8.11.3节“并发插入”
。
HIGH_PRIORITY
影响使用仅表级锁定仅存储引擎(如
MyISAM
,
MEMORY
,和
MERGE
)。
如果使用
IGNORE
修饰符,
INSERT
则忽略
执行
语句
时发生的错误
。
例如,如果没有
IGNORE
,则复制
表中
现有
UNIQUE
索引或
PRIMARY KEY
值
的行
会导致重复键错误,并且语句将中止。
使用时
IGNORE
,该行将被丢弃并且不会发生错误。
忽略的错误会生成警告。
IGNORE
对插入到分区表中的效果类似,其中没有找到与给定值匹配的分区。
没有
IGNORE
,这样的
INSERT
语句会因错误而中止。
当
INSERT
IGNORE
被使用时,插入操作默默地失效含有不匹配的值的行,但会插入匹配的行。
有关示例,请参见
第23.2.2节“LIST分区”
。
如果
IGNORE
未指定
,将触发错误的数据转换将中止语句
。
使用时
IGNORE
,将无效值调整为最接近的值并插入;
产生警告,但声明不会中止。
您可以使用
mysql_info()
C API函数
确定
实际插入表中的行数。
有关更多信息,请参阅 IGNORE关键字和严格SQL模式的比较 。
如果指定
ON DUPLICATE KEY UPDATE
,行插入,将在导致重复值
UNIQUE
索引或者
PRIMARY
KEY
,一个
UPDATE
旧行的发生。
如果将行作为新行插入,则每行的受影响行值为1;如果更新现有行,则为2,如果现有行设置为其当前值,则为0。
如果
在连接到
mysqld
时
指定
C API函数
的
CLIENT_FOUND_ROWS
标志,则
如果将现有行设置为其当前值,则affected-rows值为1(不为0)。
请参见
第13.2.6.2节“INSERT ... ON DUPLICATE KEY UPDATE语法”
。
mysql_real_connect()
INSERT
DELAYED
在MySQL 5.6中已弃用,并计划最终删除。
在MySQL 8.0中,
DELAYED
修饰符被接受但被忽略。
使用
INSERT
(不
DELAYED
)代替。
请参见
第13.2.6.3节“INSERT DELAYED语法”
。
INSERT
使用存储引擎(例如
MyISAM
使用表级锁)
影响分区表
的
语句
仅锁定实际插入行的分区。
(对于
InnoDB
使用行级锁定的
存储引擎
,不会发生分区锁定。)有关更多信息,请参阅
分区和锁定
。
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE] [INTO]tbl_name
[PARTITION(partition_name
[,partition_name
] ...)] [(col_name
[,col_name
] ......)] 选择 ... [ON DUPLICATE KEY UPDATEassignment_list
]value
: {expr
| 默认}assignment
:col_name
=value
assignment_list
:assignment
[,assignment
] ......
使用
INSERT ...
SELECT
,您可以根据
SELECT
语句
的结果快速将多行插入到表中,该
语句可以从一个或多个表中进行选择。
例如:
INSERT INTO tbl_temp2(fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id> 100;
以下条件适用于
INSERT ...
SELECT
陈述:
指定
IGNORE
忽略会导致重复键违规的行。
INSERT
语句
的目标表
可能出现在
查询部分
的
FROM
子句中
SELECT
。
但是,您无法插入表中并从子查询中的同一表中进行选择。
当从同一个表中进行选择和插入时,MySQL会创建一个内部临时表来保存行中的行
SELECT
,然后将这些行插入到目标表中。
但是,您不能
INSERT INTO t ... SELECT ... FROM t
在何时
t
使用
TEMPORARY
表,因为
TEMPORARY
表不能在同一语句中引用两次。
请参见
第8.4.4节“MySQL中的内部临时表使用”
和
第B.4.6.2节“临时表问题”
。
AUTO_INCREMENT
列像往常一样工作。
为确保二进制日志可用于重新创建原始表,MySQL不允许对
INSERT
... SELECT
语句
进行并发插入
(请参见
第8.11.3节“并发插入”
)。
为了避免
SELECT
在
INSERT
引用同一个表
时出现模糊的列引用问题
,
请为
SELECT
部件
中使用的每个表提供唯一的别名
,并使用适当的别名限定
该
部分中的列名。
您可以显式选择源表或目标表(或两者)的哪些分区或子分区(或两者)与表
PARTITION
的名称后面的选项
一起使用
。
如果
在语句
PARTITION
的
SELECT
部分
中使用源表的名称,则
仅从其分区列表中指定的分区或子分区中选择行。
当
PARTITION
与
INSERT
语句部分
的目标表的名称一起使用时
,必须可以将选定的所有行插入到该选项后面的分区列表中指定的分区或子分区中。
否则,该
INSERT ...
SELECT
语句失败。
有关更多信息和示例,请参阅
第23.5节“分区选择”
。
有关
INSERT
... SELECT
语句,请参见
第13.2.6.2节“INSERT ... ON DUPLICATE KEY UPDATE语法”,
了解
SELECT
可在
ON DUPLICATE KEY UPDATE
子句中
引用列的
条件
。
SELECT
带有no
ORDER BY
子句的语句返回行
的顺序
是不确定的。
这意味着,在使用复制时,无法保证此类
SELECT
在主服务器和从服务器上以相同的顺序返回行,这可能导致它们之间的不一致。
要防止这种情况发生,请始终
INSERT ... SELECT
使用
ORDER BY
在主服务器和从服务器上生成相同行顺序
的
子句
编写
要复制的
语句。
另请参见
第17.4.1.18节“复制和限制”
。
由于这个问题,
INSERT ...
SELECT ON DUPLICATE KEY UPDATE
并
INSERT IGNORE ...
SELECT
声明是基于语句的复制标记为不安全。
当使用基于语句的模式时,此类语句在错误日志中生成警告,并在使用
MIXED
模式
时使用基于行的格式写入二进制日志
。
(Bug#11758262,Bug#50439)
另请参见 第17.2.1.1节“基于语句和基于行的复制的优点和缺点” 。
INSERT ... SELECT
使用存储引擎(例如
MyISAM
使用表级锁)
影响分区表
的
语句
会锁定目标表的所有分区;
但是,只有那些实际从源表中读取的分区才会被锁定。
(对于使用存储引擎的表,例如
InnoDB
使用行级锁定的
表,不会发生这种情况
。)有关更多信息,请参阅
分区和锁定
。
如果指定
ON DUPLICATE KEY UPDATE
子句并且要插入的行将导致
UNIQUE
索引中
出现重复值,
则会出现旧行的
PRIMARY
KEY
某个
UPDATE
行。
例如,如果将column
a
声明为
UNIQUE
并包含该值
1
,则以下两个语句具有类似的效果:
插入t1(a,b,c)值(1,2,3) ON DUPLICATE KEY UPDATE c = c + 1; 更新t1 SET c = c + 1 WHERE a = 1;
(对于
自动增量列
的
InnoDB
表,
效果不相同
a
。对于自动增量列,
INSERT
语句会增加自动增量值,但
UPDATE
不会。)
如果column
b
也是唯一的,
INSERT
则相当于此
UPDATE
语句:
UPDATE t1 SET c = c + 1 WHERE a = 1 OR b = 2 LIMIT 1;
如果
a=1 OR b=2
几个行相匹配,只有
一个
行被更新。
通常,您应该尽量避免
ON DUPLICATE KEY UPDATE
在具有多个唯一索引的表上
使用
子句。
对于
ON DUPLICATE KEY UPDATE
,如果将行作为新行插入,则每行的受影响行值为1;如果更新现有行,则为2,如果现有行设置为其当前值,则为0。
如果
在连接到
mysqld
时
指定
C API函数
的
CLIENT_FOUND_ROWS
标志,则
如果将现有行设置为其当前值,则affected-rows值为1(不为0)。
mysql_real_connect()
如果表包含
AUTO_INCREMENT
列并
INSERT
... ON DUPLICATE KEY UPDATE
插入或更新行,则该
LAST_INSERT_ID()
函数返回该
AUTO_INCREMENT
值。
该
ON DUPLICATE KEY UPDATE
子句可以包含多个列分配,以逗号分隔。
在
ON DUPLICATE KEY
UPDATE
子句
中的赋值表达式中
,您可以使用该
函数来引用
语句
部分中的
列值
。
换句话说,
在
子句中引用了
将插入
的值
,没有发生重复键冲突。
此功能在多行插入中特别有用。
该
函数仅在
子句或
语句中
有意义
,
否则
返回
。
例:
VALUES(
col_name
)INSERT
INSERT ...
ON DUPLICATE KEY UPDATE
VALUES(
col_name
)ON DUPLICATE KEY UPDATE
col_name
VALUES()
ON DUPLICATE KEY UPDATE
INSERT
NULL
插入t1(a,b,c)值(1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE c = VALUES(a)+ VALUES(b);
该陈述与以下两个陈述相同:
插入t1(a,b,c)值(1,2,3) ON DUPLICATE KEY UPDATE c = 3; 插入到t1(a,b,c)值(4,5,6) ON DUPLICATE KEY UPDATE c = 9;
对于
INSERT
... SELECT
语句,这些规则适用于
SELECT
您可以在
ON DUPLICATE KEY
UPDATE
子句中
引用的
可接受形式的
查询表达式
:
对单个表上的查询的列的引用,该表可以是派生表。
对多个表上的连接的查询引用列。
引用
DISTINCT
查询中的
列
。
引用其他表中的列,只要
SELECT
不使用
GROUP BY
。
一个副作用是您必须限定对非唯一列名的引用。
UNION
不支持
对a
中
列的引用
。
要解决此限制,请将
UNION
其
重写
为派生表,以便可以将其行视为单表结果集。
例如,此语句产生错误:
插入到t1(a,b) SELECT c,d FROM t2 联盟 SELECT e,f FROM t3 ON DUPLICATE KEY UPDATE b = b + c;
相反,使用重写
UNION
为派生表
的等效语句
:
插入到t1(a,b) SELECT * FROM (SELECT c,d FROM t2 联盟 选择e,f FROM t3)AS dt ON DUPLICATE KEY UPDATE b = b + c;
将查询重写为派生表的技术还允许从
GROUP BY
查询中
引用列
。
因为
INSERT ...
SELECT
语句
的结果
取决于来自的
SELECT
顺序,并且无法始终保证此顺序,所以当
INSERT ...
SELECT ON DUPLICATE KEY UPDATE
主服务器和从服务器的
日志记录
发散
时,可能会发生这种情况
。
因此,
INSERT ...
SELECT ON DUPLICATE KEY UPDATE
语句被标记为基于语句的复制不安全。
当使用基于语句的模式时,此类语句在错误日志中生成警告,并在使用
MIXED
模式
时使用基于行的格式写入二进制日志
。
INSERT ...
ON DUPLICATE KEY UPDATE
对具有多个唯一键或主键的表
的
声明也标记为不安全。
(Bug#11765650,Bug#58637)
另请参见 第17.2.1.1节“基于语句和基于行的复制的优点和缺点” 。
一个
INSERT ... ON DUPLICATE KEY UPDATE
使用的存储引擎,诸如分区表
MyISAM
,其使用表级锁锁定在其中一个分区键列被更新表中的任何分区。
(对于使用存储引擎的表,例如
InnoDB
使用行级锁定的
表,不会发生这种情况
。)有关更多信息,请参阅
分区和锁定
。
INSERT DELAYED ...
该
语句
的
DELAYED
选项
INSERT
是标准SQL的MySQL扩展。
在以前版本的MySQL中,它可以用于某些类型的表(例如
MyISAM
),这样当客户端使用时
INSERT DELAYED
,它可以立即从服务器获得,并且当表不是时,行排队等待插入由任何其他线程使用。
DELAYED
MySQL 5.6中不推荐使用插入和替换。
在MySQL 8.0中,
DELAYED
不受支持。
服务器识别但忽略
DELAYED
关键字,将插入作为非延迟插入处理,并生成
ER_WARN_LEGACY_SYNTAX_CONVERTED
警告(
“
不再支持INSERT DELAYED。语句已转换为INSERT
”
)。
该
DELAYED
关键字计划在将来的版本中删除。
负载数据 [LOW_PRIORITY | CONCURRENT] [当地] INFILE'file_name
' [REPLACE | 忽视] INTO TABLEtbl_name
[PARTITION(partition_name
[,partition_name
] ...)] [字符集charset_name
] [{FIELDS | 列} [终止于'string
'] [[OPTIONALLY]封闭'char
'] [ESCAPED BY'char
'] ] [LINES [开始'string
'] [终止于'string
'] ] [IGNOREnumber
{LINES | ROWS}] [(col_name_or_user_var
[,col_name_or_user_var
] ......)] [SETcol_name
= {expr
| 默认}, [,col_name
= {expr
| DEFAULT}] ...]
该
LOAD
DATA
语句以非常高的速度将文本文件中的行读入表中。
LOAD
DATA
是补充
SELECT ... INTO
OUTFILE
。
(请参见
第13.2.10.1节“SELECT ... INTO语法”
。)要将表中的数据写入文件,请使用
SELECT ... INTO
OUTFILE
。
要将文件读回表中,请使用
LOAD
DATA
。
两个语句
的
FIELDS
和
LINES
子句
的语法
相同。
您还可以使用
mysqlimport
实用程序
加载数据文件
;
请参见
第4.5.5节“
mysqlimport
- 数据导入程序”
。
mysqlimport
通过向
LOAD
DATA
服务器
发送
语句来进行操作。
有关效率的详细信息
INSERT
与
LOAD
DATA
和加速
LOAD
DATA
,请参见
第8.2.5.1,“优化INSERT语句”
。
LOAD
DATA
支持显式分区选择,使用
PARTITION
带有一个或多个以逗号分隔的分区,子分区或两者的名称列表
的
选项。
使用此选项时,如果文件中的任何行无法插入列表中指定的任何分区或子分区,则语句将失败,并显示错误“
找到与给定分区集不匹配的行”
。
有关更多信息和示例,请参见
第23.5节“分区选择”
。
对于使用使用表锁的存储引擎的分区表,例如
MyISAM
,
LOAD
DATA
无法修剪任何分区锁。
这不适用于使用采用行级锁定的存储引擎的表,例如
InnoDB
。
有关更多信息,请参阅
分区和锁定
。
文件名必须以文字字符串形式给出。
在Windows上,将路径名中的反斜杠指定为正斜杠或加倍反斜杠。
该
character_set_filesystem
系统变量控制的文件名字符集的解释。
服务器使用
character_set_database
系统变量
指示的字符集
来解释文件中的信息。
SET
NAMES
并且设置
character_set_client
不影响输入的解释。
如果输入文件的内容使用的字符集与默认值不同,通常最好使用该
CHARACTER SET
子句
指定文件的字符集
。
字符集
binary
指定
“
无转换。
”
LOAD
DATA
无论加载字段值的列的数据类型如何,都将文件中的所有字段解释为具有相同的字符集。
要正确解释文件内容,必须确保使用正确的字符集编写它。
例如,如果使用
mysqldump -T
编写数据文件
或
SELECT
... INTO OUTFILE
在
mysql中
发出
语句
,请务必使用
--default-character-set
选项,以便在加载文件时使用的字符集中输出输出
LOAD
DATA
。
这是不可能的加载使用数据文件
ucs2
,
utf16
,
utf16le
,或者
utf32
字符集。
如果使用
LOW_PRIORITY
修饰符,则
LOAD
DATA
语句的
执行将
延迟,直到没有其他客户端从表中读取。
这会影响只使用表级锁只存储引擎(例如
MyISAM
,
MEMORY
和
MERGE
)。
如果使用
满足并发插入条件
CONCURRENT
的
MyISAM
表
指定
修饰符
(即,它在中间不包含空闲块),则其他线程可以在
LOAD
DATA
执行时
从表中检索数据
。
LOAD
DATA
即使没有其他线程同时使用该表,
此修饰符
也会
影响
位
的性能
。
有关
LOAD
DATA
复制的信息,请参见
第17.4.1.19节“复制和装入数据”
。
该
LOCAL
修改影响的文件和错误处理预期的位置,如下文所述。
LOCAL
仅当您的服务器和客户端都已配置为允许它时才有效。
例如,如果
mysqld
在
local_infile
禁用系统变量的情况
下启动
,
LOCAL
则不起作用。
请参见
第6.1.6节“LOAD DATA LOCAL的安全问题”
。
该
LOCAL
修改会影响该文件预计将发现:
如果
LOCAL
指定,则文件由客户端主机上的客户端程序读取并发送到服务器。
该文件可以作为完整路径名提供,以指定其确切位置。
如果以相对路径名的形式给出,则相对于启动客户端程序的目录解释名称。
使用
LOCAL
时
LOAD
DATA
,会在MySQL服务器存储临时文件的目录中创建该文件的副本。
请参见
第B.4.3.5节“MySQL存储临时文件的位置”
。
此目录中的副本缺少足够的空间可能导致
LOAD
DATA
LOCAL
语句失败。
如果
LOCAL
未指定,则文件必须位于服务器主机上,并由服务器直接读取。
服务器使用以下规则来定位文件:
如果文件名是绝对路径名,则服务器将其用作给定的名称。
如果文件名是具有一个或多个前导组件的相对路径名,则服务器将搜索相对于服务器数据目录的文件。
如果给出没有前导组件的文件名,则服务器在默认数据库的数据库目录中查找该文件。
在非本
LOCAL
例中,这些规则意味着
./myfile.txt
从服务器的数据目录
myfile.txt
中读取
名为的文件,而
从默认数据库的数据库目录中读取
名为的文件
。
例如,如果
db1
是缺省数据库,则以下
LOAD
DATA
语句
data.txt
将从数据库目录中
读取该文件
db1
,即使该语句显式将该文件加载到
db2
数据库中
的表中
:
LOAD DATA INFILE'Data.txt'INTO TABLE db2.my_table;
服务器还使用非
LOCAL
规则来定位
语句的
.sdi
文件
IMPORT
TABLE
。
非
LOCAL
加载操作读取位于服务器上的文本文件。
出于安全原因,此类操作要求您拥有该
FILE
权限。
请参见
第6.2.2节“MySQL提供的权限”
。
此外,非
LOCAL
加载操作受
secure_file_priv
系统变量设置的限制。
如果变量值是非空目录名,则要加载的文件必须位于该目录中。
如果变量值为空(这是不安全的),则文件只需要服务器可读。
使用
LOCAL
比让服务器直接访问文件要慢一些,因为文件内容必须通过客户端连接发送到服务器。
另一方面,您不需要该
FILE
权限来加载本地文件。
LOCAL
也会影响错误处理:
使用
LOAD
DATA
,数据解释和重复键错误会终止操作。
随着
LOAD
DATA
LOCAL
,数据解释和重复键错误成为警告,并且操作继续,因为服务器无法在操作过程中停止传输文件。
对于重复键错误,这与
IGNORE
指定
的相同
。
IGNORE
本节后面将进一步解释。
在
REPLACE
与
IGNORE
输入行的修饰处理控制复制唯一键值的现有行:
如果指定
REPLACE
,则输入行将替换现有行。
换句话说,主键或唯一索引的值与现有行的值相同。
请参见
第13.2.9节“REPLACE语法”
。
如果指定
IGNORE
,则会丢弃复制唯一键值上现有行的行。
有关更多信息,请参阅
IGNORE关键字和严格SQL模式的比较
。
如果未指定任何修饰符,则行为取决于是否
LOCAL
指定
了
修饰符。
如果没有
LOCAL
,则在找到重复键值时会发生错误,并忽略文本文件的其余部分。
使用时
LOCAL
,默认行为与
IGNORE
指定
的相同
;
这是因为服务器无法在操作过程中停止传输文件。
要在加载操作期间忽略外键约束,请在执行
SET foreign_key_checks = 0
前执行语句
LOAD
DATA
。
如果
LOAD
DATA
在空
MyISAM
表上使用,则所有非唯一索引都在单独的批处理中创建(至于
REPAIR
TABLE
)。
通常,
LOAD
DATA
当您有许多索引时
,这会
更快。
在某些极端情况下,您可以通过
ALTER
TABLE ... DISABLE KEYS
在将文件加载到表中之前
关闭它们
并使用
ALTER
TABLE ...
ENABLE KEYS
在加载文件后重新创建索引来
更快地
创建索引。
请参见
第8.2.5.1节“优化INSERT语句”
。
对于
LOAD
DATA
和
SELECT ... INTO
OUTFILE
语句,
FIELDS
和
LINES
子句
的语法
是相同的。
两个子句都是可选的,但
FIELDS
必须在
LINES
两者都指定
之前
。
如果指定
FIELDS
子句,则每个子句(
TERMINATED BY
,
[OPTIONALLY] ENCLOSED BY
和
ESCAPED BY
)也是可选的,但必须至少
指定其中一个
子句
。
允许这些子句的参数仅包含ASCII字符。
如果指定no
FIELDS
或
LINES
clause,则默认值与您编写的相同:
由'''''''''''''''''''''''''''''''''''''''''''''''''''' 由'\ n'开始''终止的线路''
反斜杠是SQL语句中字符串中的MySQL转义字符。
因此,要指定文字反斜杠,必须为该值指定两个反斜杠,以将其解释为单个反斜杠。
转义序列
'\t'
并分别
'\n'
指定制表符和换行符。
换句话说,默认值导致
LOAD
DATA
在读取输入时如下操作:
在换行符处查找行边界。
不要跳过任何行前缀。
将行分隔为选项卡中的字段。
不要指望字段包含在任何引用字符中。
将转义字符前面的字符解释
\
为转义序列。
例如,
\t
,
\n
,和
\\
分别表示选项卡,换行,反斜线。
有关
FIELDS ESCAPED
BY
转义序列的完整列表,
请参阅
稍后
的讨论
。
相反,默认值导致
SELECT ... INTO
OUTFILE
在写入输出时如下操作:
在字段之间写标签。
不要在任何引号字符中包含字段。
使用
\
逃脱制表符,换行符的情况下,或
\
字段值内出现。
在行的末尾写下换行符。
对于在Windows系统上生成的文本文件,可能需要正确读取文件,
LINES TERMINATED BY
'\r\n'
因为Windows程序通常使用两个字符作为行终止符。
某些程序(如
写字板)
\r
在编写文件时
可能会
用作行终止符。
要阅读此类文件,请使用
LINES TERMINATED BY '\r'
。
如果所有输入行都有一个您想要忽略的公共前缀,则可以使用
跳过前缀
和前面的任何内容
。
如果一行不包含前缀,则跳过整行。
假设您发出以下语句:
LINES STARTING BY
'
prefix_string
'
LOAD DATA INFILE'/tmp/test.txt'INTO TABLE test 字段由'''起点'xxx'终止;
如果数据文件如下所示:
XXX “ABC”,1 东西xxx“def”,2 “GHI”,3
生成的行将是
("abc",1)
和
("def",2)
。
跳过文件中的第三行,因为它不包含前缀。
该
选项可用于忽略文件开头的行。
例如,您可以使用
跳过包含列名的初始标题行:
IGNORE
number
LINESIGNORE 1
LINES
LOAD DATA INFILE'/tmp/test.txt'INTO TABLE test IGNORE 1 LINES;
当您
SELECT
... INTO OUTFILE
串联使用
LOAD
DATA
以将数据从数据库写入文件然后稍后将文件读回数据库时,两个语句的字段和行处理选项必须匹配。
否则,
LOAD
DATA
将无法正确解释文件的内容。
假设您使用
SELECT ... INTO
OUTFILE
逗号分隔的字段来编写文件:
SELECT * INTO OUTFILE'Data.txt' 字段被','终止 FROM table2;
要读取逗号分隔的文件,正确的语句将是:
LOAD DATA INFILE'Data.txt'INTO TABLE table2 FIELDS终止',';
如果你试图用下面显示的语句读取文件,它将无法工作,因为它指示
LOAD
DATA
在字段之间查找选项卡:
LOAD DATA INFILE'Data.txt'INTO TABLE table2 字段由'\ t'终止;
可能的结果是每个输入行将被解释为单个字段。
LOAD
DATA
可用于读取从外部源获取的文件。
例如,许多程序可以以逗号分隔值(CSV)格式导出数据,这样行的字段用逗号分隔并用双引号括起来,并带有一行初始的列名。
如果此类文件中的行由回车符/换行符对终止,则此处显示的语句说明了用于加载文件的字段和行处理选项:
LOAD DATA INFILE'data.txt'INTO TABLE tbl_name
字段由'''封闭''''
由'\ r \ n'终止的线路
IGNORE 1 LINES;
如果输入值不一定用引号括起来,请
OPTIONALLY
在
ENCLOSED BY
选项
之前
使用
。
任何字段或行处理选项都可以指定空字符串(
''
)。
如果不为空,则
FIELDS [OPTIONALLY] ENCLOSED BY
和
FIELDS ESCAPED BY
值必须是单个字符。
的
FIELDS TERMINATED BY
,
LINES STARTING BY
和
LINES
TERMINATED BY
值可超过一个字符。
例如,要写入由回车符/换行符对终止的行,或者要读取包含这些行的文件,请指定一个
LINES TERMINATED BY '\r\n'
子句。
要读取包含由组成的行分隔的笑话的文件
%%
,您可以执行此操作
CREATE TABLE笑话 (INT NOT NOT AUTO_INCREMENT PRIMARY KEY, 笑话TEXT NOT NULL); LOAD DATA INFILE'/tmp/jokes.txt'INTO TABLE笑话 字段被''终止 由'\ n %% \ n'终止的行(笑话);
FIELDS [OPTIONALLY] ENCLOSED BY
控制字段引用。
对于output(
SELECT ... INTO
OUTFILE
),如果省略该单词
OPTIONALLY
,则所有字段都由该
ENCLOSED BY
字符
包围
。
此处显示了此类输出的示例(使用逗号作为字段分隔符):
“1”,“一根弦”,“100.20” “2”,“包含逗号的字符串”,“102.20” “3”,“包含”引号“的字符串,”102.20“ “4”,“包含\”的字符串,引号和逗号“,”102.20“
如果指定
OPTIONALLY
的
ENCLOSED BY
字符仅用于从具有字符串数据类型(如柱围值
CHAR
,
BINARY
,
TEXT
,或
ENUM
):
1,“一串”,100.20 2,“包含逗号的字符串”,102.20 3,“包含”引号“的字符串,102.20 4,“包含\”的字符串,引号和逗号“,102.20
ENCLOSED BY
字段值中字符的
出现通过在
字符前加上前缀来转义
ESCAPED BY
。
此外,如果指定空
ESCAPED BY
值,则可能会无意中生成无法正确读取的输出
LOAD
DATA
。
例如,如果转义字符为空,则刚刚显示的前面的输出将显示如下。
注意第四行中的第二个字段在引号后面包含一个逗号,它(错误地)显示为终止字段:
1,“一串”,100.20 2,“包含逗号的字符串”,102.20 3,“包含”引用“的字符串,102.20 4,“包含”,引号和逗号“的字符串,102.20
对于输入,
ENCLOSED BY
字符(如果存在)将从字段值的末尾剥离。
(无论是否
OPTIONALLY
指定,
都是如此
;
OPTIONALLY
对输入解释没有影响。)
ENCLOSED
BY
字符前面的
ESCAPED
BY
字符的出现被解释为当前字段值的一部分。
如果字段以
ENCLOSED BY
字符
开头,则
仅当后跟字段或行
TERMINATED BY
序列时,
才会
将该
字符的实例识别为终止字段值
。
为了避免歧义,
ENCLOSED BY
字段值中字符的
出现
可以加倍并被解释为字符的单个实例。
例如,如果
ENCLOSED BY '"'
指定了
if
,则处理引号,如下所示:
“”大“”老板“ - >”大“老板 “大”老板 - >“大”老板 “”BIG“”老板 - >“”BIG“”老板
FIELDS ESCAPED BY
控制如何读取或写入特殊字符:
对于输入,如果
FIELDS ESCAPED BY
字符不为空,则剥离该字符的出现,并且字面上将后续字符作为字段值的一部分。
一些双字符序列是异常,其中第一个字符是转义字符。
这些序列如下表所示(
\
用于转义字符)。
NULL
处理
规则
将在本节后面介绍。
有关
\
-escape语法的
更多信息
,请参见
第9.1.1节“字符串文字”
。
如果
FIELDS ESCAPED BY
字符为空,则不会发生转义序列解释。
对于输出,如果
FIELDS ESCAPED BY
字符不为空,则用于在输出中为后面的字符添加前缀:
这个
FIELDS ESCAPED BY
角色。
这个
FIELDS [OPTIONALLY] ENCLOSED BY
角色。
如果
字符为空或未指定
,则为
FIELDS TERMINATED
BY
和
LINES TERMINATED BY
值
的第一个字符
ENCLOSED BY
。
ASCII
0
(转义字符后面实际写入的是ASCII
0
,而不是零值字节)。
如果
FIELDS ESCAPED BY
字符是空的,没有字符被转义,并且
NULL
是输出
NULL
,没有
\N
。
指定空的转义字符可能不是一个好主意,特别是如果数据中的字段值包含刚刚给出的列表中的任何字符。
在某些情况下,现场和线路处理选项相互作用:
如果
LINES TERMINATED BY
是一个空字符串且
FIELDS TERMINATED BY
非空,则行也将终止
FIELDS TERMINATED
BY
。
如果
FIELDS TERMINATED BY
和
FIELDS ENCLOSED BY
值都为空(
''
),则使用固定行(非定界)格式。
对于固定行格式,字段之间不使用分隔符(但您仍然可以使用行终止符)。
相反,使用足够宽的字段宽度来读取和写入列值,以保存字段中的所有值。
为
TINYINT
,
SMALLINT
,
MEDIUMINT
,
INT
,和
BIGINT
,场宽度是4,6,8,11,和20,分别,不管声明显示宽度是什么。
LINES TERMINATED BY
仍然用于分隔线。
如果某行不包含所有字段,则其余列将设置为其默认值。
如果您没有行终止符,则应将其设置为
''
。
在这种情况下,文本文件必须包含每行的所有字段。
固定行格式也会影响
NULL
值的
处理
,如后面所述。
如果您使用多字节字符集,则固定大小格式不起作用。
NULL
值的
处理
根据使用的
FIELDS
和
LINES
选项
而有所不同
:
对于默认值
FIELDS
和
LINES
值,
NULL
写
\N
为输出的字段值,
\N
并且读取
字段值为
NULL
输入(假设
ESCAPED BY
字符为
\
)。
如果
FIELDS ENCLOSED BY
不为空,
则将
包含文字
NULL
作为其值
的字段
作为值读取
NULL
。
这与
字符中
NULL
包含
的单词不同
FIELDS ENCLOSED BY
,后者被读作字符串
'NULL'
。
如果
FIELDS ESCAPED BY
为空,
NULL
则写为单词
NULL
。
使用固定行格式(
在空
FIELDS
TERMINATED BY
和时
FIELDS ENCLOSED
BY
都使用),
NULL
写为空字符串。
这会导致
NULL
表中的值和空字符串在写入文件时无法区分,因为两者都写为空字符串。
如果您在重新读取文件时需要能够区分两者,则不应使用固定行格式。
尝试加载
NULL
到
NOT
NULL
列会导致为列的数据类型和警告分配隐式默认值,或者在严格SQL模式下分配错误。
第11.7节“数据类型默认值”
中讨论了隐式默认值
。
有些情况不受以下方面的支持
LOAD
DATA
:
固定大小的行(
FIELDS TERMINATED BY
以及
FIELDS ENCLOSED BY
空的)和/
BLOB
或
TEXT
列。
如果指定一个与另一个相同的分隔符或另一个的前缀,
LOAD
DATA
则无法正确解释输入。
例如,以下
FIELDS
子句会导致问题:
字段被''''封闭'''终止
如果
FIELDS ESCAPED BY
为空,则包含值的出现
FIELDS
ENCLOSED BY
或
LINES TERMINATED
BY
后跟
的字段
FIELDS TERMINATED
BY
值会导致
LOAD
DATA
过早地停止读取字段或行。
发生这种情况是因为
LOAD
DATA
无法正确确定字段或行值的结束位置。
以下示例加载表的所有列
persondata
:
LOAD DATA INFILE'persondata.txt'INTO TABLE persondata;
默认情况下,如果在
LOAD
DATA
语句
末尾没有提供列列表
,则输入行应包含每个表列的字段。
如果只想加载某些表的列,请指定列列表:
LOAD DATA INFILE'persondata.txt'INTO TABLE persondata (col_name_or_user_var
[,col_name_or_user_var
] ......);
如果输入文件中字段的顺序与表中列的顺序不同,则还必须指定列列表。 否则,MySQL无法告诉如何将输入字段与表列匹配。
每个
col_name_or_user_var
值都是列名或用户变量。
使用用户变量,该
SET
子句使您可以在将结果分配给列之前对其值执行预处理转换。
SET
子句
中的用户变量
可以以多种方式使用。
下面的示例直接使用第一个输入列作为值
t1.column1
,并将第二个输入列分配给用户变量,该变量在用于以下值之前经过除法运算
t1.column2
:
LOAD DATA INFILE'file.txt' INTO表t1 (column1,@ var1) SET column2 = @ var1 / 100;
该
SET
子句可用于提供不是从输入文件派生的值。
以下语句设置
column3
为当前日期和时间:
LOAD DATA INFILE'file.txt' INTO表t1 (column1,column2) SET column3 = CURRENT_TIMESTAMP;
您还可以通过将输入值分配给用户变量而不将变量分配给表列来丢弃输入值:
LOAD DATA INFILE'file.txt' INTO表t1 (column1,@ dummy,column2,@ dad,column3);
使用列/变量列表和
SET
子句受以下限制:
SET
子句中的
赋值
应该只在赋值运算符的左侧有列名。
您可以在
SET
分配
的右侧使用子查询
。
返回要分配给列的值的子查询可能只是标量子查询。
此外,您不能使用子查询从正在加载的表中进行选择。
IGNORE
不会为列/变量列表或
SET
子句
处理子句
忽略的行
。
加载固定行格式的数据时,无法使用用户变量,因为用户变量没有显示宽度。
处理输入行时,
LOAD
DATA
将其拆分为字段,并根据列/变量列表和
SET
子句
使用值
(如果存在)。
然后将生成的行插入表中。
如果有
表
BEFORE INSERT
或
AFTER
INSERT
触发器,则分别在插入行之前或之后激活它们。
如果输入行包含太多字段,则会忽略额外字段并增加警告数。
如果输入行的字段太少,则缺少输入字段的表列将设置为其默认值。 第11.7节“数据类型默认值”中 描述了默认值分配 。
空字段值的解释与缺少的字段不同:
对于字符串类型,该列设置为空字符串。
对于数字类型,列设置为
0
。
对于日期和时间类型,该列设置 为该类型 的相应 “ 零 ” 值。 请参见 第11.3节“日期和时间类型” 。
如果在
INSERT
or
UPDATE
语句中
显式地将空字符串明确分配给字符串,数字或日期或时间类型,则会产生相同的值
。
如果将SQL模式设置为限制值,则处理空或不正确的字段值与刚刚描述的不同。
例如,如果
sql_mode
设置为
TRADITIONAL
,则转换空值或值(例如
'x'
数字列)会导致错误,而不是转换为0.(使用
LOCAL
或者
IGNORE
,警告会发生而不是错误,即使有限制
sql_mode
值,使用与非限制性SQL模式相同的最接近值行为插入行。这是因为服务器无法在操作过程中停止传输文件。)
TIMESTAMP
仅当
NULL
列
的
值(即,
\N
)没有声明列允许
NULL
值,或者
TIMESTAMP
列的默认值是当前时间戳并且从字段中省略时,
列才会设置为当前日期和时间
指定字段列表时列出。
LOAD
DATA
将所有输入视为字符串,因此您不能像使用
语句
那样使用数值
ENUM
或
SET
列
INSERT
。
必须将
all
ENUM
和
SET
值指定为字符串。
BIT
无法使用二进制表示法直接加载值(例如,
b'011010'
)。
要解决此问题,请使用该
SET
子句去除前导
b'
和尾随
'
并执行base-2到base-10转换,以便MySQL
BIT
正确地
将值加载到
列中:
外壳>cat /tmp/bit_test.txt
b'10' b'1111111' shell>mysql test
mysql>LOAD DATA INFILE '/tmp/bit_test.txt'
INTO TABLE bit_test (@var1)
SET b = CAST(CONV(MID(@var1, 3, LENGTH(@var1)-3), 2, 10) AS UNSIGNED);
查询正常,2行受影响(0.00秒) 记录:2删除:0跳过:0警告:0 MySQL的>SELECT BIN(b+0) FROM bit_test;
+ ---------- + | BIN(b + 0)| + ---------- + | 10 | | 1111111 | + ---------- + 2行(0.00秒)
对于
二进制表示法
BIT
中的
0b
值(例如,
0b011010
),请使用此
SET
子句去除前导
0b
:
SET b = CAST(CONV(MID(@ var1,3,LENGTH(@ var1)-2),2,10)AS UNSIGNED)
当
LOAD
DATA
语句完成,它返回以下格式的信息字符串:
记录:1已删除:0跳过:0警告:0
警告在与使用
INSERT
语句
插入值时相同的情况下发生
(请参见
第13.2.6节“INSERT语法”
),但
LOAD
DATA
输入行中字段太少或太多时也会生成警告。
您可以使用
SHOW WARNINGS
获取第一个
max_error_count
警告
的列表
作为有关错误的信息。
请参见
第13.7.6.40节“显示警告语法”
。
如果您使用的是C API,则可以通过调用该
mysql_info()
函数
来获取有关该语句的信息
。
请参见
第28.7.7.36节“mysql_info()”
。
在Unix上,如果需要
LOAD
DATA
从管道读取,可以使用以下技术(该示例将
/
目录
列表加载
到表中
db1.t1
):
mkfifo /mysql/data/db1/ls.dat chmod 666 /mysql/data/db1/ls.dat find / -ls> /mysql/data/db1/ls.dat& mysql -e“LOAD DATA INFILE'ls.dat'INTO TABLE t1”db1
在这里,您必须 在不同的终端上 运行生成要加载的数据和 mysql 命令的命令,或者在后台运行数据生成过程(如上例所示)。 如果不这样做,管道将阻塞,直到 mysql 进程 读取数据 。
加载XML [LOW_PRIORITY | CONCURRENT] [当地] INFILE'file_name
' [REPLACE | 忽视] INTO TABLE [db_name
。]tbl_name
[字符集charset_name
] [由'<tagname
>' 识别的行号] [IGNOREnumber
{LINES | ROWS}] [(field_name_or_user_var
[,field_name_or_user_var
] ......)] [SETcol_name
= {expr
| 默认}, [,col_name
= {expr
| DEFAULT}] ...]
该
LOAD
XML
语句将XML文件中的数据读入表中。
在
file_name
必须作为一个字符串。
所述
tagname
可选的在
ROWS IDENTIFIED BY
条款也必须给予作为文字串,并且必须由尖括号(包围
<
和
>
)。
LOAD
XML
作为
在XML输出模式下
运行
mysql
客户端
的补充
(即,使用该
--xml
选项
启动客户端
)。
要将表中的数据写入XML文件,可以
使用
系统shell中
的
和
选项
调用
mysql
客户端
,如下所示:
--xml
-e
外壳> mysql --xml -e 'SELECT * FROM mydb.mytable' > file.xml
要将文件读回表中,请使用
LOAD
XML
。
默认情况下,该
<row>
元素被认为是数据库表行的等价物;
这可以使用该
ROWS IDENTIFIED
BY
子句
进行更改
。
该语句支持三种不同的XML格式:
列名称作为属性,列值作为属性值:
< =“ ” =“ ”...... />row
column1
value1
column2
value2
列名作为标记,列值作为这些标记的内容:
<row
> <column1
>value1
</column1
> <column2
>value2
</column2
> </row
>
列名是
标记
的
name
属性
<field>
,值是这些标记的内容:
<行> <field name ='column1
'>value1
</ field> <field name ='column2
'>value2
</ field> </行>
这是其他MySQL工具使用的格式,例如 mysqldump 。
所有三种格式都可以在同一个XML文件中使用; 导入例程自动检测每行的格式并正确解释它。 根据标记或属性名称和列名称匹配标记。
下列条款基本上是连续工作以同样的方式
LOAD
XML
,因为他们对做
LOAD
DATA
:
LOW_PRIORITY
要么
CONCURRENT
LOCAL
REPLACE
要么
IGNORE
CHARACTER SET
SET
有关这些子句的更多信息 , 请参见 第13.2.7节“LOAD DATA语法” 。
(
是一个或多个以逗号分隔的XML字段或用户变量的列表。
用于此目的的用户变量的名称必须与XML文件中的字段名称匹配,前缀为
field_name_or_user_var
,
...)@
。
您可以使用字段名称仅选择所需的字段。
用户变量可用于存储相应的字段值以供后续重用。
在
或
子句使第一
XML文件中的行被跳过。
它类似于
声明的
条款。
IGNORE
number
LINESIGNORE
number
ROWSnumber
LOAD
DATA
IGNORE ... LINES
假设我们有一个名为的表
person
,如下所示:
使用测试; CREATE TABLE人( person_id INT NOT NULL PRIMARY KEY, fname VARCHAR(40)NULL, lname VARCHAR(40)NULL, 创造了TIMESTAMP );
进一步假设该表最初为空。
现在假设我们有一个简单的XML文件
person.xml
,其内容如下所示:
<列表> <person person_id =“1”fname =“Kapek”lname =“Sainnouine”/> <person person_id =“2”fname =“Sajon”lname =“Rondela”/> <person person_id =“3”> <fname> Likame </ fname> <lname>Örrtmons</ lname> </ person> <person person_id =“4”> <fname> Slar </ fname> <lname> Manlanth </ lname> </ person> <person> <field name =“person_id”> 5 </ field> <field name =“fname”> Stoma </ field> <field name =“lname”> Milu </ field> </ person> <person> <field name =“person_id”> 6 </ field> <field name =“fname”> Nirtam </ field> <field name =“lname”>Sklöd</ field> </ person> <person person_id =“7”> <fname> Sungam </ fname> <lname>Dulbåd</ lname> </ person> <person person_id =“8”fname =“Sraref”lname =“Encmelt”/> </列表>
前面讨论的每种允许的XML格式都在此示例文件中表示。
要将数据
person.xml
导入
person
表中,可以使用以下语句:
mysql>LOAD XML LOCAL INFILE 'person.xml'
- >INTO TABLE person
- >ROWS IDENTIFIED BY '<person>';
查询OK,8行受影响(0.00秒) 记录:8删除:0跳过:0警告:0
在这里,我们假设它
person.xml
位于MySQL数据目录中。
如果找不到该文件,则会出现以下错误:
错误2(HY000):找不到文件'/person.xml'(错误代码:2)
该
ROWS IDENTIFIED BY '<person>'
子句意味着
<person>
XML文件
中的每个
元素被认为等同于要导入数据的表中的行。
在这种情况下,这是
数据库中
的
person
表
test
。
从服务器的响应中可以看出,将8行导入
test.person
表中。
这可以通过一个简单的
SELECT
声明
来验证
:
MySQL的> SELECT * FROM person;
+ ----------- + -------- + ------------ + --------------- ------ +
| person_id | fname | lname | 创建|
+ ----------- + -------- + ------------ + --------------- ------ +
| 1 | Kapek | Sainnouine | 2007-07-13 16:18:47 |
| 2 | Sajon | Rondela | 2007-07-13 16:18:47 |
| 3 | Likame | Örrtmons| 2007-07-13 16:18:47 |
| 4 | Slar | Manlanth | 2007-07-13 16:18:47 |
| 5 | 气孔| Nilu | 2007-07-13 16:18:47 |
| 6 | Nirtam | Sklöd| 2007-07-13 16:18:47 |
| 7 | Sungam | Dulbåd| 2007-07-13 16:18:47 |
| 8 | Sreraf | Encmelt | 2007-07-13 16:18:47 |
+ ----------- + -------- + ------------ + --------------- ------ +
8行(0.00秒)
如本节前面所述,这表明3种允许的XML格式中的任何一种或全部都可以出现在单个文件中并使用
LOAD
XML
。
刚刚显示的导入操作的反转 - 即将MySQL表数据转储到XML文件中 - 可以使用 系统shell中 的 mysql 客户端 完成 ,如下所示:
shell>mysql --xml -e "SELECT * FROM test.person" > person-dump.xml
shell>cat person-dump.xml
<?xml version =“1.0”?> <resultset statement =“SELECT * FROM test.person”xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”> <行> <field name =“person_id”> 1 </ field> <field name =“fname”> Kapek </ field> <field name =“lname”> Sainnouine </ field> </行> <行> <field name =“person_id”> 2 </ field> <field name =“fname”> Sajon </ field> <field name =“lname”> Rondela </ field> </行> <行> <field name =“person_id”> 3 </ field> <field name =“fname”> Likema </ field> <field name =“lname”>Örrtmons</ field> </行> <行> <field name =“person_id”> 4 </ field> <field name =“fname”> Slar </ field> <field name =“lname”> Manlanth </ field> </行> <行> <field name =“person_id”> 5 </ field> <field name =“fname”> Stoma </ field> <field name =“lname”> Nilu </ field> </行> <行> <field name =“person_id”> 6 </ field> <field name =“fname”> Nirtam </ field> <field name =“lname”>Sklöd</ field> </行> <行> <field name =“person_id”> 7 </ field> <field name =“fname”> Sungam </ field> <field name =“lname”>Dulbåd</ field> </行> <行> <field name =“person_id”> 8 </ field> <field name =“fname”> Sreraf </ field> <field name =“lname”> Encmelt </ field> </行> </结果集>
该
--xml
选项使
mysql
客户端对其输出使用XML格式;
该
-e
选项使客户端在该选项后立即执行SQL语句。
请参见
第4.5.1节“
mysql
- MySQL命令行客户端”
。
您可以通过创建
person
表
的副本
并将转储文件导入新表
来验证转储是否有效
,如下所示:
mysql>USE test;
mysql>CREATE TABLE person2 LIKE person;
查询正常,0行受影响(0.00秒) mysql>LOAD XML LOCAL INFILE 'person-dump.xml'
- >INTO TABLE person2;
查询OK,8行受影响(0.01秒) 记录:8删除:0跳过:0警告:0 MySQL的>SELECT * FROM person2;
+ ----------- + -------- + ------------ + --------------- ------ + | person_id | fname | lname | 创建| + ----------- + -------- + ------------ + --------------- ------ + | 1 | Kapek | Sainnouine | 2007-07-13 16:18:47 | | 2 | Sajon | Rondela | 2007-07-13 16:18:47 | | 3 | Likema | Örrtmons| 2007-07-13 16:18:47 | | 4 | Slar | Manlanth | 2007-07-13 16:18:47 | | 5 | 气孔| Nilu | 2007-07-13 16:18:47 | | 6 | Nirtam | Sklöd| 2007-07-13 16:18:47 | | 7 | Sungam | Dulbåd| 2007-07-13 16:18:47 | | 8 | Sreraf | Encmelt | 2007-07-13 16:18:47 | + ----------- + -------- + ------------ + --------------- ------ + 8行(0.00秒)
不要求XML文件中的每个字段都与相应表中的列匹配。
跳过没有相应列的字段。
您可以通过首先清空
person2
表并删除
created
列,然后使用
LOAD
XML
我们之前
使用的相同
语句
来看到这一点
,如下所示:
MySQL的>TRUNCATE person2;
查询OK,8行受影响(0.26秒) MySQL的>ALTER TABLE person2 DROP COLUMN created;
查询OK,0行受影响(0.52秒) 记录:0重复:0警告:0 MySQL的>SHOW CREATE TABLE person2\G
*************************** 1。排******************** ******* 表:person2 创建表:CREATE TABLE`person2`( `person_id` int(11)NOT NULL, `fname` varchar(40)DEFAULT NULL, `lname` varchar(40)DEFAULT NULL, 主键(`person_id`) )ENGINE = InnoDB DEFAULT CHARSET = utf8 1排(0.00秒) mysql>LOAD XML LOCAL INFILE 'person-dump.xml'
- >INTO TABLE person2;
查询OK,8行受影响(0.01秒) 记录:8删除:0跳过:0警告:0 MySQL的>SELECT * FROM person2;
+ ----------- + -------- + ------------ + | person_id | fname | lname | + ----------- + -------- + ------------ + | 1 | Kapek | Sainnouine | | 2 | Sajon | Rondela | | 3 | Likema | Örrtmons| | 4 | Slar | Manlanth | | 5 | 气孔| Nilu | | 6 | Nirtam | Sklöd| | 7 | Sungam | Dulbåd| | 8 | Sreraf | Encmelt | + ----------- + -------- + ------------ + 8行(0.00秒)
在XML文件的每一行中给出字段的顺序不会影响操作
LOAD
XML
;
字段顺序可以在行之间变化,并且不需要与表中的相应列具有相同的顺序。
如前所述,您可以使用
一个或多个XML字段
的
列表(仅选择所需的字段)或用户变量(以存储相应的字段值供以后使用)。
当您希望将XML文件中的数据插入名称与XML字段名称不匹配的表列时,用户变量尤其有用。
要查看其工作原理,我们首先创建一个名为
其
表
的结构与
表
的结构相匹配的
表,但其列的名称不同:
(
field_name_or_user_var
,
...)individual
person
mysql>CREATE TABLE individual (
- >individual_id INT NOT NULL PRIMARY KEY,
- >name1 VARCHAR(40) NULL,
- >name2 VARCHAR(40) NULL,
- >made TIMESTAMP
- >); 查询OK,0行受影响(0.42秒)
在这种情况下,您不能简单地将XML文件直接加载到表中,因为字段和列名称不匹配:
MySQL的> LOAD XML INFILE '../bin/person-dump.xml' INTO TABLE test.individual;
ERROR 1263(22004):列设置为默认值; NULL提供给第1行的NOT NULL列'individual_id'
发生这种情况是因为MySQL服务器查找与目标表的列名匹配的字段名称。
您可以通过在用户变量中选择字段值,然后使用目标表的列设置等于这些变量的值来解决此问题
SET
。
您可以在单个语句中执行这两个操作,如下所示:
mysql>LOAD XML INFILE '../bin/person-dump.xml'
- >INTO TABLE test.individual (@person_id, @fname, @lname, @created)
- >SET individual_id=@person_id, name1=@fname, name2=@lname, made=@created;
查询OK,8行受影响(0.05秒) 记录:8删除:0跳过:0警告:0 MySQL的>SELECT * FROM individual;
+ --------------- + -------- + ------------ + ----------- ---------- + | individual_id | name1 | name2 | 制作| + --------------- + -------- + ------------ + ----------- ---------- + | 1 | Kapek | Sainnouine | 2007-07-13 16:18:47 | | 2 | Sajon | Rondela | 2007-07-13 16:18:47 | | 3 | Likema | Örrtmons| 2007-07-13 16:18:47 | | 4 | Slar | Manlanth | 2007-07-13 16:18:47 | | 5 | 气孔| Nilu | 2007-07-13 16:18:47 | | 6 | Nirtam | Sklöd| 2007-07-13 16:18:47 | | 7 | Sungam | Dulbåd| 2007-07-13 16:18:47 | | 8 | Srraf | Encmelt | 2007-07-13 16:18:47 | + --------------- + -------- + ------------ + ----------- ---------- + 8行(0.00秒)
用户变量的名称
必须
与XML文件中相应字段
的名称相
匹配,并添加必需的
@
前缀以指示它们是变量。
不需要以与相应字段相同的顺序列出或分配用户变量。
使用
子句,可以将同一XML文件中的数据导入具有不同定义的数据库表中。
对于此示例,假设您有一个名为
包含以下XML
的文件
:
ROWS IDENTIFIED BY
'<
tagname
>'address.xml
<?xml version =“1.0”?> <列表> <person person_id =“1”> <FNAME>罗伯特</ FNAME> <L-NAME>琼斯</ L-NAME> <address address_id =“1”street =“Mill Creek Road”zip =“45365”city =“Sidney”/> <address address_id =“2”street =“Main Street”zip =“28681”city =“Taylorsville”/> </人> <person person_id =“2”> <FNAME>玛丽</ FNAME> <L-NAME>史密斯</ L-NAME> <address address_id =“3”street =“River Road”zip =“80239”city =“Denver”/> <! - <address address_id =“4”street =“North Street”zip =“37920”city =“Knoxville”/> - > </人> </列表>
test.person
在清除表中的所有现有记录并显示其结构后,
您可以再次使用
本节前面定义的表,如下所示:
MySQL的<TRUNCATE person;
查询正常,0行受影响(0.04秒) MySQL的<SHOW CREATE TABLE person\G
*************************** 1。排******************** ******* 表:人 创建表:CREATE TABLE`person`( `person_id` int(11)NOT NULL, `fname` varchar(40)DEFAULT NULL, `lname` varchar(40)DEFAULT NULL, `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 主键(`person_id`) )ENGINE = MyISAM DEFAULT CHARSET = utf8mb4 1排(0.00秒)
现在
使用以下
语句
address
在
test
数据库中
创建一个
表
CREATE
TABLE
:
CREATE TABLE地址( address_id INT NOT NULL PRIMARY KEY, person_id INT NULL, street VARCHAR(40)NULL, zip INT NULL, city VARCHAR(40)NULL, 创造了TIMESTAMP );
要将XML文件中的数据导入
person
表中,请执行以下
LOAD
XML
语句,该语句指定要由
<person>
元素
指定行
,如此处所示;
mysql>LOAD XML LOCAL INFILE 'address.xml'
- >INTO TABLE person
- >ROWS IDENTIFIED BY '<person>';
查询正常,2行受影响(0.00秒) 记录:2删除:0跳过:0警告:0
您可以使用
SELECT
语句
验证是否已导入记录
:
MySQL的> SELECT * FROM person;
+ ----------- + -------- + ------- + -------------------- - +
| person_id | fname | lname | 创建|
+ ----------- + -------- + ------- + -------------------- - +
| 1 | 罗伯特| 琼斯| 2007-07-24 17:37:06 |
| 2 | 玛丽| 史密斯| 2007-07-24 17:37:06 |
+ ----------- + -------- + ------- + -------------------- - +
2行(0.00秒)
由于
<address>
XML文件中
的
元素在表中没有对应的列
person
,因此会跳过它们。
要将
<address>
元素中
的数据导入
address
表中,请使用
LOAD
XML
此处显示
的
语句:
mysql>LOAD XML LOCAL INFILE 'address.xml'
- >INTO TABLE address
- >ROWS IDENTIFIED BY '<address>';
查询OK,3行受影响(0.00秒) 记录:3删除:0跳过:0警告:0
您可以看到使用如下
SELECT
语句
导入数据
:
MySQL的> SELECT * FROM address;
+ ------------ + ----------- + ----------------- + ------ - + -------------- + --------------------- +
| address_id | person_id | 街道| zip | 城市| 创建|
+ ------------ + ----------- + ----------------- + ------ - + -------------- + --------------------- +
| 1 | 1 | Mill Creek Road | 45365 | 西德尼| 2007-07-24 17:37:37 |
| 2 | 1 | 主街| 28681 | 泰勒斯维尔| 2007-07-24 17:37:37 |
| 3 | 2 | 河道| 80239 | 丹佛| 2007-07-24 17:37:37 |
+ ------------ + ----------- + ----------------- + ------ - + -------------- + --------------------- +
3组(0.00秒)
<address>
不会导入XML注释中包含
的
元素
的数据
。
然而,由于有一个
person_id
在列
address
表中,值
person_id
从父属性
<person>
的每个元素
<address>
被
导入到
address
表中。
安全考虑因素。
与该
LOAD
DATA
语句一样,XML文件从客户端主机到服务器主机的传输由MySQL服务器启动。
理论上,可以构建修补的服务器,该服务器将告诉客户端程序传输服务器选择的文件而不是
LOAD
XML
语句中
客户端指定的文件
。
这样的服务器可以访问客户端用户具有读访问权限的客户端主机上的任何文件。
在Web环境中,客户端通常从Web服务器连接到MySQL。
可以对MySQL服务器运行任何命令的用户可以
LOAD
XML
LOCAL
用来读取Web服务器进程具有读访问权限的任何文件。
在此环境中,与MySQL服务器相关的客户端实际上是Web服务器,而不是由连接到Web服务器的用户运行的远程程序。
您可以通过使用
--local-infile=0
或
启动服务器来禁用从客户端加载XML文件
--local-infile=OFF
。
启动
mysql
客户端以
LOAD
XML
在客户端会话期间
禁用
此选项也可以使用
。
要防止客户端从服务器加载XML文件,请不要将
FILE
权限
授予
相应的MySQL用户帐户,或者如果客户端用户帐户已拥有该权限,则撤消此权限。
撤销
FILE
只能从执行权限(或没有在第一时间给予它)让用户
LOAD
XML
声明(还有
LOAD_FILE()
功能;它并
不能
阻止用户执行
LOAD
XML
LOCAL
。要禁止这种说法,你必须启动服务器或客户端与
--local-infile=OFF
。
换句话说,该
FILE
权限仅影响客户端是否可以读取服务器上的文件;
它与客户端是否可以读取本地文件系统上的文件无关。
对于使用使用表锁的存储引擎的分区表,例如
MyISAM
,由
LOAD
XML
表的所有分区上的执行锁
引起的任何锁
。
这不适用于使用采用行级锁定的存储引擎的表,例如
InnoDB
。
有关更多信息,请参阅
分区和锁定
。
REPLACE [LOW_PRIORITY | 延迟] [INTO]tbl_name
[PARTITION(partition_name
[,partition_name
] ...)] [(col_name
[,col_name
] ......)] {VALUES | VALUE}(value_list
)[,(value_list
)] ...... REPLACE [LOW_PRIORITY | 延迟] [INTO]tbl_name
[PARTITION(partition_name
[,partition_name
] ...)] 组assignment_list
REPLACE [LOW_PRIORITY | 延迟] [INTO]tbl_name
[PARTITION(partition_name
[,partition_name
] ...)] [(col_name
[,col_name
] ......)] 选择 ...value
: {expr
| 默认}value_list
:value
[,value
] ......assignment
:col_name
=value
assignment_list
:assignment
[,assignment
] ......
REPLACE
与此类似
INSERT
,除非表中的旧行与a
PRIMARY KEY
或
UNIQUE
索引
的新行具有相同的值,
否则
在插入新行之前将删除旧行。
请参见
第13.2.6节“INSERT语法”
。
REPLACE
是SQL标准的MySQL扩展。
它可以插入,
删除
和插入。
对于标准SQL的另一个MySQL扩展 - 插入或
更新
- 请
参见第13.2.6.2节“INSERT ... ON DUPLICATE KEY UPDATE语法”
。
DELAYED
MySQL 5.6中不推荐使用插入和替换。
在MySQL 8.0中,
DELAYED
不受支持。
服务器识别但忽略
DELAYED
关键字,将替换作为非延迟替换处理,并生成
ER_WARN_LEGACY_SYNTAX_CONVERTED
警告。
(
“
不再支持REPLACE DELAYED。语句已转换为REPLACE。
”
)
DELAYED
关键字将在以后的版本中删除。
所有列的值都取自
REPLACE
语句中
指定的值
。
任何缺少的列都设置为默认值,就像发生的那样
INSERT
。
您不能引用当前行中的值并在新行中使用它们。
如果使用诸如的赋值
,则对右侧列名的引用将被视为
,因此赋值等效于
。
SET
col_name
=
col_name
+ 1DEFAULT(
col_name
)SET
col_name
=
DEFAULT(col_name
) + 1
要使用
REPLACE
,您必须拥有
表的权限
INSERT
和
DELETE
权限。
如果显式替换生成的列,则唯一允许的值为
DEFAULT
。
有关生成的列的信息,请参见
第13.1.20.9节“创建表和生成的列”
。
REPLACE
支持使用
PARTITION
带有分区,子分区或两者的逗号分隔名称列表
的
关键字进行
显式分区选择
。
与此同时
INSERT
,如果无法将新行插入任何这些分区或子分区,则
REPLACE
语句将失败,并显示错误“
找到与给定分区集不匹配的行”
。
有关更多信息和示例,请参见
第23.5节“分区选择”
。
该
REPLACE
语句返回一个计数以指示受影响的行数。
这是删除和插入的行的总和。
如果单行的计数为1,
REPLACE
则插入一行并且不删除任何行。
如果计数大于1,则在插入新行之前删除一个或多个旧行。
如果表包含多个唯一索引,并且新行为不同唯一索引中的不同旧行重复值,则单行可以替换多个旧行。
受影响的行数使得可以轻松确定是
REPLACE
仅添加了行还是替换了任何行:检查计数是1(已添加)还是更高(已替换)。
如果您使用的是C API,则可以使用该
mysql_affected_rows()
函数
获取受影响的行数
。
您无法替换为表并从子查询中的同一表中进行选择。
MySQL对
REPLACE
(和
LOAD
DATA ...
REPLACE
)
使用以下算法
:
尝试将新行插入表中
插入失败,因为主键或唯一索引发生重复键错误:
从表中删除具有重复键值的冲突行
再次尝试将新行插入表中
在重复键错误的情况下,存储引擎可能执行
REPLACE
更新而不是删除加插入,但语义是相同的。
除了存储引擎增加
状态变量
的可能差异之外,没有用户可见的效果
。
Handler_
xxx
因为
REPLACE ... SELECT
语句
的结果
取决于来自的行的顺序,
SELECT
并且不能总是保证这个顺序,所以当记录这些语句以使主服务器和从服务器发散时,可能是这样。
因此,
REPLACE ... SELECT
语句被标记为基于语句的复制不安全。
当使用基于语句的模式时,此类语句在错误日志中生成警告,并在使用
MIXED
模式
时使用基于行的格式写入二进制日志
。
另请参见
第17.2.1.1节“基于语句和基于行的复制的优点和缺点”
。
修改未分区以适应分区的现有表时,或者在修改已分区表的分区时,可以考虑更改表的主键(请参见
第23.6.1节“分区键,主键和唯一键”) “
)。
您应该知道,如果这样做,
REPLACE
语句
的结果
可能会受到影响,就像您修改非分区表的主键一样。
考虑以下
CREATE
TABLE
语句
创建的表
:
CREATE TABLE测试( id INT UNSIGNED NOT NULL AUTO_INCREMENT, data VARCHAR(64)DEFAULT NULL, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY(id) );
当我们创建这个表并运行mysql客户端中显示的语句时,结果如下:
MySQL的>REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');
查询正常,1行受影响(0.04秒) MySQL的>REPLACE INTO test VALUES (1, 'New', '2014-08-20 18:47:42');
查询OK,2行受影响(0.04秒) MySQL的>SELECT * FROM test;
+ ---- + ------ + --------------------- + | id | 数据| ts | + ---- + ------ + --------------------- + | 1 | 新的| 2014-08-20 18:47:42 | + ---- + ------ + --------------------- + 1排(0.00秒)
现在我们创建一个几乎与第一个表相同的第二个表,除了主键现在覆盖2列,如此处所示(强调文本):
CREATE TABLE test2(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
data VARCHAR(64)DEFAULT NULL,
ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(id,ts)
);
当我们
在原始
表
上
运行
test2
相同的两个
REPLACE
语句时
test
,我们获得了不同的结果:
MySQL的>REPLACE INTO test2 VALUES (1, 'Old', '2014-08-20 18:47:00');
查询OK,1行受影响(0.05秒) MySQL的>REPLACE INTO test2 VALUES (1, 'New', '2014-08-20 18:47:42');
查询正常,1行受影响(0.06秒) MySQL的>SELECT * FROM test2;
+ ---- + ------ + --------------------- + | id | 数据| ts | + ---- + ------ + --------------------- + | 1 | 老| 2014-08-20 18:47:00 | | 1 | 新的| 2014-08-20 18:47:42 | + ---- + ------ + --------------------- + 2行(0.00秒)
这是因为,当运行时
test2
,
id
和
ts
值必须匹配要替换的行的现有行的值;
否则,插入一行。
甲
REPLACE
使用存储引擎例如影响分区表声明
MyISAM
了采用表级锁锁只有那些含有匹配的行的分区
REPLACE
声明
WHERE
子句,只要没有表分区的列被更新;
否则整个表都被锁定。
(对于
InnoDB
使用行级锁定的
存储引擎
,不会发生分区锁定。)有关更多信息,请参阅
分区和锁定
。
选择 [全部| DISTINCT | DISTINCTROW] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]select_expr
[,select_expr
...] [来自table_references
[PARTITIONpartition_list
] [哪里where_condition
] [GROUP BY {col_name
|expr
|position
},... [WITH ROLLUP]] [HAVINGwhere_condition
] [WINDOWwindow_name
AS(window_spec
) [,window_name
AS(window_spec
)] ...] [ORDER BY {col_name
|expr
|position
} [ASC | DESC],... [与ROLLUP]] [LIMIT {[offset
,]row_count
|row_count
OFFSEToffset
}] [INTO OUTFILE'file_name
' [字符集charset_name
]export_options
| INTO DUMPFILE'file_name
' | INTOvar_name
[,var_name
]] [FOR {更新| 分享} [OFtbl_name
[,tbl_name
] ...] [NOWAIT | SKIP LOCKED] | 锁定共享模式]]
SELECT
用于检索从一个或多个表中选择的行,并且可以包括
UNION
语句和子查询。
请参见
第13.2.10.3节“UNION语法”
和
第13.2.11节“子查询语法”
。
一个
SELECT
语句可以用开始
WITH
子句来定义内访问的公共表表达式
SELECT
。
请参见
第13.2.13节“WITH语法(公用表表达式)”
。
最常用的
SELECT
陈述
条款
是:
每个都
select_expr
表示要检索的列。
必须至少有一个
select_expr
。
table_references
表示从中检索行的一个或多个表。
其语法在
第13.2.10.2节“JOIN语法”中描述
。
SELECT
支持使用
PARTITION
带有一个分区列表或子分区(或两者)的
显式分区选择
,这些分区或子分区位于a的表名后面
table_reference
(参见
第13.2.10.2节“JOIN语法”
)。
在这种情况下,仅从列出的分区中选择行,并忽略表的任何其他分区。
有关更多信息和示例,请参见
第23.5节“分区选择”
。
SELECT ... PARTITION
从使用存储引擎的
MyISAM
表中执行表级锁(以及分区锁)仅锁定该
PARTITION
选项
指定的分区或子分区
。
有关更多信息,请参阅 分区和锁定 。
WHERE
如果给出
该
子句,则表示行必须满足要选择的条件。
where_condition
是一个表达式,对于要选择的每一行,计算结果为true。
如果没有
WHERE
子句,
该语句将选择所有行
。
在
WHERE
表达式中,您可以使用MySQL支持的任何函数和运算符,但聚合(汇总)函数除外。
请参见
第9.5节“表达式”
和
第12章
“
函数和运算符”
。
SELECT
也可用于检索计算的行而不引用任何表。
例如:
MySQL的> SELECT 1 + 1;
- > 2
MySQL的> SELECT 1 + 1 FROM DUAL;
- > 2
DUAL
纯粹是为了方便那些要求所有
SELECT
陈述应该具有的人
FROM
以及可能的其他条款。
MySQL可能会忽略这些子句。
FROM DUAL
如果没有引用表,
MySQL不需要
。
通常,使用的子句必须完全按照语法描述中显示的顺序给出。
例如,一个
HAVING
条款必须在任何
GROUP BY
条款之后和任何
ORDER
BY
条款
之前
。
例外情况是该
INTO
子句可以如语法描述中所示出现,也可以紧接在
select_expr
列表
后面出现
。
有关更多信息
INTO
,请参见
第13.2.10.1节“SELECT ... INTO语法”
。
select_expr
术语
列表
包括指示要检索哪些列的选择列表。
术语指定列或表达式或可以使用
*
-shorthand:
仅包含单个非限定条件的选择列表
*
可用作从所有表中选择所有列的简写:
SELECT * FROM t1 INNER JOIN t2 ...
可以用作合格的速记来选择命名表中的所有列:
tbl_name
.*
SELECT t1。*,t2。* FROM t1 INNER JOIN t2 ...
*
在选择列表中
使用不合格
的其他项可能会产生解析错误。
要避免此问题,请使用限定
参考
tbl_name
.*
SELECT AVG(得分),t1。* FROM t1 ...
以下列表提供了有关其他
SELECT
子句的
其他信息
:
A
select_expr
可以使用别名
。
别名用作表达式的列名,并且可以在被使用
,
或
条款。
例如:
AS
alias_name
GROUP BY
ORDER BY
HAVING
SELECT CONCAT(last_name,',',first_name)AS full_name FROM mytable ORDER BY full_name;
使用标识符
AS
别名化时
,
关键字是可选
select_expr
的。
前面的例子可能是这样编写的:
SELECT CONCAT(last_name,',',first_name)full_name FROM mytable ORDER BY full_name;
但是,因为它
AS
是可选的,如果您忘记两个
select_expr
表达式
之间的逗号,则会出现一个微妙的问题
:MySQL将第二个解释为别名。
例如,在以下语句中,
columnb
将被视为别名:
SELECT columna columnb FROM mytable;
因此,
AS
在指定列别名时
习惯
明确
使用是一种好习惯
。
不允许在
WHERE
子句中
引用列别名
,因为在
WHERE
执行子句
时可能尚未确定列值
。
请参见
第B.4.4.4节“列别名的问题”
。
该
子句指示要从中检索行的一个或多个表。
如果您为多个表命名,则表示您正在执行连接。
有关连接语法的信息,请参见
第13.2.10.2节“JOIN语法”
。
对于指定的每个表,您可以选择指定别名。
FROM
table_references
tbl_name
[[AS]alias
] [index_hint
]
索引提示的使用为优化器提供了有关如何在查询处理期间选择索引的信息。 有关指定这些提示的语法的说明,请参见 第8.9.4节“索引提示” 。
您可以使用
另一种方法强制MySQL更喜欢键扫描而不是表扫描。
请参见
第5.1.8节“服务器系统变量”
。
SET
max_seeks_for_key=
value
您可以将默认数据库中的表称为
tbl_name
或
db_name
。
tbl_name
明确指定数据库。
您可以将列引用为
col_name
,
tbl_name
。
col_name
或者
db_name
。
tbl_name
。
col_name
。
您无需指定
tbl_name
或
db_name
。
tbl_name
列引用的前缀,除非引用不明确。
有关
需要更明确的列引用形式的歧义的示例,
请参见
第9.2.1节“标识符限定符”
。
表引用可以使用
或
别名
。
这些陈述是等价的:
tbl_name
AS
alias_name
tbl_name alias_name
SELECT t1.name,t2.salary FROM employee AS t1,info AS t2 WHERE t1.name = t2.name; SELECT t1.name,t2.salary FROM employee t1,info t2 WHERE t1.name = t2.name;
可以
使用列名,列别名或列位置
在
ORDER BY
和
GROUP BY
子句中
引用为输出选择的
列。
列位置是整数,以1开头:
选择大学,地区,种子来自锦标赛 ORDER BY地区,种子; 选择大学,地区AS r,种子AS s FROM锦标赛 ORDER BY r,s; 选择大学,地区,种子来自锦标赛 订购2,3;
要按相反顺序排序,请将
DESC
(descending)关键字
添加到要排序
的
ORDER BY
子句中
列的名称
。
默认为升序;
这可以使用
ASC
关键字
明确指定
。
如果
ORDER BY
在子查询中发生并且也在外部查询中应用,则最外层
ORDER BY
优先。
例如,以下语句的结果按降序排序,而不是按升序排序:
(选择......由a命令)由DESC命令;
不推荐使用列位置,因为已从SQL标准中删除了语法。
在MySQL 8.0.13之前,MySQL支持允许显式的非标准语法扩展
ASC
列的
或
DESC
指定
GROUP
BY
。
MySQL 8.0.12及更高版本支持
ORDER BY
分组功能,因此不再需要使用此扩展。
(Bug#86312,Bug#26073525)这也意味着您可以在使用时对任意一列或多列进行排序
GROUP BY
,如下所示:
SELECT a,b,COUNT(c)AS t FROM test_table GROUP BY a,b ORDER BY a,t DESC;
从MySQL 8.0.13开始,
GROUP BY
不再支持扩展:
ASC
或者是
DESC
指示符
GROUP
BY
不允许
列的
。
当您使用
ORDER BY
或
GROUP
BY
对列中的列进行排序时
SELECT
,服务器仅使用
max_sort_length
系统变量
指示的初始字节数对值进行排序
。
MySQL扩展了使用
GROUP BY
以允许选择
GROUP
BY
子句
中未提及的字段
。
如果你没有得到你从你的查询所期望的结果,请阅读的描述
GROUP BY
中发现的
第12.20,“集合(GROUP BY)功能”
。
GROUP BY
允许
WITH
ROLLUP
修饰符。
请参见
第12.20.2节“GROUP BY Modifiers”
。
以前,不允许
ORDER
BY
在具有
WITH
ROLLUP
修饰符
的查询中
使用
它
。
从MySQL 8.0.12开始,此限制被取消。
请参见
第12.20.2节“GROUP BY Modifiers”
。
该
HAVING
条款几乎在最后一次应用,就在项目发送到客户端之前,没有优化。
(
LIMIT
之后适用
HAVING
。)
SQL标准要求
HAVING
必须仅引用
GROUP BY
聚合函数中使用
的
子句中的列。
但是,MySQL支持对此行为的扩展,并允许
HAVING
引用
SELECT
列表
中的
列和外部子查询中的列。
如果
HAVING
子句引用不明确的列,则会发出警告。
在下面的语句中,
col2
它是不明确的,因为它既用作别名又用作列名:
SELECT COUNT(col1)AS col2 FROM t GROUP BY col2 HAVING col2 = 2;
优先考虑标准SQL行为,因此如果
在输出列列表
HAVING
中
GROUP BY
和作为别
名列使用列名,则会
优先选择列中的
GROUP BY
列。
不要
HAVING
用于应该在该
WHERE
条款中的项目。
例如,不要写下面的内容:
SELECTcol_name
FROMtbl_name
HAVINGcol_name
> 0;
写这个:
SELECTcol_name
FROMtbl_name
WHEREcol_name
> 0;
该
HAVING
子句可以引用聚合函数,该
WHERE
子句不能:
SELECT用户,MAX(薪水)FROM用户 GROUP BY用户HAVING MAX(薪水)> 10;
(这在一些旧版本的MySQL中不起作用。)
MySQL允许重复的列名。
也就是说,可以有多个
select_expr
具有相同名称的。
这是标准SQL的扩展。
因为MySQL也允许
GROUP BY
并
HAVING
引用
select_expr
值,这可能会导致歧义:
SELECT 12 AS a,FROM t GROUP BY a;
在该语句中,两列都有名称
a
。
要确保使用正确的列进行分组,请为每个列使用不同的名称
select_expr
。
该
WINDOW
子句(如果存在)定义了可由窗口函数引用的命名窗口。
有关详细信息,请参见
第12.21.4节“命名Windows”
。
MySQL
ORDER BY
通过搜索
select_expr
值,然后在
FROM
子句
中的表的列中
搜索子句中的
非限定列或别名引用
。
对于
GROUP BY
or
HAVING
子句,它
FROM
在搜索
select_expr
值
之前搜索子句
。
(对于
GROUP BY
和
HAVING
,这与使用相同规则的MySQL 5.0之前的行为不同
ORDER
BY
。)
该
LIMIT
子句可用于约束
SELECT
语句
返回的行数
。
LIMIT
取一个或两个数字参数,它们都必须是非负整数常量,但有以下例外:
在预准备语句中,
LIMIT
可以使用
?
占位符标记
指定参数
。
在存储的程序中,
LIMIT
可以使用整数值例程参数或局部变量来指定参数。
使用两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。 初始行的偏移量为0(不是1):
SELECT * FROM tbl LIMIT 5,10; #检索行6-15
要从特定偏移量检索所有行直到结果集的末尾,可以使用一些大数字作为第二个参数。 此语句检索从第96行到最后一行的所有行:
SELECT * FROM tbl LIMIT 95,18446744073709551615;
使用一个参数,该值指定从结果集的开头返回的行数:
SELECT * FROM tbl LIMIT 5; #检索前5行
换句话说,
相当于
。
LIMIT
row_count
LIMIT 0,
row_count
对于预准备语句,您可以使用占位符。
以下语句将从
tbl
表中
返回一行
:
SET @ a = 1; 从'SELECT * FROM tbl LIMIT'中预备STMT? 使用@a执行STMT;
以下语句将返回表中的第二行到第六行
tbl
:
SET @ skip = 1; SET @ numrows = 5; 准备STMT从'SELECT * FROM tbl LIMIT?,?'; 使用@skip执行STMT,@ numrows;
为了与PostgreSQL兼容,MySQL还支持
语法。
LIMIT
row_count
OFFSET
offset
如果
LIMIT
在子查询中发生并且也在外部查询中应用,则最外层
LIMIT
优先。
例如,以下语句生成两行,而不是一行:
(SELECT ... LIMIT 1)LIMIT 2;
这种
SELECT ...
INTO
形式
SELECT
使查询结果能够写入文件或存储在变量中。
有关更多信息,请参见
第13.2.10.1节“SELECT ... INTO语法”
。
如果使用
FOR UPDATE
使用页锁或行锁的存储引擎,则查询检查的行将被写入锁定,直到当前事务结束。
您不能将其
FOR UPDATE
用作
SELECT
声明中的
一部分
。
(如果您尝试这样做,则该语句将被拒绝并显示错误
无法更新表'
'
正在创建
'
'
。)
CREATE
TABLE
new_table
SELECT ... FROM
old_table
...old_table
new_table
FOR SHARE
并
LOCK IN SHARE
MODE
设置共享锁,允许其他事务读取已检查的行,但不允许更新或删除它们。
FOR SHARE
并且
LOCK IN SHARE
MODE
是等价的。
然而
FOR
SHARE
,喜欢
FOR UPDATE
,支持
NOWAIT
,
SKIP LOCKED
和
选项。
是替代
,但
仍可用于向后兼容。
OF
tbl_name
FOR SHARE
LOCK IN SHARE MODE
LOCK IN
SHARE MODE
NOWAIT
导致
FOR
UPDATE
或
FOR SHARE
查询立即执行,如果由于另一个事务持有的锁而无法获得行锁,则返回错误。
SKIP LOCKED
导致
FOR
UPDATE
或
FOR SHARE
查询立即执行,排除结果集中由另一个事务锁定的行。
NOWAIT
和
SKIP LOCKED
选项对于基于语句的复制是不安全的。
跳过锁定行的查询会返回数据的不一致视图。
SKIP LOCKED
因此不适合一般交易工作。
但是,当多个会话访问同一个类似队列的表时,它可用于避免锁争用。
OF
对命名表
应用
tbl_name
FOR UPDATE
和
FOR
SHARE
查询。
例如:
SELECT * FROM t1,t2 for tARE for t1 for update of t2;
省略
时,查询块引用的所有表都将被锁定
。
因此,使用不
与另一个锁定子句组合的锁定子句会返回错误。
在多个锁定子句中指定相同的表会返回错误。
如果在
语句
中将别名指定为表名,则
锁定子句只能使用别名。
如果
语句未明确指定别名,则锁定子句只能指定实际的表名。
OF
tbl_name
OF
tbl_name
SELECT
SELECT
有关详细信息
FOR UPDATE
,并
FOR SHARE
请参见
第15.7.2.4,“锁定读”
。
有关
NOWAIT
和
SKIP
LOCKED
选项的
其他信息
,请
参阅使用NOWAIT和SKIP LOCKED锁定读取并发
。
在
SELECT
关键字之后,您可以使用许多影响语句操作的修饰符。
HIGH_PRIORITY
和
STRAIGHT_JOIN
,以及开头的修饰符
SQL_
是标准SQL的MySQL扩展。
在
ALL
和
DISTINCT
修饰符指定重复行是否应该返回。
ALL
(默认值)指定应返回所有匹配的行,包括重复行。
DISTINCT
指定从结果集中删除重复的行。
指定两个修饰符是错误的。
DISTINCTROW
是...的同义词
DISTINCT
。
在MySQL 8.0.12及更高版本中,
DISTINCT
可以与也使用的查询一起使用
WITH
ROLLUP
。
(Bug#87450,Bug#26640100)
HIGH_PRIORITY
SELECT
比更新表的语句
提供
更高的优先级。
您应该仅将此用于非常快速且必须立即执行的查询。
SELECT HIGH_PRIORITY
在表被锁定以进行读取时发出
的
查询即使存在等待表空闲的更新语句也会运行。
这会影响只使用表级锁只存储引擎(例如
MyISAM
,
MEMORY
和
MERGE
)。
STRAIGHT_JOIN
强制优化器按照
FROM
子句
中列出的顺序连接表
。
如果优化程序以非最佳顺序连接表,则可以使用此方法加速查询。
STRAIGHT_JOIN
也可以在
table_references
列表中使用。
请参见
第13.2.10.2节“JOIN语法”
。
STRAIGHT_JOIN
不适用于优化程序视为
const
或
system
表的
任何
表。
这样的表生成单行,在查询执行的优化阶段读取,并且在查询执行进行之前用适当的列值替换对其列的引用。
这些表将首先显示在显示的查询计划中
EXPLAIN
。
请参见
第8.8.1节“使用EXPLAIN优化查询”
。
此异常可能不适用于
const
或
system
那些在使用的表
NULL
外的-complemented侧连接(即,a的右侧表
LEFT
JOIN
或的左侧表
RIGHT
JOIN
。
SQL_BIG_RESULT
或者
SQL_SMALL_RESULT
可以与
优化器
一起使用
GROUP BY
或
DISTINCT
告诉优化器结果集分别有很多行或很小。
因为
SQL_BIG_RESULT
,MySQL在创建时直接使用基于磁盘的临时表,并且更喜欢使用带有
GROUP BY
元素
键的临时表进行排序
。
因为
SQL_SMALL_RESULT
,MySQL使用内存中的临时表来存储结果表而不是使用排序。
通常不需要这样做。
SQL_BUFFER_RESULT
强制将结果放入临时表中。
这有助于MySQL尽早释放表锁,并在需要很长时间将结果集发送到客户端的情况下提供帮助。
此修饰符只能用于顶级
SELECT
语句,不能用于子查询或后续语句
UNION
。
SQL_CALC_FOUND_ROWS
告诉MySQL计算结果集中有多少行,忽略任何
LIMIT
子句。
然后可以使用检索行数
SELECT
FOUND_ROWS()
。
请参见
第12.15节“信息功能”
。
该
SQL_CALC_FOUND_ROWS
查询修改和相应的
FOUND_ROWS()
功能已被弃用例如MySQL 8.0.17,并会在将来的MySQL版本中删除。
有关
FOUND_ROWS()
替代策略的信息,
请参阅
说明。
在
SQL_CACHE
和
SQL_NO_CACHE
改进剂与之前的MySQL 8.0查询缓存使用。
MySQL 8.0中删除了查询缓存。
该
SQL_CACHE
修改被移除。
SQL_NO_CACHE
已弃用,无效,将在未来的MySQL版本中删除。
SELECT
来自使用存储引擎(例如
MyISAM
使用表级锁)
的分区表中的
A
仅锁定包含与
SELECT
语句
WHERE
子句
匹配的行的分区
。
(
InnoDB
对于使用行级锁定的
存储引擎,不会发生这种情况
。)有关更多信息,请参阅
分区和锁定
。
该
SELECT ...
INTO
形式
SELECT
使查询结果存储在变量或将其写入文件:
SELECT ... INTO
选择列值并将它们存储到变量中。
var_list
SELECT ... INTO OUTFILE
将选定的行写入文件。
可以指定列和行终止符以生成特定的输出格式。
SELECT ... INTO DUMPFILE
将单行写入文件而不进行任何格式化。
在
SELECT
语法描述(见
第13.2.10,“SELECT语法”
)显示
INTO
附近的语句结尾条款。
也可以
INTO
在
select_expr
列表后
立即
使用
。
的
INTO
条款不应该在嵌套使用
SELECT
,因为这样一个
SELECT
必须将其结果返回到外部环境。
该
INTO
子句可以命名一个或多个变量的列表,这些变量可以是用户定义的变量,存储过程或函数参数,或存储的程序局部变量。
(在准备好的
SELECT ... INTO
OUTFILE
语句中,只允许用户定义的变量;请参见
第13.6.4.2节“局部变量范围和分辨率”
。)
选定的值将分配给变量。
变量的数量必须与列数相匹配。
查询应返回单行。
如果查询未返回任何行,则会发生错误代码为1329的警告(
No data
),并且变量值保持不变。
如果查询返回多行,则发生错误1172(
Result consisted of
more than one row
)。
如果语句可能检索多行,则可以使用
LIMIT
1
将结果集限制为单行。
SELECT id,data INTO @x,@ y FROM test.t1 LIMIT 1;
用户变量名称不区分大小写。 请参见 第9.4节“用户定义的变量” 。
所述
的形式
的选择的行写入到一个文件中。
该文件是在服务器主机上创建的,因此您必须具有
使用此语法
的
权限。
不能是现有文件,除其他外,它会阻止文件如
数据库表和数据库表被销毁。
该
系统变量控制文件名的解释。
SELECT ... INTO
OUTFILE '
file_name
'SELECT
FILE
file_name
/etc/passwd
character_set_filesystem
该
SELECT ... INTO
OUTFILE
语句主要用于让您快速将表转储到服务器计算机上的文本文件中。
如果要在服务器主机之外的其他主机上创建生成的文件,通常无法使用,
SELECT ... INTO
OUTFILE
因为无法相对于服务器主机的文件系统写入文件的路径。
但是,如果MySQL客户端软件安装在远程计算机上,则可以使用客户端命令(例如
在客户端主机上生成文件)。
mysql -e "SELECT ..." >
file_name
如果可以使用服务器文件系统上的网络映射路径访问远程主机上文件的位置,则还可以在服务器主机以外的其他主机上创建生成的文件。 在这种情况下, 目标主机上不需要 存在 mysql (或其他一些MySQL客户端程序)。
SELECT
... INTO
OUTFILE
是补充
LOAD
DATA
。
列值将写入转换为
CHARACTER SET
子句中
指定的字符集
。
如果不存在此类子句,则使用
binary
字符集转
储值
。
实际上,没有字符集转换。
如果结果集包含多个字符集中的列,则输出数据文件也将如此,您可能无法正确重新加载文件。
export_options
语句部分
的语法
由
FIELDS
与
LINES
语句一起使用
的相同
和
子句
组成
LOAD
DATA
。
参见
第13.2.7,“LOAD DATA语法”
,以获取有关信息
FIELDS
和
LINES
条款,包括它们的默认值和允许值。
FIELDS ESCAPED BY
控制如何写特殊字符。
如果
FIELDS ESCAPED BY
字符不为空,则在必要时使用它以避免歧义作为输出后面字符之前的前缀:
这个
FIELDS ESCAPED BY
角色
这个
FIELDS [OPTIONALLY] ENCLOSED BY
角色
FIELDS TERMINATED
BY
和
LINES TERMINATED BY
值
的第一个字符
ASCII
NUL
(零值字节;转义字符后面实际写入的是ASCII
0
,而不是零值字节)
的
FIELDS TERMINATED BY
,
ENCLOSED
BY
,
ESCAPED BY
,或
LINES
TERMINATED BY
字符
必须
进行转义,这样就可以读取该文件回可靠。
ASCII
NUL
被转义,以便使用某些寻呼机更容易查看。
生成的文件不必符合SQL语法,因此不需要转义任何其他内容。
如果
FIELDS ESCAPED BY
字符是空的,没有字符被转义,并且
NULL
是输出
NULL
,没有
\N
。
指定空的转义字符可能不是一个好主意,特别是如果数据中的字段值包含刚刚给出的列表中的任何字符。
下面是一个以许多程序使用的逗号分隔值(CSV)格式生成文件的示例:
选择a,b,a + b INTO OUTFILE'/tmp/result.txt' 字段被',''选择性地封闭''' 由'\ n'终止的线路 FROM test_table;
如果您使用
INTO DUMPFILE
而不是
INTO OUTFILE
,MySQL只在文件中写入一行,没有任何列或行终止,也没有执行任何转义处理。
如果要将
BLOB
值
存储
在文件中,
这非常有用
。
由
mysqld
帐户
运行
的操作系统用户
创建
INTO OUTFILE
或
INTO DUMPFILE
拥有的
任何文件
。
(你应该
永远
运行
mysqld的
是
,这和其他的原因。)从MySQL 8.0.17中,对文件创建的umask是0640;
您必须具有足够的访问权限才能操作文件内容。
在MySQL 8.0.17之前,umask是0666,并且该文件可由服务器主机上的所有用户写入。
root
如果
secure_file_priv
系统变量设置为非空目录名,则要写入的文件必须位于该目录中。
在
SELECT ...
INTO
作为事件调度程序执行的事件的一部分发生
的
语句
的上下文中
,诊断消息(不仅是错误,还包括警告)将写入错误日志,并在Windows上写入应用程序事件日志。
有关其他信息,请参见
第24.4.5节“事件调度程序状态”
。
MySQL支持
语句
部分
和多表
和
语句
的以下
JOIN
语法
:
table_references
SELECT
DELETE
UPDATE
table_references:
escaped_table_reference
[,escaped_table_reference
] ......escaped_table_reference
:table_reference
| {OJtable_reference
}table_reference
:table_factor
|joined_table
table_factor
:tbl_name
[PARTITION(partition_names
)] [[AS]alias
] [index_hint_list
] |table_subquery
[AS]alias
[(col_list
)] | (table_references
)joined_table
:table_reference
{[INNER | CROSS]加入| STRAIGHT_JOIN}table_factor
[join_specification
] |table_reference
{LEFT | RIGHT} [OUTER] JOIN | NATURAL [INNER | {LEFT | RIGHT} [OUTER]]加入table_reference
join_specification
table_reference
table_factor
join_specification
: ONsearch_condition
| 使用(join_column_list
)join_column_list
:column_name
[,column_name
] ......index_hint_list
:index_hint
[,index_hint
] ......index_hint
: 使用{INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY}]([index_list
]) | {IGNORE | FORCE} {INDEX | KEY} [FOR {JOIN | ORDER BY | GROUP BY}](index_list
)index_list
:index_name
[,index_name
] ......
表引用也称为连接表达式。
表引用(当它引用分区表时)可以包含一个
PARTITION
选项,包括逗号分隔的分区,子分区或两者的列表。
此选项遵循表的名称,并在任何别名声明之前。
此选项的作用是仅从列出的分区或子分区中选择行。
将忽略列表中未命名的任何分区或子分区。
有关更多信息和示例,请参见
第23.5节“分区选择”
。
table_factor
与标准SQL相比,MySQL中扩展了
语法
。
标准只接受
table_reference
,而不是在一对括号内的列表。
如果
table_reference
项目
列表中的每个逗号
被视为等同于内部
联接,则这是保守扩展
。
例如:
SELECT * FROM t1 LEFT JOIN(t2,t3,t4) ON(t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)
相当于:
SELECT * FROM t1 LEFT JOIN(t2 CROSS JOIN t3 CROSS JOIN t4) ON(t2.a = t1.a AND t3.b = t1.b AND t4.c = t1.c)
在MySQL, ,
JOIN
,
CROSS
JOIN
和
INNER JOIN
是句法当量(它们可以彼此替换)。
在标准SQL中,它们不等效。
INNER JOIN
与
ON
子句一起
CROSS JOIN
使用,否则使用。
通常,在仅包含内部联接操作的联接表达式中可以忽略括号。 MySQL还支持嵌套连接。 请参见 第8.2.1.7节“嵌套连接优化” 。
可以指定索引提示以影响MySQL优化器如何使用索引。
有关更多信息,请参见
第8.9.4节“索引提示”
。
优化器提示和
optimizer_switch
系统变量是影响优化器使用索引的其他方法。
请参见
第8.9.3节“优化程序提示”
和
第8.9.2节“可切换的优化”
。
以下列表描述了在编写联接时要考虑的一般因素:
表引用可以使用
或
使用别名
:
tbl_name
AS
alias_name
tbl_name alias_name
SELECT t1.name,t2.salary FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name; SELECT t1.name,t2.salary FROM employee t1 INNER JOIN info t2 ON t1.name = t2.name;
A
table_subquery
也称为
FROM
子句中
的派生表或子查询
。
请参见
第13.2.11.8节“派生表”
。
此类子查询
必须
包含别名,以便为子查询结果提供表名,并且可以选择在括号中包含表列名列表。
一个简单的例子如下:
SELECT * FROM(SELECT 1,2,3)AS t1;
INNER JOIN
和
,
(逗号)在没有连接条件的情况下在语义上是等价的:两者在指定的表之间产生笛卡尔积(即,第一个表中的每一行都连接到第二个表中的每一行)。
然而,逗号运算符的优先级低于的
INNER JOIN
,
CROSS
JOIN
,
LEFT JOIN
,等等。
如果在存在连接条件时将逗号连接与其他连接类型混合,则
可能会出现
表单错误
。
有关处理此问题的信息将在本节后面给出。
Unknown
column '
col_name
' in 'on
clause'
的
search_condition
使用
ON
是可以在中可以使用的形式的任何条件表达式
WHERE
子句。
通常,该
ON
子句用于指定如何连接表的条件,并且该
WHERE
子句限制要包含在结果集中的行。
如果
a
ON
或
USING
a中
的右侧表没有匹配的行,则将
LEFT JOIN
所有列设置为的行
NULL
用于右表。
您可以使用此事实在表中查找在另一个表中没有对应项的行:
SELECT left_tbl。* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;
此示例查找
left_tbl
具有
id
不存在
的
值的
所有行
right_tbl
(即,
left_tbl
没有相应行的
所有行
right_tbl
)。
请参见
第8.2.1.8节“外部连接优化”
。
该
子句命名两个表中必须存在的列的列表。
如果表
和
两者都包含列
,
和
,以下连接将比较两个表中的相应列:
USING(
join_column_list
)a
b
c1
c2
c3
a LEFT JOIN b使用(c1,c2,c3)
的
NATURAL [LEFT] JOIN
两个表被定义为语义上等同于一个
INNER
JOIN
或一个
LEFT JOIN
带有
USING
条款名称存在两个表中的所有列。
RIGHT JOIN
类似于
LEFT JOIN
。
为了使代码可以跨数据库移植,建议您使用
LEFT
JOIN
而不是
RIGHT JOIN
。
将
{ OJ ... }
在联接语法描述中显示存在语法只是为了与ODBC兼容。
语法中的花括号应按字面编写;
它们不是语法描述中其他地方使用的metasyntax。
SELECT left_tbl。* FROM {OJ left_tbl LEFT OUTER JOIN right_tbl ON left_tbl.id = right_tbl.id} WHERE right_tbl.id IS NULL;
您可以在其中使用其他类型的连接
{ OJ ...
}
,例如
INNER JOIN
或
RIGHT OUTER JOIN
。
这有助于与某些第三方应用程序兼容,但不是官方ODBC语法。
STRAIGHT_JOIN
类似于
JOIN
,除了左表总是在右表之前读取。
这可以用于连接优化器以次优顺序处理表的那些(少数)情况。
一些连接示例:
SELECT * FROM table1,table2; SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id; SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id; SELECT * FROM table1 LEFT JOIN table2 USING(id); SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id LEFT JOIN table3 ON table2.id = table3.id;
自然连接和连接
USING
,包括外连接变体,根据SQL:2003标准进行处理:
NATURAL
不显示
联接的冗余列
。
考虑这组陈述:
CREATE TABLE t1(i INT,j INT); CREATE TABLE t2(k INT,j INT); 插入t1值(1,1); 插入t2值(1,1); SELECT * FROM t1 NATURAL JOIN t2; SELECT * FROM t1 JOIN t2 USING(j);
在第一个
SELECT
语句中,列出
j
现在两个表中,因此成为连接列,因此,根据标准SQL,它应该只在输出中出现一次,而不是两次。
类似地,在第二个SELECT语句中,列
j
在
USING
子句中
命名,
并且应该只在输出中出现一次,而不是两次。
因此,语句产生了这个输出:
+ ------ + ------ + ------ + | j | 我| k | + ------ + ------ + ------ + | 1 | 1 | 1 | + ------ + ------ + ------ + + ------ + ------ + ------ + | j | 我| k | + ------ + ------ + ------ + | 1 | 1 | 1 | + ------ + ------ + ------ +
根据标准SQL发生冗余列消除和列排序,生成此显示顺序:
首先,两个连接表的合并公共列按它们在第一个表中出现的顺序排列
第二,第一个表所特有的列,按照它们在该表中出现的顺序排列
第三,第二个表所特有的列,它们在该表中出现的顺序
使用coalesce操作定义替换两个公共列的单个结果列。
也就是说,对于两个
t1.a
而且
t2.a
生成的单个连接列
a
被定义为
a = COALESCE(t1.a, t2.a)
,其中:
COALESCE(x,y)=(例如,当x不为空时,则为x结束)
如果连接操作是任何其他连接,则连接的结果列由连接表的所有列的串联组成。
合并列定义的结果是,对于外连接,
NULL
如果两列中的一列始终
为合并列,则合并列包含非
列
的值
NULL
。
如果两列都不是
NULL
,则两个公共列具有相同的值,因此选择哪一列作为合并列的值无关紧要。
解释这一点的一种简单方法是考虑外连接的合并列由a的内部表的公共列表示
JOIN
。
假设表
t1(a, b)
,并
t2(a, c)
具有下列内容:
t1 t2 ---- ---- 1 x 2 z 2 y 3 w
然后,对于此连接,列
a
包含以下值
t1.a
:
MySQL的> SELECT * FROM t1 NATURAL LEFT JOIN t2;
+ ------ + ------ + ------ +
| a | b | c |
+ ------ + ------ + ------ +
| 1 | x | NULL |
| 2 | y | z |
+ ------ + ------ + ------ +
相反,对于此连接,列
a
包含值
t2.a
。
MySQL的> SELECT * FROM t1 NATURAL RIGHT JOIN t2;
+ ------ + ------ + ------ +
| a | c | b |
+ ------ + ------ + ------ +
| 2 | z | y |
| 3 | w | NULL |
+ ------ + ------ + ------ +
将这些结果与其他等效查询进行比较
JOIN ... ON
:
MySQL的> SELECT * FROM t1 LEFT JOIN t2 ON (t1.a = t2.a);
+ ------ + ------ + ------ + ------ +
| a | b | a | c |
+ ------ + ------ + ------ + ------ +
| 1 | x | NULL | NULL |
| 2 | y | 2 | z |
+ ------ + ------ + ------ + ------ +
MySQL的> SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a = t2.a);
+ ------ + ------ + ------ + ------ +
| a | b | a | c |
+ ------ + ------ + ------ + ------ +
| 2 | y | 2 | z |
| NULL | NULL | 3 | w |
+ ------ + ------ + ------ + ------ +
甲
USING
子句可以改写为一个
ON
用于比较对应列子句。
然而,虽然
USING
并且
ON
相似,但它们并不完全相同。
考虑以下两个查询:
a LEFT JOIN b使用(c1,c2,c3) a LEFT JOIN b ON a.c1 = b.c1 AND a.c2 = b.c2 AND a.c3 = b.c3
关于确定哪些行满足连接条件,两个连接在语义上是相同的。
关于确定要显示哪些列以进行
SELECT *
扩展,这两个连接在语义上不相同。
该
USING
而加入选择对应列的聚结的值,
ON
从所有表加入选择的所有列。
对于
USING
连接,请
SELECT *
选择以下值:
COALESCE(a.c1,b.c1),COALESCE(a.c2,b.c2),COALESCE(a.c3,b.c3)
为了
ON
连接,请
SELECT
*
选择以下值:
a.c1,a.c2,a.c3,b.c1,b.c2,b.c3
使用内部联接,
COALESCE(a.c1,
b.c1)
与
两者中
的相同
a.c1
或
b.c1
两个列具有相同的值。
使用外连接(例如
LEFT JOIN
),两列中的一列可以
NULL
。
结果中省略了该列。
一个
ON
子句只能参考它的操作数。
例:
CREATE TABLE t1(i1 INT); CREATE TABLE t2(i2 INT); CREATE TABLE t3(i3 INT); SELECT * FROM t1 JOIN t2 ON(i1 = i3)JOIN t3;
该语句因
Unknown column 'i3' in
'on clause'
错误而
失败,
因为它
i3
是一个列
t3
,它不是该
ON
子句
的操作数
。
要启用联接,请按如下所示重写语句:
SELECT * FROM t1 JOIN t2 JOIN t3 ON(i1 = i3);
JOIN
优先级高于逗号运算符(
,
),因此连接表达式
t1, t2 JOIN t3
被解释为
(t1, (t2 JOIN t3))
,而不是
((t1,
t2) JOIN t3)
。
这会影响使用
ON
子句的
语句,
因为该子句只能引用连接操作数中的列,并且优先级会影响对这些操作数的解释。
例:
CREATE TABLE t1(i1 INT,j1 INT); CREATE TABLE t2(i2 INT,j2 INT); CREATE TABLE t3(i3 INT,j3 INT); 插入t1值(1,1); 插入t2值(1,1); 插入t3值(1,1); SELECT * FROM t1,t2 JOIN t3 ON(t1.i1 = t3.i3);
该
JOIN
过逗号运算符的优先级,所以对于操作数
ON
子句
t2
和
t3
。
因为
t1.i1
不是任何一个操作数中的列,结果是
Unknown column
't1.i1' in 'on clause'
错误。
要启用联接,请使用以下任一策略:
使用括号显式地对前两个表进行分组,以使
ON
子句
的操作数为
(t1, t2)
和
t3
:
SELECT * FROM(t1,t2)JOIN t3 ON(t1.i1 = t3.i3);
避免使用逗号运算符
JOIN
而是
使用
:
SELECT * FROM t1 JOIN t2 JOIN t3 ON(t1.i1 = t3.i3);
优先级相同的解释也适用于与混合逗号操作语句
INNER
JOIN
,
CROSS JOIN
,
LEFT
JOIN
,并且
RIGHT JOIN
,所有这些都具有比逗号操作符更高的优先级。
与SQL:2003标准相比,MySQL扩展是MySQL允许您限定常见(合并)列
NATURAL
或
USING
连接,而标准不允许。
选择 ... UNION [全部| DISTINCT]选择...... [UNION [全部| DISTINCT] SELECT ...]
UNION
用于将多个
SELECT
语句
的结果组合
到单个结果集中。
第一个
SELECT
语句中的列名称用作返回结果的列名称。
在每个
SELECT
语句的
相应位置列出的选定列
应具有相同的数据类型。
(例如,第一个语句选择的第一列应该与其他语句选择的第一列具有相同的类型。)
如果相应
SELECT
列
的数据类型
不匹配,则
UNION
结果中
列的类型和长度
会考虑所有
SELECT
语句
检索的值
。
例如,请考虑以下事项:
MySQL的> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+ --------------- +
| 重复('a',1)|
+ --------------- +
| a |
| bbbbbbbbbb |
+ --------------- +
这些
SELECT
语句是普通的select语句,但有以下限制:
默认行为
UNION
是从结果中删除重复的行。
可选
DISTINCT
关键字除了默认值之外没有任何效果,因为它还指定了重复行删除。
使用可选
ALL
关键字,不会发生重复行删除,结果包括所有
SELECT
语句中的
所有匹配行
。
你可以混合
UNION
ALL
和
UNION
DISTINCT
在相同的查询。
UNION
处理
混合
类型,使得
DISTINCT
联合覆盖
ALL
其左侧的
任何
联合。
甲
DISTINCT
工会可以明确,通过使用来产生
UNION
DISTINCT
或隐式地通过使用
UNION
没有以下
DISTINCT
或
ALL
关键字。
要应用
ORDER BY
或
LIMIT
个人
SELECT
,请将子句放在括起来的括号内
SELECT
:
(选择一个FROM t1 WHERE a = 10 AND B = 1 ORDER by LIMIT 10) 联盟 (选择一个FROM t2 WHERE a = 11 AND B = 2 ORDER by LIMIT 10);
但是,
ORDER BY
对于单个
SELECT
语句的
使用
并不意味着行在最终结果中出现的顺序,因为
UNION
默认情况下会生成一组无序行。
因此,
ORDER
BY
在此上下文中
的使用
通常与结合使用
LIMIT
,以便它用于确定要检索的所选行的子集
SELECT
,即使它不一定影响最终
UNION
结果
中那些行的顺序
。
如果
ORDER
BY
没有出现
LIMIT
在
SELECT
,它被优化掉,因为它不会有任何效果呢。
要使用
ORDER BY
or
LIMIT
子句对整个
UNION
结果
进行排序或限制
,请将各个
SELECT
语句
括起来
并放在
最后一个
ORDER BY
或
LIMIT
之后。
以下示例使用两个子句:
(选择一个FROM t1 WHERE a = 10 AND B = 1) 联盟 (选择一个FROM t2 WHERE a = 11 AND B = 2) 订购限额10;
没有括号的语句相当于刚刚显示的一个括号。
这种类型
ORDER BY
不能使用包含表名的列引用(即
tbl_name
。
col_name
格式的
名称
)。
相反,在第一个
SELECT
语句中
提供列别名
并引用其中的别名
ORDER BY
。
(或者,请参阅
ORDER BY
使用其列位置
中的
列。但是,不推荐使用列位置。)
此外,如果要排序的列是别名,则该
ORDER
BY
子句
必须
引用别名,而不是列名。
以下第一个语句将起作用,但第二个语句将失败并显示
Unknown column 'a' in 'order clause'
错误:
(选择一个AS b FROM t)UNION(SELECT ...)ORDER BY b; (选择一个AS b FROM t)UNION(SELECT ...)ORDER BY a;
要使
UNION
结果中的行包含由每个行检索到的行集,请在每个行中
SELECT
选择一个附加列
SELECT
以用作排序列,并
ORDER BY
在最后
添加
以下内容
SELECT
:
(SELECT 1 AS sort_col,col1a,col1b,... FROM t1) 联盟 (SELECT 2,col2a,col2b,... FROM t2)ORDER BY sort_col;
要在单个
SELECT
结果中
另外维护排序顺序
,请在
ORDER BY
子句中
添加辅助列
:
(SELECT 1 AS sort_col,col1a,col1b,... FROM t1) 联盟 (SELECT 2,col2a,col2b,... FROM t2)ORDER BY sort_col,col1a;
使用附加列还可以确定
SELECT
每行来自
哪一
行。
额外列也可以提供其他标识信息,例如表示表名的字符串。
UNION
具有
ORDER BY
子句中
的聚合函数的查询将
被拒绝并出现
ER_AGGREGATE_ORDER_FOR_UNION
错误。
例:
SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);
子查询是
SELECT
另一个语句中的语句。
支持SQL标准所需的所有子查询表单和操作,以及一些特定于MySQL的功能。
以下是子查询的示例:
SELECT * FROM t1 WHERE column1 =(SELECT column1 FROM t2);
在此示例中,
SELECT * FROM t1 ...
是
外部查询
(或
外部语句
),并且
(SELECT column1 FROM
t2)
是
子查询
。
我们说子查询
嵌套
在外部查询中,实际上可以将子查询嵌套在其他子查询中,达到相当深的程度。
子查询必须始终出现在括号内。
子查询的主要优点是:
它们允许 结构化的 查询, 以便可以隔离语句的每个部分。
它们提供了执行操作的替代方法,否则需要复杂的连接和联合。
许多人发现子查询比复杂的联接或联合更具可读性。 实际上,正是子查询的创新给人们提供了调用早期SQL “ 结构化查询语言 ” 的最初想法 。 ”
下面是一个示例语句,显示了SQL标准指定并在MySQL中支持的子查询语法的主要观点:
从t1删除 在哪里>任何人 (SELECT COUNT(*)/ * no提示* / FROM t2 什么不存在 (SELECT * FROM t3 在哪里(5 * t2.s1,77)= (从T4 UNION SELECT 50,77 FROM中选择50,11 * s1 (SELECT * FROM t5)AS t5)));
子查询可以返回标量(单个值),单个行,单个列或表(一个或多个列的一行或多行)。 这些称为标量,列,行和表子查询。 返回特定类型结果的子查询通常只能在某些上下文中使用,如以下各节所述。
对可以使用子查询的语句类型的限制很少。
子查询可以包含许多普通的关键字或条款
SELECT
可能包含:
DISTINCT
,
GROUP BY
,
ORDER BY
,
LIMIT
,连接,索引提示,
UNION
结构,注释,函数等等。
子查询的外部语句可以是任何一个:
SELECT
,
INSERT
,
UPDATE
,
DELETE
,
SET
,或
DO
。
在MySQL中,您无法修改表并从子查询中的同一个表中进行选择。
这适用于语句,例如
DELETE
,
INSERT
,
REPLACE
,
UPDATE
,和(因为子查询可以在中使用
SET
子句)
LOAD
DATA
。
有关优化程序如何处理子查询的信息,请参见 第8.2.2节“优化子查询,派生表,视图引用和公用表表达式” 。 有关子查询使用限制的讨论,包括某些形式的子查询语法的性能问题,请参见 第C.4节“子查询的限制” 。
在其最简单的形式中,子查询是一个返回单个值的标量子查询。
标量子查询是一个简单的操作数,您几乎可以在单个列值或文字合法的任何地方使用它,并且您可以期望它具有所有操作数具有的特征:数据类型,长度,它可以指示它是
NULL
,依此类推。
例如:
CREATE TABLE t1(s1 INT,s2 CHAR(5)NOT NULL); 插入t1 VALUES(100,'abcde'); SELECT(SELECT s2 FROM t1);
其中的子查询
SELECT
返回单个值(
'abcde'
),该
值
具有数据类型
CHAR
,长度为5,字符集和排序规则等于当时有效的默认值
CREATE
TABLE
,并指示列中的值可以是
NULL
。
不会复制标量子查询所选值的可为空性,因为如果子查询结果为空,则结果为
NULL
。
对于刚刚显示的子查询,如果
t1
为空,则结果
NULL
即使
s2
是
NOT NULL
。
有一些上下文不能使用标量子查询。
如果语句仅允许文字值,则不能使用子查询。
例如,
LIMIT
需要文字整数参数,并且
LOAD
DATA
需要文字字符串文件名。
您不能使用子查询来提供这些值。
当您在以下部分中看到包含相当简洁的构造的示例时,请
(SELECT column1 FROM
t1)
想象您自己的代码包含更多样化和复杂的构造。
假设我们制作两个表:
CREATE TABLE t1(s1 INT); 插入t1值(1); CREATE TABLE t2(s1 INT); 插入t2值(2);
然后执行
SELECT
:
SELECT(SELECT s1 FROM t2)FROM t1;
结果是
2
因为
t2
包含
s1
一个值为的
列
的行
2
。
标量子查询可以是表达式的一部分,但请记住括号,即使子查询是为函数提供参数的操作数。 例如:
SELECT UPPER((从s1中选择s1))FROM t2;
子查询的最常见用法是以下形式:
non_subquery_operand
comparison_operator
(subquery
)
comparison_operator
这些运营商之一
在哪里
:
=> <> = <= <>!= <=>
例如:
... WHERE'a'=(SELECT column1 FROM t1)
MySQL也允许这种结构:
non_subquery_operand
喜欢(subquery
)
有一次,子查询的唯一合法位置是在比较的右侧,您可能仍然会发现一些坚持这一点的旧DBMS。
下面是一个常见形式子查询比较的示例,您无法对连接执行此操作。
它查找表中的所有行,
t1
其
column1
值等于表中的最大值
t2
:
SELECT * FROM t1 WHERE column1 =(SELECT MAX(column2)FROM t2);
这是另一个例子,连接也是不可能的,因为它涉及聚合其中一个表。
它查找表中
t1
包含在给定列中出现两次的值的
所有行
:
SELECT * FROM t1 AS t WHERE 2 =(SELECT COUNT(*)FROM t1 WHERE t1.id = t.id);
为了将子查询与标量进行比较,子查询必须返回标量。 为了将子查询与行构造函数进行比较,子查询必须是行子查询,该子查询返回与行构造函数具有相同数量值的行。 请参见 第13.2.11.5节“行子查询” 。
句法:
operand
comparison_operator
ANY(subquery
)operand
IN(subquery
) SOME()operand
comparison_operator
subquery
comparison_operator
这些运营商之一
在哪里
:
=> <> = <= <>!=
该
ANY
关键字,它必须遵循一个比较操作符,表示
“
回报
TRUE
如果比较
TRUE
的
ANY
列的子查询返回的值。
“
例如:
SELECT s1 FROM t1 WHERE s1> ANY(SELECT s1 FROM t2);
假设表
t1
中
有一行
包含
(10)
。
表达是
TRUE
如果表
t2
包含
(21,14,7)
因为有一个值
7
在
t2
小于
10
。
表达式是
FALSE
if表
t2
包含
(20,10)
,或者表
t2
是否为空。
如果表
包含
,
表达式是
未知的
(即
NULL
)
。
t2
(NULL,NULL,NULL)
与子查询一起使用时,该单词
IN
是别名
= ANY
。
因此,这两个陈述是相同的:
SELECT s1 FROM t1 WHERE s1 = ANY(SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 IN(SELECT s1 FROM t2);
IN
并且
= ANY
与表达式列表一起使用时不是同义词。
IN
可以采用表达式列表,但
= ANY
不能。
请参见
第12.3.2节“比较函数和运算符”
。
NOT IN
不是别名
<>
ANY
,而是for
<> ALL
。
请参见
第13.2.11.4节“带有ALL的子查询”
。
这个词
SOME
是别名
ANY
。
因此,这两个陈述是相同的:
SELECT s1 FROM t1 WHERE s1 <> ANY(SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 <> SOME(SELECT s1 FROM t2);
使用这个词
SOME
很少见,但这个例子说明了它可能有用的原因。
对于大多数人来说,英语短语
“
a不等于任何b
”
意味着
“
没有b等于a
”,
但这不是SQL语法的含义。
语法意味着
“
有一些不相等的b。
“
使用
<> SOME
相反有助于确保每个人都理解查询的真正含义。
句法:
operand
comparison_operator
全部(subquery
)
ALL
必须遵循比较运算符
的单词
表示
“
如果进行比较则
返回
”
TRUE
TRUE
的
ALL
列的子查询返回的值。
“
例如:
SELECT s1 FROM t1 WHERE s1> ALL(SELECT s1 FROM t2);
假设表
t1
中
有一行
包含
(10)
。
表达式是
TRUE
if表
t2
包含
(-5,0,+5)
因为
10
大于所有三个值
t2
。
表达是
FALSE
如果表
t2
包含
(12,6,NULL,-100)
,因为有一个单一的值
12
在表
t2
是大于
10
。
如果表
包含
,
表达式是
未知的
(即
NULL
)
。
t2
(0,NULL,1)
最后,表达式是
TRUE
表格
t2
是否为空。
因此,以下表达式是
TRUE
表
t2
为空时:
SELECT * FROM t1 WHERE 1> ALL(SELECT s1 FROM t2);
但是这个表达式是
NULL
表
t2
空时:
SELECT * FROM t1 WHERE 1>(SELECT s1 FROM t2);
另外,以下表达式是
NULL
表
t2
为空时:
SELECT * FROM t1 WHERE 1> ALL(SELECT MAX(s1)FROM t2);
通常,
包含
NULL
值
和
空表的表
是
“
边缘情况”。
“
在编写子查询时,请始终考虑是否考虑了这两种可能性。
NOT IN
是别名
<>
ALL
。
因此,这两个陈述是相同的:
SELECT s1 FROM t1 WHERE s1 <> ALL(SELECT s1 FROM t2); SELECT s1 FROM t1 WHERE s1 NOT IN(SELECT s1 FROM t2);
标量或列子查询返回单个值或一列值。 甲 行子查询 是一个子查询变体返回单个行,因此可以返回多个列值。 行子查询比较的合法运算符是:
=> <> = <= <>!= <=>
这是两个例子:
SELECT * FROM t1 WHERE(col1,col2)=(SELECT col3,col4 FROM t2 WHERE id = 10); SELECT * FROM t1 WHERE ROW(col1,col2)=(SELECT col3,col4 FROM t2 WHERE id = 10);
对于这两个查询,如果表
t2
包含单行
id = 10
,则子查询返回单行。
如果此行的
值
col3
和
col4
值等于
任何行的值
col1
和
col2
值
t1
,则
WHERE
表达式为,
TRUE
并且每个查询都返回这些
t1
行。
如果
t2
行
col3
和
col4
值不等于
任何
行的
值
col1
和
col2
值
t1
,则表达式为
FALSE
,并且查询返回空结果集。
表达方式
未知
(即,
NULL
)如果子查询没有产生任何行。
如果子查询产生多行,则会发生错误,因为行子查询最多只能返回一行。
有关每个运算符如何进行行比较的信息,请参见 第12.3.2节“比较函数和运算符” 。
表达
(1,2)
和
ROW(1,2)
有时被称为
行构造函数
。
两者是等价的。
行构造函数和子查询返回的行必须包含相同数量的值。
行构造函数用于与返回两列或更多列的子查询进行比较。 当子查询返回单个列时,这被视为标量值而不是行,因此行构造函数不能与不返回至少两列的子查询一起使用。 因此,以下查询失败并出现语法错误:
SELECT * FROM t1 WHERE ROW(1)=(SELECT column1 FROM t2)
行构造函数在其他上下文中是合法的。 例如,以下两个语句在语义上是等效的(并且由优化器以相同的方式处理):
SELECT * FROM t1 WHERE(column1,column2)=(1,1); SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
以下查询回答请求,
“
查找表
t1
中也存在于表中的
所有行
t2
”
:
SELECT column1,column2,column3 从t1 WHERE(column1,column2,column3)IN (SELECT column1,column2,column3 FROM t2);
有关优化程序和行构造函数的更多信息,请参见 第8.2.1.21节“行构造函数表达式优化”
如果一个子查询返回任何行可言,
是
和
是
。
例如:
EXISTS
subquery
TRUE
NOT EXISTS
subquery
FALSE
SELECT column1 FROM t1 WHERE EXISTS(SELECT * FROM t2);
传统上,
EXISTS
子查询开始于
SELECT *
,但它可以以
SELECT 5
或
SELECT column1
或任何东西
开头
。
MySQL忽略了
SELECT
这样一个子查询中
的
列表,所以没有区别。
对于前面的示例,如果
t2
包含任何行,甚至包含除了
NULL
值之外的
行
,则
EXISTS
条件为
TRUE
。
这实际上是一个不太可能的例子,因为
[NOT] EXISTS
子查询几乎总是包含相关性。
以下是一些更现实的例子:
一个或多个城市有哪种商店?
SELECT DISTINCT store_type FROM stores 在哪里存在(SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
没有城市有什么样的商店?
SELECT DISTINCT store_type FROM stores 什么不存在(SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);
所有城市都有哪种商店?
SELECT DISTINCT store_type FROM存储s1 什么地方没有( SELECT * FROM CITY不存在( SELECT * FROM cities_stores cities_ cities.city = cities.city AND cities_stores.store_type = stores.store_type));
最后一个示例是双嵌套
NOT
EXISTS
查询。
也就是说,它在一个
NOT
EXISTS
子句中有一个
NOT EXISTS
子句。
在形式上,它回答了
“
一个城市存在与不存在的商店
Stores
”的问题
吗?
但它更容易地说,嵌套
NOT EXISTS
的答案的问题
“
是
对所有
?
x
TRUE
y
”
甲 相关子 是包含要也出现在外部查询表的基准的子查询。 例如:
SELECT * FROM t1 WHERE column1 = ANY(SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);
请注意,子查询包含对列的引用
t1
,即使子查询的
FROM
子句未提及表
t1
。
因此,MySQL在子查询之外查找,并
t1
在外部查询中查找。
假设该表
t1
包含一行where
column1 = 5
和
column2 =
6
;
同时,表中
t2
包含一行
column1 = 5
和
column2 =
7
。
简单的表达式
... WHERE column1 =
ANY (SELECT column1 FROM t2)
是
TRUE
,但在这个例子中,
WHERE
子查询中
的
子句是
FALSE
(因为
(5,6)
不等于
(5,7)
),所以表达式作为一个整体
FALSE
。
范围规则: MySQL从内到外进行评估。 例如:
SELECT column1 FROM t1 AS x WHERE x.column1 =(SELECT column1 FROM t2 AS x WHERE x.column1 =(SELECT column1 FROM t3 WHERE x.column2 = t3.column1));
在此语句中,
x.column2
必须是表中的列,
t2
因为
SELECT column1
FROM t2 AS x ...
重命名
t2
。
它不是表中的列,
t1
因为它
SELECT column1 FROM t1 ...
是一个
更远
的外部查询
。
对于
HAVING
or或
ORDER
BY
子句中的
子查询
,MySQL还会在外部选择列表中查找列名。
对于某些情况,优化了相关子查询。 例如:
val
IN(key_val
从tbl_name
哪里选择correlated_condition
)
否则,它们效率低下并且可能很慢。 将查询重写为连接可能会提高性能。
相关子查询中的聚合函数可能包含外部引用,前提是该函数只包含外部引用,并且该函数不包含在另一个函数或表达式中。
本节讨论派生表的一般特征。
有关以
LATERAL
关键字
开头的横向派生表的
信息
,请参见
第13.2.11.9节“横向派生表”
。
派生表是一个表达式,用于在查询
FROM
子句
的范围内生成表
。
例如,
SELECT
statement
FROM
子句中
的子查询
是派生表:
SELECT ... FROM(subquery
)[AS]tbl_name
...
该
JSON_TABLE()
函数生成一个表,并提供另一种创建派生表的方法:
SELECT * FROM JSON_TABLE(arg_list
)[AS]tbl_name
...
该
子句是必需的,因为子句中的每个表都
必须具有名称。
派生表中的任何列都必须具有唯一名称。
或者,
可以跟随派生表列的带括号的名称列表:
[AS]
tbl_name
FROM
tbl_name
SELECT ... FROM(subquery
)[AS]tbl_name
(col_list
)...
列名称的数量必须与表列的数量相同。
为了便于说明,假设您有此表:
CREATE TABLE t1(s1 INT,s2 CHAR(5),s3 FLOAT);
以下是
FROM
使用示例表
在
子句中使用
子查询的
方法:
插入t1值(1,'1',1.0); 插入t1值(2,'2',2.0); SELECT sb1,sb2,sb3 FROM(SELECT s1 AS sb1,s2 AS sb2,s3 * 2 AS sb3 FROM t1)AS sb WHERE sb1> 1;
结果:
+ ------ + ------ + ------ + | sb1 | sb2 | sb3 | + ------ + ------ + ------ + | 2 | 2 | 4 | + ------ + ------ + ------ +
这是另一个例子:假设您想知道分组表的一组总和的平均值。 这不起作用:
SELECT AVG(SUM(column1))FROM t1 GROUP BY column1;
但是,此查询提供了所需的信息:
SELECT AVG(sum_column1) FROM(SELECT SUM(column1)AS sum_column1 FROM t1 GROUP BY column1)AS t1;
请注意,子查询(
sum_column1
)中
使用的列名称
在外部查询中被识别。
派生表的列名来自其选择列表:
MySQL的> SELECT * FROM (SELECT 1, 2, 3, 4) AS dt;
+ --- + --- + --- + --- +
| 1 | 2 | 3 | 4 |
+ --- + --- + --- + --- +
| 1 | 2 | 3 | 4 |
+ --- + --- + --- + --- +
要显式提供列名,请使用带括号的列名列表跟随派生表名:
MySQL的> SELECT * FROM (SELECT 1, 2, 3, 4) AS dt (a, b, c, d);
+ --- + --- + --- + --- +
| a | b | c | d |
+ --- + --- + --- + --- +
| 1 | 2 | 3 | 4 |
+ --- + --- + --- + --- +
派生表可以返回标量,列,行或表。
派生表受这些限制的约束:
派生表不能是相关子查询。
派生表不能包含对其他表的引用
SELECT
。
在MySQL 8.0.14之前,派生表不能包含外部引用。
这是在MySQL 8.0.14中解除的MySQL限制,而不是SQL标准的限制。
例如,
dt
以下查询中
的派生表
包含
对外部查询中
t1.b
的表
的引用
t1
:
SELECT * FROM t1 在哪里t1.d>(SELECT AVG(dt.a) FROM(SELECT SUM(t2.a)AS a 从t2开始 在哪里t2.b = t1.b GROUP BY t2.c)dt 在哪里dt.a> 10);
该查询在MySQL 8.0.14及更高版本中有效。
在8.0.14之前,它会产生错误:
Unknown column 't1.b'
in 'where clause'
优化器以
EXPLAIN
不需要实现
派生表的方式确定有关派生表的信息
。
请参见
第8.2.2.4节“使用合并或实现优化派生表,视图引用和公用表表达式”
。
在某些情况下,使用
EXPLAIN
SELECT
将修改表数据
是可能的
。
如果外部查询访问任何表并且内部查询调用更改表的一行或多行的存储函数,则会发生这种情况。
假设有两个表
t1
,并
t2
在数据库
d1
和存储功能
f1
来修改
t2
,如下所示创建:
创建数据库d1; 使用d1; CREATE TABLE t1(c1 INT); CREATE TABLE t2(c1 INT); CREATE FUNCTION f1(p1 INT)RETURNS INT 开始 插入t2值(p1); 返回p1; 结束;
直接在an中引用该函数
EXPLAIN
SELECT
对此没有影响
t2
,如下所示:
MySQL的>SELECT * FROM t2;
空集(0.02秒) MySQL的>EXPLAIN SELECT f1(5)\G
*************************** 1。排******************** ******* id:1 select_type:SIMPLE table:NULL 分区:NULL type:NULL possible_keys:NULL key:NULL key_len:NULL ref:NULL rows:NULL 已过滤:NULL 额外:不使用表格 1排(0.01秒) MySQL的>SELECT * FROM t2;
空集(0.01秒)
这是因为
SELECT
语句没有引用任何表,如
输出
的
table
和
Extra
列中所示。
以下嵌套也是如此
SELECT
:
MySQL的>EXPLAIN SELECT NOW() AS a1, (SELECT f1(5)) AS a2\G
*************************** 1。排******************** ******* id:1 select_type:PRIMARY table:NULL type:NULL possible_keys:NULL key:NULL key_len:NULL ref:NULL rows:NULL 已过滤:NULL 额外:不使用表格 1排,1警告(0.00秒) MySQL的>SHOW WARNINGS;
+ ------- + ------ + ---------------------------------- -------- + | 等级| 代码| 消息| + ------- + ------ + ---------------------------------- -------- + | 注意| 1249 | 在优化期间,选择2减少了| + ------- + ------ + ---------------------------------- -------- + 1排(0.00秒) MySQL的>SELECT * FROM t2;
空集(0.00秒)
但是,如果外部
SELECT
引用任何表,优化器也会在子查询中执行语句,
t2
并修改
结果
:
MySQL的>EXPLAIN SELECT * FROM t1 AS a1, (SELECT f1(5)) AS a2\G
*************************** 1。排******************** ******* id:1 select_type:PRIMARY table:<derived2> 分区:NULL 类型:系统 possible_keys:NULL key:NULL key_len:NULL ref:NULL 行:1 过滤:100.00 额外:NULL *************************** 2.排******************** ******* id:1 select_type:PRIMARY 表:a1 分区:NULL 类型:全部 possible_keys:NULL key:NULL key_len:NULL ref:NULL 行:1 过滤:100.00 额外:NULL *************************** 3。排******************** ******* id:2 select_type:DERIVED table:NULL 分区:NULL type:NULL possible_keys:NULL key:NULL key_len:NULL ref:NULL rows:NULL 已过滤:NULL 额外:不使用表格 3组(0.00秒) MySQL的>SELECT * FROM t2;
+ ------ + | c1 | + ------ + | 5 | + ------ + 1排(0.00秒)
这也意味着
EXPLAIN
SELECT
诸如此处所示
的
语句可能需要很长时间才能执行,因为该
BENCHMARK()
函数对于每一行执行一次
t1
:
EXPLINE SELECT * FROM t1 AS a1,(SELECT BENCHMARK(1000000,MD5(NOW())));
派生表通常不能引用同一
FROM
子句
中前面表的(依赖于)列
。
从MySQL 8.0.14开始,可以将派生表定义为横向派生表,以指定允许此类引用。
使用
第13.2.11.8节“派生表”中
讨论的语法指定非
边界派生表
。
横向派生表的语法与非边界派生表的语法相同,只是
LATERAL
在派生表规范之前指定
了关键字
。
的
LATERAL
关键字必须先于每个表以用作横向派生表。
横向派生表受这些限制:
横向派生表可以只发生在一个
FROM
条款,无论是在用逗号分隔的表的列表中或在加入规范(
JOIN
,
INNER JOIN
,
CROSS JOIN
,
LEFT [OUTER]
JOIN
,或
RIGHT [OUTER] JOIN
)。
如果横向派生表是在一个连接子句的右操作数和包含对左操作数的引用,所述加入操作必须是
INNER JOIN
,
CROSS JOIN
,或
LEFT [OUTER]
JOIN
。
如果表是在左边的操作数,并包含右操作数的引用,连接操作必须是
INNER JOIN
,
CROSS
JOIN
或
RIGHT [OUTER] JOIN
。
如果横向派生表引用聚合函数,则函数的聚合查询不能是拥有
FROM
横向派生表发生
的
子句
的聚合查询
。
根据SQL标准,表函数具有隐式
LATERAL
,因此它的行为与8.0.14之前的MySQL 8.0版本相同。
但是,按照标准,
LATERAL
之前不允许
使用
该词
JSON_TABLE()
,即使它是隐含的。
以下讨论显示了横向派生表如何使某些SQL操作成为可能,这些SQL操作无法使用非边界派生表或需要效率较低的变通方法。
假设我们想要解决这个问题:给出销售人员中的人员表(每行描述销售人员的成员),以及所有销售的表格(每行描述销售:销售人员,客户,金额) ,日期),确定每个销售人员最大销售的规模和客户。 这个问题可以通过两种方式解决。
解决问题的第一种方法:对于每个销售人员,计算最大销售量,并找到提供此最大值的客户。 在MySQL中,可以这样做:
选择 salesperson.name, - 找到该销售人员的最大销售规模 (SELECT MAX(金额)AS金额 来自all_sales 所有all_sales.salesperson_id = salesperson.id) AS金额, - 找到最大尺寸的客户 (SELECT customer_name 来自all_sales 所有all_sales.salesperson_id = salesperson.id AND all_sales.amount = - 再次找到最大尺寸 (SELECT MAX(金额)AS金额 来自all_sales all where allsales.salesperson_id = salesperson.id)) AS customer_name 从 营业员;
该查询效率低下,因为它计算每个销售人员两次的最大大小(一次在第一个子查询中,一次在第二个子查询中)。
我们可以尝试通过计算每个销售人员一次的最大值并 在派生表中 “ 缓存 ” 它 来实现效率提升 ,如此修改后的查询所示:
选择 salesperson.name, max_sale.amount, max_sale_customer.customer_name 从 营业员, - 计算最大大小,将其缓存在瞬态派生表max_sale中 (SELECT MAX(金额)AS金额 来自all_sales 所有all_sales.salesperson_id = salesperson.id) AS max_sale, - 找到客户,重用缓存的最大大小 (SELECT customer_name 来自all_sales 所有all_sales.salesperson_id = salesperson.id AND all_sales.amount = - 缓存的最大大小 max_sale.amount) AS max_sale_customer;
但是,该查询在SQL-92中是非法的,因为派生表不能依赖于同一
FROM
子句
中的其他表
。
派生表在查询的持续时间内必须是常量,不包含对其他列的引用
FROM
表的
。
如上所述,查询会产生此错误:
ERROR 1054(42S22):'where子句'中的未知列'salesperson.id'
在SQL:1999中,如果派生表前面有
LATERAL
关键字(这意味着
“
此派生表依赖于其左侧的先前表
”
)
,则查询变得合法
:
选择 salesperson.name, max_sale.amount, max_sale_customer.customer_name 从 营业员, - 计算最大大小,将其缓存在瞬态派生表max_sale中 侧 (SELECT MAX(金额)AS金额 来自all_sales 所有all_sales.salesperson_id = salesperson.id) AS max_sale, - 找到客户,重用缓存的最大大小 侧 (SELECT customer_name 来自all_sales 所有all_sales.salesperson_id = salesperson.id AND all_sales.amount = - 缓存的最大大小 max_sale.amount) AS max_sale_customer;
横向派生表不需要是常量的,并且每次从顶部查询处理它所依赖的前一个表的新行时都会更新。
解决问题的第二种方法:如果
SELECT
列表中
的子查询
可以返回多个列
,则可以使用不同的解决方案
:
选择 salesperson.name, - 同时找到最大尺寸和客户 (选择金额,customer_name 来自all_sales 所有all_sales.salesperson_id = salesperson.id 按订单金额DESC限制1) 从 营业员;
这是有效但非法的。 它不起作用,因为此类子查询只能返回一列:
ERROR 1241(21000):操作数应包含1列
重写查询的一种尝试是从派生表中选择多个列:
选择 salesperson.name, max_sale.amount, max_sale.customer_name 从 营业员, - 同时找到最大尺寸和客户 (选择金额,customer_name 来自all_sales 所有all_sales.salesperson_id = salesperson.id 按订单金额DESC限制1) AS max_sale;
但是,这也行不通。
派生表依赖于
salesperson
表,因此在没有
LATERAL
:
ERROR 1054(42S22):'where子句'中的未知列'salesperson.id'
添加
LATERAL
关键字会使查询合法:
选择 salesperson.name, max_sale.amount, max_sale.customer_name 从 营业员, - 同时找到最大尺寸和客户 侧 (选择金额,customer_name 来自all_sales 所有all_sales.salesperson_id = salesperson.id 按订单金额DESC限制1) AS max_sale;
简而言之,
LATERAL
是刚才讨论的两种方法中所有缺点的有效解决方案。
有些错误仅适用于子查询。 本节介绍它们。
不支持的子查询语法:
错误1235(ER_NOT_SUPPORTED_YET) SQLSTATE = 42000 消息=“此版本的MySQL尚不支持 'LIMIT&IN / ALL / ANY / SOME子查询'“
这意味着MySQL不支持以下形式的语句:
SELECT * FROM t1 WHERE s1 IN(选择s2 FROM t2 ORDER BY s1 LIMIT 1)
子查询中的列数不正确:
错误1241(ER_OPERAND_COL) SQLSTATE = 21000 Message =“操作数应包含1列”
在这种情况下会发生此错误:
SELECT(SELECT column1,column2 FROM t2)FROM t1;
如果目的是行比较,则可以使用返回多个列的子查询。 在其他上下文中,子查询必须是标量操作数。 请参见 第13.2.11.5节“行子查询” 。
子查询中的行数不正确:
错误1242(ER_SUBSELECT_NO_1_ROW) SQLSTATE = 21000 Message =“子查询返回超过1行”
对于子查询必须最多返回一行但返回多行的语句,会发生此错误。 请考虑以下示例:
SELECT * FROM t1 WHERE column1 =(SELECT column1 FROM t2);
如果
SELECT column1 FROM t2
只返回一行,则前一个查询将起作用。
如果子查询返回多行,则会发生错误1242。
在这种情况下,查询应该重写为:
SELECT * FROM t1 WHERE column1 = ANY(SELECT column1 FROM t2);
子查询中的表使用不正确:
错误1093(ER_UPDATE_TABLE_USED) SQLSTATE = HY000 消息=“您无法指定目标表'x' 用于FROM子句中的更新“
在以下情况下会发生此错误,该错误会尝试修改表并从子查询中的同一个表中进行选择:
UPDATE t1 SET column2 =(SELECT MAX(column1)FROM t1);
您可以在
UPDATE
语句中
使用子查询进行赋值,
因为子查询在
语句
UPDATE
和
DELETE
语句以及语句中
都是合法的
SELECT
。
但是,您不能
t1
对子查询
FROM
子句和更新目标
使用相同的表(在本例中
为
表
)
。
对于事务存储引擎,子查询失败会导致整个语句失败。 对于非事务性存储引擎,将保留在遇到错误之前进行的数据修改。
开发正在进行中,因此从长远来看,没有优化技巧可靠。 以下列表提供了一些您可能想要使用的有趣技巧。 另请参见 第8.2.2节“优化子查询,派生表,视图引用和公用表表达式” 。
使用子查询子句影响子查询中行的数量或顺序。 例如:
SELECT * FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2 ORDER BY column1); SELECT * FROM t1 WHERE t1.column1 IN (SELECT DISTINCT column1 FROM t2); SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 LIMIT 1);
用子查询替换连接。 例如,试试这个:
SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN( SELECT column1 FROM t2);
而不是这个:
SELECT DISTINCT t1.column1 FROM t1,t2 在哪里t1.column1 = t2.column1;
某些子查询可以转换为连接,以便与不支持子查询的旧版MySQL兼容。 但是,在某些情况下,将子查询转换为连接可能会提高性能。 请参见 第13.2.11.12节“将子查询重写为连接” 。
将子句从外部移动到子查询内部。 例如,使用此查询:
SELECT * FROM t1 在哪里s1 IN(从s1选择s1 UNION ALL SELECT s1 FROM t2);
而不是这个查询:
SELECT * FROM t1 WH1 s1 IN(SELECT s1 FROM t1)或s1 IN(SELECT s1 FROM t2);
再举一个例子,使用这个查询:
SELECT(SELECT column1 + 5 FROM t1)FROM t2;
而不是这个查询:
SELECT(SELECT column1 FROM t1)+ 5 FROM t2;
使用行子查询而不是相关子查询。 例如,使用此查询:
SELECT * FROM t1 WHERE(column1,column2)IN(SELECT column1,column2 FROM t2);
而不是这个查询:
SELECT * FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.column1 = t1.column1 AND t2.column2 = t1.column2);
使用
NOT (a = ANY (...))
而不是
a <> ALL (...)
。
使用
而不是
。
x = ANY (
table containing
(1,2)
)x=1 OR
x=2
使用
= ANY
而不是
EXISTS
。
对于始终返回一行的不相关子查询,
IN
总是慢于
=
。
例如,使用此查询:
SELECT * FROM t1 在哪里t1。col_name
=(选择一个FROM t2 WHERE b =some_const
);
而不是这个查询:
SELECT * FROM t1 在哪里t1。col_name
IN(选择一个FROM t2 WHERE b =some_const
);
这些技巧可能会导致程序变得更快或更慢。
使用像
BENCHMARK()
函数
这样的MySQL工具
,你可以了解在你自己的情况下有什么帮助。
请参见
第12.15节“信息功能”
。
MySQL本身的一些优化是:
MySQL只执行一次不相关的子查询。
用于
EXPLAIN
确保给定的子查询确实不相关。
MySQL的重写
IN
,
ALL
,
ANY
,和
SOME
子查询,企图采取的是,在子查询选择列表中的列索引的可能性优势。
MySQL使用索引查找函数替换以下表单的子查询,该函数
EXPLAIN
描述为特殊的连接类型(
unique_subquery
或
index_subquery
):
... IN(indexed_column
从single_table
...中选择)
MySQL使用包含
MIN()
或
的表达式增强以下表单的表达式
MAX()
,除非
涉及
NULL
值或空集:
value
{ALL | ANY | SOME} {> | <| > = | <=}(uncorrelated subquery
)
例如,这个
WHERE
子句:
在哪里5> ALL(SELECT x FROM t)
优化器可能会像这样对待:
在哪里5>(SELECT MAX(x)FROM t)
另请参阅 MySQL内部:MySQL如何转换子查询 。
有时,除了使用子查询之外,还有其他方法可以测试一组值中的成员资格。
此外,在某些情况下,不仅可以在没有子查询的情况下重写查询,但使用其中一些技术而不是使用子查询可能更有效。
其中一个是
IN()
构造:
例如,这个查询:
SELECT * FROM t1 WHERE id IN(SELECT id FROM t2);
可以改写为:
SELECT DISTINCT t1。* FROM t1,t2 WHERE t1.id = t2.id;
查询:
SELECT * FROM t1 WHERE id NOT IN(SELECT id FROM t2); SELECT * FROM t1 WHERE NOT EXISTS(SELECT id FROM t2 WHERE t1.id = t2.id);
可以改写为:
SELECT table1。* FROM table1 LEFT JOIN table2 ON table1.id = table2.id WHERE table2.id IS NULL;
A
LEFT [OUTER] JOIN
可以比等效的子查询更快,因为服务器可能能够更好地优化它 - 这一事实并非仅针对MySQL服务器。
在SQL-92之前,外连接不存在,因此子查询是执行某些操作的唯一方法。
今天,MySQL Server和许多其他现代数据库系统提供了广泛的外连接类型。
MySQL Server支持多表
DELETE
语句,可用于根据一个表甚至多个表中的信息同时有效地删除行。
UPDATE
还支持
多表
语句。
请参见
第13.2.2节“删除语法”
和
第13.2.12节“更新语法”
。
UPDATE
是一个修改表中行的DML语句。
一个
UPDATE
语句可以用开始
WITH
子句来定义内访问的公共表表达式
UPDATE
。
请参见
第13.2.13节“WITH语法(公用表表达式)”
。
单表语法:
更新[LOW_PRIORITY] [IGNORE]table_reference
SETassignment_list
[WHEREwhere_condition
] [订购...] [限制row_count
]value
: {expr
| 默认}assignment
:col_name
=value
assignment_list
:assignment
[,assignment
] ......
多表语法:
更新[LOW_PRIORITY] [IGNORE]table_references
SETassignment_list
[WHEREwhere_condition
]
对于单表语法,该
UPDATE
语句使用新值更新指定表中现有行的列。
该
SET
子句指出要修改的列以及应该给出的值。
每个值都可以作为表达式给出,或者将关键字
DEFAULT
显式设置为默认值。
WHERE
如果给出
该
子句,则指定标识要更新的行的条件。
如果没有
WHERE
子句,则更新所有行。
如果
ORDER BY
指定了
该
子句,则按指定的顺序更新行。
该
LIMIT
子句限制了可以更新的行数。
对于多表语法,
UPDATE
更新
table_references
满足条件的
每个表中的行
。
每个匹配的行都会更新一次,即使它与条件多次匹配也是如此。
对于多表的语法,
ORDER BY
而
LIMIT
不能使用。
对于分区表,此语句的单表和多表形式都支持将
PARTITION
选项用作表引用的一部分。
此选项采用一个或多个分区或子分区(或两者)的列表。
仅检查列出的分区(或子分区)是否匹配,并且不更新任何这些分区或子分区中的行,无论它是否满足
where_condition
。
与使用时的情况
PARTITION
有一个
INSERT
或
REPLACE
声明,一个非常有效的
UPDATE ... PARTITION
声明被认为是成功的,即使在列出的分区(或子)没有行匹配
where_condition
。
有关更多信息和示例,请参见 第23.5节“分区选择” 。
where_condition
是一个表达式,对于要更新的每一行,计算结果为true。
有关表达式语法,请参见
第9.5节“表达式”
。
table_references
并按
第13.2.10节“SELECT语法”
where_condition
中的说明进行指定
。
您
UPDATE
只
需要
UPDATE
为实际更新的
列中引用的列提供权限
。
您只需要
SELECT
读取但未修改的任何列
的
权限。
该
UPDATE
语句支持以下修饰符:
使用
LOW_PRIORITY
修饰符,
UPDATE
延迟
执行,
直到没有其他客户端从表中读取。
这会影响只使用表级锁只存储引擎(例如
MyISAM
,
MEMORY
和
MERGE
)。
使用
IGNORE
修饰符,即使在更新期间发生错误,update语句也不会中止。
不更新在唯一键值上发生重复键冲突的行。
更新为导致数据转换错误的值的行将更新为最接近的有效值。
有关更多信息,请参阅
IGNORE关键字和严格SQL模式的比较
。
UPDATE
IGNORE
语句(包括具有
ORDER BY
子句的语句)被标记为基于语句的复制不安全。
(这是因为更新行的顺序决定了哪些行被忽略。)这些语句在使用基于语句的模式时在错误日志中产生警告,并在使用
MIXED
模式
时使用基于行的格式写入二进制日志
。
(Bug#11758262,Bug#50439)有关详细
信息,
请参见
第17.2.1.3节“二进制日志记录中安全和不安全语句的确定”
。
如果从表中访问要在表达式中更新
UPDATE
的列
,请
使用列的当前值。
例如,以下语句设置
col1
为比其当前值多一个:
更新t1 SET col1 = col1 + 1;
以下语句中的第二个赋值设置
col2
为当前(更新的)
col1
值,而不是原始
col1
值。
结果就是
col1
并且
col2
具有相同的值。
此行为与标准SQL不同。
UPDATE t1 SET col1 = col1 + 1,col2 = col1;
单表
UPDATE
分配通常从左到右进行评估。
对于多表更新,无法保证以任何特定顺序执行分配。
如果将列设置为当前具有的值,MySQL会注意到这一点并且不会更新它。
如果更新已
NOT
NULL
通过设置为
声明的列,则在
NULL
启用严格SQL模式时会发生错误;
否则,将列设置为列数据类型的隐式默认值,并增加警告计数。
隐式默认值
0
用于数字类型,空字符串(
''
)用于字符串类型,
“
零
”
值用于日期和时间类型。
请参见
第11.7节“数据类型默认值”
。
如果显式更新生成的列,则唯一允许的值为
DEFAULT
。
有关生成的列的信息,请参见
第13.1.20.9节“创建表和生成的列”
。
UPDATE
返回实际更改的行数。
在
mysql_info()
C API函数返回被匹配和更新的行数,并在发生警告的数量
UPDATE
。
您可以
用来限制范围
。
甲
子句是行匹配限制。
一旦找到
满足该
子句的
行,
该语句就会停止
,无论它们是否实际被更改。
LIMIT
row_count
UPDATE
LIMIT
row_count
WHERE
如果
UPDATE
语句包含
ORDER BY
子句,则按照子句指定的顺序更新行。
这在某些可能导致错误的情况下非常有用。
假设一个表
t
包含一个
id
具有唯一索引
的列
。
以下语句可能会因重复键错误而失败,具体取决于更新行的顺序:
UPDATE t SET id = id + 1;
例如,如果表中的
id
列
包含1和2,
并且在2更新为3之前1更新为2,则会发生错误。
要避免此问题,请添加一个
ORDER BY
子句以使具有较大
id
值
的行在具有较小
值
的行
之前更新:
UPDATE t SET id = id + 1 ORDER BY id DESC;
您还可以执行
UPDATE
涵盖多个表的操作。
但是,您不能使用
ORDER BY
或
LIMIT
使用多表
UPDATE
。
该
table_references
子句列出了连接中涉及的表。
其语法在
第13.2.10.2节“JOIN语法”中描述
。
这是一个例子:
更新项目,月份SET items.price = month.price WHERE items.id = month.id;
前面的示例显示了使用逗号运算符的内部联接,但多表
UPDATE
语句可以使用语句中允许的任何类型的联接
SELECT
,例如
LEFT JOIN
。
如果您使用
UPDATE
涉及
InnoDB
具有外键约束
的表的多表
语句
,则MySQL优化器可能会按照与其父/子关系不同的顺序处理表。
在这种情况下,语句失败并回滚。
相反,更新单个表并依赖提供的
ON UPDATE
功能,
InnoDB
以便相应地修改其他表。
请参见
第15.6.1.5节“InnoDB和FOREIGN KEY约束”
。
您无法更新表并从子查询中的同一表中进行选择。
一个
UPDATE
使用的存储引擎,诸如分区表
MyISAM
,其使用表级锁锁只有那些含有匹配的行的分区
UPDATE
声明
WHERE
子句,只要没有表分区的列被更新的。
(对于
InnoDB
使用行级锁定的
存储引擎
,不会发生分区锁定。)有关更多信息,请参阅
分区和锁定
。
公用表表达式(CTE)是一个命名的临时结果集,它存在于单个语句的范围内,并且可以在该语句中稍后引用,可能多次。 以下讨论描述了如何编写使用CTE的语句。
有关CTE优化的信息,请参见 第8.2.2.4节“使用合并或实现优化派生表,视图引用和公用表表达式” 。
这些文章包含有关在MySQL中使用CTE的其他信息,包括许多示例:
要指定公用表表达式,请使用
WITH
具有一个或多个逗号分隔子句的子句。
每个子条款都提供一个子查询,用于生成结果集,并将名称与子查询相关联。
下面的示例定义名为的CTE
cte1
和
cte2
中
WITH
子句,并且是指在它们的顶层
SELECT
下面的
WITH
子句:
WITH cte1 AS(SELECT a,b FROM table1), cte2 AS(SELECT c,d FROM table2) SELECT b,d FROM cte1 JOIN cte2 WHERE cte1.a = cte2.c;
在包含该
WITH
子句
的语句中
,可以引用每个CTE名称以访问相应的CTE结果集。
CTE名称可以在其他CTE中引用,从而可以基于其他CTE定义CTE。
CTE可以引用自身来定义递归CTE。 递归CTE的常见应用包括分层或树状结构数据的序列生成和遍历。
公用表表达式是DML语句语法的可选部分。
它们使用以下
WITH
子句
定义
:
with_clause
: 带[RECURSIVE]cte_name
[(col_name
[,col_name
] ...)] AS(subquery
) [,cte_name
[(col_name
[,col_name
] ...)] AS(subquery
)] ......
cte_name
命名单个公用表表达式,可以在包含该
WITH
子句
的语句中用作表引用
。
这
subquery
部分
被称为
“
CTE的子查询
”
,它是产生CTE结果集的原因。
以下括号
是必需的。
AS
(
subquery
)AS
如果公用表表达式的子查询引用自己的名称,则表达式是递归的。
该
RECURSIVE
关键字必须被包含,如果任何的CTE的
WITH
条款是递归的。
有关更多信息,请参阅
递归公用表表达式
。
确定给定CTE的列名如下:
如果带括号的名称列表遵循CTE名称,则这些名称是列名称:
与cte(col1,col2)AS ( 选择1,2 UNION ALL 选择3,4 ) SELECT col1,col2 FROM cte;
列表中的名称数必须与结果集中的列数相同。
否则,列名来自首的选择列表中
SELECT
的内
部分:
AS (
subquery
)
与cte AS ( SELECT 1 AS col1,2 AS col2 UNION ALL 选择3,4 ) SELECT col1,col2 FROM cte;
WITH
在这些情况下允许
使用
条款:
在开始时
SELECT
,
UPDATE
和
DELETE
语句。
WITH ... SELECT ... WITH ... UPDATE ... WITH ...删除...
在子查询的开头(包括派生表子查询):
SELECT ... WHERE id IN(WITH ... SELECT ...)... SELECT * FROM(WITH ... SELECT ...)AS dt ...
INSERT ... WITH ... SELECT ... 更换......用...选择...... CREATE TABLE ... WITH ... SELECT ... 创建视图... ... ...选择... DECLARE CURSOR ... WITH ... SELECT ... EXPLAIN ... WITH ... SELECT ...
WITH
在同一级别
只
允许
一个
条款。
WITH
随后
WITH
在同一水平是不允许的,所以这是非法的:
WITH cte1 AS(...)WITH cte2 AS(...)SELECT ...
要使语句合法,请使用单个
WITH
子句以逗号分隔子句:
使用cte1 AS(...),cte2 AS(...)SELECT ...
但是,如果语句
WITH
出现在不同级别
,则语句可以包含多个
子句:
使用cte1 AS(SELECT 1) SELECT * FROM(WITH cte2 AS(SELECT 2)SELECT * FROM cte2 JOIN cte1)AS dt;
一个
WITH
子句可以定义一个或多个公用表表达式,但每个CTE名称必须是唯一的条款。
这是非法的:
使用cte1 AS(...),cte1 AS(...)SELECT ...
要使语句合法,请使用唯一名称定义CTE:
使用cte1 AS(...),cte2 AS(...)SELECT ...
CTE可以指自己或其他CTE:
自引用CTE是递归的。
CTE可以引用同一
WITH
子句中
前面定义的CTE
,但不能
引用
后面定义的
CTE
。
该约束排除了相互递归的CTE,其中
cte1
引用
cte2
和
cte2
引用
cte1
。
其中一个引用必须是稍后定义的CTE,这是不允许的。
给定查询块中的CTE可以引用在更外层的查询块中定义的CTE,但不是在更内层的查询块中定义的CTE。
为了解析对具有相同名称的对象的引用,派生表隐藏了CTE;
和CTE隐藏基表,
TEMPORARY
表和视图。
通过在同一查询块中搜索对象,然后在没有找到具有该名称的对象的情况下依次前进到外部块来进行名称解析。
与派生表一样,CTE在MySQL 8.0.14之前不能包含外部引用。 这是在MySQL 8.0.14中解除的MySQL限制,而不是SQL标准的限制。 有关递归CTE特有的其他语法注意事项,请参阅 递归公用表表达式 。
递归公用表表达式是具有引用其自己名称的子查询的表达式。 例如:
WITH RECURSIVE cte(n)AS ( 选择1 UNION ALL SELECT n + 1 FROM cte WHERE n <5 ) SELECT * FROM cte;
执行时,语句生成此结果,包含简单线性序列的单个列:
+ ------ + | n | + ------ + | 1 | | 2 | | 3 | | 4 | | 5 | + ------ +
递归CTE具有以下结构:
如果
WITH
条款中的
WITH RECURSIVE
任何CTE
WITH
引用自身
,
则
该
条款必须以
该
条款开头
。
(如果CTE没有提及,
RECURSIVE
则允许但不要求。)
如果您忘记
RECURSIVE
了递归CTE,则可能会出现此错误:
ERROR 1146(42S02):表' cte_name
'不存在
递归CTE子查询有两个部分,由
UNION
[ALL]
或
分隔
UNION
DISTINCT
:
SELECT ... - 返回初始行集 UNION ALL SELECT ... - 返回其他行集
第一个
SELECT
产生CTE的初始行或不引用CTE名称。
第二个
SELECT
通过引用其
FROM
子句中
的CTE名称来生成其他行和递归
。
当此部分不产生新行时,递归结束。
因此,递归CTE由非递归
SELECT
部分和递归
SELECT
部分组成。
CTE结果列的类型
SELECT
仅从
非递归
部分
的列类型推断
,并且列都可以为空。
对于类型确定,将
SELECT
忽略
递归
部分。
如果非递归和递归部分被分开
UNION
DISTINCT
,则消除重复的行。
这对于执行传递闭包的查询很有用,可以避免无限循环。
递归部分的每次迭代仅对前一次迭代产生的行进行操作。 如果递归部分具有多个查询块,则以未指定的顺序调度每个查询块的迭代,并且每个查询块对由其先前迭代或自上一次迭代结束以来的其他查询块产生的行进行操作。
前面显示的递归CTE子查询具有这个非递归部分,它检索单个行以生成初始行集:
选择1
CTE子查询也有这个递归部分:
SELECT n + 1 FROM cte WHERE n <5
在每次迭代时,会
SELECT
生成一个行,其值大于
n
前一行集
的值
。
第一次迭代对初始行set(
1
)进行操作并生成
1+1=2
;
第二次迭代在第一次迭代的行set(
2
)上运行并产生
2+1=3
;
等等。
这一直持续到递归结束,当
n
不再小于5
时发生递归
。
如果CTE的递归部分为列生成比非递归部分更宽的值,则可能需要加宽非递归部分中的列以避免数据截断。 请考虑以下声明:
与RECURSIVE cte AS ( SELECT 1 AS n,'abc'AS str UNION ALL SELECT n + 1,CONCAT(str,str)FROM cte WHERE n <3 ) SELECT * FROM cte;
在非严格SQL模式下,该语句生成此输出:
+ ------ + ------ + | n | str | + ------ + ------ + | 1 | abc | | 2 | abc | | 3 | abc | + ------ + ------ +
的
str
列值都是
'abc'
因为非递归
SELECT
确定列宽。
因此,
str
递归产生
的更宽的
值
SELECT
被截断。
在严格的SQL模式下,该语句会产生错误:
ERROR 1406(22001):第1行的列'str'的数据太长
要解决此问题,以便语句不会产生截断或错误,请
CAST()
在nonrecursive中
使用
SELECT
以使
str
列更宽:
与RECURSIVE cte AS ( SELECT 1 AS n,CAST('abc'AS CHAR(20))AS str UNION ALL SELECT n + 1,CONCAT(str,str)FROM cte WHERE n <3 ) SELECT * FROM cte;
现在语句产生了这个结果,没有截断:
+ ------ + -------------- + | n | str | + ------ + -------------- + | 1 | abc | | 2 | abcabc | | 3 | abcabcabcabc | + ------ + -------------- +
列是按名称而不是位置访问的,这意味着递归部分中的列可以访问非递归部分中具有不同位置的列,如此CTE所示:
与RECURSIVE cte AS ( SELECT 1 AS n,1 AS p,-1 AS q UNION ALL SELECT n + 1,q * 2,p * 2 FROM cte WHERE n <5 ) SELECT * FROM cte;
因为
p
在一行中派生自
q
前一行,反之亦然,正值和负值在输出的每个连续行中交换位置:
+ ------ + ------ + ------ + | n | p | q | + ------ + ------ + ------ + | 1 | 1 | -1 | | 2 | -2 | 2 | | 3 | 4 | -4 | | 4 | -8 | 8 | | 5 | 16 | -16 | + ------ + ------ + ------ +
一些语法约束适用于递归CTE子查询:
这些约束来自于SQL标准,比其他的MySQL特定的排除
ORDER BY
,
LIMIT
和
DISTINCT
。
对于递归CTE,
EXPLAIN
递归
SELECT
部分的
输出行
显示
Recursive
在
Extra
列中。
显示的成本估算
EXPLAIN
表示每次迭代的成本,这可能与总成本有很大差异。
优化程序无法预测迭代次数,因为它无法预测
WHERE
子句何时变为false。
CTE实际成本也可能受结果集大小的影响。 产生许多行的CTE可能需要一个足够大的内部临时表,以便从内存转换为磁盘格式,并且可能会受到性能损失。 如果是这样,增加允许的内存临时表大小可以提高性能; 请参见 第8.4.4节“MySQL中的内部临时表使用” 。
对于递归CTE来说,递归
SELECT
部分包括终止递归的条件
是很重要的
。
作为防止失控递归CTE的开发技术,您可以通过限制执行时间来强制终止:
该
cte_max_recursion_depth
系统变量强制对CTE的递归水平的数量限制。
服务器终止执行任何CTE,该CTE递归的级别高于此变量的值。
所述
max_execution_time
系统变量强制用于执行超时
SELECT
在当前会话中执行的语句。
该
MAX_EXECUTION_TIME
优化器提示强制为每个查询执行超时
SELECT
在它出现的语句。
假设错误地写入递归CTE而没有递归执行终止条件:
WITH RECURSIVE cte(n)AS ( 选择1 UNION ALL SELECT n + 1 FROM cte ) SELECT * FROM cte;
默认情况下,
cte_max_recursion_depth
其值为1000,导致CTE在递归过去1000级时终止。
应用程序可以更改会话值以根据其要求进行调整:
SET SESSION cte_max_recursion_depth = 10; - 只允许浅递归 SET SESSION cte_max_recursion_depth = 1000000; - 允许更深层次的递归
您还可以设置全局
cte_max_recursion_depth
值以影响随后开始的所有会话。
对于执行缓慢递归或在有理由将
cte_max_recursion_depth
值
设置得
非常高的
上下文中的查询,
防止深度递归的另一种方法是设置每会话超时。
为此,在执行CTE语句之前执行如下语句:
SET max_execution_time = 1000; - 施加一秒钟超时
或者,在CTE语句本身中包含优化器提示:
WITH RECURSIVE cte(n)AS ( 选择1 UNION ALL SELECT n + 1 FROM cte ) SELECT / * + MAX_EXECUTION_TIME(1000)* / * FROM cte;
如果没有执行时间限制的递归查询进入无限循环,则可以使用另一个会话终止它
KILL
QUERY
。
在会话本身内,用于运行查询的客户端程序可能提供一种终止查询的方法。
例如,在
mysql中
,键入
Control + C会
中断当前语句。
如前所述,递归公用表表达式(CTE)经常用于序列生成和遍历分层或树结构数据。 本节介绍这些技术的一些简单示例。
Fibonacci系列以两个数字0和1(或1和1)开头,之后的每个数字是前两个数字的总和。
如果递归生成的每一行都
SELECT
可以访问该系列中的前两个数字,则
递归公用表表达式可以生成Fibonacci
系列。
以下CTE使用0和1作为前两个数字生成10个数字系列:
WITH RECURSIVE fibonacci(n,fib_n,next_fib_n)AS ( SELECT 1,0,1 UNION ALL SELECT n + 1,next_fib_n,fib_n + next_fib_n 来自斐波纳契,其中n <10 ) SELECT * FROM fibonacci;
CTE产生这样的结果:
+ ------ + ------- + ------------ + | n | fib_n | next_fib_n | + ------ + ------- + ------------ + | 1 | 0 | 1 | | 2 | 1 | 1 | | 3 | 1 | 2 | | 4 | 2 | 3 | | 5 | 3 | 5 | | 6 | 5 | 8 | | 7 | 8 | 13 | | 8 | 13 | 21 | | 9 | 21 | 34 | | 10 | 34 | 55 | + ------ + ------- + ------------ +
CTE如何运作:
n
是一个显示列,表示该行包含
n
第-Fibonacci数。
例如,第8个斐波纳契数是13。
该
fib_n
列显示斐波纳契数
n
。
该
next_fib_n
列显示编号后的下一个斐波纳契数
n
。
此列为下一行提供下一个系列值,以便该行可以在其
fib_n
列中
生成前两个系列值的总和
。
n
到达10
时递归结束
。这是一个任意选择,将输出限制为一小组行。
前面的输出显示了整个CTE结果。
要仅选择其中的一部分,请
WHERE
在顶级
添加适当的
子句
SELECT
。
例如,要选择第8个Fibonacci数,请执行以下操作:
MySQL的>WITH RECURSIVE fibonacci ...
...SELECT fib_n FROM fibonacci WHERE n = 8;
+ ------- + | fib_n | + ------- + | 13 | + ------- +
公用表表达式可以生成一系列连续日期,这对于生成包含系列中所有日期的行的摘要非常有用,包括未在汇总数据中表示的日期。
假设销售数字表包含以下行:
MySQL的> SELECT * FROM sales ORDER BY date, price;
+ ------------ + -------- +
| 日期| 价格|
+ ------------ + -------- +
| 2017-01-03 | 100.00 |
| 2017-01-03 | 200.00 |
| 2017-01-06 | 50.00 |
| 2017-01-08 | 10.00 |
| 2017-01-08 | 20.00 |
| 2017-01-08 | 150.00 |
| 2017-01-10 | 5.00 |
+ ------------ + -------- +
此查询总结了每天的销售额:
MySQL的>SELECT date, SUM(price) AS sum_price
FROM sales
GROUP BY date
ORDER BY date;
+ ------------ + ----------- + | 日期| sum_price | + ------------ + ----------- + | 2017-01-03 | 300.00 | | 2017-01-06 | 50.00 | | 2017-01-08 | 180.00 | | 2017-01-10 | 5.00 | + ------------ + ----------- +
但是,该结果包含
未在表格跨越的日期范围中表示的日期的
“
洞
”
。
可以使用递归CTE生成表示范围中所有日期的结果,以生成该组日期,并与a连接
LEFT JOIN
与销售数据相结合。
以下是生成日期范围系列的CTE:
WITH RECURSIVE日期(日期)AS ( SELECT MIN(日期)FROM销售 UNION ALL 选择日期+间隔日期1天 WHERE日期+ INTERVAL 1 DAY <=(SELECT MAX(date)FROM sales) ) SELECT * FROM dates;
CTE产生这样的结果:
+ ------------ + | 日期| + ------------ + | 2017-01-03 | | 2017-01-04 | | 2017-01-05 | | 2017-01-06 | | 2017-01-07 | | 2017-01-08 | | 2017-01-09 | | 2017-01-10 | + ------------ +
CTE如何运作:
用加入CTE
LEFT JOIN
对
sales
表产生与一排范围内的每个日期的销售汇总:
WITH RECURSIVE日期(日期)AS ( SELECT MIN(日期)FROM销售 UNION ALL 选择日期+间隔日期1天 WHERE日期+ INTERVAL 1 DAY <=(SELECT MAX(date)FROM sales) ) SELECT dates.date,COALESCE(SUM(price),0)AS sum_price FROM日期LEFT JOIN销售日期date.date = sales.date GROUP BY dates.date ORDER BY dates.date;
输出如下所示:
+ ------------ + ----------- + | 日期| sum_price | + ------------ + ----------- + | 2017-01-03 | 300.00 | | 2017-01-04 | 0.00 | | 2017-01-05 | 0.00 | | 2017-01-06 | 50.00 | | 2017-01-07 | 0.00 | | 2017-01-08 | 180.00 | | 2017-01-09 | 0.00 | | 2017-01-10 | 5.00 | + ------------ + ----------- +
有些要点需要注意:
查询是否效率低下,尤其
MAX()
是递归中每行执行子查询的查询
SELECT
?
检查
EXPLAIN
显示子查询已经过优化以提高效率。
使用
COALESCE()
避免
NULL
在
sum_price
列中
显示
sales
表中
没有销售数据的日期
。
递归公用表表达式对于遍历形成层次结构的数据非常有用。
考虑这些创建小数据集的语句,该数据集为公司中的每个员工显示员工姓名和ID号以及员工经理的ID。
顶级员工(CEO)的经理ID为
NULL
(无经理)。
CREATE TABLE员工( id INT PRIMARY KEY NOT NULL, name VARCHAR(100)NOT NULL, manager_id INT NULL, INDEX(manager_id), FOREIGN KEY(manager_id)REFERENCES EMPLOYEES(id) ); 插入员工价值观 (333,“Yasmina”,NULL),#Yasmina是CEO(manager_id为NULL) (198,“John”,333),#John的身份证号为198,并向333报告(Yasmina) (692,“Tarek”,333), (29,“Pedro”,198), (4610,“莎拉”,29), (72,“皮埃尔”,29), (123,“Adil”,692);
结果数据集如下所示:
MySQL的> SELECT * FROM employees ORDER BY id;
+ ------ + --------- + ------------ +
| id | 名字| manager_id |
+ ------ + --------- + ------------ +
| 29 | 佩德罗| 198 |
| 72 | 皮埃尔| 29 |
| 123 | Adil | 692 |
| 198 | 约翰| 333 |
| 333 | Yasmina | NULL |
| 692 | Tarek | 333 |
| 4610 | 莎拉| 29 |
+ ------ + --------- + ------------ +
要使用每个员工的管理链(即从CEO到员工的路径)生成组织结构图,请使用递归CTE:
WITH RECURSIVE employee_paths(id,name,path)AS ( SELECT id,name,CAST(id AS CHAR(200)) 来自员工 WHERE manager_id为NULL UNION ALL SELECT e.id,e.name,CONCAT(ep.path,',',e.id) FROM employee_paths AS ep JOIN员工AS e 在ep.id = e.manager_id上 ) SELECT * FROM employee_paths ORDER BY路径;
CTE产生这个输出:
+ ------ + --------- + ----------------- + | id | 名字| 路径| + ------ + --------- + ----------------- + | 333 | Yasmina | 333 | | 198 | 约翰| 333,198 | | 29 | 佩德罗| 333,198,29 | | 4610 | 莎拉| 333,198,29,4610 | | 72 | 皮埃尔| 333,198,29,72 | | 692 | Tarek | 333,692 | | 123 | Adil | 333,692,123 | + ------ + --------- + ----------------- +
CTE如何运作:
要查找特定员工或员工的路径,请
WHERE
在顶级
添加
子句
SELECT
。
例如,要显示Tarek和Sarah的结果,请
SELECT
像这样
修改
:
MySQL的>WITH RECURSIVE ...
...SELECT * FROM employees_extended
WHERE id IN (692, 4610)
ORDER BY path;
+ ------ + ------- + ----------------- + | id | 名字| 路径| + ------ + ------- + ----------------- + | 4610 | 莎拉| 333,198,29,4610 | | 692 | Tarek | 333,692 | + ------ + ------- + ----------------- +
公用表表达式(CTE)在某些方面类似于派生表:
两个结构都被命名。
这两种结构都存在于单个语句的范围内。
由于这些相似性,CTE和派生表通常可以互换使用。 作为一个简单的例子,这些陈述是等价的:
WITH cte AS(SELECT 1)SELECT * FROM cte; SELECT * FROM(SELECT 1)AS dt;
但是,CTE比派生表有一些优势:
派生表只能在查询中一次引用。 CTE可以多次引用。 要使用派生表结果的多个实例,必须多次派生结果。
CTE可以是自引用(递归)。
一个CTE可以引用另一个。
当CTE的定义出现在语句的开头而不是嵌入其中时,CTE可能更容易阅读。
CTE类似于使用
CREATE
[TEMPORARY]
TABLE
但不需要显式定义或删除的表。
对于CTE,您无需创建表的权限。
MySQL支持通过语句,如本地事务(一个给定的客户端会话内)
SET autocommit
,
START TRANSACTION
,
COMMIT
,和
ROLLBACK
。
请参见
第13.3.1节“START TRANSACTION,COMMIT和ROLLBACK语法”
。
XA事务支持也使MySQL能够参与分布式事务。
请参见
第13.3.8节“XA事务”
。
开始交易 [transaction_characteristic
[,transaction_characteristic
] ......]transaction_characteristic
:{ 一致的快照 | 读写 | 只读 } 开始[工作] COMMIT [WORK] [和[NO] CHAIN] [[NO] RELEASE] ROLLBACK [WORK] [和[NO] CHAIN] [[NO] RELEASE] SET autocommit = {0 | 1}
这些陈述提供对 交易 使用的控制 :
START TRANSACTION
或
BEGIN
开始新的交易。
COMMIT
提交当前事务,使其更改永久化。
ROLLBACK
回滚当前事务,取消其更改。
SET autocommit
禁用或启用当前会话的默认自动提交模式。
默认情况下,MySQL在 启用 自动提交 模式的 情况下运行 。 这意味着只要执行更新(修改)表的语句,MySQL就会将更新存储在磁盘上以使其永久化。 无法回滚更改。
要为一系列语句隐式禁用自动提交模式,请使用
START TRANSACTION
语句:
开始交易; SELECT @A:= SUM(薪水)FROM table1 WHERE type = 1; UPDATE table2 SET summary = @ A WHERE type = 1; 承诺;
使用
START TRANSACTION
,自动提交保持禁用状态,直到您使用
COMMIT
或
结束事务
ROLLBACK
。
然后,自动提交模式将恢复为先前的状态。
START TRANSACTION
允许几个控制交易特征的修饰符。
要指定多个修饰符,请用逗号分隔它们。
该
WITH CONSISTENT SNAPSHOT
修正开始
一致读取
存储引擎,能够它。
这仅适用于
InnoDB
。
效果与
从任何
表
发出a
START TRANSACTION
后跟a
相同
。
请参见
第15.7.2.3节“一致的非锁定读取”
。
该
修改不改变当前的事务
隔离级别
,所以它提供了一个一致的快照仅在当前隔离级别是一个允许连续读取。
允许一致读取的唯一隔离级别是
。
对于所有其他隔离级别,
SELECT
InnoDB
WITH
CONSISTENT SNAPSHOT
REPEATABLE READ
WITH CONSISTENT
SNAPSHOT
子句被忽略。
该
时会生成警告
WITH CONSISTENT SNAPSHOT
子句被忽略。
在
READ WRITE
与
READ
ONLY
修饰符设置事务访问模式。
它们允许或禁止更改交易中使用的表格。
该
READ ONLY
限制可防止事务修改或锁定对其他事务可见的事务和非事务表;
事务仍然可以修改或锁定临时表。
InnoDB
当事务已知为只读时,
MySQL可以对
表的
查询进行额外的优化
。
指定
READ ONLY
确保在无法自动确定只读状态的情况下应用这些优化。
有关
更多信息
,
请参见
第8.5.3节“优化InnoDB只读事务”
。
如果未指定访问模式,则应用默认模式。
除非更改了默认值,否则它是可读/写的。
它不允许同时指定
READ WRITE
,并
READ ONLY
在同一语句。
在只读模式下,仍然可以更改使用。创建的表
TEMPORARY
使用DML语句
关键字
表。
与永久表一样,不允许使用DDL语句进行更改。
有关事务访问模式的其他信息,包括更改默认模式的方法,请参见 第13.3.7节“SET TRANSACTION语法” 。
如果
read_only
启用
了
系统变量,则显式启动事务
START TRANSACTION READ WRITE
需要
CONNECTION_ADMIN
或
SUPER
权限。
用于编写MySQL客户端应用程序(例如JDBC)的许多API提供了自己的方法来启动可以(有时应该)使用而不是
START TRANSACTION
从客户端
发送
语句的
事务
。
请参见
第28章,
连接器和API
更多信息
或
的文档。
要显式禁用自动提交模式,请使用以下语句:
SET autocommit = 0;
通过将
autocommit
变量
设置
为零来
禁用自动提交模式后
,对事务安全表(例如
InnoDB
or或
表)的更改
NDB
不会立即成为永久
更改
。
您必须使用
COMMIT
将更改存储到磁盘或
ROLLBACK
忽略更改。
autocommit
是一个会话变量,必须为每个会话设置。
要禁用自动提交模式为每个新连接,看到的描述
autocommit
在系统变量
第5.1.8节,“服务器系统变量”
。
BEGIN
并
BEGIN WORK
作为
START TRANSACTION
启动事务的
别名支持
。
START TRANSACTION
是标准的SQL语法,是启动ad-hoc事务的推荐方法,并允许使用修饰符
BEGIN
不具有的
。
该
BEGIN
语句不同于使用
BEGIN
启动
BEGIN ... END
复合语句
的
关键字
。
后者不会开始交易。
请参见
第13.6.1节“BEGIN ... END复合语句语法”
。
在所有存储的程序(存储过程和函数,触发器和事件)中,解析器将其
BEGIN
[WORK]
视为
BEGIN ...
END
块
的开头
。
START
TRANSACTION
相反,
在此上下文中开始一个事务
。
和
,
以及和
子句
一样
WORK
支持
可选
关键字
。
和
可用于在事务完成额外控制。
系统变量
的值
确定默认的完成行为。
请参见
第5.1.8节“服务器系统变量”
。
COMMIT
ROLLBACK
CHAIN
RELEASE
CHAIN
RELEASE
completion_type
该
AND CHAIN
子句导致新事务在当前事务结束后立即开始,并且新事务与刚刚终止的事务具有相同的隔离级别。
新事务还使用与
刚刚终止的事务
相同的访问模式(
READ
WRITE
或
READ ONLY
)。
该
RELEASE
子句使服务器在终止当前事务后断开当前客户端会话。
包括
NO
关键字抑制
CHAIN
或
RELEASE
完成,如果
completion_type
系统变量设置为默认情况下导致链接或释放完成
,这可能很有用
。
开始事务会导致提交任何挂起的事务。 有关 更多信息 , 请参见 第13.3.3节“导致隐式提交的语句” 。
开始事务还会导致获取的表锁
LOCK TABLES
被释放,就像您已执行一样
UNLOCK
TABLES
。
开始事务不会释放获取的全局读锁
FLUSH TABLES
WITH READ LOCK
。
为获得最佳结果,应仅使用由单个事务安全存储引擎管理的表来执行事务。 否则,可能会出现以下问题:
如果您使用来自多个事务安全存储引擎(例如
InnoDB
)的表,而事务隔离级别不是
SERIALIZABLE
,那么当一个事务提交时,另一个使用相同表的正在进行的事务可能只会看到一些更改由第一笔交易制作。
也就是说,混合引擎无法保证事务的原子性,并且可能导致不一致。
(如果混合引擎事务很少发生,您可以
根据需要在每个事务的基础上
SET
TRANSACTION ISOLATION LEVEL
设置隔离级别
SERIALIZABLE
。)
如果在事务中使用非事务安全的表,则无论自动提交模式的状态如何,都会立即存储对这些表的更改。
如果
ROLLBACK
在更新事务中的非事务表后
发出
语句,则会
ER_WARNING_NOT_COMPLETE_ROLLBACK
发出警告。
将回滚对事务安全表的更改,但不会更改对非事务安全表的更改。
每个事务都存储在二进制日志中的一个块中
COMMIT
。
回滚的事务不会被记录。
(
例外
:修改到非事务性表不能被回滚如果被回滚的事务包括修改非事务性表,则整个事务与记录
ROLLBACK
在结束语句,以确保修改到非事务性表被复制)。请参见
第5.4.4,“二进制日志”
。
您可以使用该
SET TRANSACTION
语句
更改事务的隔离级别或访问模式
。
请参见
第13.3.7节“SET TRANSACTION语法”
。
回滚可能是一种缓慢的操作,可能会在没有用户明确要求的情况下隐式发生(例如,发生错误时)。
因此,
在
会话列中
SHOW
PROCESSLIST
显示
,不仅用于使用
语句
执行的显式回滚,
还用于隐式回滚。
Rolling back
State
ROLLBACK
在MySQL 8.0, ,
BEGIN
,
COMMIT
和
ROLLBACK
不受
--replicate-do-db
或
--replicate-ignore-db
规则。
某些语句无法回滚。 通常,这些语句包括数据定义语言(DDL)语句,例如创建或删除数据库的语句,创建,删除或更改表或存储例程的语句。
您应该将交易设计为不包括此类声明。
如果您在无法回滚的事务中提前发出语句,然后另一个语句失败,则在这种情况下,通过发出
ROLLBACK
语句
无法回滚事务的完整效果
。
本节中列出的语句(以及它们的任何同义词)隐式结束当前会话中活动的任何事务,就像您
COMMIT
在执行语句之前
完成了
一样。
大多数这些语句在执行后也会导致隐式提交。 目的是在自己的特殊交易中处理每个这样的陈述。 事务控制和锁定语句是例外:如果在执行之前发生隐式提交,则之后不会发生另一次提交。
定义或修改数据库对象的数据定义语言(DDL)语句。
ALTER
EVENT
,
ALTER FUNCTION
,
ALTER PROCEDURE
,
ALTER
SERVER
,
ALTER
TABLE
,
ALTER
VIEW
,
CREATE DATABASE
,
CREATE EVENT
,
CREATE FUNCTION
,
CREATE INDEX
,
CREATE PROCEDURE
,
CREATE
ROLE
,
CREATE SERVER
,
CREATE SPATIAL REFERENCE
SYSTEM
,
CREATE TABLE
,
CREATE TRIGGER
,
CREATE
VIEW
,
DROP DATABASE
,
DROP
EVENT
,
DROP FUNCTION
,
DROP
INDEX
,
DROP PROCEDURE
,
DROP
ROLE
,
DROP
SERVER
,
DROP SPATIAL REFERENCE SYSTEM
,
DROP
TABLE
,
DROP TRIGGER
,
DROP
VIEW
,
INSTALL PLUGIN
,
RENAME TABLE
,
TRUNCATE TABLE
,
UNINSTALL PLUGIN
。
CREATE
TABLE
而
DROP
TABLE
如果语句不提交事务
TEMPORARY
时使用的关键字。
(这不适用于临时表上的其他操作,例如
ALTER
TABLE
和
CREATE
INDEX
,它们确实会导致提交。)但是,虽然没有发生隐式提交,但是语句也不能回滚,这意味着使用这样的语句会导致事务的原子性被侵犯。
例如,如果您使用
CREATE
TEMPORARY TABLE
然后回滚事务,则该表仍然存在。
该
CREATE TABLE
报表
InnoDB
被处理成一个单一的交易。
这意味着
ROLLBACK
来自用户的
a
不撤消
CREATE
TABLE
用户在该事务期间所做的语句。
CREATE
TABLE ...
SELECT
在创建非临时表时,在执行语句之前和之后会导致隐式提交。
(没有提交
CREATE TEMPORARY TABLE
... SELECT
。)
隐式使用或修改
mysql
数据库中的
表的语句
。
ALTER
USER
,
CREATE
USER
,
DROP
USER
,
GRANT
,
RENAME
USER
,
REVOKE
,
SET PASSWORD
。
事务控制和锁定语句。
BEGIN
,
LOCK TABLES
,
SET
autocommit = 1
(如果该值不是1), ,
。
START
TRANSACTION
UNLOCK
TABLES
UNLOCK
TABLES
仅
LOCK
TABLES
当当
前已锁定任何表
以获取非事务性表锁
时才提交事务
。
UNLOCK
TABLES
后续
操作不会发生,
FLUSH TABLES
WITH READ LOCK
因为后一个语句不会获取表级锁。
事务不能嵌套。
这是在您发出
START
TRANSACTION
语句或其同义词之一
时对任何当前事务执行的隐式提交的结果
。
当事务处于一个XA事务中时,不能在XA事务中使用导致隐式提交的语句
ACTIVE
状态
。
该
BEGIN
语句不同于使用
BEGIN
启动
BEGIN ...
END
复合语句
的
关键字
。
后者不会导致隐式提交。
请参见
第13.6.1节“BEGIN ... END复合语句语法”
。
行政声明。
ANALYZE
TABLE
,
CACHE
INDEX
,
CHECK
TABLE
,
FLUSH
,
LOAD INDEX INTO
CACHE
,
OPTIMIZE
TABLE
,
REPAIR TABLE
,
RESET
(但不是
RESET PERSIST
)。
复制控制语句
。
START
SLAVE
,
STOP
SLAVE
,
RESET
SLAVE
,
CHANGE MASTER TO
。
SAVEPOINTidentifier
ROLLBACK [WORK]到[SAVEPOINT]identifier
发布SAVEPOINTidentifier
InnoDB
支持SQL语句
SAVEPOINT
和
ROLLBACK TO
SAVEPOINT
,
RELEASE
SAVEPOINT
以及可选
WORK
关键字
ROLLBACK
。
该
SAVEPOINT
语句设置名为的命名事务保存点
identifier
。
如果当前事务具有相同名称的保存点,则删除旧保存点并设置新保存点。
该
ROLLBACK TO
SAVEPOINT
语句将事务回滚到指定的保存点,而不终止事务。
保存点被设置后,当前事务对行所做的修改会撤消在回退,但
InnoDB
不
不
释放被保存点后存储在内存中的行锁。
(对于新插入的行,锁定信息由存储在行中的事务ID承载;锁定不单独存储在内存中。在这种情况下,行锁定在撤消时释放。)在a中设置的保存点比命名保存点更晚的时间被删除。
如果
ROLLBACK TO
SAVEPOINT
语句返回以下错误,则表示不存在具有指定名称的保存点:
ERROR 1305(42000):SAVEPOINT identifier
不存在
该
RELEASE
SAVEPOINT
语句从当前事务的保存点集中删除指定的保存点。
不会发生提交或回滚。
如果保存点不存在则会出错。
如果执行a
COMMIT
或未
ROLLBACK
命名保存点
,
则删除当前事务的所有保存
点。
调用存储的函数或激活触发器时,将创建新的保存点级别。 先前级别上的保存点变得不可用,因此不会与新级别上的保存点冲突。 当函数或触发器终止时,将释放它创建的任何保存点,并恢复先前的保存点级别。
锁定实例备份 解锁实例
LOCK INSTANCE FOR BACKUP
获取实例级
备份锁
,该
锁
在联机备份期间允许DML,同时防止可能导致快照不一致的操作。
执行该
LOCK INSTANCE FOR BACKUP
语句需要该
BACKUP_ADMIN
权限。
从早期版本执行就地升级到MySQL 8.0时,
该
BACKUP_ADMIN
权限会自动授予具有该
RELOAD
权限的
用户
。
多个会话可以同时保存备份锁。
UNLOCK INSTANCE
释放当前会话持有的备份锁。
如果会话终止,则会释放会话持有的备份锁。
LOCK INSTANCE FOR BACKUP
防止创建,重命名或删除文件。
,
和帐户管理声明被阻止。
请参见
第13.7.1节“帐户管理语句”
。
修改
未在
重做日志中
记录的文件的
操作
也会被阻止。
REPAIR
TABLE
TRUNCATE TABLE
OPTIMIZE TABLE
InnoDB
InnoDB
LOCK INSTANCE FOR BACKUP
允许仅影响用户创建的临时表的DDL操作。
实际上,在保留备份锁定时,可以创建,重命名或删除属于用户创建的临时表的文件。
还允许创建二进制日志文件。
获取的备份锁
LOCK INSTANCE FOR
BACKUP
独立于事务锁和锁定
,并允许以下语句序列:
FLUSH
TABLES
tbl_name
[,
tbl_name
] ... WITH READ LOCK
锁定实例备份; FLUSH TABLEStbl_name
[,tbl_name
] ......阅读锁定; 解锁表; 解锁实例;
FLUSH TABLEStbl_name
[,tbl_name
] ......阅读锁定; 锁定实例备份; 解锁实例; 解锁表;
该
lock_wait_timeout
设置定义了
LOCK INSTANCE FOR
BACKUP
语句在放弃之前等待获取锁定
的时间量
。
LOCK TABLEStbl_name
[[AS]alias
]lock_type
[,tbl_name
[[AS]alias
]lock_type
] ......lock_type
:{ 阅读[本地] | [LOW_PRIORITY]写 } 解锁表格
MySQL使客户端会话能够显式获取表锁,以便与其他会话协作以访问表,或者防止其他会话在会话需要对其进行独占访问期间修改表。 会话只能为自己获取或释放锁。 一个会话无法获取另一个会话的锁定或释放另一个会话持有的锁定。
锁可用于模拟事务或在更新表时获得更快的速度。 这在 表锁定限制和条件 中有更详细的解释 。
LOCK TABLES
显式获取当前客户端会话的表锁。
可以为基表或视图获取表锁。
您必须具有该
LOCK TABLES
特权,并且
SELECT
每个对象
的
特权都被锁定。
对于视图锁定,
LOCK TABLES
将
视图中
使用的所有基表添加到要锁定的表集中并自动锁定它们。
如果
LOCK TABLES
使用
显式锁定
表,则触发器中使用的任何表也会被隐式锁定,如
LOCK TABLES和Triggers中所述
。
如果使用显式锁定表
LOCK
TABLES
,则会打开并隐式锁定由外键约束关联的任何表。
对于外键检查,
LOCK
TABLES READ
对相关表
执行共享只读锁(
)。
对于级联更新,
LOCK TABLES
WRITE
对操作中涉及的相关表
采用无共享写锁(
)。
UNLOCK
TABLES
显式释放当前会话持有的任何表锁。
LOCK TABLES
在获取新锁之前,隐式释放当前会话持有的任何表锁。
另一个用途
UNLOCK
TABLES
是释放使用该
FLUSH TABLES WITH
READ LOCK
语句
获取的全局读锁定
,这使您可以锁定所有数据库中的所有表。
请参见
第13.7.7.3节“FLUSH语法”
。
(如果您拥有可以及时拍摄快照的Veritas等文件系统,这是一种非常方便的备份方式。)
表锁仅保护其他会话不适当的读取或写入。
持有
WRITE
锁
的会话
可以执行表级操作,例如
DROP
TABLE
或
TRUNCATE TABLE
。
对于会话持有
READ
锁,
DROP
TABLE
并且
TRUNCATE TABLE
操作是不允许的。
以下讨论仅适用于非
TEMPORARY
表。
LOCK
TABLES
允许(但忽略)
TEMPORARY
表。
该表可以通过创建它的会话自由访问,而不管其他锁定可能有效。
不需要锁定,因为没有其他会话可以看到该表。
要在当前会话中获取表锁,请使用
LOCK TABLES
获取元数据锁
的
语句(请参见
第8.11.4节“元数据锁定”
)。
可以使用以下锁定类型:
READ [LOCAL]
锁:
持有锁的会话可以读取表(但不能写入)。
多个会话可以同时获取
READ
表
的
锁定。
其他会话可以在不明确获取
READ
锁的
情况下读取表
。
该
LOCAL
修改使不冲突的
INSERT
其他会话语句(并发插入),而持有锁来执行。
(请参见
第8.11.3节“并发插入”
。)但是,
READ LOCAL
如果要在保持锁定时使用服务器外部的进程操作数据库
,
则无法使用。
对于
InnoDB
表格,
READ
LOCAL
与之相同
READ
。
[LOW_PRIORITY] WRITE
锁:
持有锁的会话可以读写表。
只有持有锁的会话才能访问该表。 在释放锁之前,没有其他会话可以访问它。
在锁定时,其他会话阻止对表的请求
WRITE
。
该
LOW_PRIORITY
修饰符无效。
在以前的MySQL版本中,它会影响锁定行为,但这不再适用。
它现已弃用,其使用会产生警告。
WRITE
无需
使用
LOW_PRIORITY
。
WRITE
锁通常具有比
READ
锁
更高的优先级,
以确保尽快处理更新。
这意味着,如果一个会话获得
READ
锁定,然后另一个会话请求
WRITE
锁定,则后续
READ
锁定请求将一直等到请求
WRITE
锁定
的会话
获得锁定并将其释放。
(对于
max_write_lock_count
系统变量的
小值,可能会出现此策略的例外情况
;请参见
第8.11.4节“元数据锁定”
。)
如果
LOCK TABLES
语句必须由于其他会话在任何表上持有的锁而等待,则它将一直阻塞,直到可以获取所有锁。
需要锁定的会话必须在单个
LOCK TABLES
语句中
获取所需的所有锁定
。
在保持如此获得的锁的同时,会话只能访问锁定的表。
例如,在以下语句序列中,尝试访问时发生错误,
t2
因为它未在
LOCK TABLES
语句中
锁定
:
mysql>LOCK TABLES t1 READ;
mysql>SELECT COUNT(*) FROM t1;
+ ---------- + | COUNT(*)| + ---------- + | 3 | + ---------- + MySQL的>SELECT COUNT(*) FROM t2;
ERROR 1100(HY000):表't2'未使用LOCK TABLES锁定
INFORMATION_SCHEMA
数据库中的
表
是一个例外。
即使会话持有获得的表锁,也可以在不显式锁定的情况下访问它们
LOCK TABLES
。
您不能使用相同的名称在单个查询中多次引用锁定的表。 请改用别名,并为表和每个别名获取单独的锁:
mysql>LOCK TABLE t WRITE, t AS t1 READ;
mysql>INSERT INTO t SELECT * FROM t;
ERROR 1100:表't'未使用LOCK TABLES锁定 MySQL的>INSERT INTO t SELECT * FROM t AS t1;
第一个错误发生,
INSERT
因为对锁定表有两个相同名称的引用。
第二个
INSERT
成功,因为对表的引用使用不同的名称。
如果您的语句通过别名引用表,则必须使用相同的别名锁定表。 如果不指定别名,则无法锁定表:
mysql>LOCK TABLE t READ;
mysql>SELECT * FROM t AS myalias;
ERROR 1100:表'myalias'没有锁定LOCK TABLES
相反,如果使用别名锁定表,则必须使用该别名在语句中引用它:
mysql>LOCK TABLE t AS myalias READ;
mysql>SELECT * FROM t;
ERROR 1100:表't'未使用LOCK TABLES锁定 MySQL的>SELECT * FROM t AS myalias;
LOCK TABLES
或者
UNLOCK
TABLES
,当应用于分区表时,始终锁定或解锁整个表;
这些语句不支持分区锁定修剪。
请参阅
分区和锁定
。
当释放会话持有的表锁时,它们都会同时释放。 会话可以显式释放其锁,或者可以在某些条件下隐式释放锁。
会话可以显式释放其锁
UNLOCK
TABLES
。
如果会话
LOCK
TABLES
在已经持有锁的情况下
发出
获取锁
的
语句,则在授予新锁之前将隐式释放其现有锁。
如果会话开始事务(例如,with
START
TRANSACTION
),
UNLOCK
TABLES
则执行
隐式
操作,这会导致释放现有锁。
(有关表锁定和事务之间交互的其他信息,请参阅
表锁定和事务的交互
。)
如果客户端会话的连接终止,无论是正常还是异常,服务器都会隐式释放会话持有的所有表锁(事务性和非事务性)。 如果客户端重新连接,则锁将不再有效。 此外,如果客户端具有活动事务,则服务器在断开连接时回滚事务,如果发生重新连接,则新会话将以启用自动提交开始。 因此,客户可能希望禁用自动重新连接。 使用自动重新连接时,如果发生重新连接,则不会通知客户端,但任何表锁或当前事务都将丢失。 禁用自动重新连接后,如果连接断开,则发出的下一个语句将发生错误。 客户端可以检测错误并采取适当的操作,例如重新获取锁或重做事务。 看到 第28.7.28节“C API自动重新连接控制” 。
如果您
ALTER
TABLE
在锁定的表上
使用
它,它可能会被解锁。
例如,如果您尝试第二次
ALTER
TABLE
操作,结果可能是错误
。
要处理此问题,请在第二次更改之前再次锁定表格。
另请参见
第B.4.6.1节“ALTER TABLE的问题”
。
Table
'
tbl_name
' was not locked with LOCK
TABLES
LOCK TABLES
并
UNLOCK
TABLES
与交易的使用互动如下:
LOCK TABLES
不是事务安全的,并且在尝试锁定表之前隐式提交任何活动事务。
UNLOCK
TABLES
隐式提交任何活动事务,但仅限
LOCK TABLES
于已用于获取表锁。
例如,在以下一组语句中,
UNLOCK
TABLES
释放全局读锁但不提交事务,因为没有表锁有效:
带读锁的冲洗表; 开始交易; 选择 ... ; 解锁表;
开始事务(例如,with
START
TRANSACTION
)隐式提交任何当前事务并释放现有表锁。
FLUSH TABLES WITH
READ LOCK
获得全局读锁定,而不是表锁,所以它不会受到相同的行为
LOCK TABLES
,并
UNLOCK
TABLES
相对于表锁定和隐式的提交。
例如,
START
TRANSACTION
不释放全局读锁定。
请参见
第13.7.7.3节“FLUSH语法”
。
隐式导致事务提交的其他语句不会释放现有的表锁。 有关此类语句的列表,请参见 第13.3.3节“导致隐式提交的语句” 。
使用
LOCK
TABLES
和
UNLOCK
TABLES
使用事务表(如
InnoDB
表)
的正确方法是使用
SET autocommit = 0
(非
START
TRANSACTION
)后跟
开始事务
LOCK
TABLES
,并且
UNLOCK
TABLES
在显式提交事务之前
不调用
。
例如,如果您需要写入表
t1
并从表中读取
t2
,则可以执行以下操作:
SET autocommit = 0;
LOCK TABLES t1 WRITE,t2 READ,...;
... do something with tables t1 and t2 here ...
承诺;
解锁表;
当你调用时
LOCK TABLES
,
InnoDB
内部采用自己的表锁,并且MySQL采用自己的表锁。
InnoDB
在下次提交时释放其内部表锁,但是要释放其表锁,MySQL必须调用
UNLOCK
TABLES
。
你不应该
autocommit =
1
,因为然后
InnoDB
在调用之后立即释放它的内部表锁
LOCK
TABLES
,并且很容易发生死锁。
InnoDB
如果
autocommit =
1
,为了帮助旧应用程序避免不必要的死锁,
根本不获取内部表锁
。
ROLLBACK
不释放表锁。
如果
LOCK
TABLES
使用
显式锁定
表,则触发器中使用的任何表也会被隐式锁定:
锁定与使用
LOCK
TABLES
语句
明确获取的锁定同时进行
。
锁定在触发器中使用的表取决于该表是否仅用于读取。 如果是这样,读锁定就足够了。 否则,使用写锁定。
如果显式锁定表以进行读取
LOCK TABLES
,但需要锁定以进行写入,因为它可能在触发器中被修改,则会执行写锁定而不是读取锁定。
(也就是说,由于表在触发器中的出现而需要隐式写锁定会导致表的显式读锁定请求转换为写锁定请求。)
假设您锁定了两个表,
t1
并
t2
使用以下语句:
LOCK TABLES t1 WRITE,t2 READ;
如果
t1
或
t2
有任何触发器,触发器中使用的表也将被锁定。
假设
t1
有一个如下定义的触发器:
创建触发器t1_a_ins在每次插入t1之后插入 开始 更新t4 SET count = count + 1 WHERE id = NEW.id AND EXISTS(SELECT a FROM t3); 插入t2值(1,2); 结束;
该
LOCK TABLES
语句
的结果
是
t1
并且
t2
因为它们出现在语句中
t3
而
t4
被锁定
,并且
因为它们在触发器中使用
而
被锁定:
t1
根据
WRITE
锁定请求
被锁定以进行写入
。
t2
即使请求是锁定,也会被锁定以进行写入
READ
。
发生这种情况是因为
t2
插入到触发器中,因此
READ
请求将转换为
WRITE
请求。
t3
被锁定以进行读取,因为它只能从触发器中读取。
t4
被锁定以进行写入,因为它可能在触发器中更新。
您可以安全地用于
KILL
终止等待表锁定的会话。
请参见
第13.7.7.4节“KILL语法”
。
LOCK TABLES
并且
UNLOCK
TABLES
不能在存储的程序中使用。
在表
performance_schema
的数据库不能被锁定
LOCK
TABLES
,除了
表。
setup_
xxx
而下面的语句是禁止的
LOCK TABLES
:声明生效
CREATE
TABLE
,
CREATE
TABLE ...
LIKE
,
CREATE
VIEW
,
DROP
VIEW
,和存储函数和过程和事件DDL语句。
对于某些操作,
mysql
必须访问数据库中的
系统表
。
例如,该
HELP
语句需要服务器端帮助表的内容,并且
CONVERT_TZ()
可能需要读取时区表。
服务器隐式锁定系统表以供必要时读取,以便您无需显式锁定它们。
这些表如上所述:
mysql.help_category mysql.help_keyword mysql.help_relation mysql.help_topic mysql.time_zone mysql.time_zone_leap_second mysql.time_zone_name mysql.time_zone_transition mysql.time_zone_transition_type
如果要
WRITE
使用
LOCK
TABLES
语句
显式地
锁定任何这些表
,则表必须是唯一锁定的表;
没有其他表可以使用相同的语句锁定。
通常,您不需要锁定表,因为所有单个
UPDATE
语句都是原子的;
没有其他会话可以干扰任何其他当前正在执行的SQL语句。
但是,在某些情况下,锁定表可能会提供一个优势:
如果要在一组
MyISAM
表
上运行许多操作
,则锁定要使用的表会快得多。
锁定
MyISAM
表加快了对它们的插入,更新或删除,因为MySQL在
UNLOCK
TABLES
调用
之前不会刷新锁定表的密钥缓存
。
通常,在每个SQL语句之后刷新密钥缓存。
锁定表的缺点是没有会话可以更新
READ
锁定表(包括持有锁的表),并且没有会话可以访问
WRITE
除了持有锁的表之外的锁定表。
如果要将表用于非事务性存储引擎,则必须使用,
LOCK
TABLES
如果要确保没有其他会话修改a
SELECT
和
a之间的表
UPDATE
。
此处显示的示例需要
LOCK TABLES
安全执行:
LOCK TABLES trans READ,客户写信; SELECT SUM(value)FROM trans WHERE customer_id =some_id
; 更新客户 SET total_value =sum_from_previous_statement
WHERE customer_id =some_id
; 解锁表;
如果没有
LOCK TABLES
,则另一个会话可能会
trans
在执行
SELECT
和
UPDATE
语句
之间
在
表中
插入一个新行
。
LOCK TABLES
在许多情况下,
您可以
通过使用相对更新(
)或
函数
来避免使用
。
UPDATE
customer SET
value
=value
+new_value
LAST_INSERT_ID()
您也可以通过避免使用用户级别咨询锁功能锁定在某些情况下,表
GET_LOCK()
和
RELEASE_LOCK()
。
这些锁保存在服务器的哈希表中,
pthread_mutex_lock()
并
pthread_mutex_unlock()
以高速实现。
请参见
第12.14节“锁定功能”
。
有关 锁定策略的更多信息, 请参见 第8.11.1节“内部锁定方法” 。
SET [GLOBAL | SESSION] TRANSACTIONtransaction_characteristic
[,transaction_characteristic
] ......transaction_characteristic
:{ 隔离级别level
|access_mode
}level
:{ 可重复阅读 | 阅读提交 | 阅读不满意 | SERIALIZABLE }access_mode
:{ 读写 | 只读 }
此语句指定
事务
特征。
它采用逗号分隔的一个或多个特征值的列表。
每个特征值设置事务
隔离级别
或访问模式。
隔离级别用于
InnoDB
表上的
操作
。
访问模式指定事务是以读/写还是只读模式运行。
另外,
SET TRANSACTION
可以包含一个可选的
GLOBAL
或
SESSION
关键字来表示该语句的范围。
要设置事务隔离级别,请使用
子句。
不允许
在同一
语句中
指定多个
子句
。
ISOLATION LEVEL
level
ISOLATION LEVEL
SET
TRANSACTION
默认隔离级别为
REPEATABLE
READ
。
其他允许值是
READ
COMMITTED
,
READ
UNCOMMITTED
和
SERIALIZABLE
。
有关这些隔离级别的信息,请参见
第15.7.2.1节“事务隔离级别”
。
要设置事务访问模式,请使用
READ
WRITE
or
READ ONLY
子句。
不允许在同一
SET TRANSACTION
语句中
指定多个access-mode子句
。
默认情况下,事务以读/写模式进行,读取和写入都允许在事务中使用的表。
可以使用
SET TRANSACTION
访问模式
明确指定此模式
READ WRITE
。
如果将事务访问模式设置为
READ
ONLY
,则禁止对表进行更改。
这可以使存储引擎能够在不允许写入时实现性能改进。
在只读模式下,仍然可以
TEMPORARY
使用DML语句
更改使用
关键字
创建的
表。
与永久表一样,不允许使用DDL语句进行更改。
该
READ WRITE
和
READ
ONLY
接入方式也可以使用一个独立的事务中指定
START
TRANSACTION
的语句。
您可以在全局,当前会话或仅下一个事务中设置事务特征:
使用
GLOBAL
关键字:
该声明适用于所有后续会话。
现有会话不受影响。
使用
SESSION
关键字:
该语句适用于当前会话中执行的所有后续事务。
该等陈述在交易中是允许的,但不会影响当前正在进行的交易。
如果在事务之间执行,则该语句将覆盖任何先前的语句,该语句设置命名特征的下一个事务值。
没有任何
SESSION
或
GLOBAL
关键字:
该声明仅适用于会话中执行的下一个单个事务。
后续事务将恢复为使用指定特征的会话值。
交易中不允许使用该声明:
MySQL的>START TRANSACTION;
查询OK,0行受影响(0.02秒) MySQL的>SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ERROR 1568(25001):无法更改交易特征 交易正在进行中
对全局事务特征的更改需要
CONNECTION_ADMIN
或
SUPER
特权。
任何会话都可以自由更改其会话特征(即使在事务中间),也可以更改其下一个事务的特征(在该事务开始之前)。
要在服务器启动时设置全局隔离级别,请使用
命令行或选项文件中的选项。
值
此选项使用破折号,而不是空间,所以允许值是
,
,
,或
。
--transaction-isolation=
level
level
READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE
同样,要在服务器启动时设置全局事务访问模式,请使用该
--transaction-read-only
选项。
默认值为
OFF
(读/写模式),但可以将该值设置
ON
为只读模式。
例如,要将隔离级别设置为
REPEATABLE
READ
和访问模式
READ WRITE
,请在
[mysqld]
选项文件
的
部分中
使用以下行
:
的[mysqld] transaction-isolation = REPEATABLE-READ transaction-read-only = OFF
在运行时,可以使用
SET TRANSACTION
语句
间接设置全局,会话和下一个事务范围级别的特征
,如前所述。
它们也可以使用直接设置
SET
语句分配值
transaction_isolation
和
transaction_read_only
系统变量:
SET
TRANSACTION
允许使用可选项
GLOBAL
和
SESSION
关键字来设置不同范围级别的事务特征。
SET
为值
transaction_isolation
和
transaction_read_only
系统变量
赋值
的
语句
具有在不同范围级别设置这些变量的语法。
下表显示了每个
SET TRANSACTION
和变量赋值语法
设置的特征范围级别
。
表13.9事务特征的SET TRANSACTION语法
句法 | 受影响的特征范围 |
---|---|
SET GLOBAL TRANSACTION
|
全球 |
SET SESSION TRANSACTION
|
会议 |
SET TRANSACTION
|
仅限下一笔交易 |
表13.10事务特征的SET语法
句法 | 受影响的特征范围 |
---|---|
SET GLOBAL |
全球 |
SET @@GLOBAL. |
全球 |
SET PERSIST |
全球 |
SET @@PERSIST. |
全球 |
SET PERSIST_ONLY |
没有运行时效果 |
SET @@PERSIST_ONLY. |
没有运行时效果 |
SET SESSION |
会议 |
SET @@SESSION. |
会议 |
SET |
会议 |
SET @@ |
仅限下一笔交易 |
可以在运行时检查事务特征的全局值和会话值:
SELECT @@ GLOBAL.transaction_isolation,@@ GLOBAL.transaction_read_only; SELECT @@ SESSION.transaction_isolation,@@ SESSION.transaction_read_only;
存储引擎
可以
支持
XA
事务
InnoDB
。
MySQL XA实现基于X / Open CAE文档
分布式事务处理:XA规范
。
本文件由The Open Group出版,可从
http://www.opengroup.org/public/pubs/catalog/c193.htm获取
。
第C.6节“XA事务限制”
中描述了当前XA实现的
限制
。
在客户端,没有特殊要求。
MySQL服务器的XA接口由以
XA
关键字
开头的SQL语句组成
。
MySQL客户端程序必须能够发送SQL语句并理解XA语句接口的语义。
它们不需要与最近的客户端库链接。
较旧的客户端库也可以工作。
在MySQL连接器中,MySQL Connector / J 5.0.0和更高版本通过一个为您处理XA SQL语句接口的类接口直接支持XA。
XA支持分布式事务,即允许多个单独的事务资源参与全局事务的能力。 事务资源通常是RDBMS,但可能是其他类型的资源。
全局事务涉及几个本身是事务性的操作,但所有操作必须作为一个组成功完成,或者全部作为一个组回滚。
从本质上讲,这会将ACID属性
“
扩展
到一个级别
”,
这样多个ACID事务就可以作为具有ACID属性的全局操作的组件一起执行。
(与非分布式事务一样,
SERIALIZABLE
如果您的应用程序对读取现象敏感
,则
可能是首选。
REPEATABLE
READ
可能不足以进行分布式事务。)
分布式事务的一些示例:
应用程序可以充当将消息传递服务与RDBMS相结合的集成工具。 该应用程序确保处理涉及事务数据库的消息发送,检索和处理的事务都发生在全局事务中。 您可以将其视为 “ 交易电子邮件”。 ”
应用程序执行涉及不同数据库服务器的操作,例如MySQL服务器和Oracle服务器(或多个MySQL服务器),其中涉及多个服务器的操作必须作为全局事务的一部分发生,而不是作为每个服务器本地的单独事务。
银行将帐户信息保存在RDBMS中,并通过自动柜员机(ATM)分配和接收资金。 有必要确保ATM操作正确地反映在帐户中,但仅靠RDBMS无法做到这一点。 全球事务管理器集成了ATM和数据库资源,以确保金融交易的整体一致性。
使用全局事务的应用程序涉及一个或多个资源管理器和事务管理器:
资源管理器(RM)提供对事务资源的访问。 数据库服务器是一种资源管理器。 必须可以提交或回滚RM管理的事务。
事务管理器(TM)协调作为全局事务一部分的事务。 它与处理每个事务的RM进行通信。 全局事务中的各个事务是全局事务的 “ 分支 ” 。 全局事务及其分支由后面描述的命名方案标识。
XA的MySQL实现使MySQL服务器可以充当资源管理器,处理全局事务中的XA事务。 连接到MySQL服务器的客户端程序充当事务管理器。
要执行全局事务,必须知道涉及哪些组件,并将每个组件置于可以提交或回滚的位置。 根据每个组件报告的成功能力,它们必须全部提交或回滚为原子组。 也就是说,要么所有组件都必须提交,要么所有组件都必须回滚。 要管理全局事务,必须考虑任何组件或连接网络可能会失败。
执行全局事务的过程使用两阶段提交(2PC)。 这是在执行了全局事务的分支执行的操作之后发生的。
在第一阶段,所有分支都准备好了。 也就是说,TM告诉他们准备提交。 通常,这意味着管理分支的每个RM都会记录稳定存储中分支的操作。 分支表明他们是否能够这样做,并且这些结果用于第二阶段。
在第二阶段,TM告诉RM是否提交或回滚。 如果所有分支在准备好时表示他们能够提交,则告知所有分支都要提交。 如果任何分支在准备时指示它将无法提交,则告知所有分支都回滚。
在某些情况下,全局事务可能使用单阶段提交(1PC)。 例如,当事务管理器发现全局事务只包含一个事务资源(即单个分支)时,可以告诉该资源同时准备和提交。
要在MySQL中执行XA事务,请使用以下语句:
XA {START | BEGIN}xid
[JOIN | RESUME] XA ENDxid
[SUSPEND [FOR MIGRATE]] XA PREPARExid
XA COMMITxid
[单相] XA ROLLBACKxid
XA RECOVER [CONVERT XID]
因为
XA
START
,
不支持
JOIN
和
RESUME
子句。
因为
XA
END
该
SUSPEND [FOR MIGRATE]
条款不受支持。
每个XA语句都以
XA
关键字
开头,其中
大多数都需要一个
xid
值。
An
xid
是XA事务标识符。
它指示该语句适用于哪个事务。
xid
值由客户端提供,或由MySQL服务器生成。
一个
xid
值有一到三个部分:
xid
:gtrid
[,bqual
[,formatID
]]
gtrid
是一个全局事务标识符,
bqual
是一个分支限定符,
formatID
是一个标识
gtrid
和
bqual
值
使用的格式的数字
。
如语法所示,
bqual
并且
formatID
是可选的。
如果没有给出
默认
bqual
值
''
。
formatID
如果没有给出
,默认
值为1。
gtrid
并且
bqual
必须是字符串文字,每个字符长度最多为64个字节(不是字符)。
gtrid
并且
bqual
可以通过多种方式指定。
您可以使用带引号的字符串(
'ab'
),十六进制字符串(
X'6162'
,
0x6162
)或位值(
)。
b'
nnnn
'
formatID
是无符号整数。
该
gtrid
和
bqual
值以字节为MySQL服务器的底层XA支持例程解释。
但是,在解析包含XA语句的SQL语句时,服务器将使用某些特定字符集。
为安全起见,写作
gtrid
和
bqual
十六进制字符串。
xid
值通常由事务管理器生成。
一个TM生成的值必须与其他TM生成的值不同。
给定的TM必须能够
xid
在
XA
RECOVER
语句
返回的值列表中
识别自己的
值
。
XA
START
使用给定
xid
xid
值
启动XA事务
。
每个XA事务必须具有唯一
xid
值,因此该值当前不能由另一个XA事务使用。
使用
gtrid
和
bqual
值
评估唯一性
。
必须使用与
语句
xid
中给出的值
相同的
值
来指定XA事务的所有后续XA
XA
START
语句。
如果您使用任何这些语句但指定的
xid
值与某些现有XA事务不对应,则会发生错误。
一个或多个XA事务可以是同一全局事务的一部分。
给定全局事务中的所有XA事务必须在
gtrid
值中
使用相同
的
xid
值。
因此,
gtrid
值必须是全局唯一的,这样才不会对给定XA事务所属的全局事务产生歧义。
对于
全局事务中的每个XA事务
bqual
,
xid
值
的
一部分
必须不同。
(
bqual
值不同
的要求
是当前MySQL XA实现的限制。它不是XA规范的一部分。)
该
XA
RECOVER
语句返回MySQL服务器上处于该
PREPARED
状态的
那些XA事务的信息
。
(请参见
第13.3.8.2节“XA事务状态”
。)输出包括服务器上每个此类XA事务的行,而不管哪个客户端启动它。
XA
RECOVER
需要
XA_RECOVER_ADMIN
特权。
此权限要求可防止用户发现除自己以外的未完成的准备XA事务的XID值。
它不会影响XA事务的正常提交或回滚,因为启动它的用户知道它的XID。
XA
RECOVER
输出行如下所示(对于例如
xid
由部件的值
'abc'
,
'def'
和
7
):
MySQL的> XA RECOVER;
+ ---------- + -------------- -------------- + -------- + +
| formatID | gtrid_length | bqual_length | 数据|
+ ---------- + -------------- -------------- + -------- + +
| 7 | 3 | 3 | abcdef |
+ ---------- + -------------- -------------- + -------- + +
输出列具有以下含义:
formatID
是
formatID
交易
的
一部分
xid
gtrid_length
在的字节长度
gtrid
的部分
xid
bqual_length
在的字节长度
bqual
的部分
xid
data
是
gtrid
和
bqual
部分的连接
xid
XID值可能包含不可打印的字符。
XA
RECOVER
允许一个可选
CONVERT
XID
子句,以便客户端可以以十六进制的形式请求XID值。
XA事务通过以下状态进行:
使用
XA
START
启动一个XA事务,并把它的
ACTIVE
状态。
对于
ACTIVE
XA事务,发出
构成
事务的SQL语句,然后发出
XA
END
语句。
XA
END
将交易置于该
IDLE
州。
对于
IDLE
XA事务,您可以发出
XA
PREPARE
语句或
XA COMMIT ... ONE
PHASE
语句:
XA
PREPARE
将交易置于该
PREPARED
州。
此时的
XA
RECOVER
语句将
xid
在其输出中
包含事务的
值,因为
XA
RECOVER
列出了该
PREPARED
状态
中的所有XA事务
。
XA COMMIT ... ONE PHASE
准备并提交交易。
由于事务终止
xid
,
XA
RECOVER
因此
不会列出
该
值
。
对于
PREPARED
XA事务,您可以发出
XA
COMMIT
语句来提交和终止事务,或者
XA
ROLLBACK
回滚并终止事务。
这是一个简单的XA事务,它将一行作为全局事务的一部分插入表中:
MySQL的>XA START 'xatest';
查询正常,0行受影响(0.00秒) MySQL的>INSERT INTO mytable (i) VALUES(10);
查询正常,1行受影响(0.04秒) MySQL的>XA END 'xatest';
查询正常,0行受影响(0.00秒) MySQL的>XA PREPARE 'xatest';
查询正常,0行受影响(0.00秒) MySQL的>XA COMMIT 'xatest';
查询正常,0行受影响(0.00秒)
在给定客户端连接的上下文中,XA事务和本地(非XA)事务是互斥的。
例如,如果
XA
START
已发出以开始XA事务,则在提交或回滚XA事务之前,无法启动本地事务。
相反,如果已启动本地事务
START
TRANSACTION
,则在提交或回滚事务之前,不能使用任何XA语句。
如果XA事务处于该
ACTIVE
状态,则不能发出任何导致隐式提交的语句。
这会违反XA合同,因为您无法回滚XA交易。
如果您尝试执行此类语句,您将收到以下错误:
错误1399(XAE07):XAER_RMFAIL:无法执行命令 当全局事务处于ACTIVE状态时
上述注释适用的 语句 在 第13.3.3节“导致隐式提交的语句” 中列出 。
可以使用本节中描述的语句通过SQL接口控制复制。 语句分为控制主服务器的组,控制从服务器的组和可应用于任何复制服务器的组。
本节讨论管理主复制服务器的语句。 第13.4.2节“用于控制从属服务器的SQL语句” 讨论了用于管理从属服务器的语句。
除了此处描述的语句之外,以下
SHOW
语句还用于复制中的主服务器。
有关这些语句的信息,请参见
第13.7.6节“SHOW语法”
。
PURGE {BINARY | MASTER} LOGS { 至 'log_name
'' | 之前datetime_expr
}
二进制日志是一组文件,其中包含有关MySQL服务器进行的数据修改的信息。 该日志由一组二进制日志文件和一个索引文件组成(请参见 第5.4.4节“二进制日志” )。
该
PURGE BINARY LOGS
语句删除指定日志文件名或日期之前的日志索引文件中列出的所有二进制日志文件。
BINARY
并且
MASTER
是同义词。
删除的日志文件也将从索引文件中记录的列表中删除,以便给定的日志文件成为列表中的第一个。
PURGE BINARY LOGS
需要
BINLOG_ADMIN
特权。
如果未使用
--log-bin
启用二进制日志记录
的
选项
启动服务器,则此语句无效
。
例子:
PURGE BINARY登录'mysql-bin.010'; 在'2019-04-02 22:46:26'之前的PURGE BINARY LOGS
该
BEFORE
变种的
datetime_expr
参数值应该为一个
DATETIME
值(一个值
'YYYY-MM-DD hh:mm:ss'
格式)。
当从属设备复制时,此语句可以安全运行。 你无需阻止它们。 如果您有一个当前正在读取您尝试删除的日志文件之一的活动从服务器,则此语句不会删除正在使用的日志文件或晚于该日志文件的任何日志文件,但会删除任何早期日志文件。 在这种情况下会发出警告消息。 但是,如果未连接从属设备并且您正在清除其尚未读取的其中一个日志文件,则从属设备将在重新连接后无法复制。
要安全地清除二进制日志文件,请执行以下过程:
在每个从属服务器上,用于
SHOW SLAVE
STATUS
检查它正在读取的日志文件。
获取主服务器上的二进制日志文件列表
SHOW BINARY LOGS
。
确定所有从属中最早的日志文件。 这是目标文件。 如果所有从站都是最新的,则这是列表中的最后一个日志文件。
备份要删除的所有日志文件。 (此步骤是可选的,但始终是可取的。)
清除所有日志文件,但不包括目标文件。
PURGE BINARY LOGS TO
PURGE
BINARY LOGS BEFORE
当
.index
通过其他方式(例如
在Linux上
使用
rm
)
从系统中删除
文件中列出的二进制日志文件时
,
两者都会失败并显示错误
。
(Bug#18199,Bug#18453)要处理此类错误,请
.index
手动
编辑
文件(简单文本文件)以确保它仅列出实际存在的二进制日志文件,然后再次运行
PURGE BINARY LOGS
失败
的
语句。
在服务器的二进制日志到期期限后,将自动删除二进制日志文件。
可以在启动时以及刷新二进制日志时删除文件。
默认的二进制日志有效期为30天。
您可以使用
binlog_expire_logs_seconds
系统变量
指定备用到期期限
。
如果使用复制,则应指定一个有效期,该有效期不低于从属服务器可能滞后于主服务器的最长时间。
RESET MASTER [TO binary_log_file_index_number
]
RESET MASTER
使您能够删除任何二进制日志文件及其相关的二进制日志索引文件,将主服务器返回到启动二进制日志记录之前的状态。
RESET
MASTER
需要
RELOAD
特权。
请谨慎使用此语句,以确保不会丢失二进制日志文件数据。
在
RESET MASTER
没有可选
TO
子句的
情况下
发出
将
删除索引文件中列出的所有二进制日志文件,将二进制日志索引文件重置为空,并从中开始创建新的二进制日志文件
1
。
使用optional
TO
子句从
1
重置后的
数字开始创建二进制日志文件索引
。
发布
RESET MASTER
还清除
gtid_purged
系统变量和
gtid_executed
系统变量的值;
也就是说,发出此语句会将每个值设置为空字符串(
''
)。
此语句还清除
mysql.gtid_executed
表(请参阅
mysql.gtid_executed表
)。
使用
RESET MASTER
with
TO
子句指定要启动的二进制日志文件索引号,通过提供替换
FLUSH BINARY
LOGS
和
PURGE BINARY
LOGS TO
语句
的单个语句来简化故障转移
。
检查您是否使用合理的索引号值。
如果输入的值不正确,可以通过发出
RESET
MASTER
包含或不包含该
TO
子句的
另一个
语句
来纠正此问题
。
如果未更正超出范围的值,则无法重新启动服务器。
以下示例演示了
TO
子句用法:
RESET MASTER TO 1234; 显示二进制日志; + ------------------- + ----------- ----------- + + | Log_name | File_size | 加密| + ------------------- + ----------- ----------- + + | master-bin.001234 | 154 | 没有| + ------------------- + ----------- ----------- + +
RESET MASTER
没有该
TO
条款
的影响
与以下
PURGE BINARY LOGS
两个关键方式的影响不同:
RESET
MASTER
删除
索引文件中列出的
所有
二进制日志文件,只留下一个带有数字后缀的空二进制日志文件
.000001
,而编号不会被重置
PURGE BINARY LOGS
。
RESET
MASTER
是
不是
打算,而任何复制的奴隶正在运行使用。
RESET MASTER
从属服务器运行时使用
的行为
是未定义的(因此不受支持),而
PURGE BINARY
LOGS
在复制从服务器运行时可以安全使用。
RESET
MASTER
在
TO
第一次设置主服务器和从服务器时,
没有该
子句可以证明是有用的,这样您就可以按如下方式验证设置:
启动主服务器和从服务器,然后开始复制(请参见 第17.1.2节“设置基于二进制日志文件位置的复制” )。
在主服务器上执行一些测试查询。
检查查询是否已复制到从属服务器。
当复制运行正常,问题
STOP
SLAVE
后面
RESET SLAVE
的奴隶,然后验证从测试查询没有多余的数据在从服务器上存在。
RESET MASTER
在master上
发出问题
以清理测试查询。
验证设置,重置主设备和从设备并确保测试生成的不需要的数据或二进制日志文件保留在主设备或从设备上后,您可以启动从设备并开始复制。
SET sql_log_bin = {OFF | ON}
该
sql_log_bin
变量控制是否为当前会话启用了对二进制日志的记录(假设已启用二进制日志本身)。
默认值为
ON
。
要禁用或启用当前会话的二进制日志记录,请将会话
sql_log_bin
变量
设置
为
OFF
或
ON
。
将此变量设置
OFF
为会话以临时禁用二进制日志记录,同时更改不希望复制到从属服务器的主服务器。
设置此系统变量的会话值是受限制的操作。 会话用户必须具有足以设置受限会话变量的权限。 请参见 第5.1.9.1节“系统变量权限” 。
无法
sql_log_bin
在事务或子查询中
设置会话值
。
设置此变量
OFF
可防止将GTID分配给二进制日志中的事务
。
如果您使用GTID进行复制,这意味着即使稍后再次启用二进制日志记录,从此处写入日志的GTID也不会考虑同时发生的任何事务,因此实际上这些事务将丢失。
本节讨论管理从属复制服务器的语句。 第13.4.1节“用于控制主服务器的SQL语句” 讨论了用于管理主服务器的语句。
除了此处描述的语句,
SHOW SLAVE STATUS
并且
SHOW RELAYLOG EVENTS
还使用复制的奴隶。
有关这些语句的信息,请参见
第13.7.6.34节“显示从动状态语法”
和
第13.7.6.32节“显示RELAYLOG事件语法”
。
改变主要option
[,option
] ...... [channel_option
]option
: MASTER_BIND ='interface_name
' | MASTER_HOST ='host_name
' | MASTER_USER ='user_name
' | MASTER_PASSWORD ='password
' | MASTER_PORT =port_num
| MASTER_CONNECT_RETRY =interval
| MASTER_RETRY_COUNT =count
| MASTER_DELAY =interval
| MASTER_HEARTBEAT_PERIOD =interval
| MASTER_LOG_FILE ='master_log_name
' | MASTER_LOG_POS =master_log_pos
| MASTER_AUTO_POSITION = {0 | 1} | RELAY_LOG_FILE ='relay_log_name
' | RELAY_LOG_POS =relay_log_pos
| MASTER_SSL = {0 | 1} | MASTER_SSL_CA ='ca_file_name
' | MASTER_SSL_CAPATH ='ca_directory_name
' | MASTER_SSL_CERT ='cert_file_name
' | MASTER_SSL_CRL ='crl_file_name
' | MASTER_SSL_CRLPATH ='crl_directory_name
' | MASTER_SSL_KEY ='key_file_name
' | MASTER_SSL_CIPHER ='cipher_list
' | MASTER_SSL_VERIFY_SERVER_CERT = {0 | 1} | MASTER_TLS_VERSION ='protocol_list
' | MASTER_PUBLIC_KEY_PATH ='key_file_name
' | GET_MASTER_PUBLIC_KEY = {0 | 1} | IGNORE_SERVER_IDS =(server_id_list
)channel_option
: FOR CHANNELchannel
server_id_list
: [server_id
[,server_id
] ......]
CHANGE MASTER TO
更改从服务器用于连接主服务器的参数,读取主二进制日志和读取从中继日志。
它还会更新主信息和中继日志信息存储库的内容(请参见
第17.2.4节“复制中继和状态日志”
)。
CHANGE
MASTER TO
需要
REPLICATION_SLAVE_ADMIN
或
SUPER
特权。
您可以
CHANGE MASTER TO
在没有先停止它的情况下在正在运行的从站上
发出
语句,具体取决于从属SQL线程和从属I / O线程的状态。
有关此类使用的规则将在本节后面提供。
当使用多线程从站(换句话说
slave_parallel_workers
大于0)时,停止从站可能会导致
从中继日志执行的事务序列中出现
“
间隙
”
,无论从站是故意停用还是其他方式。
当存在这种差距时,发布
CHANGE MASTER TO
失败。
在这种情况下的解决方案是
START
SLAVE UNTIL
SQL_AFTER_MTS_GAPS
确保间隙被关闭的问题。
使用optional
子句可以命名该语句适用的复制通道。
提供
子句将
语句
应用于
特定复制通道,并用于添加新通道或修改现有通道。
例如,要添加名为channel2的新频道:
FOR CHANNEL
channel
FOR CHANNEL
channel
CHANGE MASTER TO
CHANGE MASTER TO MASTER_HOST = host1,MASTER_PORT = 3002 FOR CHANNEL'channel2'
如果未命名子句且不存在额外通道,则该语句将应用于默认通道。
使用多个复制通道时,如果
CHANGE
MASTER TO
语句未使用
子句
命名通道
,则会发生错误。
有关
更多信息
,
请参见
第17.2.3节“复制通道”
。
FOR CHANNEL
channel
未指定的选项保留其值,除非在以下讨论中指出。 因此,在大多数情况下,不需要指定不更改的选项。
MASTER_HOST
,
MASTER_USER
,
MASTER_PASSWORD
,和
MASTER_PORT
到有关如何连接到其主从提供信息:
MASTER_HOST
并且
MASTER_PORT
是主主机及其TCP / IP端口的主机名(或IP地址)。
复制不能使用Unix套接字文件。 您必须能够使用TCP / IP连接到主MySQL服务器。
如果指定
MASTER_HOST
或
MASTER_PORT
选项,则从属服务器假定主服务器与以前不同(即使选项值与其当前值相同。)在这种情况下,主二进制日志文件名和位置的旧值为考虑不再适用,因此,如果不指定
MASTER_LOG_FILE
,并
MASTER_LOG_POS
在声明中,
MASTER_LOG_FILE=''
并
MASTER_LOG_POS=4
以静默追加到它。
设置
MASTER_HOST=''
(即,明确其值设置为空字符串)是
不
一样的没有设置
MASTER_HOST
在所有。
尝试设置
MASTER_HOST
为空字符串失败并显示错误。
检查用于换行(
或
)字符的
值
MASTER_HOST
和其他
CHANGE MASTER TO
选项
;
这些值中存在此类字符会导致语句失败
。
(Bug#11758581,Bug#50801)
\n
0x0A
ER_MASTER_INFO
MASTER_USER
并且
MASTER_PASSWORD
是用于连接到主服务器的帐户的用户名和密码。
MASTER_USER
不能空虚;
设置
MASTER_USER = ''
值时
设置
或保持不设置
MASTER_PASSWORD
会导致错误(Bug#13427949)。
在
CHANGE MASTER TO
语句中
用于MySQL Replication从属帐户的密码
长度限制为32个字符;
尝试使用超过32个字符的密码会导致
CHANGE MASTER
TO
失败。
运行
CHANGE MASTER
TO
语句
的文本(
包括
MASTER_USER
和的
值)
MASTER_PASSWORD
可以在并发
SHOW
PROCESSLIST
语句
的输出中看到
。
(
START SLAVE
声明
的完整文本
也可见
SHOW PROCESSLIST
。)
该
选项与
选项指定的奴隶如何使用加密和密码,以确保复制连接。
即使在没有SSL支持的情况下编译的从站也可以更改这些选项。
它们将保存到主信息存储库,但如果从服务器未启用SSL支持,则会被忽略。
在
和
选项执行相同的功能,
并且
在描述客户端选项
第6.3.2节“的加密连接命令选项”
。
两套方案之间的对应关系,以及使用的
和
MASTER_SSL_
xxx
MASTER_TLS_VERSION
MASTER_SSL_
xxx
MASTER_TLS_VERSION
--ssl-
xxx
--tls-version
MASTER_SSL_
xxx
MASTER_TLS_VERSION
选项来建立安全连接的解释如下
第17.3.9节“设置复制以使用加密连接”中
。
要使用使用
caching_sha2_password
插件进行
身份验证的用户帐户连接到复制主
服务器,必须按
第17.3.9节“设置复制以使用加密连接”中
所述设置安全连接
,或启用未加密连接以支持密码使用RSA密钥对进行交换。
该
caching_sha2_password
认证插件是从MySQL 8.0中创建新用户的默认(详见
第6.4.1.3,“缓存SHA-2插入式验证”
)。
如果您创建或用于复制的用户帐户(由
MASTER_USER
选项)使用此身份验证插件,并且您没有使用安全连接,必须启用基于RSA密钥对的密码交换才能成功连接。
要启用基于RSA密钥对的密码交换,请指定
MASTER_PUBLIC_KEY_PATH
或
GET_MASTER_PUBLIC_KEY=1
选项。
这些选项中的任何一个都为从站提供RSA公钥:
MASTER_PUBLIC_KEY_PATH
表示包含主服务器所需公钥的从属端副本的文件的路径名,用于基于RSA密钥对的密码交换。
该文件必须采用PEM格式。
此选项适用于使用
sha256_password
或
caching_sha2_password
身份验证插件进行
身份验证的从属
服务器。
(对于
sha256_password
,
MASTER_PUBLIC_KEY_PATH
只有在使用OpenSSL构建MySQL时才能使用。)
GET_MASTER_PUBLIC_KEY
指示是否从主设备请求基于RSA密钥对的密码交换所需的公钥。
此选项适用于使用
caching_sha2_password
身份验证插件
进行
身份验证的
从属
服务器。
对于使用此插件进行身份验证的帐户的连接,除非有请求,否则主服务器不会发送公钥,因此必须在客户端中请求或指定。
如果
MASTER_PUBLIC_KEY_PATH
给定并指定了有效的公钥文件,则优先于
GET_MASTER_PUBLIC_KEY
。
的
MASTER_HEARTBEAT_PERIOD
,
MASTER_CONNECT_RETRY
和
MASTER_RETRY_COUNT
选项控制从如何认识到主机的连接已经丢失,使尝试重新连接。
所述
slave_net_timeout
系统变量指定的所述从等待任一多个数据或来自主设备的心跳信号,前从动认为连接断裂,中止读操作,并尝试重新连接的秒数。
默认值为60秒(一分钟)。
如果连接仍然良好,则在没有数据的情况下停止连接超时的心跳间隔由该
MASTER_HEARTBEAT_PERIOD
选项
控制
。
在该秒数之后,心跳信号被发送到从设备,并且每当用事件更新主设备的二进制日志时,等待时间段被重置。
因此,只有在二进制日志文件中没有未发送的事件超过此时间段时,主服务器才会发送心跳。
心跳间隔
interval
是十进制值,范围为0到4294967秒,分辨率以毫秒为单位;
最小非零值为0.001。
设置
interval
为0完全禁用心跳。
心跳间隔默认为
slave_net_timeout
系统变量
值的一半
。
它记录在主信息日志中,并显示在
replication_connection_configuration
性能模式表中。
发出
RESET
SLAVE
将心跳间隔重置为默认值。
请注意,更改值或默认设置
slave_net_timeout
不会自动更改心跳间隔,无论是已明确设置还是使用先前计算的默认值。
如果设置
@@GLOBAL.slave_net_timeout
的值小于当前心跳间隔的值,
则会发出警告
。
如果
slave_net_timeout
更改,您还必须发出
CHANGE
MASTER TO
将心跳间隔调整为适当的值,以便在连接超时之前发生心跳信号。
如果不这样做,心跳信号就没有效果,如果没有从主设备收到数据,则从设备可以重复重新连接尝试,从而创建僵尸转储线程。
如果从站确实需要重新连接,则在超时后立即进行第一次重试。
MASTER_CONNECT_RETRY
指定重新连接尝试之间的间隔,并
MASTER_RETRY_COUNT
限制重新连接尝试的次数。
如果同时使用两个默认设置
MASTER_CONNECT_RETRY=60
,则从站在
重新连接尝试之间等待60秒(
),并继续尝试以此速率重新连接60天(
MASTER_RETRY_COUNT=86400
)。
这些值记录在主信息日志中,并显示在“
replication_connection_configuration
性能架构”表中。
MASTER_RETRY_COUNT
取代
--master-retry-count
服务器启动选项。
MASTER_DELAY
指定从站必须滞后的主站后面多少秒。
从主站接收的事件
interval
要比
在主站上执行的事件至少
晚几秒才执行。
默认值为0.如果
interval
不是0到2
31
-1
范围内的非负整数,
则会发生错误
。
有关更多信息,请参见
第17.3.12节“延迟复制”
。
当从属SQL线程停止时,可以在正在运行的从属服务器上执行
CHANGE MASTER TO
使用该
MASTER_DELAY
选项
的
语句
。
MASTER_BIND
用于具有多个网络接口的复制从站,并确定选择哪个从属网络接口连接到主站。
使用此选项配置的地址(如果有)可以
Master_Bind
在输出
的
列中
看到
SHOW SLAVE STATUS
。
在主信息存储库表中
mysql.slave_master_info
,该值可以看作
Master_bind
列。
NDB Cluster还支持将复制从站绑定到特定网络接口的能力。
MASTER_LOG_FILE
并且
MASTER_LOG_POS
是下一次线程启动时从属I / O线程应从主站开始读取的坐标。
RELAY_LOG_FILE
并且
RELAY_LOG_POS
是下一次线程启动时从属SQL线程应该从中继日志开始读取的坐标。
如果指定的
MASTER_LOG_FILE
或
MASTER_LOG_POS
,你不能指定
RELAY_LOG_FILE
或
RELAY_LOG_POS
。
如果您指定的任一
MASTER_LOG_FILE
或者
MASTER_LOG_POS
,你也可以不指定
MASTER_AUTO_POSITION = 1
(在本节后面介绍)。
如果没有的
MASTER_LOG_FILE
或
MASTER_LOG_POS
指定,从使用的最后一个坐标
从SQL线程
前
CHANGE MASTER
TO
发出。
这确保了复制中没有不连续性,即使从属SQL线程与从属I / O线程相比较迟,当您只想更改要使用的密码时也是如此。
一个
CHANGE MASTER TO
声明用人
RELAY_LOG_FILE
,
RELAY_LOG_POS
或这两个选项可以在运行时从从SQL线程停止执行。
如果从属SQL线程和从属I / O线程中至少有一个正在运行,则保留中继日志;
如果两个线程都停止,则删除所有中继日志文件,除非至少
指定了
一个
RELAY_LOG_FILE
或
RELAY_LOG_POS
。
RELAY_LOG_FILE
可以使用绝对路径或相对路径,并使用相同的基本名称
MASTER_LOG_FILE
。
当
MASTER_AUTO_POSITION = 1
与使用
CHANGE MASTER TO
中,从试图连接到使用基于GTID复制协议的主站。
CHANGE MASTER TO
仅当从属SQL和从属I / O线程都已停止时,
才能使用此选项
。
无论是从设备和主必须GTIDs启用(
GTID_MODE=ON
,
ON_PERMISSIVE,
或者
OFF_PERMISSIVE
在从服务器上,并
GTID_MODE=ON
在主站)。
自动定位被用于连接,因此由下式表示的坐标
MASTER_LOG_FILE
和
MASTER_LOG_POS
没有被使用,以及使用这些选项之一或两者一起
MASTER_AUTO_POSITION = 1
导致错误。
如果从站上启用了多源复制,则需要设置
MASTER_AUTO_POSITION = 1
每个适用的复制通道的选项。
使用
MASTER_AUTO_POSITION = 1
set,在初始连接握手中,从站发送一个GTID集,其中包含已经收到,已提交或两者都已完成的事务。
主设备通过发送其二进制日志中记录的所有事务来响应,其GTID不包括在从设备发送的GTID集中。
此交换确保主服务器仅使用GTID发送从属尚未记录或已提交的事务。
如果从属设备从多个主设备接收事务,如菱形拓扑结构,则自动跳过功能可确保事务不会应用两次。
有关如何计算从站发送的GTID集的详细信息,请参见
第17.1.3.3节“GTID自动定位”
。
如果主服务器应发送的任何事务已从主服务器的二进制日志中清除,或
gtid_purged
通过其他方法
添加到
系统变量中
的GTID集中
,则主服务器将错误
ER_MASTER_HAS_PURGED_REQUIRED_GTIDS
发送
给从服务器,并且复制不会开始。
将识别丢失的清除事务的GTID,并在警告消息
ER_FOUND_MISSING_GTIDS
中的主控错误日志中
列出
。
另外,如果在事务交换期间发现从属设备已经在GTID中记录或提交了主设备UUID的事务,但是主设备本身没有提交它们,主设备发送错误
ER_SLAVE_HAS_MORE_GTIDS_THAN_MASTER
到从站并且复制无法启动。
有关如何处理这些情况的信息,请参见
第17.1.3.3节“GTID自动定位”
。
通过检查性能架构
replication_connection_status
表或输出,
可以查看复制是否在启用自动定位的情况下运行
SHOW SLAVE
STATUS
。
禁用
MASTER_AUTO_POSITION
再次选项使从恢复到基于文件的复制,在这种情况下,你还必须指定的一个或两个
MASTER_LOG_FILE
或
MASTER_LOG_POS
选项。
IGNORE_SERVER_IDS
采用以逗号分隔的0个或更多服务器ID列表。
源于相应服务器的事件将被忽略,但日志轮换和删除事件除外,这些事件仍记录在中继日志中。
在循环复制中,始发服务器通常充当其自身事件的终结符,因此它们不会被应用多次。
因此,当删除圆中的一个服务器时,此选项在循环复制中很有用。
假设您有4个服务器的循环复制设置,服务器ID为1,2,3和4,服务器3失败。
通过启动从服务器2到服务器4的复制来弥补差距,您可以
在服务器4上发出
IGNORE_SERVER_IDS =
(3)
的
CHANGE MASTER
TO
语句中
包含
它,告诉它使用服务器2作为主服务器而不是服务器3.这样做会导致它忽略而不是传播源自不再使用的服务器的任何语句。
如果
IGNORE_SERVER_IDS
包含服务器自己的ID,并且
--replicate-same-server-id
启用
了
选项启动
服务器
,则会出现错误。
当全局事务标识符(GTID)用于复制时,已自动忽略已应用的事务,因此该
IGNORE_SERVER_IDS
函数不是必需的,不推荐使用。
如果
gtid_mode=ON
为服务器设置了,则如果
IGNORE_SERVER_IDS
在
CHANGE MASTER TO
语句中
包含该
选项,
则会发出弃用警告
。
主信息存储库和输出
SHOW SLAVE STATUS
提供当前被忽略的服务器列表。
有关更多信息,请参见
第17.2.4.2节“从站状态日志”
和
第13.7.6.34节“显示从站状态语法”
。
如果在
CHANGE MASTER TO
没有任何
IGNORE_SERVER_IDS
选项的
情况下发出语句
,则会保留任何现有列表。
要清除被忽略的服务器列表,必须使用带有空列表的选项:
将主设备更改为IGNORE_SERVER_IDS =();
RESET SLAVE ALL
清除
IGNORE_SERVER_IDS
。
如果
SET
GTID_MODE=ON
在任何通道设置了现有服务器ID时
发出,
则会发出
弃用警告
IGNORE_SERVER_IDS
。
在启动基于GTID的复制之前,请检查并清除所涉及的服务器上所有被忽略的服务器ID列表。
该
SHOW_SLAVE_STATUS
语句显示被忽略的ID列表(如果有)。
如果确实收到了弃用警告,则可以
gtid_mode=ON
通过发出
CHANGE MASTER
TO
包含
IGNORE_SERVER_IDS
带有空列表
的
选项
的
语句
来设置
列表。
调用
CHANGE MASTER TO
导致原先的值
MASTER_HOST
,
MASTER_PORT
,
MASTER_LOG_FILE
,并
MASTER_LOG_POS
要写入错误日志,以及有关从执行前的状态等信息。
CHANGE MASTER TO
导致正在进行的事务的隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
从MySQL 5.7开始,
删除了
STOP
SLAVE
在发布任何
CHANGE MASTER TO
语句
之前
(以及
START
SLAVE
之后)
执行的严格要求
。
而不是依赖于从属是否停止,行为
CHANGE MASTER TO
取决于从属SQL线程和从属I / O线程的状态;
现在停止或运行这些线程中的哪一个确定了
CHANGE MASTER
TO
在给定时间点
可以或不能与
语句
一起使用的选项
。
此处列出了进行此确定的规则:
如果SQL线程停止时,可以执行
CHANGE MASTER TO
使用被允许的其他方式的任意组合
RELAY_LOG_FILE
,
RELAY_LOG_POS
和
MASTER_DELAY
选择,即使从I / O线程运行。
当I / O线程运行时,此语句不能使用其他选项。
如果I / O线程停止时,可以执行
CHANGE MASTER TO
使用任何选项,此语句(任何允许的组合)
除外
RELAY_LOG_FILE
,
RELAY_LOG_POS
,
MASTER_DELAY
,或
MASTER_AUTO_POSITION = 1
SQL线程运行时也是如此。
在发出使用的
CHANGE MASTER TO
语句
之前,必须停止SQL线程和I / O线程
MASTER_AUTO_POSITION =
1
。
您可以使用检查从属SQL和I / O线程的当前状态
SHOW SLAVE STATUS
。
有关更多信息,请参见 第17.3.8节“在故障转移期间切换主站” 。
如果使用基于语句的复制和临时表,则
CHANGE MASTER TO
语句后面的
STOP SLAVE
语句可能会在从属服务器上留下临时表。
ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO
只要发生这种情况,就会发出
警告(
)。
在这种情况下,您可以通过
Slave_open_temp_tables
在执行此类
CHANGE MASTER TO
语句
之前
确保
系统状态变量的值等于0
来避免这种情况
。
CHANGE MASTER TO
当您拥有主服务器的快照并且已记录与快照时间对应的主二进制日志坐标时,可用于设置从服务器。
将快照加载到从站以使其与主站同步后,您可以
在从站上
运行
以指定从站应开始读取主二进制日志的坐标。
CHANGE MASTER TO
MASTER_LOG_FILE='
log_name
',
MASTER_LOG_POS=log_pos
以下示例更改从站使用的主服务器,并建立从站开始读取的主二进制日志坐标。 当您要设置从属设备以复制主设备时,可以使用此选项:
改变主人
MASTER_HOST = 'master2.example.com',
MASTER_USER = '复制',
MASTER_PASSWORD =' password
',
MASTER_PORT = 3306,
MASTER_LOG_FILE = 'master2-bin.001',
MASTER_LOG_POS = 4,
MASTER_CONNECT_RETRY = 10;
下一个示例显示了较少使用的操作。
当从站具有您希望由于某种原因再次执行的中继日志文件时使用它。
为此,无需访问主服务器。
您只需要使用
CHANGE MASTER TO
并启动SQL thread(
START SLAVE SQL_THREAD
):
改变主人 RELAY_LOG_FILE =“从属中继bin.006”, RELAY_LOG_POS = 4025;
下表显示了字符串值选项的最大允许长度。
选项 | 最大长度 |
---|---|
MASTER_HOST |
255(MySQL 8.0.17之前的60) |
MASTER_USER |
96 |
MASTER_PASSWORD |
32 |
MASTER_LOG_FILE |
511 |
RELAY_LOG_FILE |
511 |
MASTER_SSL_CA |
511 |
MASTER_SSL_CAPATH |
511 |
MASTER_SSL_CERT |
511 |
MASTER_SSL_CRL |
511 |
MASTER_SSL_CRLPATH |
511 |
MASTER_SSL_KEY |
511 |
MASTER_SSL_CIPHER |
511 |
MASTER_TLS_VERSION |
511 |
MASTER_PUBLIC_KEY_PATH |
511 |
更改复制过滤器filter
[,filter
] [,...] [FOR CHANNELchannel
]filter
: REPLICATE_DO_DB =(db_list
) | REPLICATE_IGNORE_DB =(db_list
) | REPLICATE_DO_TABLE =(tbl_list
) | REPLICATE_IGNORE_TABLE =(tbl_list
) | REPLICATE_WILD_DO_TABLE =(wild_tbl_list
) | REPLICATE_WILD_IGNORE_TABLE =(wild_tbl_list
) | REPLICATE_REWRITE_DB =(db_pair_list
)db_list
:db_name
[,db_name
] [,...]tbl_list
:db_name.table_name
[,db_name.table_name
] [,...]wild_tbl_list
: 'db_pattern.table_pattern
'[,'db_pattern.table_pattern
'] [,...]db_pair_list
: (db_pair
)[,(db_pair
)] [,...]db_pair
:from_db
,to_db
CHANGE REPLICATION FILTER
在slave上设置一个或多个复制过滤规则的方式与启动
带有复制过滤选项(如
或)
的slave
mysqld
相同
。
与服务器选项的情况不同,此语句不需要重新启动服务器才能生效,只需要
首先
使用从属SQL线程停止
(并在
之后
重新启动
)。
需要
或
特权。
使用该
子句可以创建特定于复制通道的复制过滤器,例如,在多源复制从站上。
过滤器应用时没有特定的
--replicate-do-db
--replicate-wild-ignore-table
STOP SLAVE
SQL_THREAD
START SLAVE
SQL_THREAD
CHANGE
REPLICATION FILTER
REPLICATION_SLAVE_ADMIN
SUPER
FOR CHANNEL
channel
FOR CHANNEL
子句被视为全局过滤器,这意味着它们适用于所有复制通道。
无法在为组复制配置的MySQL服务器实例上设置全局复制筛选器,因为在某些服务器上筛选事务会使该组无法就一致状态达成协议。
可以在不直接与组复制相关的复制通道上设置通道特定的复制筛选器,例如,组成员还充当组外部主服务器的复制从属服务器。
他们不能对设置
group_replication_applier
或
group_replication_recovery
通道。
以下列表显示了
CHANGE REPLICATION
FILTER
选项以及它们与
--replicate-*
服务器选项的关系:
REPLICATE_DO_DB
:包括基于数据库名称的更新。
相当于
--replicate-do-db
。
REPLICATE_IGNORE_DB
:根据数据库名称排除更新。
相当于
--replicate-ignore-db
。
REPLICATE_DO_TABLE
:根据表名包含更新。
相当于
--replicate-do-table
。
REPLICATE_IGNORE_TABLE
:根据表名排除更新。
相当于
--replicate-ignore-table
。
REPLICATE_WILD_DO_TABLE
:包括基于通配符模式匹配表名称的更新。
相当于
--replicate-wild-do-table
。
REPLICATE_WILD_IGNORE_TABLE
:根据通配符模式匹配表名排除更新。
相当于
--replicate-wild-ignore-table
。
REPLICATE_REWRITE_DB
:在从服务器上替换主服务器上的指定数据库后,对从服务器执行更新。
相当于
--replicate-rewrite-db
。
REPLICATE_DO_DB
和
REPLICATE_IGNORE_DB
过滤器
的精确效果
取决于基于语句的复制还是基于行的复制。
有关
更多信息
,
请参见
第17.2.5节“服务器如何评估复制过滤规则”
。
CHANGE REPLICATION FILTER
通过用逗号分隔
规则,可以在单个
语句中
创建多个复制过滤规则
,如下所示:
更换复制过滤器 REPLICATE_DO_DB =(d1),REPLICATE_IGNORE_DB =(d2);
发出刚刚显示的语句相当于
使用选项
启动slave
mysqld
。
--replicate-do-db=d1
--replicate-ignore-db=d2
在多源复制从属(使用多个复制通道处理来自不同源的事务)上,使用该
子句在复制通道上设置复制过滤器:
FOR CHANNEL
channel
CHANGE REPLICATION FILTER REPLICATE_DO_DB =(d1)FOR CHANNEL channel_1;
这使您可以创建特定于通道的复制筛选器,以筛选出源中的选定数据。
当
FOR
CHANNEL
设置子句,复制过滤器声明作用于该从属复制通道去除具有相同滤波器类型与指定的复制过滤器的任何现有的复制过滤器,并使用指定的过滤器替换它们。
未修改语句中未明确列出的过滤器类型。
如果针对未配置的从属复制通道发出,则该语句将失败并显示
ER_SLAVE_CONFIGURATION
错误。
如果针对组复制通道发出,则该语句将失败并显示
ER_SLAVE_CHANNEL_OPERATION_NOT_ALLOWED
错误。
在配置了多个复制通道的复制从站上,
CHANGE REPLICATION
FILTER
使用no
FOR CHANNEL
子句
发出会
为每个已配置的从复制通道和全局复制筛选器配置复制筛选器。
对于每种过滤器类型,如果语句中列出了过滤器类型,则该类型的任何现有过滤器规则将替换为最近发出的语句中指定的过滤器规则,否则将保留过滤器类型的旧值。
有关更多信息,请参见
第17.2.5.4节“基于复制通道的过滤器”
。
如果多次指定相同的过滤规则,
则实际
仅使用
最后一个
此类规则。
例如,此处显示的两个语句具有完全相同的效果,因为
REPLICATE_DO_DB
忽略了第一个语句中的第
一个
规则:
更换复制过滤器 REPLICATE_DO_DB =(db1,db2),REPLICATE_DO_DB =(db3,db4); 更换复制过滤器 REPLICATE_DO_DB =(db3,db4);
此行为与
--replicate-*
筛选选项的
行为不同,
其中多次指定相同选项会导致创建多个筛选规则。
不需要引用不包含任何特殊字符的表和数据库的名称。
与
REPLICATION_WILD_TABLE
和
REPLICATION_WILD_IGNORE_TABLE
一起
使用的值
是字符串表达式,可能包含(特殊)通配符,因此必须引用。
这在以下示例语句中显示:
更换复制过滤器 REPLICATE_WILD_DO_TABLE =('db1.old%'); 更换复制过滤器 REPLICATE_WILD_IGNORE_TABLE =('db1.new%','db2.new%');
用于
REPLICATE_REWRITE_DB
表示
数据库名称
对
的
值
;
每个这样的值必须括在括号中。
以下语句
db1
将master
上数据库
上
发生的语句重写
db2
为slave上的
数据库
:
CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB =((db1,db2));
刚才显示的语句包含两组括号,一组包含数据库名称,另一组包含整个列表。
这也许是更容易看到在下面的例子中,它创建了两个
rewrite-db
规则,一个重写的数据库
dbA
来
dbB
,和一个重写数据库
dbC
到
dbD
:
更换复制过滤器 REPLICATE_REWRITE_DB =((dbA,dbB),(dbC,dbD));
该
CHANGE REPLICATION FILTER
语句仅替换受该语句影响的过滤器类型和复制通道的复制过滤规则,并保持其他规则和通道不变。
如果要取消设置给定类型的所有过滤器,请将过滤器的值设置为显式空列表,如此示例所示,该列表将删除所有现有
REPLICATE_DO_DB
和
REPLICATE_IGNORE_DB
规则:
更换复制过滤器 REPLICATE_DO_DB =(),REPLICATE_IGNORE_DB =();
以这种方式将过滤器设置为空将删除所有现有规则,不会创建任何新规则,也不会使用
--replicate-*
命令行或配置文件中的选项
恢复在mysqld启动时设置的任何规则
。
该
RESET
SLAVE
ALL
语句删除
在
语句删除的通道上设置的通道特定复制过滤器。
重新创建删除的一个或多个通道时,会为从属服务器指定的任何全局复制过滤器复制到它们,并且不会应用任何特定于通道的复制过滤器。
有关更多信息,请参见 第17.2.5节“服务器如何评估复制过滤规则” 。
SELECT MASTER_POS_WAIT('master_log_file
',master_log_pos
[,timeout
] [,channel
])
这实际上是一个函数,而不是一个声明。 它用于确保从站已经读取并执行了主站二进制日志中给定位置的事件。 有关 完整说明, 请参见 第12.24节“其他功能” 。
重置从[全部] [channel_option
]channel_option
: FOR CHANNELchannel
RESET
SLAVE
使奴隶忘记其在主二进制日志中的复制位置。
此语句旨在用于干净启动:它清除主信息和中继日志信息存储库,删除所有中继日志文件,并启动新的中继日志文件。
它还将使用
MASTER_DELAY
选项
指定的复制延迟重置为0
CHANGE MASTER
TO
。
RESET
SLAVE
不会改变
gtid_executed
或
的值
gtid_purged
。
所有中继日志文件都被删除,即使它们尚未完全由从属SQL线程执行。
(如果您已发出
STOP
SLAVE
语句或从站高负载,则
这是复制从站上可能存在的情况
。)
RESET
SLAVE
需要
RELOAD
特权。
要使用
RESET
SLAVE
,必须停止从属复制线程,因此
STOP
SLAVE
在发布之前
运行的从属用户
RESET
SLAVE
。
要
RESET
SLAVE
在组复制组成员上使用,成员状态必须是
OFFLINE
,这意味着已加载插件但该成员当前不属于任何组。
可以使用
STOP
GROUP REPLICATION
语句使
组成员脱机
。
使用optional
子句可以命名该语句适用的复制通道。
提供
子句将
语句
应用于
特定复制通道。
将
子句与
选项
组合将
删除指定的通道。
如果未命名通道且不存在额外通道,则该语句将应用于默认通道。
当存在多个复制通道时,
发出
不带
子句
的
语句
会删除
所有
复制通道,并仅重新创建默认通道。
有关
更多信息
,
请参见
第17.2.3节“复制通道”
。
FOR CHANNEL
channel
FOR CHANNEL
channel
RESET SLAVE
FOR CHANNEL
channel
ALL
RESET SLAVE
ALL
FOR CHANNEL
channel
RESET
SLAVE
不会更改任何复制连接参数,例如主主机,主端口,主用户或主密码。
从MySQL 8.0.13开始,在
master_info_repository=TABLE
服务器上设置时(默认情况下是MySQL 8.0),复制连接参数
作为
操作的
一部分
保存在崩溃安全
InnoDB
表
mysql.slave_master_info
中
RESET SLAVE
。
它们也保留在记忆中。
如果服务器崩溃或在发出之后
RESET SLAVE
但在发布之前
故意重新启动
START SLAVE
,则从表中检索复制连接参数并重新用于新连接。
在
master_info_repository=FILE
服务器上设置时,复制连接参数仅保留在内存中。
如果
由于服务器崩溃或故意重启而
在发出后立即重新启动
从属
mysqld
RESET SLAVE
,则连接参数将丢失。
在这种情况下,您必须
CHANGE MASTER TO
在服务器开始之后
发出
声明,以便在发出之前重新指定连接参数
START
SLAVE
。
如果要有意重置连接参数,则需要使用
RESET
SLAVE
ALL
,这将清除连接参数。
在这种情况下,必须
CHANGE MASTER
TO
在服务器启动后
发出
声明以指定新的连接参数。
RESET SLAVE ALL
清除
IGNORE_SERVER_IDS
设置
的
列表
CHANGE MASTER TO
。
RESET
SLAVE
不会更改
--replicate-ignore-table
受该语句影响的通道的
任何复制过滤器设置(例如
)。
但是,
RESET
SLAVE ALL
删除在语句删除的通道上设置的复制筛选器。
重新创建删除的一个或多个通道时,会为从属服务器指定的任何全局复制过滤器复制到它们,并且不会应用任何特定于通道的复制过滤器。
有关更多信息,请参见
第17.2.5.4节“基于复制通道的过滤器”
。
RESET SLAVE
导致正在进行的事务的隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
如果从属SQL线程在停止时复制临时表并且
RESET
SLAVE
已发出,则会在从属服务器上删除这些复制的临时表。
RESET SLAVE
不重置心跳周期(
Slave_heartbeat_period
)或
SSL_VERIFY_SERVER_CERT
。
在NDB群集复制从属SQL节点上使用时,
RESET SLAVE
清除该
mysql.ndb_apply_status
表。
使用这种说法时,您应该记住
ndb_apply_status
使用
NDB
存储引擎,因此利用连接到从群集的所有SQL节点共享。
您可以通过
在执行之前
发出来覆盖此行为
,这可以防止从属程序
在这种情况下
清除
表。
SET
GLOBAL
@@
ndb_clear_apply_status=OFF
RESET SLAVE
ndb_apply_status
SET GLOBAL sql_slave_skip_counter = N
该语句跳过
N
主服务器
的下一个
事件。
这对于从语句引起的复制停止中恢复非常有用。
仅当从属线程未运行时,此语句才有效。 否则,会产生错误。
使用此语句时,重要的是要了解二进制日志实际上被组织为一组称为 事件组的组 。 每个事件组由一系列事件组成。
对于事务表,事件组对应于事务。
对于非事务性表,事件组对应于单个SQL语句。
单个事务可以包含对事务和非事务表的更改。
当您使用
SET GLOBAL
sql_slave_skip_counter
跳过事件并且结果位于组的中间时,从站会继续跳过事件,直到它到达组的末尾。
然后执行从下一个事件组开始。
START SLAVE [thread_types
] [until_option
] [connection_options
] [channel_option
]thread_types
: [thread_type
[,thread_type
] ......]thread_type
: IO_THREAD | SQL_THREADuntil_option
: UNTIL {{SQL_BEFORE_GTIDS | SQL_AFTER_GTIDS} =gtid_set
| MASTER_LOG_FILE ='log_name
',MASTER_LOG_POS =log_pos
| RELAY_LOG_FILE ='log_name
',RELAY_LOG_POS =log_pos
| SQL_AFTER_MTS_GAPS}connection_options
: [USER ='user_name
'] [PASSWORD ='user_pass
'] [DEFAULT_AUTH ='plugin_name
'] [PLUGIN_DIR ='plugin_dir
']channel_option
: FOR CHANNELchannel
gtid_set
:uuid_set
[,uuid_set
] ...... | “”uuid_set
:uuid
:interval
[:interval
] ...uuid
:hhhhhhhh
-hhhh
-hhhh
-hhhh
-hhhhhhhhhhhh
h
: [0-9,AF]interval
:n
[ -n
] (n
> = 1)
START
SLAVE
没有
thread_type
选项启动两个从属线程。
I / O线程从主服务器读取事件并将它们存储在中继日志中。
SQL线程从中继日志中读取事件并执行它们。
START
SLAVE
需要
REPLICATION_SLAVE_ADMIN
或
SUPER
特权。
如果
START
SLAVE
成功启动从属线程,则返回时没有任何错误。
但是,即使在这种情况下,也可能是从属线程启动然后停止(例如,因为它们无法连接到主服务器或读取其二进制日志,或其他一些问题)。
START
SLAVE
并没有警告你这件事。
您必须检查从站的错误日志以查找从属线程生成的错误消息,或检查它们是否正常运行
SHOW
SLAVE STATUS
。
START SLAVE
导致正在进行的事务的隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
gtid_next
必须
AUTOMATIC
在发出此声明之前
设置为
。
使用optional
子句可以命名该语句适用的复制通道。
提供
子句将
语句
应用于
特定复制通道。
如果未命名子句且不存在额外通道,则该语句将应用于默认通道。
如果
语句在使用多个通道时没有定义通道,则此语句将启动所有通道的指定线程。
该
频道
不允许使用此声明
。
有关
更多信息
,
请参见
第17.2.3节“复制通道”
。
FOR CHANNEL
channel
FOR CHANNEL
channel
START SLAVE
START SLAVE
group_replication_recovery
MySQL支持可插拔的用户密码认证
START SLAVE
与
USER
,
PASSWORD
,
DEFAULT_AUTH
和
PLUGIN_DIR
选项,如下面的列表中所述:
USER
: 用户名。
不能设置为空或空字符串,或者如果
PASSWORD
使用
则保留未设置
。
PASSWORD
:密码。
DEFAULT_AUTH
:插件名称;
默认是MySQL本机身份验证。
PLUGIN_DIR
:插件的位置。
你不能使用
SQL_THREAD
指定的任何选项时
USER
,
PASSWORD
,
DEFAULT_AUTH
,或者
PLUGIN_DIR
,除非
IO_THREAD
还提供了选项。
有关 更多信息 , 请参见 第6.2.17节“可插入验证” 。
如果将不安全的连接与任何这些选项一起使用,则服务器会发出警告警告 在没有SSL / TLS的情况下以纯文本发送密码是非常不安全的 。
START SLAVE ... UNTIL
支持两个用于全局事务标识符(GTID)的附加选项(请参见
第17.1.3节“使用全局事务标识符复制”
)。
其中每个都将一组一个或多个全局事务标识符
gtid_set
作为参数(
有关更多信息,
请参阅
GTID集
)。
如果未
thread_type
指定,则
START SLAVE UNTIL SQL_BEFORE_GTIDS
使从属SQL线程处理事务,直到它到达其中
列出GTID
的
第一个
事务
gtid_set
。
START SLAVE
UNTIL SQL_AFTER_GTIDS
导致从属线程处理所有事务,直到
两个线程都处理了
该
last
事务
gtid_set
。
换句话说,
START SLAVE UNTIL
SQL_BEFORE_GTIDS
导致从属SQL线程处理在到达第一个GTID之前发生的所有事务
gtid_set
,
START SLAVE UNTIL SQL_AFTER_GTIDS
并使从属线程处理所有事务,包括那些在其中找到GTID的事务。
gtid_set
,直到每个人遇到一个GTID不属于该集合的交易。
SQL_BEFORE_GTIDS
并且
SQL_AFTER_GTIDS
每个都支持
SQL_THREAD
和
IO_THREAD
选项,虽然
IO_THREAD
目前
使用
它们没有任何效果。
例如,
START SLAVE SQL_THREAD UNTIL
SQL_BEFORE_GTIDS =
3E11FA47-71CA-11E1-9E33-C80AA9429562:11-56
使从SQL线程以处理来自其主始发的所有事务
server_uuid
是
3E11FA47-71CA-11E1-9E33-C80AA9429562
,直到它遇到具有序列号11中的交易;
然后停止而不处理此事务。
换句话说,处理直到并包括序列号为10的交易的所有交易。
执行
START SLAVE
SQL_THREAD UNTIL SQL_AFTER_GTIDS =
3E11FA47-71CA-11E1-9E33-C80AA9429562:11-56
另一方面,会导致从属SQL线程获取刚刚从主服务器提到的所有事务,包括序列号为11到56的所有事务,然后在不处理任何其他事务的情况下停止;
也就是说,序列号为56的事务将是从属SQL线程获取的最后一个事务。
使用带有
slave_preserve_commit_order=0
set
的多线程从站时
,在以下情况下,从中继日志执行的事务序列中可能存在间隙:
杀死协调员线程
在应用程序线程中发生错误之后
mysqld 意外关闭
使用该
START
SLAVE
UNTIL SQL_AFTER_MTS_GAPS
语句可以使多线程从属的工作线程只运行,直到在中继日志中找不到间隙,然后停止。
此语句可以
SQL_THREAD
选择,但语句的效果保持不变。
它对从属I / O线程没有影响(并且不能与
IO_THREAD
选项
一起使用
)。
发出
START
SLAVE
从中继日志执行的事务的序列中具有间隙的多线程从生成警告。
在这种情况下,解决方案是使用
START
SLAVE UNTIL
SQL_AFTER_MTS_GAPS
,然后发出
RESET
SLAVE
删除任何剩余的中继日志。
有关
更多信息
,
请参见
第17.4.1.33节“复制和事务不一致”
。
要将失败的多线程从属服务器更改为单线程模式,您可以按所示顺序发出以下一系列语句:
START SLAVE UNTIL SQL_AFTER_MTS_GAPS; SET @@ GLOBAL.slave_parallel_workers = 0; 开始使用SQL_THREAD;
可以在输出中查看正在运行的
START SLAVE ...
语句
的整个文本
,包括使用的任何
USER
或
PASSWORD
值
SHOW
PROCESSLIST
。
对于运行
CHANGE MASTER TO
语句
的文本也是如此
,包括它使用的任何值
MASTER_USER
或
MASTER_PASSWORD
。
START
SLAVE
在I / O线程和SQL线程都已启动后向用户发送确认。
但是,I / O线程可能尚未连接。
出于这个原因,一个成功的
START
SLAVE
原因
SHOW SLAVE STATUS
显示
Slave_SQL_Running=Yes
,但这并不保证
Slave_IO_Running=Yes
(因为
Slave_IO_Running=Yes
只有I / O线程正在运行
和连接
)。
有关更多信息,请参见
第13.7.6.34节“显示从动状态语法”
和
第17.1.7.1节“检查复制状态”
。
您可以
为语句
添加
IO_THREAD
和
SQL_THREAD
选项,以指定要启动的线程。
在
SQL_THREAD
指定的任选项时不允许
USER
,
PASSWORD
,
DEFAULT_AUTH
,或
PLUGIN_DIR
,除非
IO_THREAD
也被提供选项。
可以添加
一个
UNTIL
子句(
until_option
在前面的语法中)来指定从属应该启动和运行,直到SQL线程到达主二进制日志中的给定点,由
MASTER_LOG_POS
和MASTER_LOG_FILE选项
指定
,或从属中继中的给定点日志,用
RELAY_LOG_POS
和
RELAY_LOG_FILE
选项
表示
。
当SQL线程到达指定的点时,它将停止。
如果
SQL_THREAD
在语句中指定了
该
选项,则它仅启动SQL线程。
否则,它启动两个从属线程。
如果SQL线程正在运行,
UNTIL
则忽略
该
子句并发出警告。
您不能使用
UNTIL
带有该
IO_THREAD
选项
的
子句
。
也可以
START SLAVE UNTIL
使用其中一个选项指定相对于给定GTID或一组GTID的停止点,
SQL_BEFORE_GTIDS
或者
SQL_AFTER_GTIDS
如本节前面所述。
当使用其中的一个选项,您可以指定
SQL_THREAD
,
IO_THREAD
,这两个,或者两者都不是的。
如果仅指定
SQL_THREAD
,则只有从属SQL线程受该语句的影响;
如果仅
IO_THREAD
使用,则仅影响从属I / O.
如果同时使用
SQL_THREAD
和
IO_THREAD
使用它们,或者它们都没有使用,那么SQL和I / O线程都会受到语句的影响。
对于
UNTIL
子句,您必须指定以下任何一项:
这两种 日志文件名,并在文件中的位置
任何
一个
SQL_BEFORE_GTIDS
或
SQL_AFTER_GTIDS
SQL_AFTER_MTS_GAPS
不要混合主日志和中继日志选项。 不要将日志文件选项与GTID选项混合使用。
UNTIL
多线程从站不支持
该
子句,除非同时使用
SQL_AFTER_MTS_GAPS
。
如果
UNTIL
在没有多线程从站的情况下使用,则从站
SQL_AFTER_MTS_GAPS
以单线程(顺序)模式运行以进行复制,直到
UNTIL
达到
该
子句
指定的点
。
任何
UNTIL
条件都由后续
STOP
SLAVE
语句,
START
SLAVE
包含无
UNTIL
子句
的
语句
或服务器重新启动
重置
。
指定日志文件和位置时,
即使只有SQL线程受此语句的影响
,也可以使用该
IO_THREAD
选项
START SLAVE
... UNTIL
。
IO_THREAD
在这种情况下,
该
选项被忽略。
使用其中一个GTID选项(
SQL_BEFORE_GTIDS
和
SQL_AFTER_GTIDS
)
时,上述限制不适用
;
在GTID选项支持
SQL_THREAD
和
IO_THREAD
,在本节前面所解释的。
该
UNTIL
子句可用于调试复制,或导致复制继续进行,直到您希望避免从属服务器复制事件。
例如,如果
DROP
TABLE
在主服务器上执行了
一个不明智的
语句,您可以使用它
UNTIL
来告诉从服务器执行到该点但不再执行。
要查找事件的内容,
请将
mysqlbinlog
与主二进制日志或从中继日志一起使用,或使用
SHOW BINLOG EVENTS
语句。
如果您正在使用
UNTIL
从属进程复制的部分查询,则建议您使用
--skip-slave-start
选项启动从服务器,以防止从服务器启动时SQL线程运行。
最好在选项文件中而不是在命令行中使用此选项,以便意外重启服务器不会导致忘记它。
该
SHOW SLAVE STATUS
语句包括显示
UNTIL
条件
当前值的输出字段
。
在非常旧版本的MySQL(4.0.5之前)中,调用了此语句
SLAVE START
。
该语法现在会产生错误。
STOP SLAVE [thread_types
] [channel_option
]thread_types
: [thread_type
[,thread_type
] ......]thread_type
:IO_THREAD | SQL_THREADchannel_option
: FOR CHANNELchannel
停止从属线程。
STOP
SLAVE
需要
REPLICATION_SLAVE_ADMIN
或
SUPER
特权。
建议的最佳实践是
STOP SLAVE
在停止从服务器之前在从站上执行(
有关更多信息,
请参见
第5.1.17节“服务器关闭过程”
)。
使用基于行的日志记录格式时
:
如果要复制使用非事务性存储引擎的任何表,
则应
在关闭从属服务器之前
执行
STOP SLAVE
或
STOP SLAVE SQL_THREAD
在从属服务器上
执行
(请参阅
本节后面
的
注释
)。
比如
START
SLAVE
,此语句可以与
IO_THREAD
和
SQL_THREAD
选项一起
使用
来命名要停止的线程。
STOP SLAVE
导致正在进行的事务的隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
gtid_next
必须
AUTOMATIC
在发出此声明之前
设置为
。
您可以
STOP SLAVE
通过设置
rpl_stop_slave_timeout
系统变量
来控制
超时前等待的时间
。
这可以用于避免使用
STOP SLAVE
与从属的不同客户端连接
之间的死锁
和其他从属SQL语句
之间的死锁
。
达到超时值时,发出客户端将返回错误消息并停止等待,但该
STOP SLAVE
指令仍然有效。
一旦从属线程不再忙,
STOP SLAVE
则执行
该
语句并且从属程序停止。
根服务器
CHANGE MASTER TO
运行时允许
一些
语句,具体取决于从属SQL和I / O线程的状态。
但是,
仍然支持在这种情况下
STOP
SLAVE
执行之前
使用
CHANGE MASTER
TO
。
有关更多信息
,
请参见
第13.4.2.1节“更改主语法”
和
第17.3.8节“在故障转移期间切换主站”
。
使用optional
子句可以命名该语句适用的复制通道。
提供
子句将
语句
应用于
特定复制通道。
如果未命名通道且不存在额外通道,则该语句将应用于默认通道。
如果
语句在使用多个通道时未命名通道,则此语句将停止所有通道的指定线程。
此声明不能与
频道
一起使用
。
有关
更多信息
,
请参见
第17.2.3节“复制通道”
。
FOR CHANNEL
channel
FOR CHANNEL
channel
STOP SLAVE
STOP SLAVE
group_replication_recovery
使用基于语句的复制时
:在主服务器打开临时表时更改主服务器可能不安全。
这是不建议基于语句的临时表复制的原因之一。
您可以通过检查值的值来确定从站上是否有临时表
Slave_open_temp_tables
。
使用基于语句的复制时,该值在执行前应为0
CHANGE MASTER TO
。
如果从站上打开了任何临时表,则在发出
CHANGE
MASTER TO
声明后发出声明
STOP
SLAVE
会导致
ER_WARN_OPEN_TEMP_TABLES_MUST_BE_ZERO
警告。
当使用多线程从属(
slave_parallel_workers
非零值)时,从中继日志执行的事务序列中的任何间隙都将作为停止工作线程的一部分而关闭。
如果在
执行语句时
意外停止从属(例如,由于工作线程中的错误或其他线程发出
KILL
)
STOP
SLAVE
,则来自中继日志的执行事务序列可能变得不一致。
有关
更多信息
,
请参见
第17.4.1.33节“复制和事务不一致”
。
如果当前复制事件组已修改了一个或多个非事务性表,则STOP SLAVE将等待最多60秒以使事件组完成,除非您
为从属SQL线程
发出
KILL
QUERY
或
KILL
CONNECTION
声明。
如果事件组在超时后仍然不完整,则会记录一条错误消息。
本节提供有关用于控制组复制的语句的信息。
START GROUP_REPLICATION
启动组复制。
此声明需要
GROUP_REPLICATION_ADMIN
或
SUPER
特权。
如果
super_read_only=ON
和成员应作为主要成员加入,
super_read_only
则设置为
OFF
成功启动组复制。
停止GROUP_REPLICATION
停止组复制。
此声明需要
GROUP_REPLICATION_ADMIN
或
SUPER
特权。
一旦您发出
STOP GROUP_REPLICATION
成员设置为
super_read_only=ON
,这将确保在组复制停止时不能对该成员进行写入。
在成员上运行的任何其他复制通道也将停止。
请谨慎使用此语句,因为它会从组中删除服务器实例,这意味着它不再受Group Replication的一致性保证机制的保护。 为了完全安全,请确保在发出此语句之前应用程序无法再连接到实例,以避免任何过时读取的可能性。
使用以下功能可以配置单主复制组的哪个成员是主要成员。
group_replication_set_as_primary()
任命该组的特定成员为新的主要成员,压倒任何选举过程。
通过在
member_uuid
这是
server_uuid
要成为新的主成员。
必须在以单主模式运行的复制组的成员上发布。
句法:
STRING group_replication_set_as_primary(member_uuid
)
返回值:
包含操作结果的字符串,例如是否成功。
例:
SELECT group_replication_set_as_primary(member_uuid
)
有关更多信息,请参见 第18.4.2.1节“更改组的主要成员”
使用以下功能可以控制运行复制组的模式,单主模式或多主模式。
group_replication_switch_to_single_primary_mode()
将以多主模式运行的组更改为单主模式,而无需停止组复制。
必须在以多主模式运行的复制组的成员上发布。
当您更改为单主模式时,还会根据单主模式(
group_replication_enforce_update_everywhere_checks=OFF
)中的
要求禁用所有组成员的严格一致性检查
。
句法:
STRING group_replication_switch_to_single_primary_mode([ str
])
参数:
str
:包含该组成员的UUID的字符串,该成员应成为新的单个主要成员。
该组的其他成员成为辅助成员。
返回值:
包含操作结果的字符串,例如是否成功。
例:
SELECT group_replication_switch_to_single_primary_mode(member_uuid
);
有关更多信息,请参见 第18.4.2.2节“更改组模式”
group_replication_switch_to_multi_primary_mode()
将以单主模式运行的组更改为多主模式。 必须在以单主模式运行的复制组的成员上发布。
句法:
STRING group_replication_switch_to_multi_primary_mode()
此功能没有参数。
返回值:
包含操作结果的字符串,例如是否成功。
例:
SELECT group_replication_switch_to_multi_primary_mode()
属于该组的所有成员都成为初选。
有关更多信息,请参见 第18.4.2.2节“更改组模式”
以下函数使您可以检查和配置组可以并行执行的最大共识实例数。
group_replication_get_write_concurrency()
检查组可以并行执行的最大共识实例数。
句法:
STRING group_replication_get_write_concurrency()
此功能没有参数。
返回值:
任何结果错误为字符串。
例:
SELECT group_replication_get_write_concurrency()
有关更多信息,请参见 第18.4.2.3节“使用组复制组写入共识” 。
group_replication_set_write_concurrency()
配置组可以并行执行的最大共识实例数。
GROUP_REPLICATION_ADMIN
使用此UDF需要
该
权限。
句法:
STRING group_replication_set_write_concurrency(instances
)
参数:
members
:设置组可以并行执行的最大共识实例数。
默认值为10,有效值为10到200范围内的整数。
返回值:
任何结果错误为字符串。
例:
SELECT group_replication_set_write_concurrency(instances
);
有关更多信息,请参见 第18.4.2.3节“使用组复制组写入共识” 。
使用以下功能可以检查和配置复制组使用的组复制通信协议版本。
group_replication_get_communication_protocol()
检查当前用于组的组复制通信协议版本。
句法:
STRING group_replication_get_communication_protocol()
此功能没有参数。
返回值:
最古老的MySQL Server版本,可以加入该组并使用该组的通信协议。
MySQL 5.7.14中的版本允许压缩消息,而MySQL 8.0.16中的版本也允许消息碎片化。
请注意,
group_replication_get_communication_protocol()
UDF返回该组支持的最小MySQL版本,该版本可能与传递给
group_replication_set_communication_protocol()
UDF
的版本号
以及安装在使用UDF的成员上的MySQL Server版本不同。
如果由于此服务器实例不属于复制组而无法检查协议,则会以字符串形式返回错误。
例:
SELECT group_replication_get_communication_protocol();
+ ------------------------------------------------ +
| group_replication_get_communication_protocol()|
+ ------------------------------------------------ +
| 8.0.16 |
+ ------------------------------------------------ +
有关更多信息,请参见 第18.4.2.4节“设置组的通信协议版本” 。
group_replication_set_communication_protocol()
降级组的组复制通信协议版本,以便早期版本的成员可以在所有成员上升级MySQL Server之后加入或升级组的组复制通信协议版本。
GROUP_REPLICATION_ADMIN
使用此UDF需要
该
权限,并且在发出语句时所有现有组成员必须联机,且不会丢失多数。
对于MySQL InnoDB集群,只要使用AdminAPI操作更改集群拓扑,就会自动管理通信协议版本。 您不必自己为InnoDB集群使用这些UDF。
句法:
STRING group_replication_set_communication_protocol(version
)
参数:
version
:对于降级,请指定具有最早安装的服务器版本的预期组成员的MySQL Server版本。
在这种情况下,该命令使组回退到与该服务器版本兼容的通信协议(如果可能)。
您可以指定的最小服务器版本是MySQL 5.7.14。
要进行升级,请指定已升级现有组成员的新MySQL服务器版本。
返回值:
包含操作结果的字符串,例如是否成功。
例:
SELECT group_replication_set_communication_protocol("5.7.25");
有关更多信息,请参见 第18.4.2.4节“设置组的通信协议版本” 。
MySQL 8.0为服务器端预处理语句提供支持。 此支持利用了高效的客户端/服务器二进制协议。 将带有占位符的预准备语句用于参数值具有以下好处:
每次执行时解析语句的开销更少。
通常,数据库应用程序处理大量几乎相同的语句,只更改子句中的文字或变量值,例如
WHERE
查询和删除,
SET
更新和
VALUES
插入。
防止SQL注入攻击。 参数值可以包含未转义的SQL引号和分隔符。
您可以通过客户端编程接口使用服务器端预处理语句,包括
MySQL C API客户端库
或
用于C程序的
MySQL Connector / C
,
用于Java程序的
MySQL Connector / J
和
用于使用.NET技术的程序的
MySQL Connector / NET
。
例如,C API提供了一组函数调用,这些函数调用构成了其准备好的语句API。
请参见
第28.7.8节“C API准备语句”
。
其他语言接口可以通过在C客户端库中链接来提供对使用二进制协议的预准备语句的支持,其中一个示例是
mysqli
扩展
,可在PHP 5.0及更高版本中使用。
可以使用备用语句的备用SQL接口。 此接口不如通过预准备语句API使用二进制协议那样高效,但不需要编程,因为它可直接在SQL级别使用:
当没有可用的编程接口时,您可以使用它。
您可以从任何可以将SQL语句发送到要执行的服务器的程序中使用它,例如 mysql 客户端程序。
只要连接到运行MySQL 4.1或更高版本的服务器,即使客户端使用的是旧版本的客户端库,也可以使用它。
预准备语句的SQL语法旨在用于以下情况:
在编写之前测试准备语句在应用程序中的工作方式。
在无法访问支持它们的编程API时使用预准备语句。
使用预准备语句以交互方式解决应用程序问题。
创建一个用预处理语句重现问题的测试用例,以便您可以提交错误报告。
预处理语句的SQL语法基于三个SQL语句:
PREPARE
准备一份执行语句(参见
第13.5.1节“PREPARE语法”
)。
EXECUTE
执行准备好的语句(参见
第13.5.2节“EXECUTE语法”
)。
DEALLOCATE PREPARE
发布
预
准备语句(请参见
第13.5.3节“DEALLOCATE PREPARE语法”
)。
以下示例显示了两种等效的方法来准备一个语句,该语句根据双方的长度计算三角形的斜边。
第一个示例显示如何使用字符串文字创建预准备语句以提供语句的文本:
mysql>PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql>SET @a = 3;
mysql>SET @b = 4;
mysql>EXECUTE stmt1 USING @a, @b;
+ ------------ + | 斜边| + ------------ + | 5 | + ------------ + MySQL的>DEALLOCATE PREPARE stmt1;
第二个示例类似,但提供语句的文本作为用户变量:
mysql>SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql>PREPARE stmt2 FROM @s;
mysql>SET @a = 6;
mysql>SET @b = 8;
mysql>EXECUTE stmt2 USING @a, @b;
+ ------------ + | 斜边| + ------------ + | 10 | + ------------ + MySQL的>DEALLOCATE PREPARE stmt2;
下面是另一个示例,演示如何通过将表的名称存储为用户变量来选择在运行时执行查询的表:
mysql>USE test;
mysql>CREATE TABLE t1 (a INT NOT NULL);
mysql>INSERT INTO t1 VALUES (4), (8), (11), (32), (80);
mysql>SET @table = 't1';
mysql>SET @s = CONCAT('SELECT * FROM ', @table);
mysql>PREPARE stmt3 FROM @s;
mysql>EXECUTE stmt3;
+ ---- + | a | + ---- + | 4 | | 8 | | 11 | | 32 | | 80 | + ---- + MySQL的>DEALLOCATE PREPARE stmt3;
准备好的语句特定于创建它的会话。 如果在不释放先前准备的语句的情况下终止会话,则服务器会自动解除分配。
准备好的声明也是本届会议的全球性声明。 如果在存储例程中创建预准备语句,则在存储例程结束时不会取消分配。
要防止同时创建太多准备好的语句,请设置
max_prepared_stmt_count
系统变量。
要防止使用预准备语句,请将值设置为0。
以下SQL语句可用作预准备语句:
更改表 更改用户 分析表 CACHE INDEX 呼叫 改变主人 CHECKSUM {TABLE | TABLES} 承诺 {创建| DROP} INDEX {创建| 重命名| DROP} DATABASE {创建| DROP} TABLE {创建| 重命名| DROP} USER {创建| DROP} VIEW 删除 做 FLUSH {表| 表格| 阅读锁定的表格 HOSTS | 特权 | LOGS | 状态| MASTER | 奴役| USER_RESOURCES} GRANT 插入 安装插件 杀 负荷指数进入高速缓存 优化表 重命名表 修理表 更换 重置{MASTER | 奴隶} 撤消 选择 组 显示{警告| 错误} 展示BINLOG活动 SHOW CREATE {PROCEDURE | 功能| 活动| 表| 视图} SHOW {MASTER | BINARY} LOGS SHOW {MASTER | SLAVE}状态 从来没有{开始| 停} TRUNCATE TABLE 卸载插件 UPDATE
为了符合SQL标准,该标准声明诊断语句是不可伪造的,MySQL不支持以下准备语句:
SHOW WARNINGS
,
SHOW COUNT(*)
WARNINGS
SHOW ERRORS
,
SHOW COUNT(*)
ERRORS
包含对任何参考语句
warning_count
或
error_count
系统变量。
MySQL 8.0不支持其他语句。
通常,SQL预处理语句中不允许的语句也不允许存储在程序中。 第C.1节“存储程序的限制” 中注明了例外情况 。
检测到由预准备语句引用的表或视图的元数据更改,并在下次执行时自动对语句进行表示。 有关更多信息,请参见 第8.10.3节“准备语句和存储程序的缓存” 。
使用预
LIMIT
准备语句时,
占位符可用于
子句
的参数
。
请参见
第13.2.10节“SELECT语法”
。
在准备
CALL
与使用的语句
PREPARE
,并
EXECUTE
为占位符的支持
OUT
和
INOUT
参数可与MySQL 8.0版以后。
有关
早期版本的示例和变通方法,
请参见
第13.2.1节“CALL语法”
。
IN
无论版本如何,
占位符都可用于
参数。
预处理语句的SQL语法不能以嵌套方式使用。
也就是说,传递给一个说法
PREPARE
本身不能成为一个
PREPARE
,
EXECUTE
或
DEALLOCATE PREPARE
声明。
预准备语句的SQL语法与使用预准备语句API调用不同。
例如,您不能使用
mysql_stmt_prepare()
C API函数来准备
PREPARE
,
EXECUTE
或
DEALLOCATE PREPARE
声明。
预准备语句的SQL语法可以在存储过程中使用,但不能在存储的函数或触发器中使用。
然而,光标不能用于被制备并用执行的动态语句
PREPARE
和
EXECUTE
。
在游标创建时检查游标的语句,因此该语句不能是动态的。
预处理语句的SQL语法不支持多语句(即,由
;
字符
分隔的单个字符串中的多个语句
)。
要编写使用
CALL
SQL语句执行包含预准备语句的存储过程的
C程序,
CLIENT_MULTI_RESULTS
必须启用
该
标志。
这是因为
CALL
除了过程中执行的语句可能返回的任何结果集之外,
每个都
返回一个结果来指示调用状态。
CLIENT_MULTI_RESULTS
可以在调用时启用
mysql_real_connect()
,可以通过传递
CLIENT_MULTI_RESULTS
标志本身
显式
启用
,也可以通过传递
隐式
CLIENT_MULTI_STATEMENTS
启用(也可以启用
CLIENT_MULTI_RESULTS
)。
有关其他信息,请参见
第13.2.1节“CALL语法”
。
准备stmt_name
来自preparable_stmt
该
PREPARE
语句准备一个SQL语句并为其指定一个名称,
stmt_name
以便稍后引用该语句。
准备语句是与执行
EXECUTE
与发布
DEALLOCATE PREPARE
。
有关示例,请参见
第13.5节“准备的SQL语句语法”
。
语句名称不区分大小写。
preparable_stmt
是字符串文字或包含SQL语句文本的用户变量。
文本必须表示单个语句,而不是多个语句。
在语句中,
?
字符可以用作参数标记,以指示稍后在执行时将数据值绑定到查询的位置。
该
?
字符不应引号括起来,即使你打算将它们绑定到字符串值。
参数标记只能用于应出现数据值的位置,而不能用于SQL关键字,标识符等。
如果已存在具有给定名称的预准备语句,则在准备新语句之前将其隐式释放。 这意味着如果新语句包含错误且无法准备,则会返回错误,并且不存在具有给定名称的语句。
准备好的声明的范围是创建声明的会话,其中包含以下几个含义:
在一个会话中创建的预准备语句不可用于其他会话。
会话结束时,无论是正常还是异常,其准备好的陈述不再存在。 如果启用了自动重新连接,则不会通知客户端连接已丢失。 因此,客户可能希望禁用自动重新连接。 请参见 第28.7.28节“C API自动重新连接控制” 。
在程序完成执行后,在存储程序中创建的预准备语句继续存在,并且可以在程序之后执行。
在存储程序上下文中准备的语句不能引用存储过程或函数参数或局部变量,因为它们在程序结束时超出范围并且将在程序之外稍后执行的语句将不可用。 作为一种解决方法,请转而使用具有会话范围的用户定义变量; 请参见 第9.4节“用户定义的变量” 。
执行stmt_name
[使用@var_name
[,@var_name
] ...]
在准备好语句之后
,使用引用预准备语句名称
PREPARE
的
EXECUTE
语句
执行它
。
如果预准备语句包含任何参数标记,则必须提供一个
USING
子句,
该
子句列出包含要绑定到参数的值的用户变量。
参数值只能由用户变量提供,并且该
USING
子句的名称必须与语句中参数标记的数量完全相同。
您可以多次执行给定的预准备语句,将不同的变量传递给它,或者在每次执行之前将变量设置为不同的值。
有关示例,请参见 第13.5节“准备的SQL语句语法” 。
{DEALLOCATE | DROP} PREPAREstmt_name
要解除分配生成的预准备语句
PREPARE
,请使用
DEALLOCATE PREPARE
引用预准备语句名称的语句。
在解除分配后尝试执行预准备语句会导致错误。
如果创建了太多准备好的语句,并且未通过
DEALLOCATE PREPARE
语句或会话结束
解除分配
,则可能会遇到
max_prepared_stmt_count
系统变量
强制执行的上限
。
有关示例,请参见 第13.5节“准备的SQL语句语法” 。
本节介绍
BEGIN ... END
复合语句
的语法
以及可在存储程序体中使用的其他语句:存储过程和函数,触发器和事件。
这些对象是根据存储在服务器上以供以后调用的SQL代码定义的(请参阅
第24章,
存储对象
)。
复合语句是一个可以包含其他块的块; 变量,条件处理程序和游标的声明; 和流控制结构,如循环和条件测试。
[begin_label
:]开始 [statement_list
] 结束[end_label
]
BEGIN ... END
语法用于编写复合语句,它可以出现在存储的程序(存储过程和函数,触发器和事件)中。
复合语句可以包含多个语句,由
BEGIN
和
END
关键字
括起来
。
statement_list
表示一个或多个语句的列表,每个语句以semicolon(
;
)语句分隔符
结尾
。
它
statement_list
本身是可选的,因此空的复合语句(
BEGIN END
)是合法的。
BEGIN ... END
块可以嵌套。
使用多个语句要求客户端能够发送包含
;
语句分隔符的
语句字符串
。
在
mysql
命令行客户端中,使用该
delimiter
命令
处理
。
更改
;
语句结束分隔符(例如,to
//
)允许
;
在程序体中使用。
有关示例,请参见
第24.1节“定义存储程序”
。
阿
BEGIN ...
END
块可以被标记。
请参见
第13.6.2节“语句标签语法”
。
[NOT] ATOMIC
不支持
可选
子句。
这意味着在指令块的开头没有设置事务保存点,并且
BEGIN
此上下文中使用
的
子句对当前事务没有影响。
在所有存储的程序中,解析器将其
BEGIN [WORK]
视为
BEGIN ...
END
块
的开头
。
要在此上下文中开始事务,请
START
TRANSACTION
改用。
[begin_label
:]开始 [statement_list
] 结束[end_label
] [begin_label
:] LOOPstatement_list
END LOOP [end_label
] [begin_label
:] REPEATstatement_list
直到search_condition
END REPEAT [end_label
] [begin_label
:] WHILEsearch_condition
DOstatement_list
END WHILE [end_label
]
标签被允许
BEGIN ... END
块和对
LOOP
,
REPEAT
和
WHILE
语句。
这些语句的标签用法遵循以下规则:
begin_label
必须跟着冒号。
begin_label
可以没有
end_label
。
如果
end_label
存在,则必须与...相同
begin_label
。
end_label
不能没有
begin_label
。
同一嵌套级别的标签必须是不同的。
标签最长可达16个字符。
要引用标记构造中的标签,请使用
ITERATE
或
LEAVE
声明。
以下示例使用这些语句继续迭代或终止循环:
CREATE PROCEDURE doiterate(p1 INT) 开始 label1:LOOP SET p1 = p1 + 1; 如果p1 <10那么ITERATE label1; 万一; LEAVE label1; END LOOP label1; 结束;
块标签的范围不包括块内声明的处理程序的代码。 有关详细信息,请参见 第13.6.7.2节“DECLARE ... HANDLER语法” 。
该
DECLARE
语句用于定义程序本地的各种项目:
局部变量。 请参见 第13.6.4节“存储程序中的变量” 。
条件和处理程序。 请参见 第13.6.7节“条件处理” 。
光标。 请参见 第13.6.6节“游标” 。
DECLARE
只允许在
BEGIN ... END
复合语句中使用,并且在任何其他语句之前必须在其开头。
声明必须遵循一定的顺序。 游标声明必须出现在处理程序声明之前。 变量和条件声明必须出现在游标或处理程序声明之前。
系统变量和用户定义的变量可以在存储的程序中使用,就像它们可以在存储程序上下文之外使用一样。
此外,存储的程序可用于
DECLARE
定义局部变量,并且可以声明存储的例程(过程和函数)以获取在例程与其调用者之间传递值的参数。
要声明局部变量,请使用该
DECLARE
语句,如
第13.6.4.1节“局部变量DECLARE语法”中所述
。
可以使用
SET
语句
直接设置变量
。
请参见
第13.7.5.1节“变量赋值的SET语法”
。
查询结果可以使用
或通过打开游标并使用
来检索到局部变量
。
请参见
第13.2.10.1节“SELECT ... INTO语法”
和
第13.6.6节“游标”
。
SELECT ...
INTO
var_list
FETCH ... INTO
var_list
有关局部变量范围以及MySQL如何解析模糊名称的信息,请参见 第13.6.4.2节“局部变量范围和分辨率” 。
不允许将值分配
DEFAULT
给存储过程或函数参数或存储的程序局部变量(例如,使用
语句)。
在MySQL 8.0中,这会导致语法错误。
SET
var_name
= DEFAULT
DECLAREvar_name
[,var_name
] ...type
[DEFAULTvalue
]
此语句声明存储程序中的局部变量。
要为变量提供默认值,请包含
DEFAULT
子句。
该值可以指定为表达式;
它不一定是常数。
如果
DEFAULT
缺少
该
子句,则初始值为
NULL
。
局部变量被视为关于数据类型和溢出检查的存储例程参数。 请参见 第13.1.17节“创建过程和创建函数语法” 。
变量声明必须出现在游标或处理程序声明之前。
局部变量名称不区分大小写。 允许的字符和引用规则与其他标识符相同,如 第9.2节“架构对象名称”中所述 。
局部变量的
BEGIN ...
END
范围是声明它
的
块。
除了那些声明具有相同名称的变量的块之外,可以在嵌套在声明块中的块中引用该变量。
有关变量声明的示例,请参见 第13.6.4.2节“局部变量范围和分辨率” 。
局部变量的
BEGIN ...
END
范围是声明它
的
块。
除了那些声明具有相同名称的变量的块之外,可以在嵌套在声明块中的块中引用该变量。
由于局部变量仅在存储程序执行期间在范围内,因此在存储程序中创建的预准备语句中不允许引用它们。
准备好的语句范围是当前会话,而不是存储的程序,因此语句可以在程序结束后执行,此时变量将不再在范围内。
例如,
不能用作预备语句。
此限制也适用于存储过程和函数参数。
请参见
第13.5.1节“PREPARE语法”
。
SELECT ... INTO
local_var
局部变量不应与表列具有相同的名称。
如果SQL语句(如
SELECT
...
INTO
语句)包含对列的引用和声明的具有相同名称的局部变量,则MySQL当前会将引用解释为变量的名称。
请考虑以下过程定义:
CREATE PROCEDURE sp1(x VARCHAR(5)) 开始 DECLARE xname VARCHAR(5)DEFAULT'bob'; DECLARE newname VARCHAR(5); DECLARE xid INT; SELECT xname,id INTO newname,xid FROM table1 WHERE xname = xname; SELECT newname; 结束;
MySQL解释
xname
了
SELECT
语句中将其
为对
xname
变量
的引用
而不是
xname
列
。
因此,在
sp1()
调用
过程时
,
无论
列
newname
的值
'bob'
如何,
变量都会返回值
table1.xname
。
同样,以下过程中的游标定义包含
SELECT
引用
的
语句
xname
。
MySQL将此解释为对该名称的变量的引用,而不是列引用。
CREATE PROCEDURE sp2(x VARCHAR(5)) 开始 DECLARE xname VARCHAR(5)DEFAULT'bob'; DECLARE newname VARCHAR(5); DECLARE xid INT; DECLARE完成了TINYINT DEFAULT 0; DECLARE cur1 CURSOR FOR SELECT xname,id FROM table1; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 打开cur1; read_loop:LOOP FETCH FROM cur1 INTO newname,xid; 如果完成那么就是read_loop; 万一; SELECT newname; 结束循环; 关闭cur1; 结束;
另请参见 第C.1节“存储程序的限制” 。
MySQL的支持
IF
,
CASE
,
ITERATE
,
,
,并
构建了存储程序中的流量控制。
它还支持
存储的功能。
LEAVE
LOOP
WHILE
REPEAT
RETURN
其中许多构造包含其他语句,如以下部分中的语法规范所示。
这样的构造可以嵌套。
例如,
IF
语句可能包含一个
WHILE
循环,它本身包含一个
CASE
语句。
MySQL不支持
FOR
循环。
CASEcase_value
WHENwhen_value
THENstatement_list
[WHENwhen_value
THENstatement_list
] ... [其他statement_list
] 结束案例
要么:
案件 WHENsearch_condition
THENstatement_list
[WHENsearch_condition
THENstatement_list
] ... [其他statement_list
] 结束案例
CASE
存储程序
的
语句实现了复杂的条件构造。
还有一个
expr
,它与
此处描述
的
语句
不同
。
请参见
第12.4节“控制流功能”
。
该
语句不能有一个
子句,它以for
而不是
。
CASE
CASE
CASE
ELSE NULL
END CASE
END
对于第一种语法,
case_value
是表达式。
将此值与
when_value
每个
WHEN
子句中
的
表达式进行
比较,
直到其中一个相等。
when_value
找到
相等
的
THEN
子句时,
statement_list
执行
相应的
子句
。
如果no不
when_value
相等,则
执行
该
ELSE
子句
statement_list
(如果有)。
此语法不能用于测试相等性,
NULL
因为它
NULL = NULL
是false。
请参见
第3.3.4.6节“使用NULL值”
。
对于第二种语法,
将评估
每个
WHEN
子句
search_condition
表达式,直到其中一个为真,此时它的相应
THEN
子句将
statement_list
执行。
如果no不
search_condition
相等,则
执行
该
ELSE
子句
statement_list
(如果有)。
如果没有
when_value
或
search_condition
匹配测试的值且该
CASE
语句不包含
ELSE
子句,则
找不到CASE语句
错误结果
的
Case
。
每个
statement_list
包含一个或多个SQL语句;
statement_list
不允许
空
。
要处理任何
WHEN
子句都
没有匹配值的情况
,请使用
ELSE
包含空
BEGIN ...
END
块的情况,如本例所示。
(本
ELSE
条款中
使用的缩进仅用于
清晰的目的,并不重要。)
DELIMITER | CREATE PROCEDURE p() 开始 DECLARE v INT DEFAULT 1; 案例v 当2那么选择v; 当3然后选择0; 其他 开始 结束; 结束案例; 结束; |
如果search_condition
那么statement_list
[ELSEIFsearch_condition
那么statement_list
] ...... [ELSEstatement_list
] 万一
IF
存储程序
的
语句实现了一个基本的条件结构。
还有一个
函数
,它与
此处描述
的
语句
不同
。
请参见
第12.4节“控制流功能”
。
该
语句可以包含
,
和
条款,并以终止
。
IF()
IF
IF
THEN
ELSE
ELSEIF
END IF
如果给定的
search_condition
计算结果为true,则
执行
相应的
THEN
or
ELSEIF
子句
statement_list
。
如果不
search_condition
匹配,则
执行
该
ELSE
子句
statement_list
。
每个
statement_list
包含一个或多个SQL语句;
statement_list
不允许
空
。
与
IF ... END IF
存储程序中使用的所有其他流控制块一样,块必须以分号结束,如下例所示:
DELIMITER // 创建函数SimpleCompare(n INT,m INT) 退货车(20) 开始 DECLARE s VARCHAR(20); 如果n> m那么设置s ='>'; ELSEIF n = m THEN SET s ='='; ELSE SET s ='<'; 万一; SET s = CONCAT(n,'',s,'',m); 返回; 结束 // DELIMITER;
与其他流控制结构一样,
IF ... END
IF
块可以嵌套在其他流控制结构中,包括其他
IF
语句。
每个
IF
必须由它自己终止,
END IF
然后是分号。
您可以使用缩进来使嵌套的流控制块更容易被人类读取(尽管MySQL不需要这样),如下所示:
DELIMITER // CREATE FUNCTION VerboseCompare(n INT,m INT) 返回VARCHAR(50) 开始 DECLARE s VARCHAR(50); IF n = m THEN SET s ='equals'; 其他 如果n> m那么SET s ='更大'; ELSE SET s ='less'; 万一; SET s = CONCAT('是',s,'比'); 万一; SET s = CONCAT(n,'',s,'',m,'。'); 返回; 结束 // DELIMITER;
在此示例中,
IF
仅在
n
不等于
内部
时才计算
内部
m
。
重复 label
ITERATE
只能出现
LOOP
,
REPEAT
和
WHILE
语句。
ITERATE
意思是
“
再次开始循环。
”
有关示例,请参见 第13.6.5.5节“LOOP语法” 。
离开 label
此语句用于退出具有给定标签的流控制结构。
如果标签用于最外面存储的程序块,则
LEAVE
退出程序。
LEAVE
可以内使用
BEGIN ...
END
或循环结构(
LOOP
,
REPEAT
,
WHILE
)。
有关示例,请参见 第13.6.5.5节“LOOP语法” 。
[begin_label
:] LOOPstatement_list
END LOOP [end_label
]
LOOP
实现一个简单的循环结构,允许重复执行语句列表,该列表由一个或多个语句组成,每个语句以semicolon(
;
)语句分隔符结束。
循环中的语句将重复,直到循环终止。
通常,这是通过
LEAVE
声明
来完成的
。
在存储的函数中,
RETURN
也可以使用,它完全退出函数。
忽略包含循环终止语句会导致无限循环。
一个
LOOP
语句可以被标记。
有关标签使用的规则,请参见
第13.6.2节“语句标签语法”
。
例:
CREATE PROCEDURE doiterate(p1 INT) 开始 label1:LOOP SET p1 = p1 + 1; 如果p1 <10那么 ITERATE label1; 万一; LEAVE label1; END LOOP label1; SET @x = p1; 结束;
[begin_label
:] REPEATstatement_list
直到search_condition
END REPEAT [end_label
]
语句中的语句列表
REPEAT
将重复,直到
search_condition
表达式为true。
因此,
REPEAT
总是至少进入一次循环。
statement_list
由一个或多个语句组成,每个语句以semicolon(
;
)语句分隔符
结尾
。
一个
REPEAT
语句可以被标记。
有关标签使用的规则,请参见
第13.6.2节“语句标签语法”
。
例:
MySQL的>delimiter //
MySQL的>CREATE PROCEDURE dorepeat(p1 INT)
BEGIN
SET @x = 0;
REPEAT
SET @x = @x + 1;
UNTIL @x > p1 END REPEAT;
END
//
查询正常,0行受影响(0.00秒) MySQL的>CALL dorepeat(1000)//
查询正常,0行受影响(0.00秒) MySQL的>SELECT @x//
+ ------ + | @x | + ------ + | 1001 | + ------ + 1排(0.00秒)
返回 expr
该
RETURN
语句终止存储函数的执行并将值返回
expr
给函数调用者。
RETURN
存储函数中
必须至少有一个
语句。
如果函数有多个退出点,则可能有多个。
此语句不用于存储过程,触发器或事件。
该
LEAVE
语句可用于退出这些类型的存储程序。
[begin_label
:] WHILEsearch_condition
DOstatement_list
END WHILE [end_label
]
WHILE
只要
search_condition
表达式为true
,语句中的语句列表
就会重复
。
statement_list
由一个或多个SQL语句组成,每个语句都以semicolon(
;
)语句分隔符结束。
一个
WHILE
语句可以被标记。
有关标签使用的规则,请参见
第13.6.2节“语句标签语法”
。
例:
CREATE PROCEDURE dowhile() 开始 DECLARE v1 INT DEFAULT 5; WHILE v1> 0 DO ... SET v1 = v1 - 1; 结束时间; 结束;
MySQL支持存储程序中的游标。 语法与嵌入式SQL中的一样。 游标具有以下属性:
敏感:服务器可能会也可能不会复制其结果表
只读:不可更新
不可滚动:只能在一个方向上遍历,不能跳过行
游标声明必须出现在处理程序声明之前以及变量和条件声明之后。
例:
CREATE PROCEDURE curdemo() 开始 DECLARE完成INT DEFAULT FALSE; 宣布CHAR(16); DECLARE b,c INT; DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1; DECLARE cur2 CURSOR FOR SELECT i FROM test.t2; DECLARE CONTINUE HANDLER for NOT FOUND SET done = TRUE; 打开cur1; 打开cur2; read_loop:LOOP FETCH cur1 INTO a,b; FETCH cur2 INTO c; 如果这样做了 LEAVE read_loop; 万一; 如果b <c那么 INSERT INTO test.t3 VALUES(a,b); 其他 INSERT INTO test.t3 VALUES(a,c); 万一; 结束循环; 关闭cur1; 关闭cur2; 结束;
关 cursor_name
该语句关闭先前打开的游标。 有关示例,请参见 第13.6.6节“游标” 。
如果光标未打开,则会发生错误。
如果未显式关闭
BEGIN ...
END
,则在声明它
的
块
的末尾关闭游标
。
DECLAREcursor_name
CURSOR FORselect_statement
此语句声明游标并将其与一个
SELECT
语句
相关联,该
语句检索游标要遍历的行。
要稍后获取行,请使用
FETCH
语句。
SELECT
语句
检索的列数
必须与语句中指定的输出变量数相匹配
FETCH
。
该
SELECT
语句不能有一个
INTO
条款。
游标声明必须出现在处理程序声明之前以及变量和条件声明之后。
存储的程序可能包含多个游标声明,但在给定块中声明的每个游标必须具有唯一的名称。 有关示例,请参见 第13.6.6节“游标” 。
对于通过
SHOW
语句
提供的信息
,在许多情况下可以通过使用带有
INFORMATION_SCHEMA
表
的游标来获得等效信息
。
FETCH [[NEXT] FROM]cursor_name
INTOvar_name
[,var_name
] ......
此语句将获取下一行
SELECT
与指定游标关联
语句
(必须打开),并使光标指针前进。
如果存在行,则获取的列将存储在命名变量中。
SELECT
语句
检索的列数
必须与语句中指定的输出变量数相匹配
FETCH
。
如果没有更多行可用,则SQLSTATE值将出现No Data条件
'02000'
。
要检测此情况,您可以为它(或
NOT FOUND
条件)
设置处理程序
。
有关示例,请参见
第13.6.6节“游标”
。
请注意,另一个操作(例如a
SELECT
或其他操作
FETCH
)也可能通过引发相同的条件来使处理程序执行。
如果有必要区分哪个操作引发了条件,则将操作放在其自己的
BEGIN ...
END
块中,以便它可以与其自己的处理程序相关联。
在存储的程序执行期间可能出现需要特殊处理的条件,例如退出当前程序块或继续执行。 可以针对一般条件(例如警告或异常)或特定条件(例如特定错误代码)定义处理程序。 可以为特定条件指定名称并在处理程序中以这种方式引用。
要命名条件,请使用该
DECLARE ...
CONDITION
语句。
要声明处理程序,请使用该
DECLARE ...
HANDLER
语句。
请参见
第13.6.7.1节“DECLARE ... CONDITION语法”
和
第13.6.7.2节“DECLARE ... HANDLER语法”
。
有关服务器在发生条件时如何选择处理程序的信息,请参见
第13.6.7.6节“处理程序的范围规则”
。
要提出条件,请使用该
SIGNAL
语句。
要修改条件处理程序中的条件信息,请使用
RESIGNAL
。
请参见
第13.6.7.1节“DECLARE ... CONDITION语法”
和
第13.6.7.2节“DECLARE ... HANDLER语法”
。
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS
语句(请参见
第13.6.7.3节“获取诊断语法”
)。
有关诊断区域的信息,请参见
第13.6.7.7节“MySQL诊断区域”
。
申请condition_name
条件condition_value
condition_value
:{mysql_error_code
| SQLSTATE [VALUE]sqlstate_value
}
该
DECLARE
... CONDITION
语句声明了一个命名错误条件,将名称与需要特定处理的条件相关联。
该名称可在后续
DECLARE ...
HANDLER
语句中
引用
(请参见
第13.6.7.2节“DECLARE ... HANDLER语法”
)。
条件声明必须出现在游标或处理程序声明之前。
该
condition_value
用于
DECLARE ...
CONDITION
指示条件与条件名称关联的特定条件或类。
它可以采取以下形式:
mysql_error_code
:表示MySQL错误代码的整数文字。
不要使用MySQL错误代码0,因为它表示成功而不是错误条件。 有关MySQL错误代码的列表,请参见 第B.3.1节“服务器错误消息参考” 。
SQLSTATE [VALUE]
sqlstate_value
:一个5个字符的字符串文字,表示SQLSTATE值。
不要使用以开头的SQLSTATE值,
'00'
因为这些
值
表示成功而不是错误条件。
有关SQLSTATE值的列表,请参见
第B.3.1节“服务器错误消息参考”
。
在
SIGNAL
或使用
RESIGNAL
语句中
引用的条件名称
必须与SQLSTATE值相关联,而不是与MySQL错误代码相关联。
使用条件名称可以帮助使存储的程序代码更清晰。 例如,此处理程序适用于删除不存在的表的尝试,但只有当您知道1051是 “ 未知表 ” 的MySQL错误代码时才会显现 :
宣布继续使用1051的HANDLER 开始 - 处理者的身体 结束;
通过声明条件的名称,更容易看到处理程序的目的:
DECLARE no_such_table 1051条件; 为no_such_table声明CONTINUE HANDLER 开始 - 处理者的身体 结束;
以下是相同条件的命名条件,但是基于相应的SQLSTATE值而不是MySQL错误代码:
为SQLSTATE'42S02'声明no_such_table条件; 为no_such_table声明CONTINUE HANDLER 开始 - 处理者的身体 结束;
宣布handler_action
HANDLER FORcondition_value
[,condition_value
] ......statement
handler_action
:{ 继续 | 出口 | UNDO }condition_value
:{mysql_error_code
| SQLSTATE [VALUE]sqlstate_value
|condition_name
| SQLWARNING | 未找到 | SQLEXCEPTION }
该
DECLARE ...
HANDLER
语句指定处理一个或多个条件的处理程序。
如果出现这些条件之一,则
statement
执行
指定的操作
。
statement
可以是一个简单的语句,例如
,或使用
和
编写的复合语句
(参见
第13.6.1节“BEGIN ... END复合语句语法”
)。
SET
var_name
=
value
BEGIN
END
处理程序声明必须出现在变量或条件声明之后。
该
handler_action
值指示执行处理程序语句后处理程序执行的操作:
CONTINUE
:继续执行当前程序。
EXIT
:执行终止为
BEGIN ...
END
声明处理程序
的
复合语句。
即使条件发生在内部块中也是如此。
UNDO
: 不支持。
的
condition_value
用于
DECLARE ...
HANDLER
表明激活处理程序中的特定条件或一类的条件。
它可以采取以下形式:
mysql_error_code
:一个整数文字,表示MySQL错误代码,例如1051指定
“
未知表
”
:
宣布继续使用1051的HANDLER 开始 - 处理者的身体 结束;
不要使用MySQL错误代码0,因为它表示成功而不是错误条件。 有关MySQL错误代码的列表,请参见 第B.3.1节“服务器错误消息参考” 。
SQLSTATE [VALUE]
sqlstate_value
:一个5个字符的字符串文字,表示SQLSTATE值,例如
'42S01'
指定
“
unknown table
”
:
为SQLSTATE'42S02'声明继续HANDLER 开始 - 处理者的身体 结束;
不要使用以开头的SQLSTATE值,
'00'
因为这些
值
表示成功而不是错误条件。
有关SQLSTATE值的列表,请参见
第B.3.1节“服务器错误消息参考”
。
condition_name
:先前使用的条件名称
DECLARE
... CONDITION
。
条件名称可以与MySQL错误代码或SQLSTATE值相关联。
请参见
第13.6.7.1节“DECLARE ... CONDITION语法”
。
SQLWARNING
:以SQLSTATE值开头的类的简写
'01'
。
用于SQLWARNING的DECLARE CONTINUE HANDLER 开始 - 处理者的身体 结束;
NOT FOUND
:以SQLSTATE值开头的类的简写
'02'
。
这与游标的上下文相关,用于控制光标到达数据集末尾时发生的情况。
如果没有更多行可用,则SQLSTATE值将出现No Data条件
'02000'
。
要检测此情况,您可以为其或
NOT FOUND
条件
设置处理程序
。
DECLARE CONTINUE HANDLER未找到 开始 - 处理者的身体 结束;
有关另一个示例,请参见
第13.6.6节“游标”
。
NOT FOUND
对于
不检索任何行的语句,
也会出现
这种
情况
。
SELECT ... INTO
var_list
SQLEXCEPTION
:速记类SQLSTATE值不开头
'00'
,
'01'
或
'02'
。
DECLARE CONTINUE HANDLER用于SQLEXCEPTION 开始 - 处理者的身体 结束;
有关服务器在发生条件时如何选择处理程序的信息,请参见 第13.6.7.6节“处理程序的范围规则” 。
如果发生没有声明处理程序的条件,则采取的操作取决于条件类:
以下示例使用处理程序
SQLSTATE
'23000'
,出现重复键错误:
MySQL的>CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
查询正常,0行受影响(0.00秒) MySQL的>delimiter //
MySQL的>CREATE PROCEDURE handlerdemo ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
SET @x = 1;
INSERT INTO test.t VALUES (1);
SET @x = 2;
INSERT INTO test.t VALUES (1);
SET @x = 3;
END;
//
查询正常,0行受影响(0.00秒) MySQL的>CALL handlerdemo()//
查询正常,0行受影响(0.00秒) MySQL的>SELECT @x//
+ ------ + | @x | + ------ + | 3 | + ------ + 1排(0.00秒)
注意
@x
是
3
在过程执行之后,这表明执行继续该过程的结束发生错误之后。
如果该
DECLARE ...
HANDLER
语句不存在,MySQL会
因为
约束
而
EXIT
在第二次
INSERT
失败
后
采取默认的action(
)
PRIMARY KEY
,并且
SELECT @x
会返回
2
。
要忽略条件,请
CONTINUE
为其
声明
处理程序并将其与空块关联。
例如:
用于SQLWARNING的DECLARE CONTINUE HANDLER开始结束;
块标签的范围不包括块内声明的处理程序的代码。
因此,与处理程序关联的语句不能使用
ITERATE
或
LEAVE
引用包含处理程序声明的块的标签。
请考虑以下示例,其中
REPEAT
块的标签为
retry
:
CREATE PROCEDURE p() 开始 DECLARE i INT DEFAULT 3; 重试: 重复 开始 用于SQLWARNING的DECLARE CONTINUE HANDLER 开始 ITERATE重试; #违法 结束; 如果我<0那么 LEAVE重试; #legal 万一; SET i = i - 1; 结束; 直到最后重复; 结束;
该
retry
标签的范围是在
IF
块内声明。
它不在
CONTINUE
处理程序的
范围内
,因此引用无效并导致错误:
ERROR 1308(42000):LEAVE没有匹配的标签:重试
要避免在处理程序中引用外部标签,请使用以下策略之一:
要离开块,请使用
EXIT
处理程序。
如果不需要块清理,则
BEGIN ...
END
处理程序主体可以为空:
用于SQLWARNING的DECLARE EXIT HANDLER开始结束;
否则,将清理语句放在处理程序体中:
用于SQLWARNING的DECLARE EXIT HANDLER
开始
block cleanup statements
结束;
要继续执行,请在
CONTINUE
可在封闭块中检查
的
处理程序中
设置状态变量,
以确定是否已调用处理程序。
以下示例将此变量
done
用于此目的:
CREATE PROCEDURE p() 开始 DECLARE i INT DEFAULT 3; DECLARE完成INT DEFAULT FALSE; 重试: 重复 开始 用于SQLWARNING的DECLARE CONTINUE HANDLER 开始 SET done = TRUE; 结束; 如果完成或者我<0那么 LEAVE重试; 万一; SET i = i - 1; 结束; 直到最后重复; 结束;
获取[当前| 堆积]诊断 {statement_information_item
[,statement_information_item
] ...... | 条件 [,] ......condition_number
condition_information_item
condition_information_item
}statement_information_item
:target
=statement_information_item_name
condition_information_item
:target
=condition_information_item_name
statement_information_item_name
: 数 | ROW_COUNTcondition_information_item_name
:{ CLASS_ORIGIN | SUBCLASS_ORIGIN | RETURNED_SQLSTATE | MESSAGE_TEXT | MYSQL_ERRNO | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAME }condition_number
,target
: (见下面的讨论)
SQL语句生成填充诊断区域的诊断信息。
该
GET
DIAGNOSTICS
语句使应用程序可以检查此信息。
(您也可以使用
SHOW
WARNINGS
或
SHOW
ERRORS
查看条件或错误。)
执行时无需特殊权限
GET DIAGNOSTICS
。
关键字
CURRENT
表示从当前诊断区域检索信息。
关键字
STACKED
表示从第二个诊断区域检索信息,该信息仅在当前上下文是条件处理程序时可用。
如果没有给出关键字,则默认使用当前诊断区域。
该
GET DIAGNOSTICS
语句通常用于存储程序中的处理程序。
它是一个MySQL扩展,
GET [CURRENT]
DIAGNOSTICS
允许在处理程序上下文之外检查任何SQL语句的执行。
例如,如果调用
mysql
客户端程序,则可以在提示符下输入以下语句:
MySQL的>DROP TABLE test.no_such_table;
ERROR 1051(42S02):未知表'test.no_such_table' mysql> mysql>GET DIAGNOSTICS CONDITION 1
@p1 = RETURNED_SQLSTATE, @p2 = MESSAGE_TEXT;
SELECT @p1, @p2;
+ ------- + ------------------------------------ + | @ p1 | @ p2 | + ------- + ------------------------------------ + | 42S02 | 未知表'test.no_such_table'| + ------- + ------------------------------------ +
此扩展仅适用于当前诊断区域。
它不适用于第二个诊断区域,因为
GET STACKED DIAGNOSTICS
仅当当前上下文是条件处理程序时才允许。
如果不是这种情况,
GET STACKED DIAGNOSTICS when handler not
active
则会发生错误。
有关诊断区域的说明,请参见 第13.6.7.7节“MySQL诊断区域” 。 简而言之,它包含两种信息:
语句信息,例如发生的条件数或受影响的行数。
条件信息,例如错误代码和消息。 如果语句引发多个条件,则诊断区域的这一部分具有每个条件区域。 如果语句没有引发任何条件,则诊断区域的这一部分为空。
对于产生三个条件的语句,诊断区域包含语句和条件信息,如下所示:
声明信息: 行数 ......其他声明信息项...... 条件区域列表: 条件范围1: 条件1的错误代码 条件1的错误消息 ......其他条件信息...... 条件区域2: 条件2的错误代码: 条件2的错误消息 ......其他条件信息...... 条件范围3: 条件3的错误代码 条件3的错误消息 ......其他条件信息......
GET
DIAGNOSTICS
可以获取语句或条件信息,但不能同时在同一语句中获取:
要获取语句信息,请将所需的语句项检索到目标变量中。
此实例
GET DIAGNOSTICS
将可用条件数和受行影响的计数分配给用户变量,
@p1
并且
@p2
:
获取诊断@ p1 = NUMBER,@ p2 = ROW_COUNT;
要获取条件信息,请指定条件编号并将所需的条件项检索到目标变量中。
此实例
GET
DIAGNOSTICS
将SQLSTATE值和错误消息分配给用户变量,
@p3
并且
@p4
:
获得诊断条件1 @ p3 = RETURNED_SQLSTATE,@ p4 = MESSAGE_TEXT;
检索列表指定一个或多个
分配,以逗号分隔。
每个赋值都命名一个目标变量和一个
或
一个
指示符,具体取决于语句是否检索语句或条件信息。
target
=
item_name
statement_information_item_name
condition_information_item_name
target
用于存储项目信息的
有效
指示符可以是存储过程或函数参数,用其声明的存储的程序局部变量
DECLARE
或用户定义的变量。
有效的
condition_number
指示符可以是存储过程或函数参数,存储的程序本地变量
DECLARE
,用户定义的变量,系统变量或文字。
字符文字可以包括
_charset
介绍人。
如果条件编号不在1到具有信息的条件区域的数量范围内,则会发出警告。
在这种情况下,警告将添加到诊断区域而不清除它。
当条件发生时,MySQL不会填充所识别的所有条件项
GET
DIAGNOSTICS
。
例如:
mysql> mysql>GET DIAGNOSTICS CONDITION 1
@p5 = SCHEMA_NAME, @p6 = TABLE_NAME;
SELECT @p5, @p6;
+ ------ + ------ + | @ p5 | @ p6 | + ------ + ------ + | | | + ------ + ------ +
在标准SQL中,如果有多个条件,则第一个条件与
SQLSTATE
前一个SQL语句返回
的
值相关。
在MySQL中,这不能保证。
要获得主要错误,您无法执行此操作:
获得诊断条件1 @errno = MYSQL_ERRNO;
相反,首先检索条件计数,然后使用它来指定要检查的条件数:
获取诊断@cno = NUMBER; 获得诊断条件@cno @errno = MYSQL_ERRNO;
有关允许的语句和条件信息项以及发生条件时填充的 信息的信息 ,请参阅“ 诊断区域信息项” 。
下面是一个示例,它使用
GET
DIAGNOSTICS
存储过程上下文中的异常处理程序来评估插入操作的结果。
如果插入成功,则该过程用于
GET DIAGNOSTICS
获取受行影响的计数。
这表明
GET DIAGNOSTICS
只要尚未清除当前诊断区域
,您就可以
多次
使用
来检索有关语句的信息。
CREATE PROCEDURE do_insert(值INT) 开始 - 声明变量以保存诊断区域信息 DECLARE代码CHAR(5)DEFAULT'00000'; DECLARE msg TEXT; DECLARE行INT; DECLARE结果TEXT; - 为失败的插入声明异常处理程序 DECLARE CONTINUE HANDLER用于SQLEXCEPTION 开始 获得诊断条件1 code = RETURNED_SQLSTATE,msg = MESSAGE_TEXT; 结束; - 执行插入 INSERT INTO t1(int_col)VALUES(value); - 检查插入是否成功 IF代码='00000'然后 GET DIAGNOSTICS行= ROW_COUNT; SET result = CONCAT('insert succeeded,row count =',rows); 其他 SET result = CONCAT('insert failed,error =',code,',message =',msg); 万一; - 说出发生了什么 SELECT结果; 结束;
假设这
t1.int_col
是一个声明为的整数列
NOT NULL
。
在调用插入非
值
NULL
和
NULL
值时,
该过程会产生这些结果
:
MySQL的>CALL do_insert(1);
+ --------------------------------- + | 结果| + --------------------------------- + | 插入成功,行计数= 1 | + --------------------------------- + MySQL的>CALL do_insert(NULL);
+ ------------------------------------------------- ------------------------ + | 结果| + ------------------------------------------------- ------------------------ + | 插入失败,错误= 23000,消息=列'int_col'不能为空| + ------------------------------------------------- ------------------------ +
当条件处理程序激活时,会发生对诊断区域堆栈的推送:
第一个(当前)诊断区域成为第二个(堆叠)诊断区域,并创建一个新的当前诊断区域作为其副本。
GET
[CURRENT] DIAGNOSTICS
并且
GET STACKED
DIAGNOSTICS
可以在处理程序中使用以访问当前和堆叠诊断区域的内容。
最初,两个诊断区域都返回相同的结果,因此可以从当前诊断区域获取有关激活处理程序的条件的信息, 只要 在处理程序中不执行任何更改其当前诊断区域的语句即可。
但是,在处理程序中执行的语句可以修改当前诊断区域,根据常规规则清除和设置其内容(请参阅 如何清除和填充诊断区域 )。
获取有关处理程序激活条件的信息的更可靠方法是使用堆栈诊断区域,除了处理程序中执行的语句不能修改该区域
RESIGNAL
。
有关何时设置和清除当前诊断区域的信息,请参见
第13.6.7.7节“MySQL诊断区域”
。
下一个示例显示了如何
GET STACKED
DIAGNOSTICS
在处理程序中使用
如何
获取有关已处理异常的信息,即使在当前诊断区域已被处理程序语句修改之后也是如此。
在存储过程中
p()
,我们尝试将两个值插入到包含
TEXT NOT
NULL
列
的表中
。
第一个值是非
NULL
字符串,第二个值是
NULL
。
该列禁止
NULL
值,因此第一个插入成功但第二个插入导致异常。
该过程包括一个异常处理程序,用于映射尝试插入
NULL
空字符串的插入:
DROP TABLE IF EXISTS t1; CREATE TABLE t1(c1 TEXT NOT NULL); DROP程序如果存在p; 分隔符// CREATE PROCEDURE p() 开始 - 声明变量以保存诊断区域信息 DECLARE errcount INT; DECLARE errno INT; DECLARE msg TEXT; DECLARE EXIT HANDLER用于SQLEXCEPTION 开始 - 这里当前的DA是非空的,因为没有先前的陈述 - 在处理程序中执行已清除它 获得当前的诊断条件1 errno = MYSQL_ERRNO,msg = MESSAGE_TEXT; 在映射插入之前选择'当前DA'AS op,errno,msg; 获得堆叠的诊断条件1 errno = MYSQL_ERRNO,msg = MESSAGE_TEXT; SELECT'在映射插入之前堆叠DA'AS op,errno,msg; - 映射尝试NULL插入到空字符串插入 INSERT INTO t1(c1)VALUES(''); - 这里当前DA应为空(如果INSERT成功), - 所以在尝试之前检查是否有条件 - 获取条件信息 获取当前诊断errcount = NUMBER; 如果errcount = 0 然后 SELECT'映射插入成功,当前DA为空'AS op; 其他 获得当前的诊断条件1 errno = MYSQL_ERRNO,msg = MESSAGE_TEXT; 映射插入后选择'当前DA'AS op,errno,msg; 万一 ; 获得堆叠的诊断条件1 errno = MYSQL_ERRNO,msg = MESSAGE_TEXT; 在映射插入后选择'堆叠DA'AS op,errno,msg; 结束; INSERT INTO t1(c1)VALUES('string 1'); INSERT INTO t1(c1)VALUES(NULL); 结束; // 分隔符; CALL p(); SELECT * FROM t1;
处理程序激活时,当前诊断区域的副本将被推送到诊断区域堆栈。 处理程序首先显示当前和堆叠诊断区域的内容,这两个区域最初都是相同的:
+ --------------------------------- + ------- ------- + --------------------- + | op | errno | 消息| + --------------------------------- + ------- ------- + --------------------- + | 映射插入前的当前DA | 1048 | 列'c1'不能为空| + --------------------------------- + ------- ------- + --------------------- + + --------------------------------- + ------- ------- + --------------------- + | op | errno | 消息| + --------------------------------- + ------- ------- + --------------------- + | 在映射插入之前堆叠DA | 1048 | 列'c1'不能为空| + --------------------------------- + ------- ------- + --------------------- +
语句后执行的
GET
DIAGNOSTICS
语句可能会重置当前诊断区域。
语句可能会重置当前的诊断区域。
例如,处理程序将
NULL
插入
映射
到空字符串插入并显示结果。
新插入成功并清除当前诊断区域,但堆栈诊断区域保持不变,并且仍包含有关激活处理程序的条件的信息:
+ ---------------------------------------------- + | op | + ---------------------------------------------- + | 映射插入成功,当前DA为空| + ---------------------------------------------- + + -------------------------------- + ------- -------- + -------------------- + | op | errno | 消息| + -------------------------------- + ------- -------- + -------------------- + | 映射插入后堆叠DA | 1048 | 列'c1'不能为空| + -------------------------------- + ------- -------- + -------------------- +
条件处理程序结束时,其当前诊断区域将从堆栈中弹出,堆叠的诊断区域将成为存储过程中的当前诊断区域。
该过程返回后,该表包含两行。
尝试插入
NULL
映射到空字符串插入
的空行产生
:
+ ---------- + | c1 | + ---------- + | string 1 | | | + ---------- +
在前面的示例中,
GET
DIAGNOSTICS
条件处理程序中从当前和堆栈诊断区域检索信息
的前两个
语句返回相同的值。
如果重置当前诊断区域的语句在处理程序中较早执行,则情况不会出现这种情况。
假设
p()
重写它以将
DECLARE
语句放在处理程序定义中而不是在它之前:
CREATE PROCEDURE p() 开始 DECLARE EXIT HANDLER用于SQLEXCEPTION 开始 - 声明变量以保存诊断区域信息 DECLARE errcount INT; DECLARE errno INT; DECLARE msg TEXT; 获得当前的诊断条件1 errno = MYSQL_ERRNO,msg = MESSAGE_TEXT; 在映射插入之前选择'当前DA'AS op,errno,msg; 获得堆叠的诊断条件1 errno = MYSQL_ERRNO,msg = MESSAGE_TEXT; SELECT'在映射插入之前堆叠DA'AS op,errno,msg; ...
在这种情况下,结果取决于版本:
在MySQL 5.7.2之前,
DECLARE
不会更改当前的诊断区域,因此前两个
GET DIAGNOSTICS
语句返回相同的结果,就像在原始版本中一样
p()
。
在MySQL 5.7.2中,完成了一项工作,以确保所有非诊断语句按照SQL标准填充诊断区域。
DECLARE
是其中之一,所以在5.7.2及更高版本中,
DECLARE
在处理程序开头执行的语句清除了当前的诊断区域和
GET
DIAGNOSTICS
语句产生不同的结果:
+ --------------------------------- + ------- + ------ + | op | errno | 消息| + --------------------------------- + ------- + ------ + | 映射插入前的当前DA | NULL | NULL | + --------------------------------- + ------- + ------ + + --------------------------------- + ------- ------- + --------------------- + | op | errno | 消息| + --------------------------------- + ------- ------- + --------------------- + | 在映射插入之前堆叠DA | 1048 | 列'c1'不能为空| + --------------------------------- + ------- ------- + --------------------- +
要在获取有关激活处理程序的条件的信息时在条件处理程序中避免此问题,请确保访问堆栈诊断区域,而不是当前诊断区域。
RESIGNAL [condition_value
] [SETsignal_information_item
[,signal_information_item
] ...]condition_value
:{ SQLSTATE [VALUE]sqlstate_value
|condition_name
}signal_information_item
:condition_information_item_name
=simple_value_specification
condition_information_item_name
:{ CLASS_ORIGIN | SUBCLASS_ORIGIN | MESSAGE_TEXT | MYSQL_ERRNO | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAME }condition_name
,simple_value_specification
: (见下面的讨论)
RESIGNAL
传递在存储过程或函数,触发器或事件内的复合语句中执行条件处理程序期间可用的错误条件信息。
RESIGNAL
可能会在传递之前更改部分或全部信息。
RESIGNAL
有关
SIGNAL
,但,而不是发起条件的
SIGNAL
呢,
RESIGNAL
继电器现有条件信息,有可能修改之后。
RESIGNAL
可以处理错误并返回错误信息。
否则,通过在处理程序中执行SQL语句,会导致导致处理程序激活的信息被破坏。
RESIGNAL
如果给定的处理程序可以处理部分情况,那么也可以使某些程序更短,然后将条件
“
上线
”
传递给另一个处理程序。
执行
RESIGNAL
语句
不需要任何特权
。
所有形式的
RESIGNAL
要求当前上下文是条件处理程序。
否则,
RESIGNAL
是非法的并且发生
RESIGNAL when handler not active
错误。
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS
语句(请参见
第13.6.7.3节“获取诊断语法”
)。
有关诊断区域的信息,请参见
第13.6.7.7节“MySQL诊断区域”
。
对于
condition_value
和
signal_information_item
,定义和规则是相同
RESIGNAL
的
SIGNAL
。
例如,
condition_value
可以是
SQLSTATE
值,值可以指示错误,警告或
“
未找到”。
“
有关其他信息,请参见
第13.6.7.5节”SIGNAL语法“
。
该
RESIGNAL
声明将
condition_value
和
SET
这两个条款,是可选的。
这导致了几种可能的用途:
这些用例都会导致诊断和条件区域发生变化:
诊断区域包含一个或多个条件区域。
条件区域包含条件信息项,例如
SQLSTATE
值
MYSQL_ERRNO
,或
MESSAGE_TEXT
。
有一堆诊断区域。 当处理程序获得控制权时,它会将诊断区域推送到堆栈顶部,因此在处理程序执行期间有两个诊断区域:
第一个(当前)诊断区域,作为最后一个诊断区域的副本启动,但将被处理程序中第一个更改当前诊断区域的语句覆盖。
最后(堆叠)诊断区域,其具有在处理程序获得控制之前设置的条件区域。
诊断区域中条件区域的最大数量由
max_error_count
系统变量
的值确定
。
请参阅与
诊断区域相关的系统变量
。
一个简单的
RESIGNAL
单独意味着
“
传递错误而不做任何改变。
“
它恢复了最后的诊断区域并使其成为当前的诊断区域。
也就是说,它
“
弹出
”
诊断区域堆栈。
在捕获条件的条件处理程序中,
RESIGNAL
单独
使用
一个是执行一些其他操作,然后传递而不更改原始条件信息(在进入处理程序之前存在的信息)。
例:
DROP TABLE IF EXISTS xx; 分隔符// CREATE PROCEDURE p() 开始 DECLARE EXIT HANDLER用于SQLEXCEPTION 开始 SET @error_count = @error_count + 1; 如果@a = 0那么RESIGNAL; 万一; 结束; DROP TABLE xx; 结束// 分隔符; SET @error_count = 0; SET @a = 0; CALL p();
假设
DROP TABLE xx
语句失败。
诊断区域堆栈如下所示:
DA 1. ERROR 1051(42S02):未知表'xx'
然后执行进入
EXIT
处理程序。
它首先将诊断区域推到堆栈顶部,现在看起来像这样:
DA 1. ERROR 1051(42S02):未知表'xx' DA 2. ERROR 1051(42S02):未知表'xx'
此时,第一(当前)和第二(堆叠)诊断区域的内容是相同的。 可以通过在处理程序内随后执行的语句来修改第一诊断区域。
通常,过程语句会清除第一个诊断区域。
BEGIN
是一个例外,它不清楚,它什么都不做。
SET
它不是一个例外,它会清除,执行操作并产生
“
成功
”
的结果
。
“
诊断区域堆栈现在看起来像这样:
DA 1. ERROR 0000(00000):成功运行 DA 2. ERROR 1051(42S02):未知表'xx'
在这一点上,如果
@a = 0
,
RESIGNAL
弹出诊断区栈,它现在看起来是这样的:
DA 1. ERROR 1051(42S02):未知表'xx'
这就是呼叫者所看到的。
如果
@a
不为0,则处理程序简单地结束,这意味着当前诊断区域(已被
“
处理
”
)
不再使用
,因此可以将其丢弃,从而使堆叠的诊断区域成为当前诊断区域再次。
诊断区域堆栈如下所示:
DA 1. ERROR 0000(00000):成功运行
细节使它看起来很复杂,但最终结果非常有用:处理程序可以执行而不会破坏有关导致处理程序激活的条件的信息。
RESIGNAL
带有一个
SET
子句提供新的信号信息,因此该语句的意思是
“
通过更改传递错误
”
:
RESIGNAL SETsignal_information_item
[,signal_information_item
] ......;
与
RESIGNAL
单独一样,想法是弹出诊断区域堆栈,以便原始信息熄灭。
与
RESIGNAL
单独
不同
,
SET
子句中
指定的任何内容都会
更改
例:
DROP TABLE IF EXISTS xx; 分隔符// CREATE PROCEDURE p() 开始 DECLARE EXIT HANDLER用于SQLEXCEPTION 开始 SET @error_count = @error_count + 1; IF @a = 0那么RESIGNAL SET MYSQL_ERRNO = 5; 万一; 结束; DROP TABLE xx; 结束// 分隔符; SET @error_count = 0; SET @a = 0; CALL p();
请记住,在前面的讨论中,
RESIGNAL
单独导致诊断区域堆栈如下:
DA 1. ERROR 1051(42S02):未知表'xx'
该
RESIGNAL SET MYSQL_ERRNO = 5
语句导致此堆栈,这是调用者看到的:
DA 1.错误5(42S02):未知表'xx'
换句话说,它改变了错误号,而没有别的。
该
RESIGNAL
语句可以改变任何或所有信号信息项,使诊断区域的第一个条件区域看起来完全不同。
RESIGNAL
条件值表示
“
将条件推入当前诊断区域。
“
如果
SET
子句存在,它也会更改错误信息。
RESIGNALcondition_value
[SETsignal_information_item
[,signal_information_item
] ...];
这种形式可以
RESIGNAL
恢复最后的诊断区域并使其成为当前的诊断区域。
也就是说,它
“
弹出
”
诊断区域堆栈,这与
RESIGNAL
单独执行
简单
操作相同。
但是,它还会根据条件值或信号信息更改诊断区域。
例:
DROP TABLE IF EXISTS xx; 分隔符// CREATE PROCEDURE p() 开始 DECLARE EXIT HANDLER用于SQLEXCEPTION 开始 SET @error_count = @error_count + 1; 如果@a = 0那么RESIGNAL SQLSTATE'45000'SET MYSQL_ERRNO = 5; 万一; 结束; DROP TABLE xx; 结束// 分隔符; SET @error_count = 0; SET @a = 0; SET @@ max_error_count = 2; CALL p(); 显示错误;
这与前面的示例类似,效果是相同的,除非
RESIGNAL
发生这种情况,当前条件区域在结尾处看起来不同。
(条件添加而不是替换现有条件的原因是使用条件值。)
该
RESIGNAL
语句包含条件值(
SQLSTATE '45000'
),因此它添加了一个新的条件区域,从而产生如下所示的诊断区域堆栈:
DA 1.(条件2)ERROR 1051(42S02):未知表'xx' (条件1)错误5(45000)未知表'xx'
结果
CALL
p()
和
SHOW
ERRORS
这个例子是:
MySQL的>CALL p();
错误5(45000):未知表'xx' MySQL的>SHOW ERRORS;
+ ------- + ------ + ---------------------------------- + | 等级| 代码| 消息| + ------- + ------ + ---------------------------------- + | 错误| 1051 | 未知表'xx'| | 错误| 5 | 未知表'xx'| + ------- + ------ + ---------------------------------- +
所有形式的
RESIGNAL
要求当前上下文是条件处理程序。
否则,
RESIGNAL
是非法的并且发生
RESIGNAL when handler not active
错误。
例如:
MySQL的>CREATE PROCEDURE p () RESIGNAL;
查询正常,0行受影响(0.00秒) MySQL的>CALL p();
ERROR 1645(0K000):处理程序未激活时的RESIGNAL
这是一个更难的例子:
分隔符// 创建功能f()返回INT 开始 RESIGNAL; 返回5; 结束// CREATE PROCEDURE p() 开始 DECLARE EXIT HANDLER for SQLEXCEPTION SET @ a = f(); SIGNAL SQLSTATE'55555'; 结束// 分隔符; CALL p();
RESIGNAL
发生在存储的函数中
f()
。
虽然
f()
它本身是在
EXIT
处理程序
的上下文中调用的
,但是其中的执行
f()
具有自己的上下文,而不是处理程序上下文。
因此,
RESIGNAL
内
f()
中一个结果
“
处理程序不活跃
”
的错误。
SIGNALcondition_value
[SETsignal_information_item
[,signal_information_item
] ...]condition_value
:{ SQLSTATE [VALUE]sqlstate_value
|condition_name
}signal_information_item
:condition_information_item_name
=simple_value_specification
condition_information_item_name
:{ CLASS_ORIGIN | SUBCLASS_ORIGIN | MESSAGE_TEXT | MYSQL_ERRNO | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAME }condition_name
,simple_value_specification
: (见下面的讨论)
SIGNAL
是
“
返回
”
错误的方法。
SIGNAL
向处理程序,应用程序的外部部分或客户端提供错误信息。
此外,它还可以控制错误的特征(错误号,
SQLSTATE
值,消息)。
如果没有
SIGNAL
,则必须采用诸如故意引用不存在的表之类的变通方法来导致例程返回错误。
执行
SIGNAL
语句
不需要任何特权
。
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS
语句(请参见
第13.6.7.3节“获取诊断语法”
)。
有关诊断区域的信息,请参见
第13.6.7.7节“MySQL诊断区域”
。
在
condition_value
一个
SIGNAL
声明中表示要返回错误值。
它可以是一个
SQLSTATE
值(一个5个字符的字符串文字)或一个
condition_name
引用之前定义的命名条件
DECLARE ...
CONDITION
(参见
第13.6.7.1节“DECLARE ... CONDITION语法”)
)。
一个
SQLSTATE
值可以指示错误,警告或
“
未找到。
“值
的前两个字符表示其错误类,如
信号条件信息项中所述
。
某些信号值导致语句终止;
请参阅
信号对处理程序,游标和语句的影响
。
语句
的
SQLSTATE
值
SIGNAL
不应该以,
'00'
因为这些值表示成功,并且对于发出错误信号无效。
无论
SQLSTATE
是直接在
SIGNAL
语句中还是在语句中引用的命名条件中
指定值,
都是如此
。
如果该值无效,
Bad SQLSTATE
则会发生错误。
为了用信号的通用
SQLSTATE
值,使用
'45000'
,这意味着
“
未处理用户定义的异常。
”
该
SIGNAL
语句可选地包括一个
SET
子句,
该
子句包含多个信号项,在
condition_information_item_name
=
simple_value_specification
赋值
列表中
,以逗号分隔。
每个
条款中
condition_information_item_name
只能指定一次
SET
。
否则,
Duplicate condition information
item
会发生错误。
simple_value_specification
可以使用存储过程或函数参数,声明的存储程序局部变量
DECLARE
,用户定义变量,系统变量或文字
来指定
有效的
指示符
。
字符文字可以包括
_charset
介绍人。
有关允许
condition_information_item_name
值的
信息
,请参阅
信号条件信息项
。
以下过程根据
pval
其输入参数
的值发出错误或警告信号
:
CREATE PROCEDURE p(pval INT) 开始 DECLARE SQLSTATE'45000'的专业条件; 如果pval = 0那么 SIGNAL SQLSTATE'01000'; ELSEIF pval = 1那么 SIGNAL SQLSTATE'45000' SET MESSAGE_TEXT ='发生错误'; ELSEIF pval = 2那么 SIGNAL专业 SET MESSAGE_TEXT ='发生错误'; 其他 SIGNAL SQLSTATE'01000' SET MESSAGE_TEXT ='发生警告',MYSQL_ERRNO = 1000; SIGNAL SQLSTATE'45000' SET MESSAGE_TEXT ='发生错误',MYSQL_ERRNO = 1001; 万一; 结束;
如果
pval
为0,则
p()
发出警告,因为以
SQLSTATE
值开头的值是
'01'
警告类中的信号。
警告不会终止该过程,并且可以
SHOW
WARNINGS
在过程返回后
看到
。
如果
pval
为1,则
p()
表示错误并设置
MESSAGE_TEXT
条件信息项。
该错误终止该过程,并返回带有错误信息的文本。
如果
pval
为2,则发出相同的错误信号,尽管
SQLSTATE
在这种情况下使用命名条件指定值。
如果
pval
是其他任何内容,请
p()
首先发出警告并设置消息文本和错误编号条件信息项。
此警告不会终止该过程,因此继续执行
p()
然后发出错误信号。
该错误会终止该过程。
警告设置的消息文本和错误编号将替换为错误设置的值,这些值随错误信息一起返回。
SIGNAL
通常在存储的程序中使用,但它是一个MySQL扩展,它允许在处理程序上下文之外。
例如,如果调用
mysql
客户端程序,则可以在提示符处输入以下任何语句:
SIGNAL SQLSTATE'77777'; 在插入之前创建触发器t_bi 对于每个行信号SQLSTATE'777777'; 创造活动e每周一次安排 DO SIGNAL SQLSTATE'777777';
SIGNAL
根据以下规则执行:
如果
SIGNAL
语句指示特定
SQLSTATE
值,则该值用于表示指定的条件。
例:
CREATE PROCEDURE p(除数INT) 开始 IF divisor = 0那么 SIGNAL SQLSTATE'22012'; 万一; 结束;
如果
SIGNAL
语句使用命名条件,则必须在适用于该
SIGNAL
语句的
某个范围中声明该条件
,并且必须使用
SQLSTATE
值而不是MySQL错误号
来定义该条件
。
例:
CREATE PROCEDURE p(除数INT) 开始 DECLARE divide_by_zero CONDITION FOR SQLSTATE'22012'; IF divisor = 0那么 SIGNAL divide_by_zero; 万一; 结束;
如果在
SIGNAL
语句
范围内不存在命名条件
,
Undefined CONDITION
则会发生错误。
如果
SIGNAL
引用使用MySQL错误号而不是
SQLSTATE
值
定义的命名条件,
SIGNAL/RESIGNAL can only use a CONDITION defined with
SQLSTATE
则会发生错误。
以下语句导致该错误,因为命名条件与MySQL错误号相关联:
DECLARE no_such_table 1051条件; SIGNAL no_such_table;
如果具有给定名称的条件在不同范围内多次声明,则应用具有最大本地范围的声明。 请考虑以下过程:
CREATE PROCEDURE p(除数INT) 开始 为SQLSTATE'45000'声明my_error条件; IF divisor = 0那么 开始 为SQLSTATE'22012'声明my_error条件; SIGNAL my_error; 结束; 万一; SIGNAL my_error; 结束;
如果
divisor
为0,则
SIGNAL
执行
第一个
语句。
提出最内层的
my_error
条件声明
SQLSTATE
'22012'
。
如果
divisor
不为0,则
SIGNAL
执行
第二个
语句。
提出最外面的
my_error
条件声明
SQLSTATE
'45000'
。
有关服务器在发生条件时如何选择处理程序的信息,请参见 第13.6.7.6节“处理程序的范围规则” 。
可以在异常处理程序中引发信号:
CREATE PROCEDURE p() 开始 DECLARE EXIT HANDLER用于SQLEXCEPTION 开始 SIGNAL SQLSTATE VALUE'999999' SET MESSAGE_TEXT ='发生错误'; 结束; DROP TABLE no_such_table; 结束;
CALL p()
到达
DROP
TABLE
声明。
没有命名的表
no_such_table
,因此激活了错误处理程序。
错误处理程序破坏原始错误(
“
没有这样的表
”
)并使用
SQLSTATE
'99999'
和消息
产生新错误
An error occurred
。
下表列出了可以在
SIGNAL
(或
RESIGNAL
)语句中
设置的诊断区域条件信息项的名称
。
所有项目都是标准SQL,但
MYSQL_ERRNO
它是MySQL扩展。
有关这些项的更多信息,请参见
第13.6.7.7节“MySQL诊断区”
。
项目名称定义 --------- ---------- CLASS_ORIGIN VARCHAR(64) SUBCLASS_ORIGIN VARCHAR(64) CONSTRAINT_CATALOG VARCHAR(64) CONSTRAINT_SCHEMA VARCHAR(64) CONSTRAINT_NAME VARCHAR(64) CATALOG_NAME VARCHAR(64) SCHEMA_NAME VARCHAR(64) TABLE_NAME VARCHAR(64) COLUMN_NAME VARCHAR(64) CURSOR_NAME VARCHAR(64) MESSAGE_TEXT VARCHAR(128) MYSQL_ERRNO SMALLINT UNSIGNED
字符项的字符集是UTF-8。
NULL
在
SIGNAL
语句中
分配
条件信息项
是非法的
。
甲
SIGNAL
语句总是指定一个
SQLSTATE
值,或者直接地或间接地通过参照具有一个定义的命名条件
SQLSTATE
值。
值的前两个字符
SQLSTATE
是其类,类确定条件信息项的默认值:
等级=
'00'
(成功)
非法。
SQLSTATE
以...开头的值
'00'
表示成功且无效
SIGNAL
。
等级=
'01'
(警告)
MESSAGE_TEXT ='未处理的用户定义警告条件';
MYSQL_ERRNO = ER_SIGNAL_WARN
等级=
'02'
(未找到)
MESSAGE_TEXT ='未处理的用户定义的未找到条件';
MYSQL_ERRNO = ER_SIGNAL_NOT_FOUND
班级>
'02'
(例外)
MESSAGE_TEXT ='未处理的用户定义的异常条件';
MYSQL_ERRNO = ER_SIGNAL_EXCEPTION
对于合法类,其他条件信息项设置如下:
CLASS_ORIGIN = SUBCLASS_ORIGIN =''; CONSTRAINT_CATALOG = CONSTRAINT_SCHEMA = CONSTRAINT_NAME =''; CATALOG_NAME = SCHEMA_NAME = TABLE_NAME = COLUMN_NAME =''; CURSOR_NAME ='';
SIGNAL
执行
后可访问的错误值是
语句和
和
项
SQLSTATE
引发
的
值
。
这些值可从C API获得:
SIGNAL
MESSAGE_TEXT
MYSQL_ERRNO
mysql_sqlstate()
返回
SQLSTATE
值。
mysql_errno()
返回
MYSQL_ERRNO
值。
mysql_error()
返回
MESSAGE_TEXT
值。
在SQL级别,输出来自
SHOW
WARNINGS
和
SHOW
ERRORS
指示
和
列中的
值
MYSQL_ERRNO
和
MESSAGE_TEXT
值
。
Code
Message
要从诊断区域检索信息,请使用该
GET DIAGNOSTICS
语句(请参见
第13.6.7.3节“获取诊断语法”
)。
有关诊断区域的信息,请参见
第13.6.7.7节“MySQL诊断区域”
。
根据信号类,信号对语句执行有不同的影响。
该类确定错误的严重程度。
MySQL忽略
sql_mode
系统变量
的值
;
特别是严格的SQL模式并不重要。
MySQL也忽略了
IGNORE
:意图
SIGNAL
是明确地引发用户生成的错误,因此永远不会忽略信号。
在以下描述中,
“
未处理
”
表示没有
SQLSTATE
定义
信号
值的
处理程序
DECLARE ...
HANDLER
。
等级=
'00'
(成功)
非法。
SQLSTATE
以...开头的值
'00'
表示成功且无效
SIGNAL
。
等级=
'01'
(警告)
warning_count
系统变量
的值
上升。
SHOW
WARNINGS
显示信号。
SQLWARNING
处理程序捕获信号。
无法从存储的函数返回警告,因为
RETURN
导致函数返回
的
语句将清除诊断区域。
因此,该声明清除了可能存在的任何警告(并重置
warning_count
为0)。
等级=
'02'
(未找到)
NOT FOUND
处理程序捕获信号。
游标没有任何影响。
如果信号在存储函数中未处理,则语句结束。
班级>
'02'
(例外)
SQLEXCEPTION
处理程序捕获信号。
如果信号在存储函数中未处理,则语句结束。
等级=
'40'
被视为普通例外。
存储的程序可以包括当在程序内发生某些条件时要调用的处理程序。 每个处理程序的适用性取决于它在程序定义中的位置以及它处理的条件或条件:
在声明的处理程序
BEGIN ...
END
块的范围只为以下的块中的处理程序声明的SQL语句。
如果处理程序本身引发了一个条件,它就无法处理该条件,也无法在块中声明任何其他处理程序。
在以下示例中,处理程序
H1
和
H2
在范围为通过发言中提出的条件
stmt1
和
stmt2
。
但无论是
H1
也不
H2
在范围上,以在体内引发条件
H1
或
H2
。
开始 - 外块 DECLARE EXIT HANDLER for ...; - 处理程序H1 DECLARE EXIT HANDLER for ...; - 处理程序H2stmt1
;stmt2
; 结束;
处理程序仅在声明它的块的范围内,并且对于在该块之外发生的条件不能被激活。
在以下示例中,handler
H1
在
stmt1
内部块的
范围
内,但不在
stmt2
外部块中:
开始 - 外块 开始 - 内部块 DECLARE EXIT HANDLER for ...; - 处理程序H1stmt1
; 结束;stmt2
; 结束;
处理程序可以是特定的或一般的。
特定处理程序用于MySQL错误代码,
SQLSTATE
值或条件名称。
一般的处理程序是用于在一个状态
SQLWARNING
,
SQLEXCEPTION
或
NOT
FOUND
类。
条件特异性与条件优先级相关,如稍后所述。
可以在不同的范围和不同的特性声明多个处理程序。
例如,外部块中可能存在特定的MySQL错误代码处理程序,而
SQLWARNING
内部块中可能
存在常规
处理程序。
或者可能存在特定MySQL错误代码和
SQLWARNING
同一块中
的通用
类的
处理程序
。
是否激活处理程序不仅取决于其自身的范围和条件值,还取决于其他处理程序的存在。
当存储的程序中出现条件时,服务器在当前范围(当前
BEGIN ...
END
块)中
搜索适用的处理程序
。
如果没有适用的处理程序,则在每个连续的包含范围(块)中使用处理程序向外继续搜索。
当服务器在给定范围内找到一个或多个适用的处理程序时,它会根据条件优先级在其中选择:
MySQL错误代码处理程序优先于
SQLSTATE
值处理程序。
一个
SQLSTATE
值处理程序优先于一般
SQLWARNING
,
SQLEXCEPTION
或
NOT
FOUND
处理程序。
一个
SQLEXCEPTION
处理程序优先于
SQLWARNING
处理程序。
可以有几个具有相同优先级的适用处理程序。 例如,语句可以生成具有不同错误代码的多个警告,对于每个错误代码,存在特定于错误的处理程序。 在这种情况下,服务器激活哪个处理程序的选择是不确定的,并且可能根据条件发生的环境而改变。
处理程序选择规则的一个含义是,如果多个适用的处理程序出现在不同的作用域中,则具有最多本地作用域的处理程序优先于外部作用域中的处理程序,甚至优先于更具体条件的处理程序。
如果条件发生时没有适当的处理程序,则采取的操作取决于条件的类:
以下示例演示了MySQL如何应用处理程序选择规则。
此过程包含两个处理程序,一个用于
尝试删除不存在的表时发生
的特定
SQLSTATE
值(
'42S02'
),另一个用于常规
SQLEXCEPTION
类:
CREATE PROCEDURE p1() 开始 为SQLSTATE'42S02'声明继续HANDLER SELECT'SQLSTATE处理程序已激活'AS msg; DECLARE CONTINUE HANDLER用于SQLEXCEPTION SELECT'SQLEXCEPTION处理程序已激活'AS msg; DROP TABLE test.t; 结束;
两个处理程序都在同一个块中声明,并具有相同的范围。
但是,
SQLSTATE
处理程序优先于
SQLEXCEPTION
处理程序,因此如果表
t
不存在,则该
DROP
TABLE
语句会引发一个激活
SQLSTATE
处理程序
的条件
:
MySQL的> CALL p1();
+ -------------------------------- +
| 消息|
+ -------------------------------- +
| SQLSTATE处理程序已激活|
+ -------------------------------- +
此过程包含相同的两个处理程序。
但这次,
DROP
TABLE
语句和
SQLEXCEPTION
处理程序位于相对于
SQLSTATE
处理程序
的内部块中
:
CREATE PROCEDURE p2() 开始 - 外块 为SQLSTATE'42S02'声明继续HANDLER SELECT'SQLSTATE处理程序已激活'AS msg; 开始 - 内部块 DECLARE CONTINUE HANDLER用于SQLEXCEPTION SELECT'SQLEXCEPTION处理程序已激活'AS msg; DROP TABLE test.t; - 发生在内部区块内 结束; 结束;
在这种情况下,更符合条件发生位置的处理程序优先。
该
SQLEXCEPTION
处理器激活,即使它是不是更一般的
SQLSTATE
处理程序:
MySQL的> CALL p2();
+ ------------------------------------ +
| 消息|
+ ------------------------------------ +
| SQLEXCEPTION处理程序已激活|
+ ------------------------------------ +
在此过程中,其中一个处理程序在
DROP
TABLE
语句
范围内的块中
声明:
CREATE PROCEDURE p3() 开始 - 外块 DECLARE CONTINUE HANDLER用于SQLEXCEPTION SELECT'SQLEXCEPTION处理程序已激活'AS msg; 开始 - 内部块 为SQLSTATE'42S02'声明继续HANDLER SELECT'SQLSTATE处理程序已激活'AS msg; 结束; DROP TABLE test.t; - 发生在外部区块内 结束;
只有
SQLEXCEPTION
处理程序适用,因为另一个处理程序不在由以下内容引发的条件的范围内
DROP
TABLE
:
MySQL的> CALL p3();
+ ------------------------------------ +
| 消息|
+ ------------------------------------ +
| SQLEXCEPTION处理程序已激活|
+ ------------------------------------ +
在此过程中,两个处理程序都在
DROP
TABLE
语句
范围内的块中
声明:
CREATE PROCEDURE p4() 开始 - 外块 开始 - 内部块 DECLARE CONTINUE HANDLER用于SQLEXCEPTION SELECT'SQLEXCEPTION处理程序已激活'AS msg; 为SQLSTATE'42S02'声明继续HANDLER SELECT'SQLSTATE处理程序已激活'AS msg; 结束; DROP TABLE test.t; - 发生在外部区块内 结束;
处理程序都不适用,因为它们不在范围内
DROP
TABLE
。
语句引发的条件未处理,并以错误终止该过程:
MySQL的> CALL p4();
ERROR 1051(42S02):未知表'test.t'
SQL语句生成填充诊断区域的诊断信息。
标准SQL具有诊断区域堆栈,其中包含每个嵌套执行上下文的诊断区域。
标准SQL还支持
GET STACKED
DIAGNOSTICS
在条件处理程序执行期间引用第二个诊断区域的语法。
以下讨论描述了MySQL中诊断区域的结构,MySQL识别的信息项,清除语句和设置诊断区域的方式,以及诊断区域如何从堆栈中推送和弹出。
诊断区域包含两种信息:
语句信息,例如发生的条件数或受影响的行数。
条件信息,例如错误代码和消息。 如果语句引发多个条件,则诊断区域的这一部分具有每个条件区域。 如果语句没有引发任何条件,则诊断区域的这一部分为空。
对于产生三个条件的语句,诊断区域包含语句和条件信息,如下所示:
声明信息: 行数 ......其他声明信息项...... 条件区域列表: 条件范围1: 条件1的错误代码 条件1的错误消息 ......其他条件信息...... 条件区域2: 条件2的错误代码: 条件2的错误消息 ......其他条件信息...... 条件范围3: 条件3的错误代码 条件3的错误消息 ......其他条件信息......
诊断区域包含语句和条件信息项。
数字项是整数。
字符项的字符集是UTF-8。
没有项目可以
NULL
。
如果填充诊断区域的语句未设置语句或条件项,则其值为0或空字符串,具体取决于项数据类型。
诊断区域的语句信息部分包含以下项目:
NUMBER
:一个整数,指示包含信息的条件区域的数量。
ROW_COUNT
:一个整数,指示受语句影响的行数。
ROW_COUNT
具有与
ROW_COUNT()
函数
相同的值
(请参见
第12.15节“信息函数”
)。
诊断区域的条件信息部分包含每个条件的条件区域。
条件区域从1到
NUMBER
语句条件项
的值编号
。
如果
NUMBER
为0,则没有条件区域。
每个条件区域都包含以下列表中的项目。
所有项目都是标准SQL,但
MYSQL_ERRNO
它是MySQL扩展。
这些定义适用于除信号之外产生的条件(即通过
SIGNAL
或
RESIGNAL
声明)。
对于非信号条件,MySQL仅填充那些未描述为始终为空的条件项。
信号对条件区域的影响将在后面描述。
CLASS_ORIGIN
:包含
RETURNED_SQLSTATE
值
类的字符串
。
如果
RETURNED_SQLSTATE
值以SQL标准文档ISO 9075-2(第24.1节,SQLSTATE)中定义的类值开头,
CLASS_ORIGIN
则为
'ISO
9075'
。
否则
CLASS_ORIGIN
就是
'MySQL'
。
SUBCLASS_ORIGIN
:包含
RETURNED_SQLSTATE
值
的子类的字符串
。
如果
CLASS_ORIGIN
是
'ISO
9075'
或
RETURNED_SQLSTATE
结束
'000'
,
SUBCLASS_ORIGIN
是
'ISO
9075'
。
否则
SUBCLASS_ORIGIN
就是
'MySQL'
。
RETURNED_SQLSTATE
:一个字符串,指示
SQLSTATE
条件
的
值。
MESSAGE_TEXT
:一个字符串,指示条件的错误消息。
MYSQL_ERRNO
:一个整数,指示条件的MySQL错误代码。
CONSTRAINT_CATALOG
,
CONSTRAINT_SCHEMA
,
CONSTRAINT_NAME
:字符串指示目录,架构,并将其命名为违反约束。
他们总是空着的。
CATALOG_NAME
,
SCHEMA_NAME
,
TABLE_NAME
,
COLUMN_NAME
:字符串指示目录,架构,表和相关的状态栏。
他们总是空着的。
CURSOR_NAME
:一个表示游标名称的字符串。
这总是空的。
对于
RETURNED_SQLSTATE
,
MESSAGE_TEXT
以及
MYSQL_ERRNO
特定的错误值,请参见
第B.3.1节,“服务器错误信息参考”
。
如果
SIGNAL
(或
RESIGNAL
)语句填充诊断区域,则其
SET
子句可以分配给任何条件信息项,除了
RETURNED_SQLSTATE
对项数据类型合法的任何值。
SIGNAL
也设置
RETURNED_SQLSTATE
值,但不直接在其
SET
子句中。
该值来自
SIGNAL
语句
SQLSTATE
参数。
SIGNAL
还设置了声明信息项。
它设置
NUMBER
为1.
ROW_COUNT
错误
设置
为-1,否则
设置
为0。
非诊断SQL语句自动填充诊断区域,其内容可以使用
SIGNAL
和
RESIGNAL
语句
显式设置
。
可以检查诊断区域
GET
DIAGNOSTICS
以提取特定项目,或者使用
SHOW WARNINGS
或
SHOW
ERRORS
查看条件或错误。
SQL语句清除并设置诊断区域如下:
当服务器在解析后开始执行语句时,它会清除非诊断语句的诊断区域。 诊断语句不会清除诊断区域。 这些陈述是诊断性的:
如果语句引发某个条件,则会清除诊断区域中属于早期语句的条件。
例外情况是由
诊断区域
引发的条件
GET DIAGNOSTICS
和
RESIGNAL
添加到诊断区域而不清除它。
因此,即使在开始执行时通常不会清除诊断区域的语句也会在语句引发条件时清除它。
以下示例显示了各种语句对诊断区域的影响,
SHOW
WARNINGS
用于显示有关存储在那里的条件的信息。
此
DROP
TABLE
语句清除诊断区域并在条件发生时填充它:
MySQL的>DROP TABLE IF EXISTS test.no_such_table;
查询正常,0行受影响,1警告(0.01秒) MySQL的>SHOW WARNINGS;
+ ------- + ------ + ---------------------------------- - + | 等级| 代码| 消息| + ------- + ------ + ---------------------------------- - + | 注意| 1051 | 未知表'test.no_such_table'| + ------- + ------ + ---------------------------------- - + 1排(0.00秒)
此
SET
语句生成错误,因此它会清除并填充诊断区域:
MySQL的>SET @x = @@x;
ERROR 1193(HY000):未知的系统变量'x' MySQL的>SHOW WARNINGS;
+ ------- + ------ + ----------------------------- + | 等级| 代码| 消息| + ------- + ------ + ----------------------------- + | 错误| 1193 | 未知的系统变量'x'| + ------- + ------ + ----------------------------- + 1排(0.00秒)
前面的
SET
语句产生了一个条件,因此1是此时唯一有效的条件数
GET
DIAGNOSTICS
。
以下语句使用条件号2,它会生成一个警告,该警告将添加到诊断区域而不清除它:
MySQL的>GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
查询正常,0行受影响,1警告(0.00秒) MySQL的>SHOW WARNINGS;
+ ------- + ------ + + ------------------------------ | 等级| 代码| 消息| + ------- + ------ + + ------------------------------ | 错误| 1193 | 未知的系统变量'xx'| | 错误| 1753年| 条件号无效| + ------- + ------ + + ------------------------------ 2行(0.00秒)
现在诊断区域中有两个条件,因此相同的
GET DIAGNOSTICS
语句成功:
MySQL的>GET DIAGNOSTICS CONDITION 2 @p = MESSAGE_TEXT;
查询正常,0行受影响(0.00秒) MySQL的>SELECT @p;
+ -------------------------- + | @p | + -------------------------- + | 条件号无效| + -------------------------- + 1排(0.01秒)
当推送到诊断区域堆栈时,第一个(当前)诊断区域成为第二个(堆叠)诊断区域,并创建一个新的当前诊断区域作为其副本。 在以下情况下,诊断区域将被推入并从堆栈中弹出:
执行存储的程序
在程序执行之前发生推送,之后发生弹出。
如果存储的程序在处理程序执行时结束,则可以弹出多个诊断区域;
这是由于没有适当的处理程序或由于处理程序中的异常而发生
RETURN
的。
然后,弹出的诊断区域中的任何警告或错误条件都会添加到当前诊断区域,但对于触发器,仅添加错误。 当存储的程序结束时,调用者在其当前的对角线区域中看到这些条件。
在存储的程序中执行条件处理程序
当由于条件处理程序激活而发生推送时,堆叠的诊断区域是在推送之前存储的程序中当前的区域。
新的当前诊断区域是处理程序的当前诊断区域。
GET
[CURRENT] DIAGNOSTICS
并且
GET
STACKED DIAGNOSTICS
可以在处理程序中使用以访问当前(处理程序)和堆栈(存储程序)诊断区域的内容。
最初,它们返回相同的结果,但在处理程序中执行的语句会修改当前诊断区域,根据常规规则清除和设置其内容(请参阅
如何清除和填充诊断区域)
)。
除了处理程序中执行的语句之外,不能修改堆叠的诊断区域
RESIGNAL
。
如果处理程序成功执行,则弹出当前(处理程序)诊断区域,堆叠(存储程序)诊断区域再次成为当前诊断区域。 在处理程序执行期间添加到处理程序诊断区域的条件将添加到当前诊断区域。
执行
RESIGNAL
该
RESIGNAL
语句传递在存储程序内的复合语句中执行条件处理程序期间可用的错误条件信息。
RESIGNAL
可能会在传递之前更改部分或全部信息,修改诊断堆栈,如
第13.6.7.4节“RESIGNAL语法”中所述
。
某些系统变量控制或与诊断区域的某些方面相关:
max_error_count
控制诊断区域中的条件区域数量。
如果出现的情况多于此情况,MySQL会默默地丢弃超出条件的信息。
(添加的条件
RESIGNAL
总是被添加,必要时会丢弃较旧的条件以腾出空间。)
warning_count
表示发生的条件数。
这包括错误,警告和注释。
通常,
NUMBER
并且
warning_count
是相同的。
但是,随着产生的条件数量的增加
max_error_count
,值
warning_count
继续上升,但
NUMBER
仍保持上限,
max_error_count
因为诊断区域中没有存储其他条件。
error_count
表示发生的错误数。
此值包括
“
未找到
”
和例外情况,但不包括警告和注释。
就像
warning_count
,它的价值可以超过
max_error_count
。
如果
sql_notes
系统变量设置为0,则不会存储注释,也不会增加注释
warning_count
。
示例:如果
max_error_count
为10,则诊断区域最多可包含10个条件区域。
假设一个语句提出了20个条件,其中12个是错误。
在这种情况下,诊断区域包含前10个条件,
NUMBER
即10,
warning_count
是20,并且
error_count
是12。
max_error_count
在下次尝试修改诊断区域之前
,对值的更改
无效。
如果诊断区域包含10个条件区域并且
max_error_count
设置为5,则不会立即影响诊断区域的大小或内容。
MySQL帐户信息存储在
mysql
系统数据库
的表中
。
该数据库和访问控制系统将在
第5章
MySQL服务器管理中
进行详细讨论
,您应该参考其中了解更多详细信息。
一些MySQL版本引入了对授权表的更改以添加新的特权或功能。 要确保您可以利用任何新功能,请在升级MySQL时将授权表更新为当前结构。 请参见 第2.11节“升级MySQL” 。
当
read_only
启用了系统变量,账户管理语句需要
CONNECTION_ADMIN
或
SUPER
特权,除了所需的其他特权。
这是因为它们修改了
mysql
系统数据库中的
表
。
帐户管理语句具有原子性和崩溃安全性。 有关更多信息,请参见 第13.1.1节“原子数据定义语句支持” 。
ALTER USER [IF EXISTS]user
[auth_option
] [,user
[auth_option
]] ...... [要求{无|]tls_option
[[AND]tls_option
] ...}] [WITHresource_option
[resource_option
] ...] [password_option
|lock_option
] ...... ALTER USER [IF EXISTS] USER()user_func_auth_option
更改用户[如果存在]user
默认角色 {无| 所有|role
[,role
] ......}user
: (参见第6.2.4节“指定帐户名”)auth_option
:{ 由'auth_string
' 识别 [REPLACE'current_auth_string
'] [保留当前密码] | 用auth_plugin
|来识别 通过auth_plugin
'auth_string
'确认 [REPLACE'current_auth_string
'] [保留当前密码] | 与auth_plugin
'auth_string
''确认 | 丢掉旧密码 }user_func_auth_option
:{ 由'auth_string
' 识别 [REPLACE'current_auth_string
'] [保留当前密码] | 丢掉旧密码 }tls_option
:{ SSL | X509 | CIPHER'cipher
' | 发行人'issuer
' | 主题'subject
' }resource_option
:{ MAX_QUERIES_PER_HOURcount
| MAX_UPDATES_PER_HOURcount
| MAX_CONNECTIONS_PER_HOURcount
| MAX_USER_CONNECTIONScount
}password_option
:{ PASSWORD EXPIRE [默认值] 永远不会 间隔日N
] | 密码历史{默认|N
} | PASSWORD REUSE INTERVAL {默认|N
天} | 密码要求当前[默认值] 可选的] }lock_option
:{ 账户锁 | 帐户解锁 }
该
ALTER
USER
语句修改了MySQL帐户。
它可以为现有帐户修改身份验证,角色,SSL / TLS,资源限制和密码管理属性。
它还可用于锁定和解锁帐户。
在大多数情况下,
ALTER
USER
需要全局
CREATE USER
特权或
系统数据库
的
UPDATE
特权
mysql
。
例外情况是:
使用非匿名帐户连接到服务器的任何客户端都可以更改该帐户的密码。
(特别是,您可以更改自己的密码。)要查看服务器对您进行身份验证的帐户,请调用以下
CURRENT_USER()
函数:
SELECT CURRENT_USER();
对于
DEFAULT ROLE
语法,
ALTER
USER
需要以下权限:
为其他用户设置默认角色需要全局
CREATE USER
权限或
系统表
的
UPDATE
权限
mysql.default_roles
。
为自己设置默认角色不需要特殊权限,只要您希望将您想要的角色授予您。
修改辅助密码的语句需要以下权限:
该
APPLICATION_PASSWORD_ADMIN
权限才能使用
RETAIN CURRENT
PASSWORD
或
DISCARD OLD
PASSWORD
子句
ALTER
USER
应用到自己的帐户报表。
由于大多数用户只需要一个密码,因此需要使用该权限来操作您自己的二级密码。
如果允许某个帐户操作所有帐户的辅助密码,则应授予其
CREATE USER
权限,而不是
APPLICATION_PASSWORD_ADMIN
。
当
read_only
启用了系统变量,
ALTER
USER
另外需要
CONNECTION_ADMIN
或
SUPER
特权。
默认情况下,如果您尝试修改不存在的用户,则会发生错误。
如果
IF EXISTS
给出了
该
子句,则该语句会为每个不存在的命名用户生成警告,而不是错误。
在某些情况下,
ALTER
USER
可以在历史文件中记录在服务器日志中或客户端上
~/.mysql_history
,这意味着任何对该信息具有读访问权限的人都可以读取明文密码。
有关服务器日志发生的条件以及如何控制它的信息,请参见
第6.1.2.3节“密码和日志记录”
。
有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql客户端日志记录”
。
该
ALTER
USER
声明
有几个方面
,在以下主题下描述:
对于每个受影响的帐户,
ALTER
USER
修改
mysql.user
系统表中
的相应行
以反映语句中指定的属性。
未指定的属性保留其当前值。
每个帐户名称使用
第6.2.4节“指定帐户名称”中
所述的格式
。
帐户名的主机名部分(如果省略)默认为
'%'
。
还可以指定
CURRENT_USER
或
CURRENT_USER()
引用与当前会话相关联的帐户。
仅对于一种语法,可以使用以下
USER()
函数
指定帐户
:
ALTER USER USER()通过' auth_string
' 标识;
此语法可以更改您自己的密码,而无需按字面指定您的帐户。
(语法还支持
REPLACE
,
RETAIN CURRENT
PASSWORD
以及
DISCARD OLD
PASSWORD
在所描述的条款
ALTER用户认证选项
。)
对于
ALTER
USER
允许
auth_option
值遵循
user
值的
语法,
auth_option
通过指定帐户身份验证插件,凭据(例如,密码)或两者来指示帐户如何进行身份验证。
每个
auth_option
值适用
只
到一个名为的前一个帐户。
遵循
user
规范,该语句可能包括SSL / TLS,资源限制,密码管理和锁定属性的选项。
所有此类选项
对于语句
都是
全局的
,并适用于语句中指定的
所有
帐户。
示例:更改帐户密码并使其过期。 因此,用户必须使用指定的密码连接,并在下一次连接时选择一个新密码:
更改用户'jeffrey'@'localhost'
由new_password
'密码出现'识别;
示例:修改帐户以使用
sha256_password
身份验证插件和给定密码。
要求每180天选择一个新密码:
更改用户'jeffrey'@'localhost'
用sha256_password BY' new_password
' 识别
密码EXPIRE间隔180天;
示例:锁定或解锁帐户:
ALTER USER'jeffrey'@'localhost'ACCOUNT LOCK; ALTER USER'jeffrey'@'localhost'ACCOUNT UNLOCK;
示例:要求帐户使用SSL进行连接,并建立每小时20个连接的限制:
更改用户'jeffrey'@'localhost' 使用MAX_CONNECTIONS_PER_HOUR 20要求SSL;
示例:更改多个帐户,指定一些每帐户属性和一些全局属性:
更改用户 '杰弗里' @ 'localhost' 的 由'jeffrey_new_password
' 识别, '珍妮' @ 'localhost' 的, '乔希' @ 'localhost' 的 由'josh_new_password
' 识别 替换'josh_current_password
' 保留当前密码 使用MAX_USER_CONNECTIONS 2要求SSL 密码历史5;
以下
IDENTIFIED BY
值
jeffrey
仅适用于其前一个帐户,因此它将密码更改为
仅适用于
。
因为
,没有每个帐户值(因此保持密码不变)。
对于
,
建立新密码(
),
指定用于验证发出该
语句
的用户是否
知道当前密码(
),并且该当前密码也保留为帐户二级密码。
(因此,
可以连接主密码或二级密码。)
'
jeffrey_new_password
'jeffrey
jeanne
josh
IDENTIFIED BY
'
josh_new_password
'REPLACE
ALTER USER
'
josh_current_password
'josh
其余属性全局应用于语句中指定的所有帐户,因此对于两个帐户:
需要连接才能使用SSL。
该帐户最多可用于两个同时连接。
密码更改无法重用五个最新密码中的任何一个。
示例:丢弃二级密码
josh
,只保留帐户的主密码:
ALTER USER'josh'@'localhost'DISCARD OLD PASSWORD;
在没有特定类型的期权的情况下,账户在这方面保持不变。 例如,如果没有锁定选项,则不会更改帐户的锁定状态。
帐户名后面可能是一个
auth_option
身份验证选项,用于指定帐户身份验证插件,凭据或两者。
它还可能包含一个password-verification子句,用于指定要替换的帐户当前密码,以及用于管理帐户是否具有二级密码的子句。
密码验证次密码条款仅适用于内部存储凭据的账户
mysql.user
系统表(
mysql_native_password
,
sha256_password
,或
caching_sha2_password
)。
对于使用对外部凭据系统执行身份验证的插件的帐户,还必须在该系统外部处理密码管理。
auth_plugin
命名一个身份验证插件。
插件名称可以是带引号的字符串文字或不带引号的名称。
插件名称存储在
系统表
的
plugin
列中
mysql.user
。
对于
auth_option
未指定身份验证插件的语法,默认插件由
default_authentication_plugin
系统变量
的值指示
。
有关每个插件的说明,请参见
第6.4.1节“身份验证插件”
。
凭据存储在
mysql.user
系统表中。
的
值指定帐户凭据,无论是作为明文(未加密)的字符串或由与该帐户,分别相关联的认证插件所预期的格式散列:
'
auth_string
'
对于使用的语法,
字符串是明文,并传递给身份验证插件以进行可能的散列。
插件返回的结果存储在
表中。
插件可以使用指定的值,在这种情况下不会发生散列。
BY
'
auth_string
'mysql.user
对于使用的语法,
假定该字符串已经采用认证插件所需的格式,并按原样存储在
表中。
如果插件需要散列值,则必须以适合插件的格式对值进行散列处理。
否则,该插件无法使用该值,并且不会发生客户端连接的正确身份验证。
AS
'
auth_string
'mysql.user
从MySQL 8.0.17开始,散列字符串可以是字符串文字或十六进制值。
后者对应于
启用系统变量
SHOW CREATE USER
时包含不可打印字符的密码哈希
显示的值的类型
print_identified_with_as_hex
。
如果身份验证插件不执行对身份验证字符串的散列,则
和
子句具有相同的效果:将身份验证字符串存储在
系统表中。
BY
'
auth_string
'AS
'
auth_string
'mysql.user
该
子句从MySQL 8.0.13开始提供。
如果给出:
REPLACE
'
current_auth_string
'
REPLACE
指定要替换的帐户当前密码,作为明文(未加密)字符串。
如果需要更改密码以指定当前密码,则必须提供该条款,作为验证尝试进行更改的用户实际知道当前密码的验证。
如果帐户的密码更改可能但不需要指定当前密码,则该子句是可选的。
如果给出了该子句但该语句与当前密码不匹配,则该语句失败,即使该子句是可选的。
REPLACE
只有在更改当前用户的帐户密码时才能指定。
有关通过指定当前密码进行密码验证的更多信息,请参见 第6.2.15节“密码管理” 。
在
RETAIN CURRENT PASSWORD
和
DISCARD OLD PASSWORD
条款实行双重密码功能,并从MySQL 8.0.14的。
两者都是可选的,但如果给出,则具有以下效果:
RETAIN CURRENT PASSWORD
保留帐户当前密码作为其辅助密码,替换任何现有的二级密码。
新密码将成为主密码,但客户端可以使用该帐户使用主密码或辅助密码连接到服务器。
(例外:如果
ALTER USER
语句
指定的新密码
为空,则辅助密码也会变为空,即使
RETAIN CURRENT PASSWORD
已给出。)
如果
RETAIN CURRENT
PASSWORD
为具有空主密码的帐户
指定
,则该语句将失败。
如果帐户具有辅助密码并且您在未指定
RETAIN CURRENT PASSWORD
的
情况下更改其主密码
,则辅助密码将保持不变。
如果更改分配给该帐户的身份验证插件,则会丢弃该辅助密码。
如果更改身份验证插件并指定
RETAIN CURRENT PASSWORD
,则语句将失败。
DISCARD OLD PASSWORD
丢弃二级密码(如果存在)。
该帐户仅保留其主密码,客户端可以使用该帐户仅使用主密码连接到服务器。
有关使用双密码的更多信息,请参见 第6.2.15节“密码管理” 。
ALTER
USER
允许这些
auth_option
语法:
IDENTIFIED BY
'
auth_string
' [REPLACE
'current_auth_string
'] [RETAIN
CURRENT PASSWORD]
将帐户身份验证插件设置为默认插件,将明文
值
传递
给插件以进行可能的散列,并将结果存储在
系统表
的帐户行中
。
'
auth_string
'mysql.user
REPLACE
如果给出
该
子句,则指定帐户当前密码,如本节前面所述。
RETAIN CURRENT PASSWORD
如果给出
该
子句,则会将帐户当前密码保留为其辅助密码,如本节前面所述。
IDENTIFIED WITH
auth_plugin
将帐户身份验证插件设置为
auth_plugin
,将凭据清除为空字符串(凭据与旧的身份验证插件相关联,而不是新的身份验证插件),并将结果存储在
mysql.user
系统表
的帐户行中
。
此外,密码标记为已过期。 用户必须在下次连接时选择一个新的。
IDENTIFIED WITH
auth_plugin
BY
'auth_string
' [REPLACE
'current_auth_string
'] [RETAIN
CURRENT PASSWORD]
将帐户身份验证插件设置为
auth_plugin
,将明文
值
传递
给插件以进行可能的散列,并将结果存储在
系统表
的帐户行中
。
'
auth_string
'mysql.user
REPLACE
如果给出
该
子句,则指定帐户当前密码,如本节前面所述。
RETAIN CURRENT PASSWORD
如果给出
该
子句,则会将帐户当前密码保留为其辅助密码,如本节前面所述。
IDENTIFIED WITH
auth_plugin
AS
'auth_string
'
将帐户身份验证插件设置为
auth_plugin
并存储
帐户行中
的
值
。
如果插件需要散列字符串,则假定该字符串已经以插件所需的格式进行了散列。
'
auth_string
'mysql.user
DISCARD OLD PASSWORD
丢弃帐户二级密码(如果有),如本节前面所述。
示例:将密码指定为明文; 使用默认插件:
更改用户'jeffrey'@'localhost'
识别' password
';
示例:指定身份验证插件以及明文密码值:
更改用户'jeffrey'@'localhost'
使用mysql_native_password标识
BY' password
';
示例:与前面的示例类似,但另外,将当前密码指定为明文值,以满足进行更改的用户知道该密码的任何帐户要求:
更改用户'jeffrey'@'localhost' 使用mysql_native_password标识 BY'password
' 替换'current_password
';
除非当前用户
jeffrey
因为
REPLACE
仅允许更改当前用户的密码,
否则上述语句将失败
。
示例:建立新的主密码并将现有密码保留为辅助密码:
更改用户'jeffrey'@'localhost'
由' new_password
' 识别
保留当前密码;
示例:丢弃二级密码,只保留帐户的主密码:
ALTER USER'jeffery'@'localhost'DISCARD OLD PASSWORD;
示例:指定身份验证插件以及散列密码值:
更改用户'jeffrey'@'localhost' 使用mysql_native_password标识 AS'* 6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4';
有关设置密码和身份验证插件的其他信息,请参见 第6.2.14节“分配帐户密码” 和 第6.2.17节“可插入身份验证” 。
ALTER
USER ...
DEFAULT ROLE
定义当用户连接到服务器并进行身份验证时,或者用户
SET
ROLE
DEFAULT
在会话期间
执行
语句
时,哪些角色变为活动状态
。
ALTER
USER ...
DEFAULT ROLE
是替代语法
SET DEFAULT ROLE
(参见
第13.7.1.9节“SET DEFAULT ROLE语法”
)。
但是,
ALTER
USER
可以仅为单个用户
SET
DEFAULT ROLE
设置默认值
,而
可以为多个用户设置默认值。
另一方面,您可以指定
语句
CURRENT_USER
的用户名
ALTER
USER
,而不能用于
SET DEFAULT
ROLE
。
每个用户帐户名称使用前面描述的格式。
每个角色名称使用 第6.2.5节“指定角色名称”中 描述的格式 。 例如:
ALTER USER'joe'@'10.0.0.1'DEFAULT ROLE管理员,开发人员;
角色名称的主机名部分(如果省略)默认为
'%'
。
DEFAULT ROLE
关键字
后面的子句
允许这些值:
NONE
:将默认值设置为
NONE
(无角色)。
ALL
:将默认值设置为授予该帐户的所有角色。
:将默认值设置为命名角色,该角色必须存在并在执行时授予帐户
role
[,
role
] ...ALTER
USER ...
DEFAULT ROLE
。
除了基于用户名和凭据的常规身份验证之外,MySQL还可以检查X.509证书属性。 有关在MySQL中使用SSL / TLS的背景信息,请参见 第6.3节“使用加密连接” 。
要为MySQL帐户指定SSL / TLS相关选项,请使用
REQUIRE
指定一个或多个
tls_option
值
的
子句
。
REQUIRE
选项
顺序
无关紧要,但不能指定选项两次。
该
AND
关键字是可选之间
REQUIRE
选择。
ALTER
USER
允许这些
tls_option
值:
NONE
表示该语句指定的所有帐户都没有SSL或X.509要求。 如果用户名和密码有效,则允许未加密的连接。 如果客户端具有适当的证书和密钥文件,则可以在客户端选择使用加密连接。
更改用户'jeffrey'@'localhost'无需提供;
客户端默认尝试建立安全连接。
对于具有
REQUIRE
NONE
此功能的
客户端,
如果无法建立安全连接,则连接尝试将回退到未加密的连接。
要求加密连接,客户端只需指定
--ssl-mode=REQUIRED
选项;
如果无法建立安全连接,则连接尝试失败。
SSL
告知服务器仅允许该语句命名的所有帐户的加密连接。
更改用户'jeffrey'@'localhost'需要SSL;
客户端默认尝试建立安全连接。
对于具有的帐户,
REQUIRE
SSL
如果无法建立安全连接,则连接尝试将失败。
X509
对于语句指定的所有帐户,要求客户端提供有效证书,但确切的证书,颁发者和主题无关紧要。
唯一的要求是应该可以使用其中一个CA证书验证其签名。
使用X.509证书始终意味着加密,因此
SSL
在这种情况下不需要
该
选项。
ALTER USER'jeffrey'@'localhost'REQUIRE X509;
对于帐户
REQUIRE X509
,客户必须指定
连接
--ssl-key
和
--ssl-cert
选项。
(建议但不要求
--ssl-ca
也要指定,以便可以验证服务器提供的公共证书。)这是正确的
ISSUER
,
SUBJECT
因为这些
REQUIRE
选项意味着要求
X509
。
ISSUER
'
issuer
'
对于语句指定的所有帐户,要求客户端提供CA颁发的有效X.509证书
。
如果客户端提供的证书有效但具有不同的颁发者,则服务器拒绝该连接。
使用X.509证书始终意味着加密,因此
在这种情况下不需要
该
选项。
'
issuer
'SSL
更改用户'jeffrey'@'localhost' 要求发行人'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O=MySQL/CN=CA/emailAddress=ca@example.com“;
因为
ISSUER
暗示了要求
X509
,客户必须指定
--ssl-key
和
--ssl-cert
连接的选项。
(建议但不要求
--ssl-ca
也要指定,以便验证服务器提供的公共证书。)
SUBJECT
'
subject
'
对于语句指定的所有帐户,要求客户端提供包含主题的有效X.509证书
subject
。
如果客户端提供的证书有效但主题不同,则服务器会拒绝该连接。
使用X.509证书始终意味着加密,因此
SSL
在这种情况下不需要
该
选项。
更改用户'jeffrey'@'localhost' 要求主题'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O = MySQL演示客户端证书/ CN=client/emailAddress=client@example.com“;
MySQL
对证书
中的
值进行
简单的字符串比较
,因此必须完全按照证书中的名称给出字母和组件排序。
'
subject
'
因为
SUBJECT
暗示了要求
X509
,客户必须指定
--ssl-key
和
--ssl-cert
连接的选项。
(建议但不要求
--ssl-ca
也要指定,以便验证服务器提供的公共证书。)
CIPHER
'
cipher
'
对于语句指定的所有帐户,需要特定的密码方法来加密连接。 需要此选项以确保使用足够强度的密码和密钥长度。 如果使用使用短加密密钥的旧算法,则加密可能很弱。
更改用户'jeffrey'@'localhost' 需要密码'EDH-RSA-DES-CBC3-SHA';
的
SUBJECT
,
ISSUER
和
CIPHER
选项可以在组合中的
REQUIRE
条款:
更改用户'jeffrey'@'localhost' 要求主题'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O = MySQL演示客户端证书/ CN=client/emailAddress=client@example.com” AND ISSUER'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O=MySQL/CN=CA/emailAddress=ca@example.com” 和CIPHER'EDH-RSA-DES-CBC3-SHA';
可以对帐户使用服务器资源
设置限制
,如
第6.2.20节“设置帐户资源限制”中所述
。
为此,请使用
WITH
指定一个或多个
resource_option
值
的
子句
。
WITH
选项
顺序
无关紧要,除非多次指定给定资源限制,最后一个实例优先。
ALTER
USER
允许这些
resource_option
值:
MAX_QUERIES_PER_HOUR
,
,
count
MAX_UPDATES_PER_HOUR
count
MAX_CONNECTIONS_PER_HOUR
count
对于语句指定的所有帐户,这些选项限制在任何给定的一小时内允许每个帐户访问服务器的查询,更新和连接的数量。
如果
count
是
0
(默认值),则表示帐户没有限制。
MAX_USER_CONNECTIONS
count
对于语句指定的所有帐户,限制每个帐户与服务器的最大并发连接数。
非零
count
指定帐户的限制。
如果
count
是
0
(默认值),则服务器根据
max_user_connections
系统变量
的全局值确定帐户的同时连接数
。
如果
max_user_connections
也为零,则帐户没有限制。
例:
更改用户'jeffrey'@'localhost' MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;
ALTER
USER
支持多个
password_option
密码管理值:
密码过期选项:您可以手动过期帐户密码并建立密码过期策略。 策略选项不会使密码失效。 相反,它们根据密码年龄确定服务器如何将自动过期应用于帐户,密码年龄是根据最近帐户密码更改的日期和时间进行评估的。
密码重用选项:您可以根据密码更改次数,已用时间或两者来限制密码重用。
密码验证所需选项:您可以指示尝试更改帐户密码是否必须指定当前密码,以验证尝试进行更改的用户是否实际知道当前密码。
本节介绍密码管理选项的语法。 有关建立密码管理策略的信息,请参见 第6.2.15节“密码管理” 。
如果给定类型(多重密码管理选项
PASSWORD EXPIRE
,
PASSWORD
HISTORY
,
PASSWORD REUSE INTERVAL
,
PASSWORD REQUIRE
被指定),最后一个优先。
密码管理选项仅适用于内部存储凭据的账户
mysql.user
系统表(
mysql_native_password
,
sha256_password
,或
caching_sha2_password
)。
对于使用对外部凭据系统执行身份验证的插件的帐户,还必须在该系统外部处理密码管理。
如果帐户密码手动过期或密码年龄被认为大于其自动过期策略的允许生命周期,则客户端的密码已过期。 在这种情况下,服务器会断开客户端连接或限制允许的操作(请参见 第6.2.16节“过期密码的服务器处理” )。 受限客户端执行的操作会导致错误,直到用户建立新的帐户密码。
可以 通过将密码设置为其当前值 来 “ 重置 ” 密码。 作为一个好的政策问题,最好选择不同的密码。 DBA可以通过建立适当的密码重用策略来强制执行非重用。 请参阅 密码重用策略 。
ALTER
USER
允许这些
password_option
值来控制密码到期:
PASSWORD EXPIRE
立即为该语句指定的所有帐户标记密码已过期。
ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE;
PASSWORD EXPIRE DEFAULT
设置由语句命名的所有帐户,以便应用全局过期策略,如
default_password_lifetime
系统变量
所指定
。
ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE DEFAULT;
PASSWORD EXPIRE NEVER
此到期选项会覆盖该语句指定的所有帐户的全局策略。 对于每个,它会禁用密码到期,以便密码永不过期。
ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE NEVER;
PASSWORD EXPIRE INTERVAL
N
DAY
此到期选项会覆盖该语句指定的所有帐户的全局策略。
对于每个,它将密码生存期设置为
N
天。
以下语句要求密码每180天更改一次:
ALTER USER'jeffrey'@'localhost'PASSWORD EXPIRE INTERVAL 180天;
ALTER
USER
允许这些
password_option
值根据所需的最小密码更改次数控制以前密码的重用:
PASSWORD HISTORY DEFAULT
设置由语句命名的所有帐户,以便应用关于密码历史记录长度的全局策略,以禁止在
password_history
系统变量
指定的更改数之前重用密码
。
ALTER USER'jeffrey'@'localhost'PASSWORD HISTORY DEFAULT;
PASSWORD HISTORY
N
此历史记录长度选项会覆盖该语句指定的所有帐户的全局策略。
对于每个密码,它将密码历史记录长度设置为
N
密码,以禁止重用任何
N
最近选择的密码。
以下声明禁止重复使用以前的6个密码:
ALTER USER'jeffrey'@'localhost'PASSWORD HISTORY 6;
ALTER
USER
允许这些
password_option
值根据已用时间控制以前密码的重用:
PASSWORD REUSE INTERVAL DEFAULT
设置帐户指定的所有语句,以便应用有关时间的全局策略,以禁止重用比
password_reuse_interval
系统变量
指定的天数更新的密码
。
ALTER USER'jeffrey'@'localhost'PASSWORD REUSE INTERVAL DEFAULT;
PASSWORD REUSE INTERVAL
N
DAY
此time-elapsed选项会覆盖该语句指定的所有帐户的全局策略。
对于每个,它将密码重用间隔设置为
N
天,以禁止重用比这多天更新的密码。
以下声明禁止密码重用360天:
ALTER USER'jeffrey'@'localhost'PASSWORD REUSE INTERVAL 360 DAY;
ALTER
USER
允许这些
password_option
值来控制是否尝试更改帐户密码必须指定当前密码,以验证尝试进行更改的用户是否实际知道当前密码:
PASSWORD REQUIRE CURRENT
此验证选项会覆盖该语句指定的所有帐户的全局策略。 对于每个,它要求密码更改指定当前密码。
更改用户'jeffrey'@'localhost'密码请求当前;
PASSWORD REQUIRE CURRENT OPTIONAL
此验证选项会覆盖该语句指定的所有帐户的全局策略。 对于每个,它不要求密码更改指定当前密码。 (可能但不需要提供当前密码。)
更改用户'jeffrey'@'localhost'密码要求当前可选;
PASSWORD REQUIRE CURRENT DEFAULT
设置帐户命名的所有语句,以便应用关于密码验证的全局策略,如
password_require_current
系统变量
所指定
。
更改用户'jeffrey'@'localhost'密码请求当前默认值;
MySQL支持使用
ACCOUNT LOCK
和
ACCOUNT
UNLOCK
选项
进行帐户锁定和解锁
,这些选项指定帐户的锁定状态。
有关其他讨论,请参见
第6.2.19节“帐户锁定”
。
如果指定了多个帐户锁定选项,则最后一个优先。
ALTER
USER
如果成功则写入二进制日志,但如果失败则不写入;
在这种情况下,发生回滚并且不进行任何更改。
写入二进制日志的语句包括所有已命名的用户。
如果
IF
EXISTS
给出
该
条款,则甚至包括不存在且未被更改的用户。
如果原始语句更改了用户的凭据,则写入二进制日志的语句将为该用户指定适用的身份验证插件,确定如下:
如果指定了一个插件,则在原始语句中命名。
否则,如果用户存在,则与用户帐户关联的插件,如果用户不存在,则为默认的身份验证插件。 (如果写入二进制日志的语句必须为用户指定特定的身份验证插件,请将其包含在原始语句中。)
如果服务器为写入二进制日志的语句中的任何用户添加了默认身份验证插件,则会向命名这些用户的错误日志写入警告。
创造角色[如果不是EXISTS]role
[,role
] ......
CREATE
ROLE
创建一个或多个角色,这些角色被命名为特权集合。
要使用此语句,您必须具有全局
CREATE
ROLE
或
CREATE USER
特权。
当
read_only
启用了系统变量,
CREATE
ROLE
另外需要
CONNECTION_ADMIN
或
SUPER
特权。
创建时的角色已锁定,没有密码,并被分配了默认的身份验证插件。
(
ALTER
USER
具有全局
CREATE USER
权限
的用户
可以稍后使用该
语句
更改这些角色属性
。)
CREATE
ROLE
要么成功执行所有已命名的角色,要么回滚,如果发生任何错误,则无效。
默认情况下,如果您尝试创建已存在的角色,则会发生错误。
如果
IF NOT EXISTS
给出了
该
子句,则该语句会为已存在的每个已命名角色生成警告,而不是错误。
如果成功,则将语句写入二进制日志,但如果失败则不写入;
在这种情况下,发生回滚并且不进行任何更改。
写入二进制日志的语句包括所有命名角色。
如果
IF NOT EXISTS
给出
了该
子句,则包括已存在且未创建的角色。
每个角色名称使用 第6.2.5节“指定角色名称”中 描述的格式 。 例如:
CREATE ROLE'管理员','开发人员'; CREATE ROLE'webapp'@'localhost';
角色名称的主机名部分(如果省略)默认为
'%'
。
有关角色使用示例,请参见 第6.2.10节“使用角色” 。
创建用户[如果不是EXISTS]user
[auth_option
] [,user
[auth_option
]] ...... 默认角色role
[,role
] ...... [要求{无|]tls_option
[[AND]tls_option
] ...}] [WITHresource_option
[resource_option
] ...] [password_option
|lock_option
] ......user
: (参见第6.2.4节“指定帐户名”)auth_option
:{ 由'auth_string
' 识别 | 用auth_plugin
|来识别 通过auth_plugin
'auth_string
'确认 | 与auth_plugin
'auth_string
''确认 }tls_option
:{ SSL | X509 | CIPHER'cipher
' | 发行人'issuer
' | 主题'subject
' }resource_option
:{ MAX_QUERIES_PER_HOURcount
| MAX_UPDATES_PER_HOURcount
| MAX_CONNECTIONS_PER_HOURcount
| MAX_USER_CONNECTIONScount
}password_option
:{ PASSWORD EXPIRE [默认值] 永远不会 间隔日N
] | 密码历史{默认|N
} | PASSWORD REUSE INTERVAL {默认|N
天} | 密码要求当前[默认值] 可选的] }lock_option
:{ 账户锁 | 帐户解锁 }
该
CREATE
USER
语句创建新的MySQL帐户。
它可以为新帐户建立身份验证,角色,SSL / TLS,资源限制和密码管理属性。
它还控制帐户最初是锁定还是解锁。
要使用
CREATE
USER
,您必须具有全局
CREATE USER
特权或
系统数据库
的
INSERT
特权
mysql
。
当
read_only
启用了系统变量,
CREATE
USER
另外需要
CONNECTION_ADMIN
或
SUPER
特权。
CREATE
USER
对所有命名用户成功或回滚,如果发生任何错误,则无效。
默认情况下,如果您尝试创建已存在的用户,则会发生错误。
如果
IF NOT EXISTS
给出了
该
子句,则该语句会为已存在的每个已命名用户生成警告,而不是错误。
在某些情况下,
CREATE
USER
可以在历史文件中记录在服务器日志中或客户端上
~/.mysql_history
,这意味着任何对该信息具有读访问权限的人都可以读取明文密码。
有关服务器日志发生的条件以及如何控制它的信息,请参见
第6.1.2.3节“密码和日志记录”
。
有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql客户端日志记录”
。
该
CREATE
USER
声明
有几个方面
,在以下主题下描述:
对于每个帐户,
CREATE
USER
在
mysql.user
系统表中
创建一个新行
。
帐户行反映了语句中指定的属性。
未指定的属性设置为其默认值:
身份验证:由
default_authentication_plugin
系统变量
定义的身份验证插件
和空凭据
默认角色:
NONE
SSL / TLS:
NONE
资源限制:无限制
密码管理:
PASSWORD EXPIRE DEFAULT
PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT
PASSWORD REQUIRE CURRENT DEFAULT
帐户锁定:
ACCOUNT UNLOCK
首次创建时,帐户没有权限,默认角色为
NONE
。
要分配权限或角色,请使用该
GRANT
语句。
每个帐户名称使用 第6.2.4节“指定帐户名称”中 所述的格式 。 例如:
创建用户'jeffrey'@'localhost'标识' password
';
帐户名的主机名部分(如果省略)默认为
'%'
。
user
命名帐户的
每个
值后面都可以跟一个可选
auth_option
值,该值指示帐户的身份验证方式。
这些值可以指定帐户身份验证插件和凭据(例如,密码)。
每个
auth_option
值适用
只
到一个名为的前一个帐户。
遵循
user
规范,该语句可能包括SSL / TLS,资源限制,密码管理和锁定属性的选项。
所有此类选项
对于语句
都是
全局的
,并适用于语句中指定的
所有
帐户。
示例:创建使用默认身份验证插件和给定密码的帐户。 标记密码已过期,以便用户必须在第一次连接到服务器时选择一个新密码:
创建用户'jeffrey'@'localhost'
由new_password
'密码出现'识别;
示例:创建使用
sha256_password
身份验证插件和给定密码
的帐户
。
要求每180天选择一个新密码:
创建用户'jeffrey'@'localhost'
用sha256_password BY' new_password
' 识别
密码EXPIRE间隔180天;
示例:创建多个帐户,指定一些每帐户属性和一些全局属性:
创建用户 'jeffrey'@'localhost'用mysql_native_password识别 BY'new_password1
', 'jeanne'@'localhost'用sha256_password识别 BY'new_password2
' 要求X509使用MAX_QUERIES_PER_HOUR 60 密码历史5 账户锁;
每个
auth_option
值(
IDENTIFIED WITH ... BY
在这种情况下)仅适用于紧接在其之前命名的帐户,因此每个帐户使用紧随其后的身份验证插件和密码。
其余属性全局应用于语句中指定的所有帐户,因此对于两个帐户:
必须使用有效的X.509证书进行连接。
每小时最多允许60个查询。
密码更改无法重用五个最新密码中的任何一个。
该帐户最初是锁定的,因此它实际上是占位符,在管理员解锁之前无法使用。
帐户名后面可能是一个
auth_option
身份验证选项,用于指定帐户身份验证插件,凭据或两者:
auth_plugin
命名一个身份验证插件。
插件名称可以是带引号的字符串文字或不带引号的名称。
插件名称存储在
系统表
的
plugin
列中
mysql.user
。
对于
auth_option
未指定身份验证插件的语法,默认插件由
default_authentication_plugin
系统变量
的值指示
。
有关每个插件的说明,请参见
第6.4.1节“身份验证插件”
。
凭据存储在
mysql.user
系统表中。
的
值指定帐户凭据,无论是作为明文(未加密)的字符串或由与该帐户,分别相关联的认证插件所预期的格式散列:
'
auth_string
'
对于使用的语法,
字符串是明文,并传递给身份验证插件以进行可能的散列。
插件返回的结果存储在
表中。
插件可以使用指定的值,在这种情况下不会发生散列。
BY
'
auth_string
'mysql.user
对于使用的语法,
假定该字符串已经采用认证插件所需的格式,并按原样存储在
表中。
如果插件需要散列值,则必须以适合插件的格式对值进行散列处理。
否则,该插件无法使用该值,并且不会发生客户端连接的正确身份验证。
AS
'
auth_string
'mysql.user
从MySQL 8.0.17开始,散列字符串可以是字符串文字或十六进制值。
后者对应于
启用系统变量
SHOW CREATE USER
时包含不可打印字符的密码哈希
显示的值的类型
print_identified_with_as_hex
。
如果身份验证插件不执行身份验证字符串的哈希,则
和
子句具有相同的效果:身份验证字符串的存储在
表中。
BY
'
auth_string
'AS
'
auth_string
'mysql.user
CREATE
USER
允许这些
auth_option
语法:
IDENTIFIED BY
'
auth_string
'
将帐户身份验证插件设置为默认插件,将明文
值
传递
给插件以进行可能的散列,并将结果存储在
系统表
的帐户行中
。
'
auth_string
'mysql.user
IDENTIFIED WITH
auth_plugin
将帐户身份验证插件设置为
auth_plugin
,将凭据清除为空字符串,并将结果存储在
mysql.user
系统表
的帐户行中
。
IDENTIFIED WITH
auth_plugin
BY
'auth_string
'
将帐户身份验证插件设置为
auth_plugin
,将明文
值
传递
给插件以进行可能的散列,并将结果存储在
系统表
的帐户行中
。
'
auth_string
'mysql.user
IDENTIFIED WITH
auth_plugin
AS
'auth_string
'
将帐户身份验证插件设置为
auth_plugin
并存储
帐户行中
的
值
。
如果插件需要散列字符串,则假定该字符串已经以插件所需的格式进行了散列。
'
auth_string
'mysql.user
示例:将密码指定为明文; 使用默认插件:
创建用户'jeffrey'@'localhost'
识别' password
';
示例:指定身份验证插件以及明文密码值:
创建用户'jeffrey'@'localhost'
使用mysql_native_password BY' password
' 识别;
在每种情况下,存储在帐户行中的密码值是在
与帐户关联的身份验证插件进行哈希处理后
的明文值
。
'
password
'
有关设置密码和身份验证插件的其他信息,请参见 第6.2.14节“分配帐户密码” 和 第6.2.17节“可插入身份验证” 。
该
DEFAULT ROLE
子句定义当用户连接到服务器并进行身份验证时,或者用户
SET
ROLE
DEFAULT
在会话期间
执行
语句
时,哪些角色变为活动状态
。
每个角色名称使用 第6.2.5节“指定角色名称”中 描述的格式 。 例如:
CREATE USER'joe'@'10.0.0.1'DEFAULT ROLE管理员,开发人员;
角色名称的主机名部分(如果省略)默认为
'%'
。
该
DEFAULT ROLE
子句允许一个或多个以逗号分隔的角色名称的列表。
CREATE
USER
执行
时不需要存在这些角色
。
除了基于用户名和凭据的常规身份验证之外,MySQL还可以检查X.509证书属性。 有关在MySQL中使用SSL / TLS的背景信息,请参见 第6.3节“使用加密连接” 。
要为MySQL帐户指定SSL / TLS相关选项,请使用
REQUIRE
指定一个或多个
tls_option
值
的
子句
。
REQUIRE
选项
顺序
无关紧要,但不能指定选项两次。
该
AND
关键字是可选之间
REQUIRE
选择。
CREATE
USER
允许这些
tls_option
值:
NONE
表示该语句指定的所有帐户都没有SSL或X.509要求。 如果用户名和密码有效,则允许未加密的连接。 如果客户端具有适当的证书和密钥文件,则可以在客户端选择使用加密连接。
创建用户'jeffrey'@'localhost'无需任何操作;
客户端默认尝试建立安全连接。
对于具有
REQUIRE
NONE
此功能的
客户端,
如果无法建立安全连接,则连接尝试将回退到未加密的连接。
要求加密连接,客户端只需指定
--ssl-mode=REQUIRED
选项;
如果无法建立安全连接,则连接尝试失败。
NONE
如果未
REQUIRE
指定
与SSL相关的
选项,
则为默认值
。
SSL
告知服务器仅允许该语句命名的所有帐户的加密连接。
创建用户'jeffrey'@'localhost'需要SSL;
客户端默认尝试建立安全连接。
对于具有的帐户,
REQUIRE
SSL
如果无法建立安全连接,则连接尝试将失败。
X509
对于语句指定的所有帐户,要求客户端提供有效证书,但确切的证书,颁发者和主题无关紧要。
唯一的要求是应该可以使用其中一个CA证书验证其签名。
使用X.509证书始终意味着加密,因此
SSL
在这种情况下不需要
该
选项。
CREATE USER'jeffrey'@'localhost'REQUIRE X509;
对于帐户
REQUIRE X509
,客户必须指定
连接
--ssl-key
和
--ssl-cert
选项。
(建议但不要求
--ssl-ca
也要指定,以便可以验证服务器提供的公共证书。)这是正确的
ISSUER
,
SUBJECT
因为这些
REQUIRE
选项意味着要求
X509
。
ISSUER
'
issuer
'
对于语句指定的所有帐户,要求客户端提供CA颁发的有效X.509证书
。
如果客户端提供的证书有效但具有不同的颁发者,则服务器拒绝该连接。
使用X.509证书始终意味着加密,因此
在这种情况下不需要
该
选项。
'
issuer
'SSL
创建用户'jeffrey'@'localhost' 要求发行人'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O=MySQL/CN=CA/emailAddress=ca@example.com“;
因为
ISSUER
暗示了要求
X509
,客户必须指定
--ssl-key
和
--ssl-cert
连接的选项。
(建议但不要求
--ssl-ca
也要指定,以便验证服务器提供的公共证书。)
SUBJECT
'
subject
'
对于语句指定的所有帐户,要求客户端提供包含主题的有效X.509证书
subject
。
如果客户端提供的证书有效但主题不同,则服务器会拒绝该连接。
使用X.509证书始终意味着加密,因此
SSL
在这种情况下不需要
该
选项。
创建用户'jeffrey'@'localhost' 要求主题'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O = MySQL演示客户端证书/ CN=client/emailAddress=client@example.com“;
MySQL
对证书
中的
值进行
简单的字符串比较
,因此必须完全按照证书中的名称给出字母和组件排序。
'
subject
'
因为
SUBJECT
暗示了要求
X509
,客户必须指定
--ssl-key
和
--ssl-cert
连接的选项。
(建议但不要求
--ssl-ca
也要指定,以便验证服务器提供的公共证书。)
CIPHER
'
cipher
'
对于语句指定的所有帐户,需要特定的密码方法来加密连接。 需要此选项以确保使用足够强度的密码和密钥长度。 如果使用使用短加密密钥的旧算法,则加密可能很弱。
创建用户'jeffrey'@'localhost' 需要密码'EDH-RSA-DES-CBC3-SHA';
的
SUBJECT
,
ISSUER
和
CIPHER
选项可以在组合中的
REQUIRE
条款:
创建用户'jeffrey'@'localhost' 要求主题'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O = MySQL演示客户端证书/ CN=client/emailAddress=client@example.com” AND ISSUER'/ C = SE / ST =斯德哥尔摩/ L =斯德哥尔摩/ O=MySQL/CN=CA/emailAddress=ca@example.com” 和CIPHER'EDH-RSA-DES-CBC3-SHA';
可以对帐户使用服务器资源
设置限制
,如
第6.2.20节“设置帐户资源限制”中所述
。
为此,请使用
WITH
指定一个或多个
resource_option
值
的
子句
。
WITH
选项
顺序
无关紧要,除非多次指定给定资源限制,最后一个实例优先。
CREATE
USER
允许这些
resource_option
值:
MAX_QUERIES_PER_HOUR
,
,
count
MAX_UPDATES_PER_HOUR
count
MAX_CONNECTIONS_PER_HOUR
count
对于语句指定的所有帐户,这些选项限制在任何给定的一小时内允许每个帐户访问服务器的查询,更新和连接的数量。
如果
count
是
0
(默认值),则表示帐户没有限制。
MAX_USER_CONNECTIONS
count
对于语句指定的所有帐户,限制每个帐户与服务器的最大并发连接数。
非零
count
指定帐户的限制。
如果
count
是
0
(默认值),则服务器根据
max_user_connections
系统变量
的全局值确定帐户的同时连接数
。
如果
max_user_connections
也为零,则帐户没有限制。
例:
创建用户'jeffrey'@'localhost' MAX_QUERIES_PER_HOUR 500 MAX_UPDATES_PER_HOUR 100;
CREATE
USER
支持多个
password_option
密码管理值:
密码过期选项:您可以手动过期帐户密码并建立密码过期策略。 策略选项不会使密码失效。 相反,它们根据密码年龄确定服务器如何将自动过期应用于帐户,密码年龄是根据最近帐户密码更改的日期和时间进行评估的。
密码重用选项:您可以根据密码更改次数,已用时间或两者来限制密码重用。
密码验证所需选项:您可以指示尝试更改帐户密码是否必须指定当前密码,以验证尝试进行更改的用户是否实际知道当前密码。
本节介绍密码管理选项的语法。 有关建立密码管理策略的信息,请参见 第6.2.15节“密码管理” 。
如果给定类型(多重密码管理选项
PASSWORD EXPIRE
,
PASSWORD
HISTORY
,
PASSWORD REUSE INTERVAL
,
PASSWORD REQUIRE
被指定),最后一个优先。
密码管理选项仅适用于内部存储凭据的账户
mysql.user
系统表(
mysql_native_password
,
sha256_password
,或
caching_sha2_password
)。
对于使用对外部凭据系统执行身份验证的插件的帐户,还必须在该系统外部处理密码管理。
如果帐户密码手动过期或密码年龄被认为大于其自动过期策略的允许生命周期,则客户端的密码已过期。 在这种情况下,服务器会断开客户端连接或限制允许的操作(请参见 第6.2.16节“过期密码的服务器处理” )。 受限客户端执行的操作会导致错误,直到用户建立新的帐户密码。
CREATE
USER
允许这些
password_option
值来控制密码到期:
PASSWORD EXPIRE
立即为该语句指定的所有帐户标记密码已过期。
创建用户'jeffrey'@'localhost'PASSWORD EXPIRE;
PASSWORD EXPIRE DEFAULT
设置由语句命名的所有帐户,以便应用全局过期策略,如
default_password_lifetime
系统变量
所指定
。
创建用户'jeffrey'@'localhost'PASSWORD EXPIRE DEFAULT;
PASSWORD EXPIRE NEVER
此到期选项会覆盖该语句指定的所有帐户的全局策略。 对于每个,它会禁用密码到期,以便密码永不过期。
创建用户'jeffrey'@'localhost'密码永远不会出现;
PASSWORD EXPIRE INTERVAL
N
DAY
此到期选项会覆盖该语句指定的所有帐户的全局策略。
对于每个,它将密码生存期设置为
N
天。
以下语句要求密码每180天更改一次:
创建用户'jeffrey'@'localhost'密码EXPIRE INTERVAL 180天;
CREATE
USER
允许这些
password_option
值根据所需的最小密码更改次数控制以前密码的重用:
PASSWORD HISTORY DEFAULT
设置由语句命名的所有帐户,以便应用关于密码历史记录长度的全局策略,以禁止在
password_history
系统变量
指定的更改数之前重用密码
。
创建用户'jeffrey'@'localhost'密码历史默认;
PASSWORD HISTORY
N
此历史记录长度选项会覆盖该语句指定的所有帐户的全局策略。
对于每个密码,它将密码历史记录长度设置为
N
密码,以禁止重用任何
N
最近选择的密码。
以下声明禁止重复使用以前的6个密码:
创建用户'jeffrey'@'localhost'密码历史6;
CREATE
USER
允许这些
password_option
值根据已用时间控制以前密码的重用:
PASSWORD REUSE INTERVAL DEFAULT
设置帐户指定的所有语句,以便应用有关时间的全局策略,以禁止重用比
password_reuse_interval
系统变量
指定的天数更新的密码
。
创建用户'jeffrey'@'localhost'密码重用间隔默认值;
PASSWORD REUSE INTERVAL
N
DAY
此time-elapsed选项会覆盖该语句指定的所有帐户的全局策略。
对于每个,它将密码重用间隔设置为
N
天,以禁止重用比这多天更新的密码。
以下声明禁止密码重用360天:
创建用户'jeffrey'@'localhost'密码重新使用INTERVAL 360天;
CREATE
USER
允许这些
password_option
值来控制是否尝试更改帐户密码必须指定当前密码,以验证尝试进行更改的用户是否实际知道当前密码:
PASSWORD REQUIRE CURRENT
此验证选项会覆盖该语句指定的所有帐户的全局策略。 对于每个,它要求密码更改指定当前密码。
创建用户'jeffrey'@'localhost'密码请求当前;
PASSWORD REQUIRE CURRENT OPTIONAL
此验证选项会覆盖该语句指定的所有帐户的全局策略。 对于每个,它不要求密码更改指定当前密码。 (可能但不需要提供当前密码。)
创建用户'jeffrey'@'localhost'密码请求当前可选;
PASSWORD REQUIRE CURRENT DEFAULT
设置帐户命名的所有语句,以便应用关于密码验证的全局策略,如
password_require_current
系统变量
所指定
。
创建用户'jeffrey'@'localhost'密码请求当前默认值;
MySQL支持使用
ACCOUNT LOCK
和
ACCOUNT
UNLOCK
选项
进行帐户锁定和解锁
,这些选项指定帐户的锁定状态。
有关其他讨论,请参见
第6.2.19节“帐户锁定”
。
如果指定了多个帐户锁定选项,则最后一个优先。
CREATE
USER
如果成功则写入二进制日志,但如果失败则不写入;
在这种情况下,发生回滚并且不进行任何更改。
写入二进制日志的语句包括所有已命名的用户。
如果
IF
NOT EXISTS
给出
了该
子句,则甚至包括已存在且未创建的用户。
写入二进制日志的语句为每个用户指定一个身份验证插件,确定如下:
如果指定了一个插件,则在原始语句中命名。
否则,默认的身份验证插件。
特别是,如果用户
u1
已经存在并使用非默认身份验证插件,则该语句将写入二进制日志以
CREATE USER IF NOT
EXISTS u1
获取默认身份验证插件的名称。
(如果写入二进制日志的语句必须为用户指定非默认身份验证插件,请将其包含在原始语句中。)
如果服务器在写入二进制日志的语句中为任何不存在的用户添加默认身份验证插件,则会向命名这些用户的错误日志写入警告。
DROP ROLE [IF EXISTS]role
[,role
] ......
DROP
ROLE
删除一个或多个角色(命名的特权集合)。
要使用此语句,您必须具有全局
DROP
ROLE
或
CREATE USER
特权。
当
read_only
启用了系统变量,
DROP
ROLE
另外需要
CONNECTION_ADMIN
或
SUPER
特权。
从MySQL 8.0.16开始,拥有该
CREATE USER
权限的
用户
可以使用此语句删除已锁定或未锁定的帐户。
拥有该
DROP ROLE
权限的
用户
只能使用此语句删除被锁定的帐户(未锁定的帐户可能是用于登录服务器的用户帐户,而不仅仅是作为角色)。
mandatory_roles
无法删除
在
系统变量值中
命名的角色
。
DROP
ROLE
要么成功执行所有已命名的角色,要么回滚,如果发生任何错误,则无效。
默认情况下,如果您尝试删除不存在的角色,则会发生错误。
如果
IF EXISTS
给出了
该
子句,则该语句会为每个不存在的命名角色生成警告,而不是错误。
如果成功,则将语句写入二进制日志,但如果失败则不写入;
在这种情况下,发生回滚并且不进行任何更改。
写入二进制日志的语句包括所有命名角色。
如果
IF EXISTS
给出
了该
子句,则包括不存在且未被删除的角色。
每个角色名称使用 第6.2.5节“指定角色名称”中 描述的格式 。 例如:
DROP ROLE'管理员','开发者'; DROP ROLE'webapp'@'localhost';
角色名称的主机名部分(如果省略)默认为
'%'
。
已删除角色会自动从已授予角色的任何用户帐户(或角色)中撤消。 在此类帐户的任何当前会话中,其调整的权限从下一个执行的语句开始应用。
有关角色使用示例,请参见 第6.2.10节“使用角色” 。
DROP USER [IF EXISTS]user
[,user
] ......
该
DROP
USER
语句删除一个或多个MySQL帐户及其权限。
它从所有授权表中删除该帐户的权限行。
mandatory_roles
无法删除
在
系统变量值中
命名的角色
。
要使用
DROP
USER
,您必须具有全局
CREATE USER
特权或
系统数据库
的
DELETE
特权
mysql
。
当
read_only
启用了系统变量,
DROP
USER
另外需要
CONNECTION_ADMIN
或
SUPER
特权。
DROP
USER
对所有命名用户成功或回滚,如果发生任何错误,则无效。
默认情况下,如果您尝试删除不存在的用户,则会发生错误。
如果
IF EXISTS
给出了
该
子句,则该语句会为每个不存在的命名用户生成警告,而不是错误。
如果成功,则将语句写入二进制日志,但如果失败则不写入;
在这种情况下,发生回滚并且不进行任何更改。
写入二进制日志的语句包括所有已命名的用户。
如果
IF EXISTS
给出
了该
子句,则甚至包括不存在且未被丢弃的用户。
每个帐户名称使用 第6.2.4节“指定帐户名称”中 所述的格式 。 例如:
DROP USER'jeffrey'@'localhost';
帐户名的主机名部分(如果省略)默认为
'%'
。
DROP
USER
不会自动关闭任何打开的用户会话。
相反,如果删除了具有打开会话的用户,则该语句在该用户的会话关闭之前不会生效。
会话关闭后,用户将被删除,该用户下次登录尝试将失败。
这是设计的
。
DROP
USER
不会自动删除或使旧用户创建的数据库或对象无效。
这包括存储的程序或视图,
DEFINER
属性为已删除的用户命名。
如果在定义的安全性上下文中执行,则尝试访问此类对象可能会产生错误。
(有关安全上下文的信息,请参见
第24.6节“存储对象访问控制”
。)
GRANTpriv_type
[(column_list
)] [,priv_type
[(column_list
)]] ...... ON [object_type
]priv_level
TOuser_or_role
[,user_or_role
] ...... [WITH GRANT OPTION] [如user
[有角色 默认 | 没有 | 所有 | 除了role
[,role
]之外...... |role
[,role
] ...... ] ] } GRANT PROXY ONuser_or_role
TOuser_or_role
[,user_or_role
] ... [WITH GRANT OPTION] GRANTrole
[,role
] ...... TOuser_or_role
[,user_or_role
] ...... [WITH ADMIN OPTION]object_type
:{ 表 | 功能 | 程序 }priv_level
:{ * | *。* |db_name
*。 |db_name.tbl_name
|tbl_name
|db_name
。routine_name
}user_or_role
:{user
|role
}user
: (参见第6.2.4节“指定帐户名”)role
: (请参见第6.2.5节“指定角色名称”)
该
GRANT
语句为MySQL用户帐户和角色分配权限和角色。
该
GRANT
声明
有几个方面
,在以下主题下描述:
该
GRANT
语句使系统管理员可以授予权限和角色,这些权限和角色可以授予用户帐户和角色。
这些语法限制适用:
有关角色的更多信息,请参阅 第6.2.10节“使用角色” 。
要使用
GRANT
,您必须拥有该
GRANT OPTION
权限,并且您必须具有您授予的权限。
当
read_only
启用了系统变量,
GRANT
另外需要
CONNECTION_ADMIN
或
SUPER
特权。
GRANT
要么为所有命名用户和角色成功,要么回滚,如果发生任何错误,则无效。
只有当所有命名用户和角色成功时,该语句才会写入二进制日志。
该
REVOKE
声明与
GRANT
管理员
相关
并使其能够删除帐户权限。
请参见
第13.7.1.8节“REVOKE语法”
。
每个帐户名称使用 第6.2.4节“指定帐户名称”中 所述的格式 。 每个角色名称使用 第6.2.5节“指定角色名称”中 描述的格式 。 例如:
全部授予db1。*给'jeffrey'@'localhost'; GRANT'rort1','role2'TO'user1'@'localhost','user2'@'localhost'; GRANT SELECT ON world。* TO'campart3';
帐户或角色名称的主机名部分(如果省略)默认为
'%'
。
通常,数据库管理员首先使用
CREATE
USER
创建帐户并定义其非特权特征(如密码),是否使用安全连接以及对服务器资源的访问限制,然后使用它
GRANT
来定义其权限。
ALTER
USER
可用于更改现有帐户的非特权。
例如:
创建用户'jeffrey'@'localhost'标识' password
';
全部授予db1。*给'jeffrey'@'localhost';
GRANT SELECT ON db2.invoice TO'jeffrey'@'localhost';
更改用户'jeffrey'@'localhost'与MAX_QUERIES_PER_HOUR 90;
从
mysql
程序,
成功执行时
GRANT
响应
Query OK, 0 rows affected
。
要确定操作产生的特权,请使用
SHOW
GRANTS
。
请参见
第13.7.6.21节“显示GRANTS语法”
。
在某些情况下,
GRANT
可以在历史文件中记录在服务器日志中或客户端上
~/.mysql_history
,这意味着任何对该信息具有读访问权限的人都可以读取明文密码。
有关服务器日志发生的条件以及如何控制它的信息,请参见
第6.1.2.3节“密码和日志记录”
。
有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql客户端日志记录”
。
GRANT
支持最长255个字符的主机名(MySQL 8.0.17之前的60个字符)。
用户名最多可包含32个字符。
数据库,表,列和例程名称最多可包含64个字符。
请勿尝试通过更改
mysql.user
系统表
来更改用户名的允许长度
。
这样做会导致不可预测的行为,甚至可能使用户无法登录MySQL服务器
。
mysql
除非通过
第2.11节“升级MySQL”中
描述的过程,否则
切勿
以任何方式
更改
系统数据库
中表的结构
。
GRANT
语句中的
几个对象
可以引用,但在许多情况下引用是可选的:帐户,角色,数据库,表,列和例程名称。
例如,如果
帐户名中的值
user_name
或
host_name
值是合法的未加引号的标识符,则无需引用它。
然而,引号是必要指定
user_name
包含特殊字符(例如字符串
-
),或一个
host_name
包含字符串的特殊字符或通配符,如
%
(例如
'test-user'@'%.com'
)。
分别引用用户名和主机名。
要指定引用的值:
引用数据库,表,列和例程名称作为标识符。
引用用户名和主机名作为标识符或字符串。
引用密码作为字符串。
有关字符串引用和标识符引用指南,请参见 第9.1.1节“字符串文字” 和 第9.2节“模式对象名称” 。
在
_
和
%
通配符在指定数据库名称时,允许
GRANT
格兰特在数据库级权限(报表
)。
这意味着,例如,要将
字符用作数据库名称的一部分,请
在
语句中
指定它
,以防止用户能够访问与通配符模式匹配的其他数据库(例如,
)。
GRANT ... ON
db_name
.*_
\_
GRANT
GRANT ... ON `foo\_bar`.* TO ...
如果不使用数据库名称在数据库级别授予权限,但作为用于向某些其他对象(例如,表)或例程(例如
)
授予权限的限定符,则将
通配符视为普通字符。
GRANT ... ON
db_name
.tbl_name
语句中
的
user
值
GRANT
表示该语句适用的MySQL帐户。
为了适应从任意主机授予用户权限,MySQL支持
user
在表单中
指定
值
。
'
user_name
'@'host_name
'
您可以在主机名中指定通配符。
例如,
适用
于
域中的
任何主机
,并
适用于
C类子网
中的任何主机
。
'
user_name
'@'%.example.com'user_name
example.com
'
user_name
'@'198.51.100.%'user_name
198.51.100
简单形式
是同义词
。
'
user_name
''
user_name
'@'%'
MySQL不支持用户名中的通配符
。
要引用匿名用户,请使用以下
GRANT
语句
指定具有空用户名的帐户
:
GRANT ALL ON test。* TO''@'localhost'...;
在这种情况下,任何从本地主机连接匿名用户密码的用户都将被允许访问,并具有与匿名用户帐户关联的权限。
有关帐户名中的用户名和主机名值的其他信息,请参见 第6.2.4节“指定帐户名” 。
如果您允许本地匿名用户连接到MySQL服务器,您还应该向所有本地用户授予权限
。
否则,匿名用户帐户
在
当指定的用户试图从本地机器上登录到MySQL服务器使用的系统表。
有关详细信息,请参见
第6.2.6节“访问控制,第1阶段:连接验证”
。
'
user_name
'@'localhost'localhost
mysql.user
要确定此问题是否适用于您,请执行以下查询,该查询列出了所有匿名用户:
SELECT Host,User FROM mysql.user WHERE User ='';
要避免上述问题,请使用以下语句删除本地匿名用户帐户:
DROP USER''@'localhost';
下表总结了
priv_type
可以为
GRANT
和
REVOKE
语句
指定
的允许的静态和动态
特权类型
,以及可以授予每个特权的级别。
有关每个权限的其他信息,请参见
第6.2.2节“MySQL提供的权限”
。
有关静态和动态权限之间差异的信息,请参阅
静态与动态权限
。
表13.11 GRANT和REVOKE的允许静态权限
特权 | 意义和可授予级别 |
---|---|
ALL [PRIVILEGES] |
授予在指定的访问级别的所有权限,除了
GRANT OPTION
和
PROXY
。
|
ALTER |
启用
ALTER TABLE
。
级别:全局,数据库,表格。
|
ALTER ROUTINE |
允许更改或删除存储的例程。 级别:全局,数据库,例程。 |
CREATE |
启用数据库和表创建。 级别:全局,数据库,表格。 |
CREATE ROLE |
启用角色创建。 等级:全球。 |
CREATE
ROUTINE |
启用存储的例程创建。 级别:全球,数据库。 |
CREATE
TABLESPACE |
启用要创建,更改或删除的表空间和日志文件组。 等级:全球。 |
CREATE
TEMPORARY TABLES |
启用
CREATE
TEMPORARY TABLE
。
级别:全球,数据库。
|
CREATE USER |
允许使用
CREATE USER
,
DROP
USER
,
RENAME USER
,和
REVOKE
ALL
PRIVILEGES
。
等级:全球。
|
CREATE VIEW |
启用要创建或更改的视图。 级别:全局,数据库,表格。 |
DELETE |
启用
DELETE
。
级别:全局,数据库,表格。
|
DROP |
启用要删除的数据库,表和视图。 级别:全局,数据库,表格。 |
DROP ROLE |
启用要删除的角色。 等级:全球。 |
EVENT |
启用事件计划程序的事件使用。 级别:全球,数据库。 |
EXECUTE |
使用户能够执行存储的例程。 级别:全局,数据库,例程。 |
FILE |
使用户能够使服务器读取或写入文件。 等级:全球。 |
GRANT OPTION |
启用授予其他帐户或从其他帐户中删除的权限。 级别:全局,数据库,表,例程,代理。 |
INDEX |
启用要创建或删除的索引。 级别:全局,数据库,表格。 |
INSERT |
启用
INSERT
。
级别:全局,数据库,表格,列。
|
LOCK TABLES |
允许使用
LOCK TABLES
您拥有该
SELECT
权限的表。
级别:全球,数据库。
|
PROCESS |
使用户能够查看所有进程
SHOW
PROCESSLIST
。
等级:全球。
|
PROXY |
启用用户代理。 级别:从用户到用户。 |
REFERENCES |
启用外键创建。 级别:全局,数据库,表格,列。 |
RELOAD |
启用
FLUSH
操作。
等级:全球。
|
REPLICATION
CLIENT |
使用户可以询问主服务器或从服务器的位置。 等级:全球。 |
REPLICATION
SLAVE |
启用复制从属以从主服务器读取二进制日志事件。 等级:全球。 |
SELECT |
启用
SELECT
。
级别:全局,数据库,表格,列。
|
SHOW
DATABASES |
启用
SHOW DATABASES
以显示所有数据库。
等级:全球。
|
SHOW VIEW |
启用
SHOW CREATE VIEW
。
级别:全局,数据库,表格。
|
SHUTDOWN |
启用 mysqladmin shutdown 。 等级:全球。 |
SUPER |
能够使用如其他行政业务
CHANGE MASTER TO
,
KILL
,
PURGE BINARY LOGS
,
SET
GLOBAL
,和
中mysqladmin调试
命令。
等级:全球。
|
TRIGGER |
启用触发操作。 级别:全局,数据库,表格。 |
UPDATE |
启用
UPDATE
。
级别:全局,数据库,表格,列。
|
USAGE |
“ no privileges ”的 同义词 |
表13.12 GRANT和REVOKE的允许动态权限
特权 | 意义和可授予级别 |
---|---|
APPLICATION_PASSWORD_ADMIN |
启用双密码管理。 等级:全球。 |
AUDIT_ADMIN |
启用审核日志配置。 等级:全球。 |
BACKUP_ADMIN |
启用备份管理。 等级:全球。 |
BINLOG_ADMIN |
启用二进制日志控制。 等级:全球。 |
BINLOG_ENCRYPTION_ADMIN |
启用二进制日志加密的激活和取消激活。 等级:全球。 |
CONNECTION_ADMIN |
启用连接限制/限制控制。 等级:全球。 |
ENCRYPTION_KEY_ADMIN |
启用
InnoDB
键旋转。
等级:全球。
|
FIREWALL_ADMIN |
启用防火墙规则管理,任何用户。 等级:全球。 |
FIREWALL_USER |
启用防火墙规则管理,自我。 等级:全球。 |
GROUP_REPLICATION_ADMIN |
启用组复制控制。 等级:全球。 |
PERSIST_RO_VARIABLES_ADMIN |
启用持久性只读系统变量。 等级:全球。 |
REPLICATION_SLAVE_ADMIN |
启用常规复制控制。 等级:全球。 |
RESOURCE_GROUP_ADMIN |
启用资源组管理。 等级:全球。 |
RESOURCE_GROUP_USER |
启用资源组管理。 等级:全球。 |
ROLE_ADMIN |
允许授予或撤销角色,使用
WITH ADMIN
OPTION
。
等级:全球。
|
SESSION_VARIABLES_ADMIN |
启用设置受限会话系统变量。 等级:全球。 |
SET_USER_ID |
启用设置非自我
DEFINER
值。
等级:全球。
|
SYSTEM_USER |
将帐户指定为系统帐户。 等级:全球。 |
SYSTEM_VARIABLES_ADMIN |
启用修改或持久化全局系统变量。 等级:全球。 |
TABLE_ENCRYPTION_ADMIN |
启用覆盖默认加密设置。 等级:全球。 |
VERSION_TOKEN_ADMIN |
允许使用版本标记UDF。 等级:全球。 |
XA_RECOVER_ADMIN |
启用
XA
RECOVER
执行。
等级:全球。
|
触发器与表关联。
要创建或删除触发器,您必须拥有
TRIGGER
该表
的
权限,而不是触发器。
在
GRANT
语句中,
ALL
[PRIVILEGES]
或
PROXY
特权必须由其自身命名,不能与其他特权一起指定。
ALL
[PRIVILEGES]
代表除了
GRANT OPTION
和
PROXY
权限
之外授予权限的级别的所有
权限。
MySQL帐户信息存储在
mysql
系统数据库
的表中
。
有关其他详细信息,请参阅
第6.2节“访问控制和帐户管理”
,其中详细讨论了
mysql
系统数据库和访问控制系统。
如果授权表包含包含混合大小写数据库或表名的特权行,并且
lower_case_table_names
系统变量设置为非零值,
REVOKE
则不能用于撤消这些特权。
有必要直接操纵授权表。
(
设置
GRANT
时不会创建此类行
lower_case_table_names
,但在设置该变量之前可能已创建此类行。该
lower_case_table_names
设置只能在服务器启动时配置。)
可以在多个级别授予权限,具体取决于
ON
子句
使用的语法
。
对于
REVOKE
,相同的
ON
语法指定要删除的权限。
对于全局,数据库,表和例程级别,
GRANT
ALL
仅分配您授予的级别上存在的权限。
例如,
是一个数据库级语句,因此它不会授予任何全局权限,例如
。
授予
不分配
或
特权。
GRANT ALL ON
db_name
.*FILE
ALL
GRANT OPTION
PROXY
该
object_type
子句(如果存在)应指定为
TABLE
,
FUNCTION
或者
PROCEDURE
当以下对象是表,存储函数或存储过程时。
用户为数据库,表,列或例程保存的权限是作为
OR
每个权限级别(包括全局级别)的帐户权限
的逻辑
而
相加形成的
。
由于在较低级别缺少该特权,因此无法拒绝在更高级别授予的特权。
例如,此语句
全局
授予
SELECT
和
INSERT
权限:
GRANT SELECT,INSERT ON *。* TO u1;
全局授予的权限适用于所有数据库,表和列,即使未在任何较低级别授予。
从MySQL 8.0.16开始,如果
partial_revokes
启用
了
系统变量
,则可以通过为特定数据库撤销在全局级别授予的权限来明确拒绝
:
GRANT SELECT,INSERT,UPDATE ON *。* TO u1; REVOKE INSERT,UPDATE on db1。* FROM u1;
上述语句的结果是,
SELECT
在全球范围适用于所有表格,而
INSERT
和
UPDATE
全局应用除了在表中
db1
。
帐户访问权限
db1
是只读的。
有关权限检查过程的详细信息,请参见 第6.2.7节“访问控制,第2阶段:请求验证” 。
如果您对一个用户使用表,列或例程权限,则服务器会检查所有用户的表,列和例程权限,这会使MySQL慢一点。 同样,如果限制任何用户的查询,更新或连接数,则服务器必须监视这些值。
MySQL使您可以授予不存在的数据库或表的权限。
对于表,要授予的
CREATE
权限
必须包括
权限。
此行为是设计使然
,旨在使数据库管理员能够为稍后要创建的数据库或表准备用户帐户和权限。
删除数据库或表时,MySQL不会自动撤消任何权限 。 但是,如果删除例程,则会撤消为该例程授予的任何例程级权限。
全局特权是管理的或适用于给定服务器上的所有数据库。
要分配全局权限,请使用
ON *.*
语法:
全部打开*。*给'someuser'@'somehost'; GRANT SELECT,INSERT ON *。*给'someuser'@'somehost';
的
CREATE TABLESPACE
,
CREATE USER
,
FILE
,
PROCESS
,
RELOAD
,
REPLICATION CLIENT
,
REPLICATION SLAVE
,
SHOW DATABASES
,
SHUTDOWN
,和
SUPER
静态特权是行政和只能在全球范围内授予。
动态权限都是全局的,只能全局授予。
其他权限可以在全球或更具体的级别授予。
GRANT OPTION
在全局级别授予
的效果
因静态和动态特权而异:
GRANT OPTION
授予任何静态全局特权适用于所有静态全局特权。
GRANT OPTION
授予任何动态权限仅适用于该动态权限。
GRANT ALL
在全局级别授予所有静态全局特权和所有当前注册的动态特权。
在执行该
GRANT
语句
之后注册的动态权限
不会追溯授予任何帐户。
MySQL将全局特权存储在
mysql.user
系统表中。
数据库权限适用于给定数据库中的所有对象。
要分配数据库级权限,请使用以下
语法:
ON
db_name
.*
全部授予mydb。*给'someuser'@'somehost'; GRANT SELECT,INSERT ON mydb。* to'someuser'@'somehost';
如果使用
ON *
语法(而不是
ON *.*
),则在数据库级别为默认数据库分配权限。
如果没有默认数据库,则会发生错误。
的
CREATE
,
DROP
,
EVENT
,
GRANT OPTION
,
LOCK TABLES
,和
REFERENCES
权限可以在数据库级别指定。
还可以在数据库级别指定表或例程特权,在这种情况下,它们适用于数据库中的所有表或例程。
MySQL将数据库权限存储在
mysql.db
系统表中。
表权限适用于给定表中的所有列。
要分配表级权限,请使用以下
语法:
ON
db_name.tbl_name
在mydb.mytbl上给所有人''someuser'@'somehost'; GRANT SELECT,在mydb.mytbl上插入'someuser'@'somehost';
如果指定
tbl_name
而不是
db_name.tbl_name
,则该语句适用
tbl_name
于默认数据库。
如果没有默认数据库,则会发生错误。
容许
priv_type
在表级的值是
ALTER
,
CREATE VIEW
,
CREATE
,
DELETE
,
DROP
,
GRANT OPTION
,
INDEX
,
INSERT
,
REFERENCES
,
SELECT
,
SHOW VIEW
,
TRIGGER
,和
UPDATE
。
表级权限适用于基表和视图。
CREATE
TEMPORARY TABLE
即使表名匹配,
它们也不适用于使用创建
的表。
有关
TEMPORARY
表特权的
信息
,请参见
第13.1.20.3节“CREATE TEMPORARY TABLE语法”
。
MySQL将表权限存储在
mysql.tables_priv
系统表中。
列权限适用于给定表中的单个列。 在列级别授予的每个权限必须后跟括号内的一列或多列。
GRANT SELECT(col1),INSERT(col1,col2)ON mydb.mytbl对'someuser'@'somehost';
可允许
priv_type
用于列(即,当你使用一个数值
column_list
条款)是
INSERT
,
REFERENCES
,
SELECT
,和
UPDATE
。
MySQL将列权限存储在
mysql.columns_priv
系统表中。
在
ALTER ROUTINE
,
CREATE ROUTINE
,
EXECUTE
,和
GRANT OPTION
权限适用于存储例程(过程和函数)。
它们可以在全局和数据库级别授予。
除此之外
CREATE ROUTINE
,可以在例程级别为单个例程授予这些特权。
在mydb上创建常规。*'someuser'@'somehost'; 程序上的执行mydb.myproc对'someuser'@'somehost';
可允许
priv_type
在常规水平值
ALTER
ROUTINE
,
EXECUTE
和
GRANT OPTION
。
CREATE ROUTINE
不是例程级特权,因为您必须具有全局或数据库级别的特权才能首先创建例程。
MySQL在
mysql.procs_priv
系统表中
存储例程级特权
。
该
PROXY
权限使一个用户成为另一个用户的代理。
代理用户冒充或取得代理用户的身份;
也就是说,它假定代理用户的特权。
授权'localuser'@'localhost'TO'externaluser'@'somehost';
当
PROXY
被授权,则必须在指定的唯一特权
GRANT
语句,唯一允许
WITH
选项
WITH
GRANT OPTION
。
代理要求代理用户通过插件进行身份验证,该插件在代理用户连接时将代理用户的名称返回给服务器,并且代理用户具有代理用户的
PROXY
权限。
有关详细信息和示例,请参见
第6.2.18节“代理用户”
。
MySQL将代理权限存储在
mysql.proxies_priv
系统表中。
GRANT
没有
ON
子句的
语法
授予角色而不是个人特权。
角色是命名的特权集合;
请参见
第6.2.10节“使用角色”
。
例如:
GRANT'rort1','role2'TO'user1'@'localhost','user2'@'localhost';
必须存在要授予的每个角色,以及要授予它的每个用户帐户或角色。 从MySQL 8.0.16开始,无法向匿名用户授予角色。
授予角色不会自动导致角色处于活动状态。 有关角色激活和失活的信息,请参阅 激活角色 。
授予角色需要这些权限:
如果您拥有
ROLE_ADMIN
或
拥有该
SUPER
权限,则可以向用户或角色授予或撤消任何角色。
如果您被授予
GRANT
包含该
WITH ADMIN OPTION
子句
的
语句
的角色
,则您可以将该角色授予其他用户或角色,或者从其他用户或角色撤消该角色,只要该角色在您随后授予时处于活动状态或撤销它。
这包括使用
WITH ADMIN OPTION
自身
的能力
。
要授予具有该
SYSTEM_USER
权限
的角色
,您必须具有该
SYSTEM_USER
权限。
可以使用创建循环引用
GRANT
。
例如:
创建用户'u1','u2'; CREATE ROLE'r1','r2'; 授予'u1'给'u1'; - 简单循环:u1 => u1 GRANT'r1'TO'r1'; - 简单循环:r1 => r1 GRANT'r2'到'u2'; GRANT'u2'to'r2'; - 混合用户/角色循环:u2 => r2 => u2
允许使用循环授权,但不向授予者添加新的特权或角色,因为用户或角色已具有其特权和角色。
从MySQL 8.0.16开始,
GRANT
有一个
子句指定有关用于语句执行的特权上下文的其他信息。
此语法在SQL级别可见,但其主要目的是通过使这些限制出现在二进制日志中,在部分撤销所强制的所有节点上实现统一复制。
有关部分撤消的信息,请参见
第6.2.12节“使用部分撤消的权限限制”
。
AS
user
[WITH
ROLE]
当
指定WHERE子句,语句的执行考虑到与指定用户相关联的任何权限限制,其中包括指定的所有角色
,如果存在的话。
结果是语句实际授予的权限可能相对于指定的权限减少。
AS
user
WITH ROLE
这些条件适用于该
条款:
AS
user
AS
仅当命名
user
具有权限限制(这意味着
partial_revokes
启用
了
系统变量)
时才有效
。
如果
WITH ROLE
给出,则必须将所有命名的角色授予named
user
。
命名
user
应指定为MySQL账户
,
或
。
当前用户可以与
执行用户想要
使用可能与当前会话中活动的角色不同的一组角色
执行的情况
一起命名
。
'
user_name
'@'host_name
'CURRENT_USER
CURRENT_USER()
WITH
ROLE
GRANT
AS
不能用于获取执行
GRANT
语句
的用户所拥有的权限
。
执行用户必须至少具有要授予的权限,但该
AS
子句只能限制授予的权限,而不能升级它们。
对于要授予的权限,
AS
无法指定具有比执行
GRANT
语句
的用户更多权限(更少限制)的用户/角色组合
。
该
AS
用户/角色组合允许具有比执行用户更多权限,但前提是该语句不授予这些额外的权限。
AS
仅支持授予全局权限(
ON *.*
)。
AS
PROXY
资助
不支持
。
以下示例说明了该
AS
子句
的效果
。
创建
u1
具有某些全局权限
的用户
,以及对这些权限的限制:
创建用户u1; GRANT SELECT,INSERT,UPDATE,DELETE ON *。* TO u1; REVOKE INSERT,更新schema1。* FROM u1; REVOKE SELECT在schema2。* FROM u1;
还要创建一个角色
r1
来解除某些权限限制并将角色授予
u1
:
创造角色r1; GRANT INSERT ON schema1。* TO r1; GRANT SELECT ON schema2。* TO r1; GRANT r1 TO u1;
现在,使用一个没有自己的权限限制的帐户,向多个用户授予相同的全局权限集,但每个
AS
权限都
受到该
子句
强加的不同限制
,并检查实际授予的权限。
GRANT
此处
的
语句没有
AS
子句,因此授予的权限正是指定的权限:
mysql>CREATE USER u2;
mysql>GRANT SELECT, INSERT, UPDATE ON *.* TO u2;
mysql>SHOW GRANTS FOR u2;
+ ------------------------------------------------- + | u2 @%|的补助金 + ------------------------------------------------- + | GRANT SELECT,INSERT,UPDATE ON *。* to`u2` @`%`| + ------------------------------------------------- +
GRANT
此处
的
语句有一个
AS
子句,因此授予的权限是指定的权限,但具有应用的限制
u1
:
mysql>CREATE USER u3;
mysql>GRANT SELECT, INSERT, UPDATE ON *.* TO u3 AS u1;
mysql>SHOW GRANTS FOR u3;
+ ------------------------------------------------- --- + | u3 @%|的补助金 + ------------------------------------------------- --- + | GRANT SELECT,INSERT,UPDATE ON *。* to`u3` @`%`| | REVOKE INSERT,更新`schema1`。* FROM`u3` @`%`| | REVOKE SELECT在`schema2`。* FROM`u3` @`%`| + ------------------------------------------------- --- +
如前所述,该
AS
子句只能添加权限限制;
它不能升级特权。
因此,虽然
u1
具有
DELETE
权限
,但
由于该语句未指定授予,因此未包含在授予的权限中
DELETE
。
此处声明
的
AS
子句
GRANT
使角色
r1
处于活动状态
u1
。
这个角色取消了一些限制
u1
。
因此,授予的权限有一些限制,但不会像以前的
GRANT
声明
那么多
:
mysql>CREATE USER u4;
mysql>GRANT SELECT, INSERT, UPDATE ON *.* TO u4 AS u1 WITH ROLE r1;
mysql>SHOW GRANTS FOR u4;
+ ------------------------------------------------- + | u4 @%|的补助金 + ------------------------------------------------- + | GRANT SELECT,INSERT,UPDATE ON *。* to`u4` @`%`| | REVOKE更新`schema1`。* FROM`u4` @`%`| + ------------------------------------------------- +
如果
GRANT
语句包含
子句,则忽略对执行语句的用户的权限限制(而不是像没有
子句时那样应用)。
AS
user
AS
optional
WITH
子句用于使用户能够向其他用户授予权限。
该
WITH
GRANT OPTION
子句使用户能够向其他用户提供用户在指定权限级别拥有的任何权限。
要在
GRANT OPTION
不更改其权限的情况下
将
权限
授予
帐户,请执行以下操作:
授予使用*。*给'someuser'@'somehost'WITH GRANT OPTION;
请注意您授予谁的
GRANT
OPTION
权限,因为具有不同权限的两个用户可能能够组合权限!
您不能授予其他用户您自己没有的权限;
该
GRANT OPTION
权限使您只能分配您自己拥有的权限。
请注意,当您授予用户
GRANT OPTION
特定权限级别的权限时,该用户在该级别拥有(或可能在将来获得)的任何权限也可由该用户授予其他用户。
假设您授予用户
INSERT
对数据库
的
权限。
如果您随后
SELECT
在数据库上
授予
权限并指定
WITH GRANT OPTION
,则该用户不仅可以向其他用户提供
SELECT
权限,还可以
INSERT
。
如果你再授予
UPDATE
权限的数据库用户,用户可以授予
INSERT
,
SELECT
和
UPDATE
。
对于非管理用户,不应
ALTER
全局或
mysql
系统数据库
授予
权限
。
如果这样做,用户可以尝试通过重命名表来破坏权限系统!
有关与特定权限相关的安全风险的其他信息,请参见 第6.2.2节“MySQL提供的权限” 。
MySQL和标准SQL版本之间的最大区别
GRANT
是:
MySQL将权限与主机名和用户名的组合相关联,而不是仅与用户名相关联。
标准SQL没有全局或数据库级特权,也不支持MySQL支持的所有特权类型。
MySQL不支持标准SQL
UNDER
权限。
标准SQL权限以分层方式构建。
如果删除用户,则会撤消已授予用户的所有权限。
如果您使用,在MySQL中也是如此
DROP
USER
。
请参见
第13.7.1.5节“DROP USER语法”
。
在标准SQL中,删除表时,将撤消表的所有权限。
在标准SQL中,撤消权限时,也会撤消基于该权限授予的所有权限。
在MySQL中,可以使用
DROP
USER
或
REVOKE
语句
删除权限
。
在MySQL中,可以
INSERT
仅对表中的某些列
具有
权限。
在这种情况下,您仍然可以
INSERT
在表上
执行
语句,前提是您只为您拥有该
INSERT
权限的
列插入值
。
如果未启用严格SQL模式,则省略的列将设置为其隐式默认值。
在严格模式下,如果任何省略的列没有默认值,则拒绝该语句。
(标准SQL要求您拥有
INSERT
所有列
的
权限。)有关严格SQL模式和隐式默认值的信息,请参阅
第5.1.11节“服务器SQL模式”
和
第11.7节“数据类型默认值”
。
重命名用户old_user
到new_user
[,old_user
TOnew_user
] ......
该
RENAME
USER
语句重命名现有的MySQL帐户。
对于不存在的旧帐户或已存在的新帐户,会出错。
要使用
RENAME
USER
,您必须具有全局
CREATE USER
特权或
系统数据库
的
UPDATE
特权
mysql
。
当
read_only
启用了系统变量,
RENAME
USER
另外需要
CONNECTION_ADMIN
或
SUPER
特权。
每个帐户名称使用 第6.2.4节“指定帐户名称”中 所述的格式 。 例如:
重命名用户'jeffrey'@'localhost'TO'jeff'@'127.0.0.1';
帐户名的主机名部分(如果省略)默认为
'%'
。
RENAME
USER
导致旧用户持有的权限是新用户持有的权限。
但是,
RENAME
USER
不会自动删除或使旧用户创建的数据库或对象无效。
这包括存储的程序或视图,
DEFINER
属性为旧用户命名。
如果在定义的安全性上下文中执行,则尝试访问此类对象可能会产生错误。
(有关安全上下文的信息,请参见
第24.6节“存储对象访问控制”
。)
权限更改将在 第6.2.13节 “特权更改生效时”中指示生效 。
REVOKEpriv_type
[(column_list
)] [,priv_type
[(column_list
)]] ...... ON [object_type
]priv_level
FROMuser_or_role
[,user_or_role
] ...... 撤消所有[特权],授予选项权限 FROMuser_or_role
[,user_or_role
] ...... REVOKE PROXYuser_or_role
来自user_or_role
[,user_or_role
] ...... REVOKErole
[,role
] ...... FROMuser_or_role
[,user_or_role
] ......user_or_role
:{user
|role
}user
: (参见第6.2.4节“指定帐户名”)role
: (请参见第6.2.5节“指定角色名称”)。
该
REVOKE
语句使系统管理员可以撤消权限和角色,这些权限和角色可以从用户帐户和角色中撤消。
有关角色的信息,请参见 第6.2.10节“使用角色” 。
当
read_only
系统变量被启用,
REVOKE
需要
CONNECTION_ADMIN
或
SUPER
特权除了在下面的讨论中描述的任何其它所需的特权。
REVOKE
要么为所有命名用户和角色成功,要么回滚,如果发生任何错误,则无效。
只有当所有命名用户和角色成功时,该语句才会写入二进制日志。
每个帐户名称使用 第6.2.4节“指定帐户名称”中 所述的格式 。 每个角色名称使用 第6.2.5节“指定角色名称”中 描述的格式 。 例如:
REVOKE INSERT ON *。* FROM'jeffrey'@'localhost'; REVOKE'rort1','role2'FROM'user1'@'localhost','user2'@'localhost'; REVOKE SELECT ON world。* FROM'rob3';
帐户或角色名称的主机名部分(如果省略)默认为
'%'
。
有关在哪些特权存在的水平,允许的细节
priv_type
,
priv_level
和
object_type
值,以及指定用户名和密码的语法,请参阅
第13.7.1.6,“GRANT和REVOKE语法”
。
要使用第一种
REVOKE
语法,您必须具有该
GRANT OPTION
权限,并且必须具有要撤消的权限。
要撤消所有权限,请使用第二种语法,该语法将删除指定用户或角色的所有全局,数据库,表,列和例程权限:
改善所有特权,授予选择权 FROMuser_or_role
[,user_or_role
] ......
REVOKE ALL PRIVILEGES, GRANT OPTION
不会撤销任何角色。
要使用此
REVOKE
语法,您必须具有全局
CREATE USER
特权或
系统数据库
的
UPDATE
特权
mysql
。
REVOKE
关键字后跟一个或多个角色名称
的语法
采用一个
FROM
子句,指示从中撤消角色的一个或多个用户或角色。
mandatory_roles
系统变量值中
命名的角色
无法撤消。
撤消的角色会立即影响撤消该角色的任何用户帐户,以便在该帐户的任何当前会话中,为下一个执行的语句调整其权限。
撤消角色会撤消角色本身,而不是撤消角色所代表的权限。
如果为帐户授予包含给定权限的角色,并且还明确授予该权限或包含该权限的其他角色,则在撤消第一个角色后,该帐户仍会被授予该权限。
例如,如果一个帐户被授予两个包含的角色
SELECT
,则该帐户仍可以在撤消任一角色后进行选择。
REVOKE ALL ON *.*
(在全局级别)撤消所有授予的静态全局特权和所有授予的动态特权。
必须存在要撤消特权和角色的用户帐户和角色,但当前不需要授予要撤消的角色。
REVOKE
删除权限,但不删除
mysql.user
系统表条目。
要完全删除用户帐户,请使用
DROP
USER
。
请参见
第13.7.1.5节“DROP USER语法”
。
如果授权表包含包含混合大小写数据库或表名的特权行,并且
lower_case_table_names
系统变量设置为非零值,
REVOKE
则不能用于撤消这些特权。
有必要直接操纵授权表。
(
设置
GRANT
时不会创建此类行
lower_case_table_names
,但在设置变量之前可能已创建此类。
lower_case_table_names
只能在初始化服务器时配置
该
设置。)
当从
mysql
程序
成功执行时
,
REVOKE
响应
Query OK, 0 rows affected
。
要确定操作后剩余的权限,请使用
SHOW
GRANTS
。
请参见
第13.7.6.21节“显示GRANTS语法”
。
设定默认角色 {无| 所有|role
[,role
] ......} TOuser
[,user
] ......
对于
user
紧跟在
TO
关键字
之后的
每个
命名
,此语句定义当用户连接到服务器并进行身份验证时,或者用户
SET
ROLE
DEFAULT
在会话期间
执行
语句
时,哪些角色变为活动状态
。
SET DEFAULT ROLE
是替代语法
ALTER
USER ... DEFAULT ROLE
(参见
第13.7.1.1节“ALTER USER语法”
)。
但是,
ALTER
USER
可以仅为单个用户
SET DEFAULT
ROLE
设置默认值
,而
可以为多个用户设置默认值。
另一方面,您可以指定
语句
CURRENT_USER
的用户名
ALTER
USER
,而不能用于
SET
DEFAULT ROLE
。
SET DEFAULT ROLE
需要这些特权:
为其他用户设置默认角色需要全局
CREATE USER
权限或
系统表
的
UPDATE
权限
mysql.default_roles
。
为自己设置默认角色不需要特殊权限,只要您希望将您想要的角色授予您。
每个角色名称使用 第6.2.5节“指定角色名称”中 描述的格式 。 例如:
SET DEFAULT ROLE管理员,开发人员TO'joe'@'10.0.0.1';
角色名称的主机名部分(如果省略)默认为
'%'
。
DEFAULT ROLE
关键字
后面的子句
允许这些值:
NONE
:将默认值设置为
NONE
(无角色)。
ALL
:将默认值设置为授予该帐户的所有角色。
:将默认值设置为命名角色,该角色必须存在并在执行时授予帐户
role
[,
role
] ...SET DEFAULT
ROLE
。
SET DEFAULT ROLE
并且
SET
ROLE
DEFAULT
是不同的陈述:
SET DEFAULT ROLE
定义帐户会话中默认激活的帐户角色。
SET
ROLE
DEFAULT
将当前会话中的活动角色设置为当前帐户默认角色。
有关角色使用示例,请参见 第6.2.10节“使用角色” 。
设置密码[FORuser
] ='auth_string
' [REPLACE'current_auth_string
'] [保留当前密码]
该
SET PASSWORD
语句为MySQL用户帐户分配密码。
它还可能包含一个password-verification子句,用于指定要替换的帐户当前密码,以及一个管理帐户是否具有二级密码的子句。
并且
每个代表一个明文(未加密)密码。
'
auth_string
''
current_auth_string
'
密码验证次密码条款仅适用于内部存储凭据的账户
mysql.user
系统表(
mysql_native_password
,
sha256_password
,或
caching_sha2_password
)。
对于使用对外部凭据系统执行身份验证的插件的帐户,还必须在该系统外部处理密码管理。
该
子句从MySQL 8.0.13开始提供。
如果给出:
REPLACE
'
current_auth_string
'
REPLACE
指定要替换的帐户当前密码,作为明文(未加密)字符串。
如果需要对帐户进行密码更改以指定当前密码,则必须提供该条款,作为尝试进行更改的用户实际知道当前密码的验证。
如果帐户的密码更改可能但不需要指定当前密码,则该子句是可选的。
如果给出了该子句但该语句与当前密码不匹配,则该语句失败,即使该子句是可选的。
REPLACE
只有在更改当前用户的帐户密码时才能指定。
有关通过指定当前密码进行密码验证的更多信息,请参见 第6.2.15节“密码管理” 。
该
RETAIN CURRENT PASSWORD
子句实现双密码功能,从MySQL 8.0.14开始提供。
如果给出:
RETAIN CURRENT PASSWORD
保留帐户当前密码作为其辅助密码,替换任何现有的二级密码。
新密码将成为主密码,但客户端可以使用该帐户使用主密码或辅助密码连接到服务器。
(例外:如果
SET PASSWORD
语句
指定的新密码
为空,则辅助密码也会变为空,即使
RETAIN CURRENT PASSWORD
已给出。)
如果
RETAIN CURRENT PASSWORD
为具有空主密码的帐户
指定
,则该语句将失败。
如果帐户具有辅助密码并且您在未指定
RETAIN CURRENT
PASSWORD
的
情况下更改其主密码
,则辅助密码将保持不变。
有关使用双密码的更多信息,请参见 第6.2.15节“密码管理” 。
语法是帐户更改的首选语句
,
而不是使用
语法
,包括分配密码。
例如:
SET PASSWORD ...
= '
auth_string
'ALTER USER
更改用户user
身份'auth_string
';
在某些情况下,
SET
PASSWORD
可以在历史文件中记录在服务器日志中或客户端上
~/.mysql_history
,这意味着任何对该信息具有读访问权限的人都可以读取明文密码。
有关服务器日志发生的条件以及如何控制它的信息,请参见
第6.1.2.3节“密码和日志记录”
。
有关客户端日志记录的类似信息,请参见
第4.5.1.3节“mysql客户端日志记录”
。
SET
PASSWORD
可以使用或不使用
FOR
明确命名用户帐户
的
子句:
使用
子句,该语句设置指定帐户的密码,该密码必须存在:
FOR
user
为'jeffrey'设置密码@'localhost'=' auth_string
';
如果没有
子句,该语句将为当前用户设置密码:
FOR
user
SET PASSWORD =' auth_string
';
使用非匿名帐户连接到服务器的任何客户端都可以更改该帐户的密码。
(特别是,您可以更改自己的密码。)要查看服务器对您进行身份验证的帐户,请调用以下
CURRENT_USER()
函数:
SELECT CURRENT_USER();
如果
给出
了
子句,则帐户名称使用
第6.2.4节“指定帐户名称”中
所述的格式
。
例如:
FOR
user
SET PASSWORD FOR'bob'@'%.example.org'=' auth_string
';
帐户名的主机名部分(如果省略)默认为
'%'
。
SET
PASSWORD
将字符串解释为明文字符串,将其传递给与帐户关联的身份验证插件,并将插件返回的结果存储在
mysql.user
系统表
的帐户行中
。
(该插件有机会将值散列为它所期望的加密格式。插件可以使用指定的值,在这种情况下不会发生散列。)
为指定帐户(带
FOR
子句)
设置密码
需要
系统数据库
的
UPDATE
权限
mysql
。
为自己设置密码(对于没有
FOR
子句
的非匿名帐户
)不需要特殊权限。
修改辅助密码的语句需要以下权限:
该
APPLICATION_PASSWORD_ADMIN
权限才能使用
RETAIN CURRENT
PASSWORD
的条款
SET
PASSWORD
适用于您自己的账户报表。
由于大多数用户只需要一个密码,因此需要使用该权限来操作您自己的二级密码。
如果允许某个帐户操作所有帐户的辅助密码,则应授予其
CREATE USER
权限,而不是
APPLICATION_PASSWORD_ADMIN
。
当
read_only
系统变量被启用,
SET PASSWORD
要求
CONNECTION_ADMIN
或
SUPER
特权,除了所需的其他特权。
有关设置密码和身份验证插件的其他信息,请参见 第6.2.14节“分配帐户密码” 和 第6.2.17节“可插入身份验证” 。
SET ROLE { 默认 | 没有 | 所有 | 除了role
[,role
]之外...... |role
[,role
] ...... }
SET
ROLE
通过指定其授予的哪些角色处于活动状态来修改当前用户在当前会话中的有效权限。
授予的角色包括明确授予用户的角色和
mandatory_roles
系统变量值中
指定的角色
。
例子:
设定角色默认; 设置角色'role1','role2'; SET ROLE ALL; SET ROLE ALL除'role1','role2'之外;
每个角色名称使用
第6.2.5节“指定角色名称”中
描述的格式
。
角色名称的主机名部分(如果省略)默认为
'%'
。
直接授予用户(而不是通过角色)的权限不受活动角色更改的影响。
该语句允许这些角色说明符:
DEFAULT
:激活帐户默认角色。
默认角色是指定的角色
SET DEFAULT ROLE
。
当用户连接到服务器并成功进行身份验证时,服务器会确定要激活哪些角色作为默认角色。
如果
activate_all_roles_on_login
启用
了
系统变量,则服务器将激活所有已授予的角色。
否则,服务器
SET
ROLE
DEFAULT
隐式
执行
。
服务器仅激活可以激活的默认角色。
对于无法激活的默认角色,服务器会将警告写入其错误日志,但客户端不会收到警告。
如果用户
SET
ROLE
DEFAULT
在会话期间
执行
,则如果无法激活任何默认角色(例如,如果它不存在或未授予用户),则会发生错误。
在这种情况下,当前活动角色不会更改。
NONE
:将活动角色设置为
NONE
(无活动角色)。
ALL
:激活授予该帐户的所有角色。
ALL EXCEPT
:激活授予帐户的所有角色,但命名的角色除外。
指定的角色不需要存在或被授予该帐户。
role
[,
role
] ...
:激活必须授予帐户的指定角色。
role
[,
role
] ...
SET DEFAULT ROLE
并且
SET
ROLE
DEFAULT
是不同的陈述:
SET DEFAULT ROLE
定义帐户会话中默认激活的帐户角色。
SET
ROLE
DEFAULT
将当前会话中的活动角色设置为当前帐户默认角色。
有关角色使用示例,请参见 第6.2.10节“使用角色” 。
MySQL支持资源组的创建和管理,并允许将服务器内运行的线程分配给特定组,以便线程根据组可用的资源执行。 本节介绍可用于资源组管理的SQL语句。 有关资源组功能的一般讨论,请参见 第8.12.5节“资源组” 。
ALTER RESOURCE GROUPgroup_name
[VCPU [=]vcpu_spec
[,vcpu_spec
] ...] [THREAD_PRIORITY [=]N
] [ENABLE | DISABLE [FORCE]]vcpu_spec
:{N
|M
-N
}
ALTER RESOURCE GROUP
用于资源组管理(请参见
第8.12.5节“资源组”
)。
此语句更改现有资源组的可修改属性。
它需要
RESOURCE_GROUP_ADMIN
特权。
group_name
标识要更改的资源组。
如果该组不存在,则会发生错误。
可以使用修改CPU亲缘关系,优先级以及是否启用组的属性
ALTER
RESOURCE GROUP
。
这些属性的描述方式与描述的相同
CREATE RESOURCE
GROUP
(参见
第13.7.2.2节“CREATE RESOURCE GROUP语法”
)。
仅更改指定的属性。
未指定的属性保留其当前值。
该
FORCE
改性剂使用
DISABLE
。
如果资源组分配了任何线程,它将确定语句行为:
如果
FORCE
未给出,则组中的现有线程将继续运行,直到它们终止,但无法将新线程分配给该组。
如果
FORCE
给定,则组中的现有线程将移动到其各自的默认组(系统线程
SYS_default
,用户线程
USR_default
)。
名称和类型属性在组创建时设置,之后不能修改
ALTER
RESOURCE GROUP
。
例子:
更改组CPU亲和性:
ALTER RESOURCE GROUP rg1 VCPU = 0-63;
更改组线程优先级:
ALTER RESOURCE GROUP rg2 THREAD_PRIORITY = 5;
禁用组,将分配给它的任何线程移动到默认组:
ALTER RESOURCE GROUP rg3 DISABLE FORCE;
资源组管理是发生它的服务器的本地管理。
ALTER RESOURCE GROUP
语句不会写入二进制日志,也不会被复制。
创建资源组group_name
TYPE = {SYSTEM | USER} [VCPU [=]vcpu_spec
[,vcpu_spec
] ......] [THREAD_PRIORITY [=]N
] [ENABLE | DISABLE]vcpu_spec
:{N
|M
-N
}
CREATE RESOURCE GROUP
用于资源组管理(请参见
第8.12.5节“资源组”
)。
此语句创建新资源组并分配其初始属性值。
它需要
RESOURCE_GROUP_ADMIN
特权。
group_name
标识要创建的资源组。
如果该组已存在,则会发生错误。
该
TYPE
属性是必需的。
它应该是
SYSTEM
系统资源组,
USER
用于用户资源组。
组类型会影响允许的
THREAD_PRIORITY
值,如稍后所述。
该
VCPU
属性表示CPU亲和性;
也就是说,组可以使用的虚拟CPU集合:
如果
VCPU
未给出,则资源组没有CPU关联,并且可以使用所有可用的CPU。
如果
VCPU
给定,则属性值是逗号分隔的CPU编号或范围的列表:
每个数字必须是一个整数,范围从0到CPU数量 - 1.例如,在具有64个CPU的系统上,数字的范围可以是0到63。
范围以
M
-
N
,
M
小于或等于
的形式给出,
N
两个数字都在CPU范围内。
如果CPU编号是超出允许范围的整数或不是整数,则会发生错误。
示例
VCPU
说明符(这些都是等效的):
VCPU = 0,1,2,3,9,10 VCPU = 0-3,9-10 VCPU = 9,10,0-3 VCPU = 0,10,1,9,3,2
该
THREAD_PRIORITY
属性指示分配给组的线程的优先级:
如果
THREAD_PRIORITY
未给出,则默认优先级为0。
如果
THREAD_PRIORITY
给定,则属性值必须在-20(最高优先级)到19(最低优先级)的范围内。
系统资源组的优先级必须介于-20到0之间。用户资源组的优先级必须介于0到19之间。对系统和用户组使用不同的范围可确保用户线程永远不会更高优先级高于系统线程。
ENABLE
并
DISABLE
指定最初启用或禁用资源组。
如果未指定,则默认情况下启用该组。
禁用的组不能分配线程。
例子:
创建具有单个CPU且优先级最低的已启用用户组:
CREATE RESOURCE GROUP rg1 TYPE = USER VCPU = 0 THREAD_PRIORITY = 19;
创建一个没有CPU关联(可以使用所有CPU)和最高优先级的已禁用系统组:
CREATE RESOURCE GROUP rg2 TYPE = SYSTEM THREAD_PRIORITY = -20 禁用;
资源组管理是发生它的服务器的本地管理。
CREATE RESOURCE GROUP
语句不会写入二进制日志,也不会被复制。
DROP RESOURCE GROUP group_name
[FORCE]
DROP RESOURCE GROUP
用于资源组管理(请参见
第8.12.5节“资源组”
)。
此语句删除资源组。
它需要
RESOURCE_GROUP_ADMIN
特权。
group_name
标识要删除的资源组。
如果该组不存在,则会发生错误。
该
FORCE
修改决定声明的行为,如果资源组具有分配给它的任何线程:
如果
FORCE
未给出并且任何线程都分配给该组,则会发生错误。
如果
FORCE
给定,则组中的现有线程将移动到其各自的默认组(系统线程
SYS_default
,用户线程
USR_default
)。
例子:
删除组,如果组包含任何线程,则失败:
DROP RESOURCE GROUP rg1;
删除组并将现有线程移动到默认组:
DROP RESOURCE GROUP rg2 FORCE;
资源组管理是发生它的服务器的本地管理。
DROP RESOURCE GROUP
语句不会写入二进制日志,也不会被复制。
SET RESOURCE GROUPgroup_name
[FORthread_id
[,thread_id
] ...]
SET RESOURCE GROUP
用于资源组管理(请参见
第8.12.5节“资源组”
)。
此语句将线程分配给资源组。
它需要
RESOURCE_GROUP_ADMIN
或
RESOURCE_GROUP_USER
特权。
group_name
标识要分配的资源组。
任何
thread_id
值都表示要分配给组的线程。
可以从Performance Schema
threads
表中
确定线程ID
。
如果资源组或任何命名的线程ID不存在,则会发生错误。
如果没有
FOR
子句,则语句将会话的当前线程分配给资源组。
使用
FOR
命名线程ID
的
子句,该语句将这些线程分配给资源组。
对于将系统线程分配给用户资源组或将用户线程分配给系统资源组的尝试,会发出警告。
例子:
将当前会话线程分配给组:
SET RESOURCE GROUP rg1;
将命名线程分配给组:
SET RESOURCE GROUP rg2 FOR 14,18,4;
资源组管理是发生它的服务器的本地管理。
SET RESOURCE GROUP
语句不会写入二进制日志,也不会被复制。
另一种方法
SET RESOURCE
GROUP
是
RESOURCE_GROUP
优化器提示,它将单个语句分配给资源组。
请参见
第8.9.3节“优化程序提示”
。
分析[NO_WRITE_TO_BINLOG | 本地] 表tbl_name
[,tbl_name
] ...... 分析[NO_WRITE_TO_BINLOG | 本地] TABLEtbl_name
UPDATE HISTOGRAM ONcol_name
[,col_name
] ... [带N
桶] 分析[NO_WRITE_TO_BINLOG | 本地] 表tbl_name
DROP HISTOGRAM ONcol_name
[,col_name
] ...
ANALYZE
TABLE
生成表统计信息:
ANALYZE
TABLE
如果没有任何一个
HISTOGRAM
子句执行密钥分发分析并存储指定表或表的分布。
对于
MyISAM
表,
ANALYZE TABLE
关键分布分析相当于使用
myisamchk --analyze
。
ANALYZE
TABLE
with
UPDATE HISTOGRAM
子句为命名表列生成直方图统计信息,并将它们存储在数据字典中。
此语法只允许使用一个表名。
ANALYZE
TABLE
with
DROP HISTOGRAM
子句从数据字典中删除指定表列的直方图统计信息。
此语法只允许使用一个表名。
如果
innodb_read_only
启用
了
系统变量,则
ANALYZE
TABLE
可能会失败,因为它无法更新数据字典中使用的统计表
InnoDB
。
对于
ANALYZE
TABLE
更新密钥分发的操作,即使操作更新表本身(例如,如果它是
MyISAM
表)
,也可能发生故障
。
要获取更新的分布统计信息,请设置
information_schema_stats_expiry=0
。
此语句需要
表的权限
SELECT
和
INSERT
特权。
ANALYZE
TABLE
有工作
InnoDB
,
NDB
和
MyISAM
表。
它不适用于视图。
ANALYZE
TABLE
分区表支持,您可以
ALTER TABLE ...
ANALYZE PARTITION
用来分析一个或多个分区;
有关更多信息,请参见
第13.1.9节“ALTER TABLE语法”
和
第23.3.4节“分区维护”
。
在分析过程中,表格被锁定,读取锁定为
InnoDB
和
MyISAM
。
默认情况下,服务器将
ANALYZE
TABLE
语句
写入
二进制日志,以便它们复制到复制从属服务器。
要禁止记录,请指定可选
NO_WRITE_TO_BINLOG
关键字或其别名
LOCAL
。
ANALYZE
TABLE
返回结果集,其中包含下表中显示的列。
柱 | 值 |
---|---|
Table |
表名 |
Op |
analyze
要么
histogram
|
Msg_type |
status
,
error
,
info
,
note
,或
warning
|
Msg_text |
信息性消息 |
ANALYZE
TABLE
如果没有任何一个
HISTOGRAM
子句执行密钥分发分析并存储一个或多个表的分布。
任何现有的直方图统计数据都不受影响。
如果自上次密钥分发分析以来表未更改,则不再对该表进行分析。
MySQL使用存储的密钥分发来决定表连接的顺序,以便在常量之外的连接上进行连接。 此外,在决定用于查询中的特定表的索引时,可以使用密钥分发。
有关密钥分发分析如何工作的更多信息
InnoDB
,请参见
第15.8.10.1节“配置持久优化器统计信息参数”
和
第15.8.10.3节“估算InnoDB表的分析表复杂度”
。
另请参见
第15.6.1.6节“InnoDB表的限制”
。
特别是,当您启用该
innodb_stats_persistent
选项时,必须
ANALYZE
TABLE
在将大量数据加载到
InnoDB
表中或为其创建新索引后运行。
要检查存储的密钥分发基数,请使用
SHOW
INDEX
语句或
INFORMATION_SCHEMA
STATISTICS
表。
请参见
第13.7.6.22节“SHOW INDEX语法”
和
第25.26节“INFORMATION_SCHEMA STATISTICS表”
。
ANALYZE
TABLE
使用
HISTOGRAM
子句可以管理表列值的直方图统计信息。
有关直方图统计信息,请参见
第8.9.6节“优化程序统计信息”
。
这些直方图操作可用:
ANALYZE
TABLE
with
UPDATE HISTOGRAM
子句为命名表列生成直方图统计信息,并将它们存储在数据字典中。
此语法只允许使用一个表名。
可选
子句指定直方图的桶数。
值
必须是1到1024之间的整数。如果省略该子句,则桶数为100。
WITH
N
BUCKETSN
ANALYZE
TABLE
with
DROP HISTOGRAM
子句从数据字典中删除指定表列的直方图统计信息。
此语法只允许使用一个表名。
存储的直方图管理语句仅影响指定的列。 请考虑以下陈述:
分析表t更新c1,c2,c3上有10个桶的直方图; 分析表t更新c1,c3上有10个桶的直方图; 在c2上分析表t DROP HISTOGRAM;
第一条语句将更新列的直方图
c1
,
c2
以及
c3
,替换任何现有的直方图那些列。
第二条语句更新直方图
c1
和
c3
,离开
c2
直方图不受影响。
第三个语句删除了直方图
c2
,留下
了直方图
c1
和
c3
不受影响
的直方图
。
加密表不支持直方图生成(以避免在统计信息中公开数据)或
TEMPORARY
表。
直方图生成适用于除几何类型(空间数据)和之外的所有数据类型的列
JSON
。
可以为存储的和虚拟生成的列生成直方图。
无法为单列唯一索引所涵盖的列生成直方图。
直方图管理语句尝试尽可能多地执行所请求的操作,并报告剩余部分的诊断消息。
例如,如果
UPDATE
HISTOGRAM
语句指定多个列,但其中一些列不存在或具有不受支持的数据类型,则会为其他列生成直方图,并为无效列生成消息。
所述
histogram_generation_max_mem_size
系统变量控制的可用于直方图生成存储器的最大量。
可以在运行时设置全局和会话值。
更改全局
histogram_generation_max_mem_size
值需要足以设置全局系统变量的权限。
更改会话
histogram_generation_max_mem_size
值需要足以设置受限会话系统变量的权限。
请参见
第5.1.9.1节“系统变量权限”
。
有关为直方图生成执行的内存分配的信息,请监视性能模式
memory/sql/histograms
工具。
请参见
第26.12.16.10节“内存汇总表”
。
直方图受这些DDL语句的影响:
DROP
TABLE
删除已删除表中列的直方图。
DROP
DATABASE
删除已删除数据库中任何表的直方图,因为该语句删除了数据库中的所有表。
RENAME
TABLE
不删除直方图。
相反,它重命名重命名表的直方图以与新表名相关联。
ALTER
TABLE
删除或修改列的语句删除该列的直方图。
ALTER
TABLE
... CONVERT TO CHARACTER SET
删除字符列的直方图,因为它们受字符集更改的影响。
非字符列的直方图不受影响。
ANALYZE TABLE
从
INFORMATION_SCHEMA.INNODB_TABLESTATS
表中
清除表统计信息
并将
STATS_INITIALIZED
列
设置
为
Uninitialized
。
下次访问表时将再次收集统计信息。
检查表tbl_name
[,tbl_name
] ...... [option
] ......option
:{ 升级 | 快 | 快速 | 介质 | EXTENDED | CHANGED }
CHECK
TABLE
检查一个或多个表是否有错误。
CHECK
TABLE
还可以检查视图是否存在问题,例如视图定义中不再存在的表。
要检查表,您必须拥有一些权限。
CHECK
TABLE
适用于
InnoDB
,
MyISAM
,
ARCHIVE
,和
CSV
表格。
在运行之前
CHECK
TABLE
对
InnoDB
表,请参见
检查表使用说明InnoDB表
。
CHECK
TABLE
分区表支持,您可以
ALTER TABLE ...
CHECK PARTITION
用来检查一个或多个分区;
有关更多信息,请参见
第13.1.9节“ALTER TABLE语法”
和
第23.3.4节“分区维护”
。
CHECK
TABLE
忽略未编制索引的虚拟生成列。
CHECK
TABLE
返回结果集,其中包含下表中显示的列。
柱 | 值 |
---|---|
Table |
表名 |
Op |
总是
check
|
Msg_type |
status
,
error
,
info
,
note
,或
warning
|
Msg_text |
信息性消息 |
该语句可能会为每个已检查的表生成许多行信息。
最后一行具有
Msg_type
的价值
status
和
Msg_text
正常应该是
OK
。
Table is already up to
date
表示表的存储引擎表示不需要检查表。
该
FOR UPGRADE
选项检查命名表是否与当前版本的MySQL兼容。
使用时
FOR UPGRADE
,服务器会检查每个表,以确定自表创建以来是否存在任何表的数据类型或索引中的任何不兼容的更改。
如果没有,检查成功。
否则,如果存在可能的不兼容性,则服务器会对表执行全面检查(可能需要一些时间)。
由于数据类型的存储格式已更改或排序顺序已更改,因此可能会出现不兼容问题。 我们的目标是避免这些变化,但偶尔也需要纠正比版本之间不兼容更糟糕的问题。
FOR UPGRADE
发现这些不兼容性:
在MySQL 4.1和5.0之间
,
TEXT
列
InnoDB
和
MyISAM
表中的
结束空间的索引顺序
发生了变化。
DECIMAL
在MySQL 5.0.3和5.0.5之间更改
了新
数据类型
的存储方法
。
有时会对需要重建表索引的字符集或排序规则进行更改。 有关此类更改的详细信息,请参见 第2.11.4节“MySQL 8.0中的更改” 。 有关重建表的信息,请参见 第2.11.13节“重建或修复表或索引” 。
MySQL 8.0不支持
YEAR(2)
旧版MySQL中允许
的
数据类型。
对于包含
YEAR(2)
列的表,
CHECK TABLE
推荐
REPAIR TABLE
,转换
YEAR(2)
为
YEAR(4)
。
触发器创建时间保持不变。
一个表被报告为需要重建,如果它包含在预5.6.4格式老时间列(
TIME
,
DATETIME
,和
TIMESTAMP
列不为小数精度秒支持)和
avoid_temporal_upgrade
系统变量被禁用。
这有助于MySQL升级过程检测和升级包含旧时间列的表。
如果
avoid_temporal_upgrade
启用,则
FOR UPGRADE
忽略表中存在的旧时间列;
因此,升级过程不会升级它们。
要检查包含此类临时列并需要重建的表,请
avoid_temporal_upgrade
在执行前
禁用
CHECK TABLE
... FOR UPGRADE
。
对使用非本地分区的表发出警告,因为在MySQL 8.0中删除了非本地分区。 请参见 第23章, 分区 。
下表显示了可以给出的其他检查选项。 这些选项将传递给存储引擎,存储引擎可能会使用或忽略它们。
类型 | 含义 |
---|---|
QUICK |
不要扫描行以检查错误的链接。
适用于
InnoDB
并
MyISAM
表和视图。
|
FAST |
仅检查未正确关闭的表。
被忽略了
InnoDB
;
仅适用于
MyISAM
表和视图。
|
CHANGED |
仅检查自上次检查后已更改的表或未正确关闭的表。
被忽略了
InnoDB
;
仅适用于
MyISAM
表和视图。
|
MEDIUM |
扫描行以验证已删除的链接是否有效。
这还计算行的密钥校验和,并使用计算的密钥校验和进行验证。
被忽略了
InnoDB
;
仅适用于
MyISAM
表和视图。
|
EXTENDED |
对每行的所有键执行完整键查找。
这可确保表格100%一致,但需要很长时间。
被忽略了
InnoDB
;
仅适用于
MyISAM
表和视图。
|
您可以组合检查选项,如以下示例中快速检查表以确定它是否已正确关闭:
检查表test_table快速快速;
如果
CHECK
TABLE
发现与被标记为表上没有问题,
“
损坏
”
或
“
不正确关闭
”
,
CHECK
TABLE
可以删除标记。
如果表已损坏,则问题很可能出现在索引中而不是数据部分中。 所有上述检查类型都会彻底检查索引,因此应该找到大多数错误。
要检查您认为合适的表,请不要使用选项或
QUICK
选项。
当你赶时间时应该使用后者,并且可以承担
QUICK
在数据文件中没有发现错误
的非常小的风险
。
(在大多数情况下,在正常使用情况下,MySQL应该在数据文件中发现任何错误。如果发生这种情况,表将被标记为
“
已损坏
”,
并且在修复之前无法使用。)
FAST
并且
CHANGED
主要用于从脚本(例如,从
cron
执行
)中定期检查表。
在大多数情况下,
FAST
是优先考虑的
CHANGED
。
(唯一不喜欢的情况是,当您怀疑自己在
MyISAM
代码中
发现了错误时
。)
EXTENDED
只有在运行正常检查后才能使用,但在MySQL尝试更新行或按键查找行时仍会从表中获取错误。
如果正常检查成功,这是不太可能的。
使用
CHECK
TABLE ... EXTENDED
可能会影响查询优化器生成的执行计划。
报告的一些问题
CHECK
TABLE
无法自动纠正:
Found row where the auto_increment column has the
value 0
。
这意味着在表中有一行,其中
AUTO_INCREMENT
索引列包含值0.(
AUTO_INCREMENT
通过使用
UPDATE
语句
将列显式设置为0,
可以创建一个列为
0
的行
。)
这本身不是错误,但如果您决定转储表并将其还原或
ALTER
TABLE
在表上
执行操作,则可能会导致问题
。
在这种情况下,
AUTO_INCREMENT
列会根据
AUTO_INCREMENT
列
的规则更改值
,这可能会导致诸如重复键错误之类的问题。
要删除警告,请执行
UPDATE
语句以将列设置为0以外的某个值。
以下说明适用于
InnoDB
表格:
如果
CHECK TABLE
遇到损坏的页面,服务器将退出以防止错误传播(Bug#10132)。
如果在辅助索引中发生损坏但表数据是可读的,则运行
CHECK TABLE
仍可导致服务器退出。
如果
CHECK TABLE
遇到
聚簇索引中
的损坏
DB_TRX_ID
或
DB_ROLL_PTR
字段,则
CHECK TABLE
可能导致
InnoDB
访问无效的撤消日志记录,从而导致与
MVCC
相关的服务器退出。
如果
CHECK TABLE
遇到
InnoDB
表或索引中的错误,它会报告错误,并且通常会标记索引,有时会将表标记为已损坏,从而阻止进一步使用索引或表。
此类错误包括辅助索引中的条目数不正确或链接不正确。
如果
CHECK TABLE
在辅助索引中找到错误的条目数,则会报告错误但不会导致服务器退出或阻止访问该文件。
CHECK
TABLE
调查索引页面结构,然后调查每个键入项。
它不验证指向聚簇记录的键指针或遵循
BLOB
指针
路径
。
当
InnoDB
表被存储在它自己的
.ibd
文件
,第一个3
页
所述的
.ibd
文件包含标题信息,而不是表或索引数据。
该
CHECK TABLE
语句不会检测仅影响标题数据的不一致性。
要验证
InnoDB
.ibd
文件
的全部内容
,请使用
innochecksum
命令。
CHECK TABLE
在大型
InnoDB
表
上
运行
时
,其他线程可能在
CHECK
TABLE
执行
期间被阻止
。
为避免超时,信号量等待阈值(600秒)延长了2小时(7200秒)以进行
CHECK
TABLE
操作。
如果
InnoDB
检测到信号量等待240秒或更长时间,则会开始将
InnoDB
监视器输出
打印
到错误日志。
如果锁定请求超出信号量等待阈值,则
InnoDB
中止该过程。
为了避免信号量等待超时的可能性,请运行
CHECK TABLE
QUICK
而不是
CHECK
TABLE
。
CHECK
TABLE
InnoDB
SPATIAL
索引的
功能
包括R树有效性检查和检查以确保R树行计数与聚簇索引匹配。
CHECK
TABLE
支持虚拟生成列上的二级索引,这些列受支持
InnoDB
。
从MySQL 8.0.14开始,
InnoDB
支持并行聚簇索引读取,这可以提高
CHECK TABLE
性能。
InnoDB
在
CHECK TABLE
操作
期间两次读取聚簇索引
。
第二次读取可以并行执行。
的
innodb_parallel_read_threads
会话变量必须被设置为一个大于1的值用于并行聚簇索引读取发生。
默认值为4.用于执行并行聚簇索引读取的实际线程
innodb_parallel_read_threads
数由要扫描的索引子树
的
设置或数量决定,取较小者。
以下说明适用于
MyISAM
表格:
CHECK
TABLE
更新
MyISAM
表的
关键统计信息
。
如果
CHECK TABLE
输出没有返回
OK
或者
Table is
already up to date
,您通常应该对表进行修复。
请参见
第7.6节“MyISAM表维护和崩溃恢复”
。
如果没有
指定
任何
CHECK TABLE
选项
QUICK
,
MEDIUM
或者
EXTENDED
指定了动态格式
MyISAM
表
的默认检查类型
MEDIUM
。
这与
在表上
运行
myisamchk --medium-check的
tbl_name
结果相同
。
除非
或
指定
,否则
默认检查类型也适用
MEDIUM
于静态格式
MyISAM
表
。
在这种情况下,默认值为
。
跳过行扫描
,
因为行很少被破坏。
CHANGED
FAST
QUICK
CHANGED
FAST
CHECKSUM TABLEtbl_name
[,tbl_name
] ... [QUICK | EXTENDED]
CHECKSUM
TABLE
报告
表的内容的
校验和
。
您可以使用此语句验证备份,回滚或其他旨在将数据恢复到已知状态的操作之前和之后的内容相同。
此语句需要
SELECT
表
的
权限。
视图不支持此语句。
如果
CHECKSUM TABLE
针对视图
运行
,则
Checksum
值始终为
NULL
,并返回警告。
对于不存在的表,
CHECKSUM
TABLE
返回
NULL
并生成警告。
在校验和操作期间,表被锁定,读取锁定为
InnoDB
和
MyISAM
。
默认情况下,逐行读取整个表并计算校验和。
对于大型表,这可能需要很长时间,因此您只会偶尔执行此操作。
这种逐行计算是您使用
EXTENDED
子句
InnoDB
以及除了之外的所有其他存储引擎
MyISAM
以及
MyISAM
不使用该
CHECKSUM=1
子句
创建的表所获得的
。
对于
MyISAM
使用该
CHECKSUM=1
子句
创建的表
,
CHECKSUM TABLE
或
CHECKSUM TABLE
... QUICK
返回
可以非常快速地
返回的
“
实时
”
表校验和。
如果表不满足所有这些条件,则
QUICK
返回
该
方法
NULL
。
表
QUICK
不支持
该
方法
InnoDB
。
有关
该
子句
的语法,
请参见
第13.1.20节“CREATE TABLE语法”
CHECKSUM
。
校验和值取决于表行格式。
如果行格式更改,则校验和也会更改。
例如,对于时间类型,如存储格式
TIME
,
DATETIME
以及
TIMESTAMP
在MySQL 5.6之前的MySQL 5.6.5改变,因此,如果5.5表升级到MySQL 5.6,校验和的值可能会改变。
如果两个表的校验和不同,那么几乎可以肯定这些表在某种程度上是不同的。
但是,由于使用的散列函数
CHECKSUM TABLE
不能保证无冲突,因此两个不相同的表可能会产生相同的校验和。
OPTIMIZE [NO_WRITE_TO_BINLOG | 本地] 表tbl_name
[,tbl_name
] ......
OPTIMIZE
TABLE
重新组织表数据和关联索引数据的物理存储,以减少存储空间并提高访问表时的I / O效率。
对每个表所做的确切更改取决于
该表使用
的
存储引擎
。
OPTIMIZE TABLE
在这些情况下
使用
,具体取决于表的类型:
在对
InnoDB
具有自己的
.ibd文件
的
表
执行实质性插入,更新或删除操作之后,
因为它是在
innodb_file_per_table
启用选项的
情况下创建的
。
重新组织表和索引,并且可以回收磁盘空间以供操作系统使用。
FULLTEXT
对作为
InnoDB
表中
索引
一部分的列进行实质性插入,更新或删除操作之后
。
首先设置配置选项
innodb_optimize_fulltext_only=1
。
要将索引维护期保持在合理的时间,请设置
innodb_ft_num_word_optimize
选项以指定要在搜索索引中更新的单词数,并运行一系列
OPTIMIZE
TABLE
语句,直到搜索索引完全更新为止。
删除的大部分后
MyISAM
或
ARCHIVE
表,或者使许多变化为
MyISAM
或
ARCHIVE
具有可变长度的行表(表具有
VARCHAR
,
VARBINARY
,
BLOB
,或
TEXT
列)。
删除的行在链表中维护,后续
INSERT
操作重用旧的行位置。
您可以
OPTIMIZE
TABLE
用来回收未使用的空间并对数据文件进行碎片整理。
在对表进行大量更改后,此语句还可能会提高使用该表的语句的性能,有时甚至会显着提高。
此语句需要
表的权限
SELECT
和
INSERT
特权。
OPTIMIZE
TABLE
工程
InnoDB
,
MyISAM
和
ARCHIVE
表。
OPTIMIZE TABLE
内存
NDB
表的
动态列也支持
。
它不适用于内存表的固定宽度列,也不适用于磁盘数据表。
OPTIMIZE
可以使用调整NDB Cluster表
的性能,该
表
--ndb-optimization-delay
控制在处理批次行之间等待的时间长度
OPTIMIZE TABLE
。
有关更多信息,请参阅
NDB Cluster 7.3中已解决的先前NDB群集问题
。
对于NDB Cluster表,
OPTIMIZE
TABLE
可以通过(例如)中断执行
OPTIMIZE
操作
的SQL线程来中断
。
默认情况下,
OPTIMIZE TABLE
也
不能
使用任何其它存储引擎创建的表工作,并返回指示这种缺乏支持的结果。
您可以
OPTIMIZE
TABLE
通过
使用该
选项
启动
mysqld
来为其他存储引擎工作
--skip-new
。
在这种情况下,
OPTIMIZE
TABLE
只是映射到
ALTER
TABLE
。
此语句不适用于视图。
OPTIMIZE
TABLE
分区表支持。
有关将此语句与分区表和表分区一起使用的信息,请参见
第23.3.4节“分区维护”
。
默认情况下,服务器将
OPTIMIZE
TABLE
语句
写入
二进制日志,以便它们复制到复制从属服务器。
要禁止记录,请指定可选
NO_WRITE_TO_BINLOG
关键字或其别名
LOCAL
。
OPTIMIZE
TABLE
返回结果集,其中包含下表中显示的列。
柱 | 值 |
---|---|
Table |
表名 |
Op |
总是
optimize
|
Msg_type |
status
,
error
,
info
,
note
,或
warning
|
Msg_text |
信息性消息 |
OPTIMIZE
TABLE
table捕获并抛出将表统计信息从旧文件复制到新创建的文件时发生的任何错误。
例如。
如果所有者的用户ID
.MYD
或
.MYI
文件是从的用户ID不同
的mysqld
过程,
OPTIMIZE TABLE
除非生成一个“不能改变文件的所有权”错误
的mysqld
由启动
root
用户。
对于
InnoDB
表,
OPTIMIZE TABLE
映射到
ALTER
TABLE ...
FORCE
,重建表以更新索引统计信息并释放聚簇索引中未使用的空间。
OPTIMIZE
TABLE
当您在
InnoDB
表格
上运行它时,它
会显示在输出中
,如下所示:
mysql> OPTIMIZE TABLE foo; + ---------- + ---------- + ---------- + ---------------- -------------------------------------------------- - + | 表| Op | Msg_type | Msg_text | + ---------- + ---------- + ---------- + ---------------- -------------------------------------------------- - + | test.foo | 优化| 注意| 表不支持优化,而是重新创建+分析 | test.foo | 优化| 状态| 好的 + ---------- + ---------- + ---------- + ---------------- -------------------------------------------------- - +
OPTIMIZE
TABLE
将
在线DDL
用于常规
InnoDB
表
和分区
表,从而减少并发DML操作的停机时间。
由
OPTIMIZE
TABLE
封面
引发
并在封面下执行
的表重建
ALTER
TABLE ...
FORCE
已就位完成。
仅在操作的准备阶段和提交阶段期间短暂地进行独占表锁定。
在准备阶段,更新元数据并创建中间表。
在提交阶段,将提交表元数据更改。
OPTIMIZE
TABLE
在以下条件下使用表复制方法重建表:
当
old_alter_table
系统变量启用。
当
mysqld的
--skip-new
选项启用。
OPTIMIZE
TABLE
包含
索引的
表
不支持
使用
联机DDL
。
而是使用表格复制方法。
InnoDB
FULLTEXT
InnoDB
使用页面分配方法存储数据,并且不会像传统存储引擎(例如
MyISAM
)
那样遭受碎片
。
在考虑是否运行优化时,请考虑服务器将处理的事务的工作负载:
预计会有一定程度的碎片化。
InnoDB
只填充
93%的
页面
,以便在不分页的情况下留出更新空间。
删除操作可能会留下空白,使页面填充不如预期,这可能使得优化表格变得有价值。
当有足够的空间时,对行的更新通常会重写同一页面中的数据,具体取决于数据类型和行格式。 请参见 第15.9.1.5节“压缩如何用于InnoDB表” 和 第15.10节“InnoDB行格式” 。
高并发工作负载可能会随着时间的推移在索引中留下空白,
InnoDB
因为通过其
MVCC
机制
保留了相同数据的多个版本
。
请参见
第15.3节“InnoDB多版本控制”
。
对于
MyISAM
表格,
OPTIMIZE TABLE
工作如下:
如果表已删除或拆分行,请修复该表。
如果索引页未排序,请对它们进行排序。
如果表的统计信息不是最新的(并且无法通过对索引进行排序来完成修复),请更新它们。
OPTIMIZE
TABLE
在线执行常规和分区
InnoDB
表。
否则,MySQL
会在
OPTIMIZE
TABLE
运行
期间
锁定表
。
OPTIMIZE
TABLE
不对R树索引进行排序,例如
POINT
列
上的空间索引
。
(缺陷号23578)
维修[NO_WRITE_TO_BINLOG | 本地] 表tbl_name
[,tbl_name
] ...... [QUICK] [EXTENDED] [USE_FRM]
REPAIR
TABLE
修复可能已损坏的表,仅适用于某些存储引擎。
此语句需要
表的权限
SELECT
和
INSERT
特权。
虽然通常你不应该运行
REPAIR
TABLE
,但是如果发生灾难,这个语句很可能会从
MyISAM
表中
获取所有数据
。
如果您的表经常损坏,请尝试找到它的原因,以消除使用的需要
REPAIR
TABLE
。
请参见
第B.4.3.3节“如果MySQL不断崩溃该怎么办”
,以及
第16.2.4节“MyISAM表问题”
。
REPAIR
TABLE
检查表以查看是否需要升级。
如果是,则按照与之相同的规则执行升级
CHECK
TABLE ... FOR
UPGRADE
。
有关
更多信息
,
请参见
第13.7.3.2节“CHECK TABLE语法”
。
在执行表修复操作之前备份表; 在某些情况下,操作可能会导致数据丢失。 可能的原因包括但不限于文件系统错误。 请参见 第7章, 备份和恢复 。
如果服务器在
REPAIR
TABLE
操作
期间崩溃
,则在重新启动它之后必须立即执行
REPAIR TABLE
该表的
另一个
语句,然后再对其执行任何其他操作。
在最坏的情况下,您可能有一个新的干净索引文件,但没有关于数据文件的信息,然后您执行的下一个操作可能会覆盖该数据文件。
这是一种不太可能但可能的情况,强调了首先进行备份的价值。
如果主服务器上的表已损坏并且您
REPAIR TABLE
在其上
运行
,则对原始表的任何更改都
不会
传播到从服务器。
REPAIR
TABLE
工程
MyISAM
,
ARCHIVE
和
CSV
表。
对于
MyISAM
表格,
默认情况下
它与
myisamchk --recover
tbl_name
具有相同的效果
。
此语句不适用于视图。
REPAIR
TABLE
分区表支持。
但是,该
USE_FRM
选项不能与分区表上的此语句一起使用。
您可以
ALTER TABLE ... REPAIR
PARTITION
用来修复一个或多个分区;
有关更多信息,请参见
第13.1.9节“ALTER TABLE语法”
和
第23.3.4节“分区维护”
。
NO_WRITE_TO_BINLOG
要么
LOCAL
默认情况下,服务器将
REPAIR
TABLE
语句
写入
二进制日志,以便它们复制到复制从属服务器。
要禁止记录,请指定可选
NO_WRITE_TO_BINLOG
关键字或其别名
LOCAL
。
QUICK
如果使用该
QUICK
选项,则
REPAIR TABLE
尝试仅修复索引文件,而不是数据文件。
这种类型的修复就像
myisamchk --recover --quick
所做的那样
。
EXTENDED
如果使用该
EXTENDED
选项,MySQL会逐行创建索引,而不是一次创建一个索引并进行排序。
这种类型的修复就像
myisamchk --safe-recover
所做的
那样
。
USE_FRM
USE_FRM
如果
.MYI
索引文件丢失或其标头已损坏,
则可以使用
该
选项
。
此选项告诉MySQL不要信任
.MYI
文件头中
的信息,
并使用数据字典中的信息重新创建它。
使用
myisamchk
无法进行此类修复
。
仅
在无法使用常规
模式
时才
使用该
USE_FRM
选项
。
告诉服务器忽略该
文件会使重要的表元数据存储在
修复过程不可用的状态,这可能会产生有害后果:
REPAIR
.MYI
.MYI
当前
AUTO_INCREMENT
值丢失。
表中已删除记录的链接将丢失,这意味着已删除记录的可用空间此后将保持未被占用状态。
的
.MYI
报头指示该表是否被压缩。
如果服务器忽略此信息,则无法判断表是否已压缩,并且修复可能导致表内容的更改或丢失。
这意味着
USE_FRM
不应该与压缩表一起使用。
无论如何,这应该是不必要的:压缩表是只读的,因此它们不应该被破坏。
如果您使用
USE_FRM
的是由不同版本的MySQL服务器创建的表而不是当前正在运行
REPAIR TABLE
的表
,
则不会尝试修复该表。
在这种情况下,返回的结果集
REPAIR
TABLE
包含
Msg_type
值为
error
和
Msg_text
值为的行
Failed
repairing incompatible .FRM file
。
如果
USE_FRM
使用,
REPAIR TABLE
则不检查表以查看是否需要升级。
REPAIR
TABLE
返回结果集,其中包含下表中显示的列。
柱 | 值 |
---|---|
Table |
表名 |
Op |
总是
repair
|
Msg_type |
status
,
error
,
info
,
note
,或
warning
|
Msg_text |
信息性消息 |
该
REPAIR TABLE
语句可能会为每个已修复的表生成许多行信息。
最后一行具有
Msg_type
的价值
status
和
Msg_test
正常应该是
OK
。
对于一张
MyISAM
桌子,如果你没有
OK
,你应该尝试用
myisamchk
修复它
--safe-recover
。
(
REPAIR TABLE
没有实现
myisamchk的
所有选项
。使用
myisamchk --safe-recover
,您也可以使用
REPAIR TABLE
不支持的
选项
,例如
--max-record-length
。)
REPAIR
TABLE
table捕获并抛出将表统计信息从旧的损坏文件复制到新创建的文件时发生的任何错误。
例如。
如果所有者的用户ID
.MYD
或
.MYI
文件是从的用户ID不同
的mysqld
过程,
REPAIR TABLE
除非生成一个“不能改变文件的所有权”错误
的mysqld
由启动
root
用户。
REPAIR
TABLE
如果表包含5.6.4之前格式的旧时间列(
TIME
和
DATETIME
,
TIMESTAMP
不支持小数秒精度的列
,并且
avoid_temporal_upgrade
系统变量被禁用
),则对
表进行升级
。
如果
avoid_temporal_upgrade
已启用,则
REPAIR TABLE
忽略表中存在的旧时间列,并且不升级它们。
要升级包含此类时间列的表,请
avoid_temporal_upgrade
在执行前
禁用
REPAIR TABLE
。
您可以
REPAIR
TABLE
通过设置某些系统变量
来提高
性能。
请参见
第8.6.3节“优化REPAIR TABLE语句”
。
创建[AGGREGATE]功能function_name
退货{STRING | INTEGER | REAL | DECIMAL} SONAMEshared_library_name
用户定义函数(UDF)是一种使用新函数扩展MySQL的方法,该函数类似于本机(内置)MySQL函数,如
ABS()
或
CONCAT()
。
function_name
是应该在SQL语句中用于调用函数的名称。
该
RETURNS
子句指示函数返回值的类型。
DECIMAL
是一个合法的值
RETURNS
,但目前
DECIMAL
函数返回字符串值,应该像
STRING
函数
一样编写
。
shared_library_name
是包含实现该功能的代码的共享库文件的基本名称。
该文件必须位于插件目录中。
该目录由
plugin_dir
系统变量
的值给出
。
有关更多信息,请参见
第5.7.1节“安装和卸载用户定义的函数”
。
要创建函数,您必须具有
系统数据库
的
INSERT
权限
mysql
。
这是必要的,因为
CREATE FUNCTION
向
mysql.func
系统表
添加一行
,记录函数的名称,类型和共享库名称。
使用注册的UDF
CREATE
FUNCTION
列在Performance Schema
user_defined_functions
表中;
请参见
第26.12.17.6节“user_defined_functions表”
。
活动功能是已加载但
CREATE FUNCTION
未被删除的功能
DROP FUNCTION
。
每次服务器启动时都会重新加载所有活动函数,除非您
使用该
选项
启动
mysqld
--skip-grant-tables
。
在这种情况下,将跳过UDF初始化并且UDF不可用。
有关编写用户定义函数的说明,请参见 第29.4.2节“添加新的用户定义函数” 。 要使UDF机制起作用,函数必须用C或C ++(或其他可以使用C调用约定的语言)编写,操作系统必须支持动态加载,并且必须 动态 编译 mysqld (非静态 编译 )。
一个
AGGREGATE
函数的工作原理完全像一个本地的MySQL骨料(摘要)功能,如
SUM
或
COUNT()
。
要升级与UDF关联的共享库,请发出
DROP FUNCTION
语句,升级共享库,然后发出
CREATE FUNCTION
语句。
如果先升级共享库然后再使用
DROP FUNCTION
,则服务器可能会崩溃。
降功能 function_name
此语句删除名为的用户定义函数(UDF)
function_name
。
要删除函数,您必须具有
系统数据库
的
DELETE
权限
mysql
。
这是因为
DROP FUNCTION
从
mysql.func
系统表中
删除了一行,该行
记录了函数的名称,类型和共享库名称。
要升级与UDF关联的共享库,请发出
DROP FUNCTION
语句,升级共享库,然后发出
CREATE FUNCTION
语句。
如果先升级共享库然后再使用
DROP FUNCTION
,则服务器可能会崩溃。
DROP
FUNCTION
也用于删除存储的函数(参见
第13.1.29节“DROP PROCEDURE和DROP FUNCTION语法”
)。
安装组件component_name
[,component_name
] ...
此语句将安装一个或多个服务器组件,这些组件将立即生效。
组件提供服务器和其他组件可用的服务;
请参见
第5.5节“MySQL服务器组件”
。
INSTALL COMPONENT
需要
系统表
的
INSERT
权限
mysql.component
。
例:
INSTALL COMPONENT'file:// component1','file:// component2';
组件名称是以开头的URN,
file://
并指示实现组件的文件的基本名称,位于
plugin_dir
系统变量
指定的目录中
。
组件名称不包括任何与平台相关的文件名后缀,例如
.so
或
.dll
。
(这些命名细节可能会发生变化,因为组件名称解释本身是由服务执行的,组件基础结构使得可以用替代实现替换默认服务实现。)
如果发生任何错误,语句将失败并且无效。 例如,如果组件名称错误,命名组件不存在或已安装,或组件初始化失败,则会发生这种情况。
加载器服务处理组件加载,包括将已安装的组件添加到
mysql.component
充当注册表
的
系统表中。
对于后续服务器重新启动,
mysql.component
加载器服务在启动序列期间加载
列出的任何组件
。
即使使用该
--skip-grant-tables
选项
启动服务器,也会发生这种情况
。
如果组件依赖于注册表中不存在的服务,并且您尝试安装组件而不安装提供其所依赖的服务的组件,则会发生错误:
ERROR 3527(HY000):无法满足服务'component_a'的依赖性 组件'component_b'需要。
要避免此问题,请在同一语句中安装所有组件,或者在安装依赖组件所依赖的任何组件之后安装它们。
安装插件plugin_name
SONAME'shared_library_name
'
此语句安装服务器插件。
它需要
系统表
的
INSERT
权限
mysql.plugin
。
plugin_name
是库文件中包含的插件描述符结构中定义的插件的名称(请参见
第29.2.4.2节“插件数据结构”
)。
插件名称不区分大小写。
为了获得最大兼容性,插件名称应限制为ASCII字母,数字和下划线,因为它们用于C源文件,shell命令行,M4和Bourne
shell脚本以及SQL环境。
shared_library_name
是包含插件代码的共享库的名称。
该名称包括文件扩展名(例如,
libmyplugin.so
,
libmyplugin.dll
,或
libmyplugin.dylib
)。
共享库必须位于插件目录(
plugin_dir
系统变量
指定的目录
)中。
该库必须位于插件目录本身,而不是在子目录中。
默认情况下,
plugin_dir
是
配置变量
plugin
指定
的
目录下的目录
pkglibdir
,但可以通过设置
plugin_dir
服务器启动时
的值来更改
目录
。
例如,将其值设置在
my.cnf
文件中:
的[mysqld]
PLUGIN_DIR =/path/to/plugin/directory
如果值
plugin_dir
是相对路径名,则将其视为相对于MySQL基目录(
basedir
系统变量
的值
)。
INSTALL
PLUGIN
加载并初始化插件代码以使插件可供使用。
插件通过执行其初始化函数进行初始化,该函数处理插件在使用之前必须执行的任何设置。
当服务器关闭时,它会为每个加载的插件执行取消初始化函数,以便插件有机会执行任何最终的清理。
INSTALL
PLUGIN
还通过向
mysql.plugin
系统表
添加指示插件名称和库文件名的行来注册插件
。
在服务器启动时,服务器会加载并初始化其中列出的任何插件
mysql.plugin
。
这意味着插件只安装
INSTALL PLUGIN
一次,而不是每次服务器启动时安装。
如果使用该
--skip-grant-tables
选项
启动服务器,则不会在启动时加载插件
。
插件库可以包含多个插件。
对于每个要安装的,请使用单独的
INSTALL
PLUGIN
语句。
每个语句都命名一个不同的插件,但它们都指定了相同的库名。
INSTALL
PLUGIN
使服务器
my.cnf
像在服务器启动期间一样
读取option(
)文件。
这使插件能够从这些文件中获取任何相关选项。
即使在加载插件之前(如果使用
loose
前缀)
,也可以将插件选项添加到选项文件中
。
也可以再次卸载插件,编辑
my.cnf
和安装插件。
以这种方式重新启动插件使其能够在不重新启动服务器的情况下使用新选项值。
有关在服务器启动时控制单个插件加载的选项,请参见
第5.6.1节“安装和卸载插件”
。
如果在
--skip-grant-tables
给出选项
时需要为单个服务器启动加载插件
(这告诉服务器不要读取系统表),请使用该
--plugin-load
选项。
请参见
第5.1.7节“服务器命令选项”
。
要删除插件,请使用该
UNINSTALL
PLUGIN
语句。
有关插件加载的其他信息,请参见 第5.6.1节“安装和卸载插件” 。
要查看安装了哪些插件,请使用该
SHOW PLUGINS
语句或查询
INFORMATION_SCHEMA
该
PLUGINS
表。
如果重新编译插件库并需要重新安装它,则可以使用以下任一方法:
使用
UNINSTALL PLUGIN
卸载所有插件库,安装在插件目录中的新插件的库文件,然后使用
INSTALL PLUGIN
安装的所有插件库。
此过程的优点是可以在不停止服务器的情况下使用它。
但是,如果插件库包含许多插件,则必须发出许多
INSTALL PLUGIN
和
UNINSTALL PLUGIN
语句。
停止服务器,在插件目录中安装新的插件库文件,然后重新启动服务器。
卸载组件component_name
[,component_name
] ......
此语句停用并卸载一个或多个服务器组件。
组件提供服务器和其他组件可用的服务;
请参见
第5.5节“MySQL服务器组件”
。
UNINSTALL COMPONENT
是补充
INSTALL COMPONENT
。
它需要
系统表
的
DELETE
权限
mysql.component
。
例:
UNINSTALL COMPONENT'file:// component1','file:// component2';
有关组件命名的信息,请参见 第13.7.4.3节“安装组件语法” 。
如果发生任何错误,语句将失败并且无效。 例如,如果组件名称错误,未安装命名组件或无法卸载,则会发生这种情况,因为其他已安装的组件依赖于它。
加载器服务处理组件卸载,其中包括从
mysql.component
充当注册表
的
系统表中
删除已卸载的组件
。
因此,在启动过程中不会加载卸载的组件,以便后续服务器重新启动。
卸载插件 plugin_name
此语句删除已安装的服务器插件。
它需要
系统表
的
DELETE
权限
mysql.plugin
。
UNINSTALL PLUGIN
是补充
INSTALL PLUGIN
。
plugin_name
必须是
mysql.plugin
表中
列出的某个插件的名称
。
服务器执行插件的取消
mysql.plugin
初始化
函数并从
系统表中
删除插件的行
,以便后续服务器重新启动不会加载并初始化插件。
UNINSTALL PLUGIN
不会删除插件的共享库文件。
如果任何使用它的表打开,则无法卸载插件。
删除插件会影响关联表的使用。
例如,如果全文解析器插件与
FULLTEXT
表上的索引
相关联
,则卸载插件会使表无法使用。
任何访问该表的尝试都会导致错误。
该表甚至无法打开,因此您无法删除使用该插件的索引。
这意味着除非您不关心表内容,否则卸载插件是需要小心的。
如果你正在卸载插件而不想在以后重新安装它而你关心表内容,你应该使用
mysqldump
转储表
并
WITH PARSER
从dumped中
删除该
子句
CREATE
TABLE
语句,以便您以后可以重新加载表。
如果您不关心该表,
DROP
TABLE
即使缺少与该表关联的任何插件
,
也可以使用该表。
有关插件加载的其他信息,请参见 第5.6.1节“安装和卸载插件” 。
该
SET
声明有几种形式。
与特定服务器功能无关的表单的描述显示在本节的小节中:
SET
使您可以将值分配给影响服务器或客户端操作的变量。
请参见
第13.7.5.1节“变量赋值的SET语法”
。
var_name
=
value
SET CHARACTER SET
并
SET
NAMES
为与服务器当前连接关联的字符集和排序规则变量赋值。
请参见
第13.7.5.2节“SET CHARACTER SET语法”
和
第13.7.5.3节“SET NAMES语法”
。
其他表单的描述出现在别处,与其帮助实现的功能相关的其他语句组合在一起:
SET DEFAULT ROLE
并
SET
ROLE
设置用户帐户的默认角色和当前角色。
请参见
第13.7.1.9节“SET DEFAULT ROLE语法”
和
第13.7.1.11节“SET ROLE语法”
。
SET
PASSWORD
分配帐户密码。
请参见
第13.7.1.10节“设置密码语法”
。
SET RESOURCE GROUP
将线程分配给资源组。
请参见
第13.7.2.4节“SET RESOURCE GROUP语法”
。
SET
TRANSACTION ISOLATION LEVEL
设置事务处理的隔离级别。
请参见
第13.3.7节“SET TRANSACTION语法”
。
SETvariable
=expr
[,variable
=expr
] ......variable
:{user_var_name
|param_name
|local_var_name
| {GLOBAL | @@ GLOBAL。}system_var_name
| {PERSIST | @@ PERSIST。}system_var_name
| {PERSIST_ONLY | @@ PERSIST_ONLY。}system_var_name
| [会话| @@会议。| @@]system_var_name
}
SET
变量赋值的语法使您可以将值分配给影响服务器或客户端操作的不同类型的变量:
用户定义的变量。 请参见 第9.4节“用户定义的变量” 。
存储过程和函数参数,以及存储的程序局部变量。 请参见 第13.6.4节“存储程序中的变量” 。
系统变量。 请参见 第5.1.8节“服务器系统变量” 。 系统变量也可以在服务器启动时设置,如 第5.1.9节“使用系统变量”中所述 。
一个
SET
是分配变量值的语句不写入二进制日志,因此在复制方案只会影响您在其上执行它的主机。
要影响所有复制主机,请在每个主机上执行该语句。
以下部分描述
SET
了设置变量的语法。
它们使用
=
赋值运算符,但
:=
也允许赋值运算符用于此目的。
用户定义的变量在会话中本地创建,仅存在于该会话的上下文中; 请参见 第9.4节“用户定义的变量” 。
用户定义的变量写为
并赋予表达式值,如下所示:
@
var_name
SET @var_name
=expr
;
例子:
SET @name = 43; SET @total_tax =(SELECT SUM(tax)FROM taxable_transactions);
正如这些语句所证明的那样,
expr
范围从简单(文字值)到更复杂(标量子查询返回的值)。
Performance Schema
user_variables_by_thread
表包含有关用户定义变量的信息。
请参见
第26.12.10节“性能模式用户定义变量表”
。
SET
适用于定义它们的存储对象上下文中的参数和局部变量。
以下过程使用
increment
procedure参数和
counter
局部变量:
CREATE PROCEDURE p(增量INT) 开始 DECLARE计数器INT DEFAULT 0; WHILE counter <10 DO - ... 做工作 ... SET counter = counter + increment; 结束时间; 结束;
MySQL服务器维护配置其操作的系统变量。
系统变量可以具有影响整个服务器操作的全局值,影响当前会话的会话值,或两者。
许多系统变量是动态的,可以在运行时使用该
SET
语句
更改,
以影响当前服务器实例的操作。
SET
也可用于将某些系统变量持久保存到
mysqld-auto.cnf
数据目录中
的
文件,以影响后续启动的服务器操作。
如果更改会话系统变量,则该值在会话中保持有效,直到您将变量更改为其他值或会话结束。 此更改对其他会话没有影响。
如果更改全局系统变量,则会记住该值并用于初始化新会话的会话值,直到将变量更改为其他值或服务器退出为止。 访问全局值的任何客户端都可以看到此更改。 但是,更改仅影响更改后连接的客户端的相应会话值。 全局变量更改不会影响任何当前客户端会话的会话值(甚至不会影响发生全局值更改的会话)。
要使全局系统变量设置为永久性以便在服务器重新启动时应用,可以将其持久保存到
mysqld-auto.cnf
数据目录中
的
文件中。
也可以通过手动修改
my.cnf
选项文件
来进行持久的配置更改
,但这样做更麻烦,并且手动输入的设置中的错误可能要到很晚才能发现。
SET
持久化系统变量的语句更方便,并避免设置格式错误的可能性,因为具有语法错误的设置不会成功并且不会更改服务器配置。
有关保留系统变量和
mysqld-auto.cnf
文件的
详细信息
,请参阅
第5.1.9.3节“持久系统变量”
。
设置或保持全局系统变量值始终需要特殊权限。 设置会话系统变量值通常不需要特殊权限,可以由任何用户完成,但也有例外。 有关更多信息,请参见 第5.1.9.1节“系统变量权限” 。
以下讨论描述了设置和保存系统变量的语法选项:
要为全局系统变量赋值,请在变量名前面加上
GLOBAL
关键字或
@@GLOBAL.
限定符:
SET GLOBAL max_connections = 1000; SET @@ GLOBAL.max_connections = 1000;
要分配一个值到会话系统变量,由前面的变量名
SESSION
或
LOCAL
关键字,由
@@SESSION.
,
@@LOCAL.
或
@@
预选赛,或没有关键字或者没有修饰可言:
SET SESSION sql_mode ='TRADITIONAL'; SET LOCAL sql_mode ='TRADITIONAL'; SET @@ SESSION.sql_mode ='TRADITIONAL'; SET @@ LOCAL.sql_mode ='TRADITIONAL'; SET @@ sql_mode ='TRADITIONAL'; SET sql_mode ='TRADITIONAL';
客户端可以更改自己的会话变量,但不能更改任何其他客户端的变量。
要将全局系统变量持久保存到
mysqld-auto.cnf
数据目录中
的
选项文件,请在变量名前面加上
PERSIST
关键字或
@@PERSIST.
限定符:
SET PERSIST max_connections = 1000; SET @@ PERSIST.max_connections = 1000;
此
SET
语法使您可以在运行时进行配置更改,这些更改也会在服务器重新启动时保持不变。
比如
SET
GLOBAL
,
SET
PERSIST
设置全局变量运行时值,但也将变量设置写入
mysqld-auto.cnf
文件(如果有的话,替换任何现有的变量设置)。
要在
mysqld-auto.cnf
不设置全局变量运行时值的情况下将
全局系统变量保留到
文件,请在变量名前面加上
PERSIST_ONLY
关键字或
@@PERSIST_ONLY.
限定符:
SET PERSIST_ONLY back_log = 100; SET @@ PERSIST_ONLY.back_log = 100;
比如
PERSIST
,
PERSIST_ONLY
将变量设置写入
mysqld-auto.cnf
。
但是,与之不同
PERSIST
,
PERSIST_ONLY
不会修改全局变量运行时值。
这
PERSIST_ONLY
适用于配置只能在服务器启动时设置的只读系统变量。
要将已编译的MySQL缺省值或会话系统变量的全局系统变量值设置为当前对应的全局值,请将该变量设置为该值
DEFAULT
。
例如,以下两个语句在将会话值设置
max_join_size
为当前全局值时
完全相同
:
SET @@ SESSION.max_join_size = DEFAULT; SET @@ SESSION.max_join_size = @@ GLOBAL.max_join_size;
使用
SET
一个全局系统变量坚持到的值
DEFAULT
或者它的字面默认值赋给变量的默认值,并增加了对变量的设置
mysqld-auto.cnf
。
要从文件中删除变量,请使用
RESET PERSIST
。
某些系统变量无法保留或持久受限。 请参见 第5.1.9.4节“不可容忍且持久限制的系统变量” 。
如果在
SET
执行语句
时安装了插件,则可以持久保存由插件实现的系统变量
。
如果仍然安装了插件,则持久插件变量的分配将对后续服务器重新启动生效。
如果不再安装插件,则在服务器读取
mysqld-auto.cnf
文件
时,插件变量将不存在
。
在这种情况下,服务器会向错误日志写入警告并继续:
目前未知的变量' var_name
'
从持久化的配置文件中读取
要显示系统变量名称和值:
使用
SHOW VARIABLES
声明;
请参见
第13.7.6.39节“显示变量语法”
。
多个Performance Schema表提供系统变量信息。 请参见 第26.12.13节“性能模式系统变量表” 。
性能模式
variables_info
表包含显示最近设置每个系统变量的用户的时间和位置的信息。
请参见
第26.12.13.2节“性能模式variables_info表”
。
Performance Schema
persisted_variables
表提供了
mysqld-auto.cnf
文件
的SQL接口
,允许在运行时使用它来检查其内容
SELECT
语句
。
请参见
第26.12.13.1节“性能模式persisted_variables表”
。
如果语句中的任何变量赋值
SET
失败,则整个语句将失败,并且不会更改任何变量,也不会
mysqld-auto.cnf
更改文件。
SET
在这里描述的情况下产生错误。
大多数例子都显示出来
SET
使用关键字语法的语句(例如,
GLOBAL
或
SESSION
),但对于使用相应修饰符(例如,
@@GLOBAL.
或
@@SESSION.
)的
语句,原则也是如此
。
使用
SET
(任何变体)设置只读变量:
MySQL的> SET GLOBAL version = 'abc';
ERROR 1238(HY000):变量'version'是只读变量
用于
GLOBAL
,
PERSIST
或
PERSIST_ONLY
设定一个只有一个会话值的变量:
MySQL的> SET GLOBAL sql_log_bin = ON;
ERROR 1228(HY000):变量'sql_log_bin'是一个SESSION
变量,不能与SET GLOBAL一起使用
用于
SESSION
设置是只有一个全局值的变量:
MySQL的> SET SESSION max_connections = 1000;
ERROR 1229(HY000):变量'max_connections'是a
GLOBAL变量,应使用SET GLOBAL设置
遗漏的
GLOBAL
,
PERSIST
或
PERSIST_ONLY
设定一个只有一个全局值的变量:
MySQL的> SET max_connections = 1000;
ERROR 1229(HY000):变量'max_connections'是a
GLOBAL变量,应使用SET GLOBAL设置
使用
PERSIST
或
PERSIST_ONLY
设置无法持久化的变量:
MySQL的>SET PERSIST port = 3307;
ERROR 1238(HY000):变量'port'是只读变量 MySQL的>SET PERSIST_ONLY port = 3307;
ERROR 1238(HY000):变量'port'是非持久只读变量
的
@@GLOBAL.
,
@@PERSIST.
,
@@PERSIST_ONLY.
,
@@SESSION.
,和
@@
修饰只适用于系统变量。
尝试将它们应用于用户定义的变量,存储过程或函数参数或存储的程序局部变量时发生错误。
并非所有系统变量都可以设置为
DEFAULT
。
在这种情况下,将
DEFAULT
结果
分配给
错误。
尝试分配
DEFAULT
给用户定义的变量,存储过程或函数参数或存储的程序局部变量时发生错误。
一个
SET
语句可以包含多个变量赋值,以逗号分隔。
此语句将值分配给用户定义的变量和系统变量:
SET @x = 1,SESSION sql_mode ='';
如果你在一个声明中设置多个系统变量,最近一段时间
GLOBAL
,
PERSIST
,
PERSIST_ONLY
,或
SESSION
在声明中关键字用于以下有没有指定的关键字分配。
多变量赋值的示例:
SET GLOBAL sort_buffer_size = 1000000,SESSION sort_buffer_size = 1000000; SET @@ GLOBAL.sort_buffer_size = 1000000,@@ LOCAL.sort_buffer_size = 1000000; SET GLOBAL max_connections = 1000,sort_buffer_size = 1000000;
的
@@GLOBAL.
,
@@PERSIST.
,
@@PERSIST_ONLY.
,
@@SESSION.
,和
@@
修饰只适用于紧随其后的系统变量,没有任何剩余的系统变量。
此语句将
sort_buffer_size
全局值设置为50000,将会话值设置为1000000:
SET @@ GLOBAL.sort_buffer_size = 50000,sort_buffer_size = 1000000;
要在表达式中引用系统变量的值,请使用其中一个
@@
-modifiers(除了
@@PERSIST.
和
@@PERSIST_ONLY.
,表达式中不允许)。
例如,您可以在如下
SELECT
语句中
检索系统变量值
:
SELECT @@ GLOBAL.sql_mode,@@ SESSION.sql_mode,@@ sql_mode;
对表达式中的系统变量的引用为
(
而不是
或
)将返回会话值(如果存在),否则返回全局值。
这不同于
,它总是指会话值。
@@
var_name
@@
@@GLOBAL.
@@SESSION.
SET @@
var_name
=
expr
SET {CHARACTER SET | CHARSET}
{' charset_name
'| 默认}
此语句将使用给定映射映射服务器和当前客户端之间发送的所有字符串。
SET CHARACTER
SET
设置三个会话系统变量:
character_set_client
并
character_set_results
设置为给定的字符集,并
character_set_connection
设置为值
character_set_database
。
请参见
第10.4节“连接字符集和排序”
。
charset_name
可以引用或不引用。
可以使用该值恢复默认字符集映射
DEFAULT
。
默认值取决于服务器配置。
某些字符集不能用作客户端字符集。
试图使用它们
SET CHARACTER
SET
会产生错误。
请参见
不允许的客户端字符集
。
设置名称{'charset_name
' [COLLATE'collation_name
'] | 默认}
该语句设置三届系统变量
character_set_client
,
character_set_connection
以及
character_set_results
给定的字符集。
设置
character_set_connection
到
charset_name
也设置
collation_connection
为默认排序规则
charset_name
。
请参见
第10.4节“连接字符集和排序”
。
可选
COLLATE
子句可用于明确指定排序规则。
如果给定,则排序规则必须是允许的排序规则之一
charset_name
。
charset_name
并且
collation_name
可以引用或不引用。
可以使用值来恢复默认映射
DEFAULT
。
默认值取决于服务器配置。
某些字符集不能用作客户端字符集。
试图使用它们
SET
NAMES
会产生错误。
请参见
不允许的客户端字符集
。
SHOW
有许多表单提供有关服务器的数据库,表,列或状态信息的信息。
本节介绍以下内容:
显示{BINARY | MASTER} LOGS 显示BINLOG事件[IN'log_name
'] [FROMpos
] [LIMIT [offset
,]row_count
] 显示字符集[like_or_where
] SHOW COLLATION [like_or_where
] 从tbl_name
[FROMdb_name
] [like_or_where
] 显示[FULL] COLUMNS 显示创建数据库db_name
显示创建事件event_name
显示创建功能func_name
显示创建过程proc_name
显示创建表tbl_name
显示创建触发器trigger_name
显示创建视图view_name
显示数据库[like_or_where
] SHOW ENGINEengine_name
{STATUS | MUTEX} 显示[存储]发动机 显示错误[限制[offset
,]row_count
] 展示活动 显示功能代码func_name
显示功能状态[like_or_where
] 显示[FROM ]user
显示索引的资助tbl_name
db_name
显示主要状态 显示打开的表格[FROMdb_name
] [like_or_where
] 显示插件 显示程序代码proc_name
显示程序状态[like_or_where
] 显示特权 显示[FULL] PROCESSLIST SHOW PROFILE [types
] [FOR QUERYn
] [OFFSETn
] [LIMITn
] 显示配置文件 显示RELAYLOG活动[IN'log_name
'] [FROMpos
] [LIMIT [offset
,]row_count
] SHOW SLAVE HOSTS SHOW SLAVE STATUS [FOR CHANNELchannel
] SHOW [GLOBAL | 会话]状态[like_or_where
] SHOW TABLE STATUS [FROMdb_name
] [like_or_where
] SHOW [FULL] TABLES [FROMdb_name
] [like_or_where
] SHOW TRIGGERS [FROMdb_name
] [like_or_where
] SHOW [GLOBAL | 会话] VARIABLES [like_or_where
] 显示警告[限制[offset
,]row_count
]like_or_where
: 喜欢'pattern
' | 哪里expr
如果给定
SHOW
语句
的语法
包含一个
部分,
则是一个可以包含SQL
和
通配符的字符串。
该模式对于将语句输出限制为匹配值很有用。
LIKE
'
pattern
''
pattern
'%
_
有几个
SHOW
语句也接受一个
WHERE
子句,它在指定要显示的行方面提供了更大的灵活性。
请参见
第25.42节“扩展显示语句”
。
许多MySQL API(例如PHP)使您能够像处理
SHOW
结果集一样
处理从
语句
返回
的结果
SELECT
;
有关更多信息,
请参见
第28章,
连接器和API
或API文档。
此外,您可以在SQL中使用对
INFORMATION_SCHEMA
数据库中的
表的查询结果
,而这些结果对于
SHOW
语句的
结果是不容易的
。
请参见
第25章,
INFORMATION_SCHEMA表
。
显示二进制日志 显示主日志
列出服务器上的二进制日志文件。
此语句用作
第13.4.1.1节“PURGE BINARY LOGS语法”中
描述的过程的一部分,该过程
说明了如何确定可以清除哪些日志。
SHOW BINARY
LOGS
需要
REPLICATION
CLIENT
或
SUPER
特权。
加密的二进制日志文件具有512字节的文件头,其存储加密和解密文件所需的信息。
这包含在显示的文件大小中
SHOW BINARY LOGS
。
该
Encrypted
列显示二进制日志文件是否已加密。
如果
binlog_encryption=ON
为服务器设置了
二进制日志加密,则它是活动
的。
如果在服务器运行时激活或停用二进制日志加密,则不会对现有二进制日志文件进行加密或解密。
MySQL的> SHOW BINARY LOGS;
+ --------------- + ----------- ----------- + +
| Log_name | File_size | 加密|
+ --------------- + ----------- ----------- + +
| binlog.000015 | 724935 | 是的|
| binlog.000016 | 733481 | 是的|
+ --------------- + ----------- ----------- + +
展示BINLOG活动 [IN'log_name
'] [FROMpos
] [限制[offset
,]row_count
]
显示二进制日志中的事件。
如果未指定
,则显示第一个二进制日志。
需要
特权。
'
log_name
'SHOW BINLOG
EVENTS
REPLICATION
SLAVE
该
LIMIT
子句的语法与
SELECT
语句
相同
。
请参见
第13.2.10节“SELECT语法”
。
发出
SHOW BINLOG EVENTS
with no
LIMIT
子句可能会启动耗费时间和资源的过程,因为服务器会向客户端返回二进制日志的完整内容(包括修改数据的服务器执行的所有语句)。
作为替代方案
SHOW
BINLOG EVENTS
,使用
mysqlbinlog
实用程序将二进制日志保存到文本文件中以供以后检查和分析。
请参见
第4.6.8节“
mysqlbinlog
- 处理二进制日志文件的实用程序”
。
SHOW BINLOG EVENTS
显示二进制日志中每个事件的以下字段:
Log_name
要列出的文件的名称。
Pos
事件发生的位置。
Event_type
描述事件类型的标识符。
Server_id
发生事件的服务器的服务器ID。
End_log_pos
下一个事件开始的位置,等于
Pos
加上事件的大小。
Info
有关事件类型的更多详细信息。 此信息的格式取决于事件类型。
与设置用户和系统变量有关的一些事件不包括在输出中
SHOW BINLOG EVENTS
。
要完全覆盖二进制日志中的事件,请使用
mysqlbinlog
。
SHOW BINLOG EVENTS
并
没有
与中继日志文件。
你可以用它
SHOW RELAYLOG EVENTS
来达到这个目的。
显示字符集 [喜欢'pattern
'| 在哪里expr
]
该
SHOW CHARACTER SET
语句显示所有可用的字符集。
该
LIKE
子句(如果存在)指示要匹配的字符集名称。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
例如:
MySQL的> SHOW CHARACTER SET LIKE 'latin%';
+ --------- + ----------------------------- + --------- ---------- + -------- +
| Charset | 说明| 默认排序规则| Maxlen |
+ --------- + ----------------------------- + --------- ---------- + -------- +
| 拉丁1 | cp1252西欧| latin1_swedish_ci | 1 |
| 拉丁文2 | ISO 8859-2中欧| latin2_general_ci | 1 |
| 拉丁语5 | ISO 8859-9土耳其语| latin5_turkish_ci | 1 |
| 拉丁语7 | ISO 8859-13 Baltic | latin7_general_ci | 1 |
+ --------- + ----------------------------- + --------- ---------- + -------- +
SHOW CHARACTER SET
输出有以下列:
Charset
字符集名称。
Description
字符集的描述。
Default collation
字符集的默认排序规则。
Maxlen
存储一个字符所需的最大字节数。
该
filename
字符集是仅供内部使用;
因此,
SHOW CHARACTER
SET
不显示它。
INFORMATION_SCHEMA
CHARACTER_SETS
表格中
也提供了字符集信息
。
请参见
第25.2节“INFORMATION_SCHEMA CHARACTER_SETS表”
。
显示收集 [喜欢'pattern
'| 在哪里expr
]
此语句列出服务器支持的排序规则。
默认情况下,输出
SHOW
COLLATION
包括所有可用的排序规则。
该
LIKE
子句(如果存在)指示要匹配的归类名称。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
例如:
MySQL的> SHOW COLLATION WHERE Charset = 'latin1';
+ ------------------- + --------- + ---- + --------- + ---- ------ + --------- +
| 整理| Charset | Id | 默认| 编译| Sortlen |
+ ------------------- + --------- + ---- + --------- + ---- ------ + --------- +
| latin1_german1_ci | 拉丁1 | 5 | | 是的| 1 |
| latin1_swedish_ci | 拉丁1 | 8 | 是的| 是的| 1 |
| latin1_danish_ci | 拉丁1 | 15 | | 是的| 1 |
| latin1_german2_ci | 拉丁1 | 31 | | 是的| 2 |
| latin1_bin | 拉丁1 | 47 | | 是的| 1 |
| latin1_general_ci | 拉丁1 | 48 | | 是的| 1 |
| latin1_general_cs | 拉丁1 | 49 | | 是的| 1 |
| latin1_spanish_ci | 拉丁1 | 94 | | 是的| 1 |
+ ------------------- + --------- + ---- + --------- + ---- ------ + --------- +
SHOW
COLLATION
输出有以下列:
Collation
整理名称。
Charset
与排序规则关联的字符集的名称。
Id
整理ID。
Default
排序规则是否为其字符集的默认值。
Compiled
字符集是否编译到服务器中。
Sortlen
这与对字符集中表示的字符串进行排序所需的内存量有关。
若要查看每个字符集的默认排序规则,请使用以下语句。
Default
是一个保留字,所以要将其用作标识符,必须引用它:
MySQL的> SHOW COLLATION WHERE `Default` = 'Yes';
+ --------------------- + ---------- + ---- + --------- + - --------- --------- + +
| 整理| Charset | Id | 默认| 编译| Sortlen |
+ --------------------- + ---------- + ---- + --------- + - --------- --------- + +
| big5_chinese_ci | big5 | 1 | 是的| 是的| 1 |
| dec8_swedish_ci | dec8 | 3 | 是的| 是的| 1 |
| cp850_general_ci | cp850 | 4 | 是的| 是的| 1 |
| hp8_english_ci | hp8 | 6 | 是的| 是的| 1 |
| koi8r_general_ci | koi8r | 7 | 是的| 是的| 1 |
| latin1_swedish_ci | 拉丁1 | 8 | 是的| 是的| 1 |
...
INFORMATION_SCHEMA
COLLATIONS
表格中
也提供了整理信息
。
请参见
第25.4节“INFORMATION_SCHEMA COLLATIONS表”
。
显示[EXTENDED] [FULL] {COLUMNS | FIELDS} {FROM | IN}tbl_name
[{FROM | IN}db_name
] [喜欢'pattern
'| 在哪里expr
]
SHOW
COLUMNS
显示有关给定表中列的信息。
它也适用于视图。
SHOW
COLUMNS
仅显示您具有某些权限的列的信息。
MySQL的> SHOW COLUMNS FROM City;
+ ------------- + ---------- + ------ + ------ + --------- + - --------------- +
| 领域| 输入| 空| 钥匙| 默认| 额外的|
+ ------------- + ---------- + ------ + ------ + --------- + - --------------- +
| ID | int(11)| 没有| PRI | NULL | auto_increment |
| 名称| char(35)| 没有| | | |
| CountryCode | char(3)| 没有| MUL | | |
| 区| char(20)| 没有| | | |
| 人口| int(11)| 没有| | 0 | |
+ ------------- + ---------- + ------ + ------ + --------- + - --------------- +
语法
的替代方法
是
。
这两个陈述是等价的:
tbl_name
FROM db_name
db_name.tbl_name
从mytable FROM mydb显示列; 显示来自mydb.mytable的列;
可选
EXTENDED
关键字使输出包含有关MySQL内部使用且用户无法访问的隐藏列的信息。
可选
FULL
关键字使输出包含列排序规则和注释,以及您对每列的权限。
该
LIKE
子句(如果存在)指示要匹配的列名称。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
数据类型可能与您希望它们基于
CREATE
TABLE
语句
的数据类型不同,
因为MySQL有时会在您创建或更改表时更改数据类型。
发生这种情况的条件在
第13.1.20.8节“无声列规范更改”中描述
。
SHOW
COLUMNS
为每个表列显示以下值:
Field
列的名称。
Type
列数据类型。
Collation
非二进制字符串列或
NULL
其他列
的排序规则
。
仅当您使用
FULL
关键字时
才会显示此值
。
Null
列可空性。
该值
YES
是否
NULL
可以将值存储在列中,
NO
如果不存在。
Key
列是否已编入索引:
如果
Key
为空,则列不会被索引,也不会仅作为多列非唯一索引中的辅助列索引。
如果
Key
是
PRI
,则列是a
PRIMARY KEY
或多列中的列之一
PRIMARY
KEY
。
如果
Key
是
UNI
,则列是
UNIQUE
索引
的第一列
。
(
UNIQUE
索引允许多个
NULL
值,但您可以
NULL
通过检查
Null
字段
来判断列是否允许
。)
如果
Key
是
MUL
,则该列是非唯一索引的第一列,其中在列中允许多次出现给定值。
如果超过一个
Key
值适用于表中给定的列,
Key
显示了一个具有最高优先级,顺序
PRI
,
UNI
,
MUL
。
甲
UNIQUE
索引可被显示为
PRI
,如果它不能包含
NULL
值并没有
PRIMARY KEY
在表中。
甲
UNIQUE
索引可能会显示为
MUL
如果若干列形成复合
UNIQUE
索引;
虽然列的组合是唯一的,但每列仍然可以保存给定值的多次出现。
Default
列的默认值。
这是
NULL
因为列具有显式默认值
NULL
,或者列定义包含无
DEFAULT
子句。
Extra
有关给定列的任何其他可用信息。 在这些情况下,该值是非空的:
Privileges
您对该列的权限。
仅当您使用
FULL
关键字时
才会显示此值
。
Comment
列定义中包含的任何注释。
仅当您使用
FULL
关键字时
才会显示此值
。
表格列表信息也可从
INFORMATION_SCHEMA
COLUMNS
表格中获得。
请参见
第25.6节“INFORMATION_SCHEMA COLUMNS表”
。
有关隐藏列的扩展信息仅可使用
SHOW EXTENDED
COLUMNS
;
它不能从
COLUMNS
表中
获得
。
您可以使用
mysqlshow
db_name
tbl_name
命令
列出表的列
。
该
DESCRIBE
声明提供类似的信息
SHOW
COLUMNS
。
请参见
第13.8.1节“DESCRIBE语法”
。
。
SHOW CREATE TABLE
,
SHOW TABLE STATUS
和
SHOW
INDEX
语句还提供有关表的信息。
请参见
第13.7.6节“显示语法”
。
SHOW CREATE {DATABASE | SCHEMA} [如果不存在]db_name
显示
CREATE DATABASE
创建指定数据库
的
语句。
如果
SHOW
语句包含一个
IF NOT
EXISTS
子句,则输出也包含这样的子句。
SHOW
CREATE SCHEMA
是...的同义词
SHOW CREATE DATABASE
。
MySQL的>SHOW CREATE DATABASE test\G
*************************** 1。排******************** ******* 数据库:测试 创建数据库:CREATE DATABASE`test` / *!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci * / / *!80014 DEFAULT ENCRYPTION ='N'* / MySQL的>SHOW CREATE SCHEMA test\G
*************************** 1。排******************** ******* 数据库:测试 创建数据库:CREATE DATABASE`test` / *!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci * / / *!80014 DEFAULT ENCRYPTION ='N'* /
SHOW CREATE DATABASE
根据
sql_quote_show_create
选项
的值引用表名和列名
。
请参见
第5.1.8节“服务器系统变量”
。
显示创建事件 event_name
此语句显示
CREATE
EVENT
重新创建给定事件所需
的
语句。
它需要
EVENT
从中显示事件的数据库
的
权限。
例如(使用
e_daily
在
第13.7.6.18节“SHOW EVENTS语法”中
定义并随后更改
的相同事件
):
MySQL的> SHOW CREATE EVENT myschema.e_daily\G
*************************** 1。排******************** *******
事件:e_daily
sql_mode:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,
NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,
NO_ENGINE_SUBSTITUTION
time_zone:SYSTEM
创建事件:CREATE DEFINER =`jon` @`ghidora` EVENT`e_daily`
每天安排一次
STARTS CURRENT_TIMESTAMP + INTERVAL 6小时
完成不保留
ENABLE
评论'然后保存会话总数
每天清理桌子'
开始吧
INSERT INTO site_activity.totals(时间,总计)
SELECT CURRENT_TIMESTAMP,COUNT(*)
来自site_activity.sessions;
从site_activity.sessions中删除;
结束
character_set_client:utf8mb4
collation_connection:utf8mb4_0900_ai_ci
数据库整理:utf8mb4_0900_ai_ci
character_set_client
是
character_set_client
创建事件时系统变量
的会话值
。
collation_connection
是
collation_connection
创建事件时系统变量
的会话值
。
Database
Collation
是与事件关联的数据库的排序规则。
输出反映了事件(
ENABLE
)
的当前状态,
而不是创建它的状态。
显示创建过程 proc_name
该语句是MySQL扩展。
它返回可用于重新创建命名存储过程的确切字符串。
类似的语句
SHOW CREATE
FUNCTION
显示有关存储函数的信息(请参见
第13.7.6.8节“显示函数语法”
)。
要使用任一语句,您必须具有全局
SELECT
特权。
MySQL的>SHOW CREATE PROCEDURE test.simpleproc\G
*************************** 1。排******************** ******* 过程:simpleproc sql_mode:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES, NO_ZERO_IN_DATE,NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION 创建过程:CREATE PROCEDURE`simpleproc`(OUT param1 INT) 开始 SELECT COUNT(*)INTO param1 FROM t; 结束 character_set_client:utf8mb4 collation_connection:utf8mb4_0900_ai_ci 数据库整理:utf8mb4_0900_ai_ci MySQL的>SHOW CREATE FUNCTION test.hello\G
*************************** 1。排******************** ******* 功能:你好 sql_mode:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES, NO_ZERO_IN_DATE,NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION 创建函数:CREATE FUNCTION`hello`(s CHAR(20)) 返回char(50)CHARSET utf8mb4 返回CONCAT('你好,',s,'!') character_set_client:utf8mb4 collation_connection:utf8mb4_0900_ai_ci 数据库整理:utf8mb4_0900_ai_ci
character_set_client
是
character_set_client
创建例程时系统变量
的会话值
。
collation_connection
是
collation_connection
创建例程时系统变量
的会话值
。
Database
Collation
是与例程关联的数据库的排序规则。
显示创建表 tbl_name
显示
CREATE
TABLE
创建命名表
的
语句。
要使用此语句,您必须拥有该表的某些权限。
此声明也适用于视图。
MySQL的> SHOW CREATE TABLE t\G
*************************** 1。排******************** *******
表:t
创建表:CREATE TABLE`t`(
`id` int(11)NOT NULL AUTO_INCREMENT,
`s` char(60)DEFAULT NULL,
PRIMARY KEY(`id`)
)ENGINE = InnoDB DEFAULT CHARSET = utf8mb4
从MySQL 8.0.16开始,MySQL实现
CHECK
约束并
SHOW CREATE TABLE
显示它们。
所有
CHECK
约束都显示为表约束。
也就是说,
CHECK
最初指定为列定义一部分的约束显示为单独的子句,而不是列定义的一部分。
例:
MySQL的>CREATE TABLE t1 (
i1 INT CHECK (i1 <> 0), -- column constraint
i2 INT,
CHECK (i2 > i1), -- table constraint
CHECK (i2 <> 0) NOT ENFORCED -- table constraint, not enforced
);
MySQL的>SHOW CREATE TABLE t1\G
*************************** 1。排******************** ******* 表:t1 创建表:CREATE TABLE`t1`( `i1` int(11)DEFAULT NULL, `i2` int(11)DEFAULT NULL, 约束`t1_chk_1`检查((``i1` <> 0)), 约束`t1_chk_2`检查((``i2`>`i1`)), 约束`t1_chk_3`检查((``i2` <> 0))/ *!80016未强制执行* / )ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci
SHOW CREATE TABLE
根据
sql_quote_show_create
选项
的值引用表名和列名
。
请参见
第5.1.8节“服务器系统变量”
。
有关
CREATE
TABLE
MySQL
如何
存储语句的
信息
,请参见
第13.1.20.1节“CREATE TABLE语句保留”
。
显示创建触发器 trigger_name
此语句显示
CREATE
TRIGGER
创建命名触发器
的
语句。
此语句需要
TRIGGER
与触发器关联的表
的
特权。
MySQL的> SHOW CREATE TRIGGER ins_sum\G
*************************** 1。排******************** *******
触发:ins_sum
sql_mode:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,
NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,
NO_ENGINE_SUBSTITUTION
SQL原声明:CREATE DEFINER =`me` @`localhost`TRIGGER`ins_sum`
在插入`帐户'之前
每个行设置@sum = @sum + NEW.amount
character_set_client:utf8mb4
collation_connection:utf8mb4_0900_ai_ci
数据库整理:utf8mb4_0900_ai_ci
创建时间:2018-08-08 10:10:12.61
SHOW CREATE TRIGGER
输出有以下列:
Trigger
:触发器名称。
sql_mode
:触发器执行时生效的SQL模式。
SQL Original Statement
:
CREATE TRIGGER
定义触发器
的
语句。
character_set_client
:
character_set_client
创建触发器时系统变量
的会话值
。
collation_connection
:
collation_connection
创建触发器时系统变量
的会话值
。
Database Collation
:与触发器关联的数据库的排序规则。
Created
:创建触发器的日期和时间。
这是
TIMESTAMP(2)
触发器
的
值(以百分之几秒为单位)。
INFORMATION_SCHEMA
TRIGGERS
表格中
也提供了触发信息
。
请参见
第25.34节“INFORMATION_SCHEMA TRIGGERS表”
。
显示创建用户 user
此语句显示
CREATE
USER
创建命名用户
的
语句。
如果用户不存在,则会发生错误。
除了查看当前用户的信息外,
该语句还需要
系统数据库
的
SELECT
权限
mysql
。
对于当前用户,
需要系统表
的
SELECT
权限才能
mysql.user
在
IDENTIFIED
AS
子句中
显示密码哈希
;
否则,哈希显示为
<secret>
。
要为帐户命名,请使用
第6.2.4节“指定帐户名称”中
所述的格式
。
帐户名的主机名部分(如果省略)默认为
'%'
。
还可以指定
CURRENT_USER
或
CURRENT_USER()
引用与当前会话相关联的帐户。
IDENTIFIED
WITH
输出子句中
显示的密码哈希值
SHOW
CREATE USER
可能包含对终端显示和其他环境有不利影响的不可打印字符。
启用
print_identified_with_as_hex
系统变量(从MySQL 8.0.17开始提供)会导致
SHOW CREATE USER
将此类哈希值显示为十六进制字符串而不是常规字符串文字。
不包含不可打印字符的哈希值仍显示为常规字符串文字,即使启用了此变量也是如此。
mysql>CREATE USER 'u1'@'localhost' IDENTIFIED BY 'secret';
mysql>SET print_identified_with_as_hex = ON;
mysql>SHOW CREATE USER 'u1'@'localhost'\G
*************************** 1。排******************** ******* u1 @ localhost的CREATE USER:CREATE USER'u1'@'localhost' 通过'caching_sha2_password'识别 AS 0x244124303035240C7745603626313D613C4C10633E0A104B1E14135A544A7871567245614F4872344643546336546F624F6C7861326932752F45622F4F473273597557627139 要求无密码存款违约帐户解锁 密码历史默认密码重新使用间隔默认值 密码要求当前默认值
要显示授予帐户的权限,请使用该
SHOW
GRANTS
语句。
请参见
第13.7.6.21节“显示GRANTS语法”
。
显示创建视图 view_name
此语句显示
CREATE
VIEW
创建命名视图
的
语句。
MySQL的> SHOW CREATE VIEW v\G
*************************** 1。排******************** *******
查看:v
创建视图:CREATE ALGORITHM = UNDEFINED
DEFINER =`bob` @`localhost`
SQL安全定义视图
`v` AS选择1 AS`a`,2 AS`b`
character_set_client:utf8mb4
collation_connection:utf8mb4_0900_ai_ci
character_set_client
是
character_set_client
创建视图时系统变量
的会话值
。
collation_connection
是
collation_connection
创建视图时系统变量
的会话值
。
使用
SHOW CREATE VIEW
需要
SHOW VIEW
特权和
SELECT
相关视图
的
特权。
查询信息也可从
INFORMATION_SCHEMA
VIEWS
表中获得。
请参见
第25.36节“INFORMATION_SCHEMA VIEWS表”
。
MySQL允许您使用不同的
sql_mode
设置来告诉服务器要支持的SQL语法的类型。
例如,您可以使用
ANSI
SQL模式来确保MySQL
||
在查询中
正确解释标准SQL连接运算符double bar(
)。
如果您随后创建了一个连接项目的视图,您可能会担心将
sql_mode
设置
更改为
不同的值
ANSI
可能会导致视图无效。
但这种情况并非如此。
无论你如何编写视图定义,MySQL总是以规范的形式存储它。
这是一个示例,显示服务器如何将双条串联运算符更改为a
CONCAT()
功能:
MySQL的>SET sql_mode = 'ANSI';
查询正常,0行受影响(0.00秒) MySQL的>CREATE VIEW test.v AS SELECT 'a' || 'b' as col1;
查询OK,0行受影响(0.01秒) MySQL的>SHOW CREATE VIEW test.v\G
*************************** 1。排******************** ******* 查看:v 创建视图:创建视图“v”AS选择连续('a','b')AS“col1” ... 1排(0.00秒)
以规范形式存储视图定义的优点是,稍后对值进行的更改
sql_mode
不会影响视图的结果。
然而,另一个后果是
SELECT
服务器从定义中删除
之前的注释
。
SHOW {DATABASES | SCHEMAS} [喜欢'pattern
'| 在哪里expr
]
SHOW
DATABASES
列出MySQL服务器主机上的数据库。
SHOW
SCHEMAS
是...的同义词
SHOW
DATABASES
。
该
LIKE
子句(如果存在)指示要匹配的数据库名称。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
您只能看到具有某种特权的数据库,除非您拥有全局
SHOW
DATABASES
特权。
您也可以使用
mysqlshow
命令
获取此列表
。
如果使用该
--skip-show-database
选项
启动服务器,则
除非您具有该
SHOW DATABASES
权限,
否则根本不能使用此语句
。
MySQL将数据库实现为数据目录中的目录,因此该语句只列出该位置中的目录。 但是,输出可能包括与实际数据库不对应的目录名称。
INFORMATION_SCHEMA
SCHEMATA
表中
还提供了数据库信息
。
请参见
第25.24节“INFORMATION_SCHEMA SCHEMATA表”
。
因为任何静态全局特权被认为是所有数据库的特权,任何静态全局特权使用户能够看到所有的数据库名称
SHOW
DATABASES
或通过检查
SCHEMATA
表
INFORMATION_SCHEMA
,除了已经在通过局部撤销数据库级别被限制的数据库。
SHOW ENGINE engine_name
{STATUS | MUTEX}
SHOW
ENGINE
显示有关存储引擎的操作信息。
它需要
PROCESS
特权。
该声明有以下变体:
显示发动机创新状态 SHOW ENGINE INNODB MUTEX SHOW ENGINE PERFORMANCE_SCHEMA状态
SHOW
ENGINE INNODB
STATUS
显示标准
InnoDB
监视器中有关
InnoDB
存储引擎
状态的
大量信息
。
有关标准监视器和其他
InnoDB
监视器的信息
InnoDB
,请参见
第15.16节“InnoDB监视器”
。
SHOW
ENGINE INNODB
MUTEX
显示
InnoDB
互斥锁
和
rw-lock
统计信息。
InnoDB
还可以使用
性能架构
表
监视互斥锁和rwlock
。
请参见
第15.15.2节“使用性能模式监视InnoDB Mutex等待”
。
使用以下选项动态配置互斥锁统计信息收集:
要启用互斥锁统计信息的收集,请运行:
SET GLOBAL innodb_monitor_enable ='latch';
要重置互斥锁统计信息,请运行:
SET GLOBAL innodb_monitor_reset ='latch';
要禁用互斥锁统计信息的收集,请运行:
SET GLOBAL innodb_monitor_disable ='latch';
SHOW ENGINE INNODB
MUTEX
也可以通过设置
innodb_monitor_enable='all'
或通过设置禁用
来启用
互斥锁统计信息的收集
innodb_monitor_disable='all'
。
SHOW
ENGINE INNODB
MUTEX
输出有以下列:
Type
永远
InnoDB
。
Name
对于互斥锁,该
Name
字段仅报告互斥锁名称。
对于rwlock,该
Name
字段报告实现rwlock的源文件,以及创建rwlock的文件中的行号。
行号特定于您的MySQL版本。
Status
互斥状态。
此字段报告旋转,等待和调用的数量。
InnoDB
不报告
在外部实现的低级操作系统互斥锁的统计信息
。
spins
表示旋转次数。
waits
表示互斥锁等待的数量。
calls
表示请求互斥锁的次数。
SHOW ENGINE INNODB MUTEX
跳过
互斥
和
RW-锁
的
缓冲池
块,作为输出的量可以在一个大缓冲池系统压倒性的。
(每个16K缓冲池块中有一个互斥锁和一个rw锁,每GB有65,536个块。)
SHOW ENGINE INNODB MUTEX
也没有列出从未等待的任何互斥锁或rw锁(
os_waits=0
)。
因此,
SHOW ENGINE
INNODB MUTEX
仅显示有关已导致至少一个OS级别
等待
的缓冲池外部的互斥锁和rw锁定的信息
。
使用
SHOW
ENGINE
PERFORMANCE_SCHEMA STATUS
检查绩效模式的代码的内部操作:
MySQL的> SHOW ENGINE PERFORMANCE_SCHEMA STATUS\G
...
*************************** 3。排******************** *******
输入:performance_schema
名称:events_waits_history.size
状态:76
****************************排******************** *******
输入:performance_schema
名称:events_waits_history.count
状态:10000
****************************排******************** *******
输入:performance_schema
名称:events_waits_history.memory
状态:760000
...
*************************** 57.排******************** *******
输入:performance_schema
名称:performance_schema.memory
状态:26459600
...
此语句旨在帮助DBA了解不同性能模式选项对内存要求的影响。
Name
值由两部分组成,分别命名内部缓冲区和缓冲区属性。
解释缓冲区名称如下:
未作为表公开的内部缓冲区在括号内命名。
例子:
(pfs_cond_class).size
,
(pfs_mutex_class).memory
。
在
performance_schema
数据库中
作为表公开的内部缓冲区以表的
形式命名,没有括号。
例子:
events_waits_history.size
,
mutex_instances.count
。
适用于整体性能模式的值以
performance_schema
。
开头
。
示例:
performance_schema.memory
。
缓冲区属性具有以下含义:
size
是实现使用的内部记录的大小,例如表中行的大小。
size
值无法更改。
count
是内部记录的数量,例如表中的行数。
count
可以使用“性能架构”配置选项更改值。
对于表,
是产品
tbl_name
.memorysize
和
count
。
对于整体性能模式,
performance_schema.memory
是所有使用的内存的总和(所有其他
memory
值
的总和
)。
在某些情况下,Performance Schema配置参数与
SHOW
ENGINE
值
之间存在直接关系
。
例如,
events_waits_history_long.count
对应于
performance_schema_events_waits_history_long_size
。
在其他情况下,这种关系更复杂。
例如,
events_waits_history.count
对应于
performance_schema_events_waits_history_size
(每个线程的行数)乘以
performance_schema_max_thread_instances
(线程数)。
SHOW ENGINE NDB状态。
如果服务器
NDB
启用
了
存储引擎,则
SHOW ENGINE NDB STATUS
显示群集状态信息,例如连接的数据节点数,群集连接字符串和群集二进制日志时期,以及MySQL服务器连接到服务器时创建的各种群集API对象的计数。簇。
此语句的示例输出如下所示:
MySQL的> SHOW ENGINE NDB STATUS;
+ ------------ + ------------ + ------------ -------------------------------------- +
| 输入| 名称| 状态|
+ ------------ + ------------ + ------------ -------------------------------------- +
| ndbcluster | 连接| cluster_node_id = 7,
connected_host = 198.51.100.103,connected_port = 1186,number_of_data_nodes = 4,
number_of_ready_data_nodes = 3,connect_count = 0 |
| ndbcluster | NdbTransaction | created = 6,free = 0,sizeof = 212 |
| ndbcluster | NdbOperation | created = 8,free = 8,sizeof = 660 |
| ndbcluster | NdbIndexScanOperation | created = 1,free = 1,sizeof = 744 |
| ndbcluster | NdbIndexOperation | created = 0,free = 0,sizeof = 664 |
| ndbcluster | NdbRecAttr | created = 1285,free = 1285,sizeof = 60 |
| ndbcluster | NdbApiSignal | created = 16,free = 16,sizeof = 136 |
| ndbcluster | NdbLabel | created = 0,free = 0,sizeof = 196 |
| ndbcluster | NdbBranch | created = 0,free = 0,sizeof = 24 |
| ndbcluster | NdbSubroutine | created = 0,free = 0,sizeof = 68 |
| ndbcluster | NdbCall | created = 0,free = 0,sizeof = 16 |
| ndbcluster | NdbBlob | created = 1,free = 1,sizeof = 264 |
| ndbcluster | NdbReceiver | created = 4,free = 0,sizeof = 68 |
| ndbcluster | binlog | latest_epoch = 155467,latest_trans_epoch = 148126,
latest_received_binlog_epoch = 0,latest_handled_binlog_epoch = 0,
latest_applied_binlog_epoch = 0 |
+ ------------ + ------------ + ------------ -------------------------------------- +
Status
每个行中
的
列分别提供有关MySQL服务器与群集的连接以及群集二进制日志状态的信息。
该
Status
信息是在逗号分隔的组的名称/值对的形式。
该
connection
行的
Status
列包含以下表中描述的名称/值对。
名称 | 值 |
---|---|
cluster_node_id |
集群中MySQL服务器的节点ID |
connected_host |
MySQL服务器所连接的集群管理服务器的主机名或IP地址 |
connected_port |
MySQL服务器用于连接管理服务器的端口(
connected_host
)
|
number_of_data_nodes |
为群集配置的数据节点数(即
[ndbd]
群集
config.ini
文件中
的
节
数
)
|
number_of_ready_data_nodes |
群集中实际运行的数据节点数 |
connect_count |
此 mysqld 已连接或重新连接到群集数据节点的次数 |
该
binlog
行的
Status
列包含与NDB群集复制信息。
它包含的名称/值对在下表中描述。
名称 | 值 |
---|---|
latest_epoch |
最近在这个MySQL服务器上运行的最新纪元(即服务器上运行的最新事务的序列号) |
latest_trans_epoch |
群集的数据节点处理的最新纪元 |
latest_received_binlog_epoch |
二进制日志线程收到的最新纪元 |
latest_handled_binlog_epoch |
二进制日志线程处理的最新纪元(用于写入二进制日志) |
latest_applied_binlog_epoch |
最近的epoch实际写入二进制日志 |
有关 更多信息 , 请参见 第22.6节“NDB群集复制” 。
其输出中剩余的行
SHOW ENGINE NDB
STATUS
最有可能在监视群集时非常有用,在此列出
Name
:
NdbTransaction
:
NdbTransaction
已创建
的
对象
的数量和大小
。
一个
NdbTransaction
每次创建一个表模式操作(例如
CREATE TABLE
或
ALTER
TABLE
)上执行
NDB
表。
NdbOperation
:
NdbOperation
已创建
的
对象
的数量和大小
。
NdbIndexScanOperation
:
NdbIndexScanOperation
已创建
的
对象
的数量和大小
。
NdbIndexOperation
:
NdbIndexOperation
已创建
的
对象
的数量和大小
。
NdbRecAttr
:
NdbRecAttr
已创建
的
对象
的数量和大小
。
通常,每次SQL节点执行数据操作语句时都会创建其中一个。
NdbBlob
:
NdbBlob
已创建
的
对象
的数量和大小
。
一个
NdbBlob
是对于涉及每个新创建的操作
BLOB
在列
NDB
表。
NdbReceiver
:
NdbReceiver
已创建
的任何
对象
的数量和大小
。
在数
created
列是相同的数据节点,其MySQL服务器具有连接在集群中的数量。
SHOW ENGINE NDB STATUS
如果
NDB
MySQL客户端访问运行此语句的SQL节点在当前会话期间
未执行涉及
表的
操作,则返回空结果
。
显示[存储]发动机
SHOW
ENGINES
显示有关服务器存储引擎的状态信息。
这对于检查是否支持存储引擎或查看默认引擎是什么特别有用。
有关MySQL存储引擎的信息,请参阅 第15章, InnoDB存储引擎 和 第16章, 备用存储引擎 。
MySQL的> SHOW ENGINES\G
*************************** 1。排******************** *******
引擎:存档
支持:是的
评论:归档存储引擎
交易:NO
XA:没有
保存点:没有
*************************** 2.排******************** *******
发动机:BLACKHOLE
支持:是的
评论:/ dev / null存储引擎(你写的东西都消失了)
交易:NO
XA:没有
保存点:没有
*************************** 3。排******************** *******
发动机:MRG_MYISAM
支持:是的
评论:收集相同的MyISAM表
交易:NO
XA:没有
保存点:没有
****************************排******************** *******
发动机:FEDERATED
支持:没有
评论:联合MySQL存储引擎
交易:NULL
XA:NULL
保存点:NULL
****************************排******************** *******
引擎:MyISAM
支持:是的
评论:MyISAM存储引擎
交易:NO
XA:没有
保存点:没有
*************************** 6.排******************** *******
引擎:PERFORMANCE_SCHEMA
支持:是的
评论:性能架构
交易:NO
XA:没有
保存点:没有
*************************** 7.排******************** *******
引擎:InnoDB
支持:默认
注释:支持事务,行级锁定和外键
交易:YES
XA:是的
保存点:是
*************************** 8.排******************** *******
发动机:记忆
支持:是的
注释:基于哈希,存储在内存中,对临时表有用
交易:NO
XA:没有
保存点:没有
*************************** 9。排******************** *******
引擎:CSV
支持:是的
评论:CSV存储引擎
交易:NO
XA:没有
保存点:没有
输出
SHOW ENGINES
可能会根据使用的MySQL版本和其他因素而有所不同。
SHOW
ENGINES
输出有以下列:
Engine
存储引擎的名称。
Support
服务器对存储引擎的支持级别,如下表所示。
值 | 含义 |
---|---|
YES |
引擎受支持且处于活动状态 |
DEFAULT |
比如
YES
,加上这是默认引擎
|
NO |
不支持引擎 |
DISABLED |
引擎受支持但已被禁用 |
值
NO
意味着在不支持引擎的情况下编译服务器,因此无法在运行时启用它。
DISABLED
发生
的值
可能是因为服务器是使用禁用引擎的选项启动的,或者因为并未提供启用它所需的所有选项。
在后一种情况下,错误日志应包含指示禁用该选项的原因。
请参见
第5.4.2节“错误日志”
。
您可能还会看到
DISABLED
存储引擎,如果服务器已编译为支持它,但是启动了一个
选项。
对于
存储引擎,
表示服务器是在支持NDB Cluster的情况下编译的,但未使用该
选项
启动
。
--skip-
engine_name
NDB
DISABLED
--ndbcluster
所有MySQL服务器都支持
MyISAM
表。
无法禁用
MyISAM
。
Comment
存储引擎的简要说明。
Transactions
存储引擎是否支持事务。
XA
存储引擎是否支持XA事务。
Savepoints
存储引擎是否支持保存点。
INFORMATION_SCHEMA
ENGINES
表中
还提供了存储引擎信息
。
请参见
第25.9节“INFORMATION_SCHEMA ENGINES表”
。
显示错误[限制[offset
,]row_count
] 显示计数(*)错误
SHOW
ERRORS
是一个类似于的诊断语句
SHOW
WARNINGS
,除了它仅显示错误信息,而不是错误,警告和注释。
该
LIMIT
子句的语法与
SELECT
语句
相同
。
请参见
第13.2.10节“SELECT语法”
。
该
SHOW
COUNT(*)
ERRORS
语句显示错误数。
您还可以从
error_count
变量中
检索此数字
:
显示计数(*)错误; SELECT @@ error_count;
SHOW
ERRORS
并
error_count
仅适用于错误,而不是警告或注释。
在其他方面,它们与
SHOW WARNINGS
和
类似
warning_count
。
特别是,
SHOW
ERRORS
不能显示超过
max_error_count
消息的信息,并且
error_count
可能超过
max_error_count
错误数量
超过的值
max_error_count
。
有关更多信息,请参见 第13.7.6.40节“显示警告语法” 。
展示活动 [{FROM | IN}schema_name
] [喜欢'pattern
'| 在哪里expr
]
此语句显示有关事件管理器事件的信息,这将在
第24.4节“使用事件调度程序”中讨论
。
它需要
EVENT
从中显示事件的数据库
的
特权。
在最简单的形式中,
SHOW
EVENTS
列出当前模式中的所有事件:
MySQL的>SELECT CURRENT_USER(), SCHEMA();
+ ---------------- + ---------- + | CURRENT_USER()| SCHEMA()| + ---------------- + ---------- + | jon @ ghidora | myschema | + ---------------- + ---------- + 1排(0.00秒) MySQL的>SHOW EVENTS\G
*************************** 1。排******************** ******* Db:myschema 姓名:e_daily 定义者:jon @ ghidora 时区:SYSTEM 类型:RECURRING 执行at:NULL 区间值:1 间隔字段:DAY 开始时间:2018-08-08 11:06:34 结束:NULL 状态:已启用 发起人:1 character_set_client:utf8mb4 collation_connection:utf8mb4_0900_ai_ci 数据库整理:utf8mb4_0900_ai_ci
要查看特定模式的事件,请使用该
FROM
子句。
例如,要查看
test
模式的
事件
,请使用以下语句:
显示测试事件;
该
LIKE
子句(如果存在)指示要匹配的事件名称。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
SHOW
EVENTS
输出有以下列:
Db
事件所属的架构(数据库)的名称。
Name
事件的名称。
Definer
以
格式
创建事件的用户的帐户
。
'
user_name
'@'host_name
'
Time zone
事件时区,用于调度事件的时区,在执行时在事件中生效。
默认值为
SYSTEM
。
Type
事件重复类型,
ONE
TIME
(瞬态)或
RECURRING
(重复)。
Execute At
对于一次性事件,这是在
用于创建事件
的
语句
DATETIME
的
AT
子句中
指定
的
值
CREATE EVENT
,或者
ALTER
EVENT
是修改事件
的最后一个
语句中
指定
的
值
。
此列中显示的值反映
INTERVAL
了事件
AT
子句中
包含
的任何
值
的加或减
。
例如,如果使用创建事件
ON SCHEDULE AT CURRENT_TIMESTAMP +
'1:6' DAY_HOUR
,并且事件是在2018-02-09 14:05:30创建的,则此列中显示的值将为
'2018-02-10 20:05:30'
。
如果事件的时间由一个
EVERY
条款而不是
一个
条款
决定
AT
子句(即,如果事件是重复出现的),则此列的值为
NULL
。
Interval Value
对于重复事件,在事件执行之间等待的间隔数。
对于瞬态事件,此列的值始终为
NULL
。
Interval Field
用于重复事件在重复之前等待的间隔的时间单位。
对于瞬态事件,此列的值始终为
NULL
。
Starts
重复活动的开始日期和时间。
这将显示为
DATETIME
值,
NULL
如果没有为事件定义开始日期和时间
,
则显示该
值
。
对于瞬态事件,此列始终为
NULL
。
对于定义包含
STARTS
子句
的定期事件
,此列包含相应的
DATETIME
值。
与
Execute At
列一样,此值可解析所使用的任何表达式。
如果没有
STARTS
影响事件发生时间的条款,则此列为
NULL
Ends
对于定义包含
ENDS
子句
的定期事件
,此列包含相应的
DATETIME
值。
与
Execute At
列一样,此值可解析所使用的任何表达式。
如果没有
ENDS
影响事件发生时间的条款,则此列为
NULL
。
Status
事件状态。
其中一个
ENABLED
,
DISABLED
或
SLAVESIDE_DISABLED
。
SLAVESIDE_DISABLED
表示事件的创建发生在充当复制主服务器的另一个MySQL服务器上并复制到充当从服务器的当前MySQL服务器,但该事件当前未在从服务器上执行。
有关更多信息,请参见
第17.4.1.16节“调用调用的功能”
。
信息。
Originator
创建事件的MySQL服务器的服务器ID;
用于复制。
ALTER
EVENT
如果在主服务器上执行,则
可以将该值更新
为发生该语句的服务器的服务器ID。
默认值为0。
character_set_client
character_set_client
创建事件时系统变量
的会话值
。
collation_connection
collation_connection
创建事件时系统变量
的会话值
。
Database Collation
与事件关联的数据库的排序规则。
有关
SLAVESIDE_DISABLED
和
Originator
列的
更多信息
,请参见
第17.4.1.16节“调用调用的功能”
。
显示的
SHOW
EVENTS
时间在事件时区中给出,如
第24.4.4节“事件元数据”中所述
。
活动信息也可从
INFORMATION_SCHEMA
EVENTS
表格中获得。
请参见
第25.10节“INFORMATION_SCHEMA事件表”
。
事件操作语句未显示在输出中
SHOW
EVENTS
。
使用
SHOW CREATE EVENT
或
INFORMATION_SCHEMA
EVENTS
表。
显示资助 [为user_or_role
[使用role
[,role
] ...]]user_or_role
:{user
|role
}
此语句以
GRANT
必须执行以复制权限和角色分配
的
语句
形式显示分配给MySQL用户帐户或角色
的权限和角色。
要显示MySQL帐户的非特权信息,请使用该
SHOW CREATE USER
语句。
请参见
第13.7.6.12节“显示创建用户语法”
。
SHOW
GRANTS
需要
系统数据库
的
SELECT
权限
mysql
,除了显示当前用户的权限和角色。
要为该帐户或角色命名
SHOW
GRANTS
,请使用与该
GRANT
语句
相同的格式
(例如
'jeffrey'@'localhost'
):
MySQL的> SHOW GRANTS FOR 'jeffrey'@'localhost';
+ ------------------------------------------------- ----------------- +
| 为jeffrey @ localhost提供补助金
+ ------------------------------------------------- ----------------- +
| 授予*。*给`jeffrey` @`localhost` |
| GRANT SELECT,INSERT,UPDATE on`db1`。* to`jeffrey` @`localhost` |
+ ------------------------------------------------- ----------------- +
主机部分(如果省略)默认为
'%'
。
有关指定帐户和角色名称的其他信息,请参见
第6.2.4节“指定帐户名”
和
第6.2.5节“指定角色名称”
。
要显示授予当前用户(用于连接服务器的帐户)的权限,可以使用以下任何语句:
显示资助; 为CURRENT_USER提供资助; 显示CURRENT_USER()的资助金额;
如果
SHOW GRANTS FOR CURRENT_USER
(或任何等效语法)在定义上下文中使用,例如在使用定义者而不是调用者权限执行的存储过程中,则显示的授权是定义者而不是调用者的授权。
在MySQL 8.0中,与之前的系列相比,
SHOW
GRANTS
不再显示
ALL PRIVILEGES
其全局特权输出,因为
ALL PRIVILEGES
全局级别
的含义
取决于定义的动态特权。
相反,
SHOW
GRANTS
明确列出每个授予的全局权限:
MySQL的> SHOW GRANTS FOR 'root'@'localhost';
+ ------------------------------------------------- -------------------- +
| root @ localhost的补助金
+ ------------------------------------------------- -------------------- +
| GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,RELOAD,|
| SHUTDOWN,PROCESS,FILE,REFERENCES,INDEX,ALTER,SHOW DATABASES,|
| 超级,创建临时表,锁定表,执行,复制|
| 奴隶,复制客户,创建视图,展示视图,创建常规,|
| ALTER ROUTINE,CREATE USER,EVENT,TRIGGER,CREATE TABLESPACE,|
| 创建角色,降低角色*。*到`root` @`localhost` WITH GRANT |
| 选项|
| 授予''''''''''''''''''''''''''''''''''''''''''''''''''''
+ ------------------------------------------------- -------------------- +
SHOW
GRANTS
应相应调整
处理
输出的
应用程序
。
在全局级别,
GRANT OPTION
如果为其中任何一个授予
,则
应用于所有已授予的静态全局特权,但单独应用于授予的动态特权。
SHOW
GRANTS
以这种方式显示全局特权:
列出所有已授予的静态权限的一行(如果有),包括
WITH GRANT OPTION
适当的
权限
。
一行列出了授予的所有授予的动态权限
GRANT OPTION
,如果有的话,包括
WITH GRANT
OPTION
。
一行列出了
GRANT OPTION
未授予的
所有已授予的动态权限
,如果有,则没有
WITH GRANT
OPTION
。
使用optional
USING
子句,
SHOW
GRANTS
可以检查与用户角色关联的权限。
USING
必须
将该
子句
中指定的每个角色
授予用户。
假设用户
u1
被赋予的角色
r1
和
r2
,如下所示:
CREATE ROLE'r1','r2'; GRANT SELECT ON db1。* TO'r1'; GRANT INSERT,UPDATE,DELETE ON db1。* TO'r2'; 创建用户'u1'@'localhost'通过'u1pass'识别; GRANT'r1','r2'到'u1'@'localhost';
SHOW
GRANTS
没有
USING
显示授予的角色:
MySQL的> SHOW GRANTS FOR 'u1'@'localhost';
+ --------------------------------------------- +
| u1 @ localhost的补助金
+ --------------------------------------------- +
| 授予使用*。*给'u1` @`localhost` |
| GRANT`r1` @`%`,`r2` @`%`to`u1` @`localhost` |
+ --------------------------------------------- +
添加
USING
子句会导致语句还显示与子句中指定的每个角色关联的权限:
MySQL的>SHOW GRANTS FOR 'u1'@'localhost' USING 'r1';
+ --------------------------------------------- + | u1 @ localhost的补助金 + --------------------------------------------- + | 授予使用*。*给'u1` @`localhost` | | GRANT SELECT ON`db1`。* to`u1` @`localhost` | | GRANT`r1` @`%`,`r2` @`%`to`u1` @`localhost` | + --------------------------------------------- + MySQL的>SHOW GRANTS FOR 'u1'@'localhost' USING 'r2';
+ ------------------------------------------------- ------------ + | u1 @ localhost的补助金 + ------------------------------------------------- ------------ + | 授予使用*。*给'u1` @`localhost` | | GRANT INSERT,UPDATE,DELETE ON`db1`。* to`u1` @`localhost` | | GRANT`r1` @`%`,`r2` @`%`to`u1` @`localhost` | + ------------------------------------------------- ------------ + MySQL的>SHOW GRANTS FOR 'u1'@'localhost' USING 'r1', 'r2';
+ ------------------------------------------------- -------------------- + | u1 @ localhost的补助金 + ------------------------------------------------- -------------------- + | 授予使用*。*给'u1` @`localhost` | | GRANT SELECT,INSERT,UPDATE,DELETE ON`db1`。* to`u1` @`localhost` | | GRANT`r1` @`%`,`r2` @`%`to`u1` @`localhost` | + ------------------------------------------------- -------------------- +
授予帐户的权限始终有效,但角色不是。
帐户的活动角色可以在会话期间和会话内不同,具体取决于
activate_all_roles_on_login
系统变量
的值
,帐户默认角色以及是否
SET
ROLE
已在会话中执行。
MySQL 8.0.16及更高版本支持部分撤销全局特权,这样可以限制全局特权应用于特定模式(请参见
第6.2.12节“使用部分撤消特权限制”
)。
要指示已为特定模式撤消了哪些全局模式特权,
SHOW GRANTS
输出包括
REVOKE
语句:
mysql>SET PERSIST partial_revokes = ON;
mysql>CREATE USER u1;
mysql>GRANT SELECT, INSERT, DELETE ON *.* TO u1;
mysql>REVOKE SELECT, INSERT ON mysql.* FROM u1;
mysql>REVOKE DELETE ON world.* FROM u1;
mysql>SHOW GRANTS FOR u1;
+ ------------------------------------------------- - + | 为u1 @%|拨款 + ------------------------------------------------- - + | GRANT SELECT,INSERT,DELETE ON *。* TO`u1` @`%`| | REVOKE SELECT,INSERT ON`mysql`。* FROM`u1` @`%`| | REVOKE DELETE ON`world`。* FROM`u1` @`%`| + ------------------------------------------------- - +
SHOW
GRANTS
不显示指定帐户可用但被授予其他帐户的权限。
例如,如果存在匿名帐户,则指定的帐户可能能够使用其权限,但
SHOW
GRANTS
不会显示它们。
SHOW
GRANTS
显示
mandatory_roles
系统变量值中
指定的必需角色
,如下所示:
SHOW
GRANTS
without
FOR
子句显示当前用户的权限,并包括必需的角色。
SHOW
GRANTS FOR
显示指定用户的权限,不包括必需的角色。
user
此行为是为了使用输出的应用程序的好处,
以确定明确授予指定用户的权限。
如果该输出包含强制角色,则很难将明确授予用户的角色与强制角色区分开来。
SHOW
GRANTS FOR
user
对于当前用户,应用程序可以
分别
使用
SHOW
GRANTS
或
确定具有或不具有强制角色的权限
SHOW
GRANTS FOR
CURRENT_USER
。
SHOW [EXTENDED] {INDEX | INDEXES | KEYS} {FROM | IN}tbl_name
[{FROM | 在}db_name
] [在哪里expr
]
SHOW
INDEX
返回表索引信息。
格式类似于
SQLStatistics
ODBC
中的
调用。
此语句需要表中任何列的某些权限。
MySQL的> SHOW INDEX FROM City\G
*************************** 1。排******************** *******
表:城市
非独特:0
Key_name:PRIMARY
Seq_in_index:1
Column_name:ID
整理:A
基数:4188
Sub_part:NULL
打包:NULL
空值:
Index_type:BTREE
评论:
Index_comment:
可见:是的
表达式:NULL
*************************** 2.排******************** *******
表:城市
非独特:1
Key_name:CountryCode
Seq_in_index:1
Column_name:CountryCode
整理:A
基数:232
Sub_part:NULL
打包:NULL
空值:
Index_type:BTREE
评论:
Index_comment:
可见:是的
表达式:NULL
语法
的替代方法
是
。
。
这两个陈述是等价的:
tbl_name
FROM db_name
db_name
tbl_name
从mytable FROM mydb显示索引; 显示来自mydb.mytable的索引;
可选
EXTENDED
关键字使输出包含有关MySQL内部使用且用户无法访问的隐藏索引的信息。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
SHOW
INDEX
返回以下字段:
Table
表的名称。
Non_unique
如果索引不能包含重复项,则为0;如果可以,则为1。
Key_name
索引的名称。
如果索引是主键,则名称始终为
PRIMARY
。
Seq_in_index
索引中的列序列号,以1开头。
Column_name
列名称。
另请参见该
Expression
列
的说明
。
Collation
列如何在索引中排序。
这可以具有值
A
(升序),
D
(降序)或
NULL
(未排序)。
Cardinality
估计索引中的唯一值的数量。
要更新此号码,请运行
ANALYZE
TABLE
或(对于
MyISAM
表格)
myisamchk -a
。
Cardinality
根据存储为整数的统计信息计算,因此即使对于小型表,该值也不一定精确。
基数越高,MySQL在进行连接时使用索引的可能性就越大。
Sub_part
索引前缀。
也就是说,
NULL
如果整列被索引
,
那么如果
列仅被部分索引,
则
索引字符的数量
。
前缀
限制
以字节为单位。
然而,前缀
长度
为索引规范
CREATE
TABLE
,
ALTER
TABLE
和
CREATE
INDEX
语句解释为非二进制字符串类型(字符数
CHAR
,
VARCHAR
,
TEXT
)和字节数为二进制串类型(
BINARY
,
VARBINARY
,
BLOB
)。
在为使用多字节字符集的非二进制字符串列指定前缀长度时,请考虑这一点。
有关索引前缀的其他信息,请参见 第8.3.5节“列索引” 和 第13.1.15节“CREATE INDEX语法” 。
Packed
指示密钥的打包方式。
NULL
如果不是。
Null
包含
YES
如果列可能包含
NULL
的值和
''
如果不。
Index_type
使用的索引方法(
BTREE
,
FULLTEXT
,
HASH
,
RTREE
)。
Comment
有关未在其自己的列中描述的索引的信息,例如
disabled
是否已禁用索引。
Index_comment
COMMENT
在创建索引时为索引
提供的任何注释都带有
属性。
Visible
索引是否对优化程序可见。 请参见 第8.3.12节“不可见索引” 。
Expression
MySQL 8.0.13及更高版本支持功能关键部分(请参阅
功能键部件
),它会影响
Column_name
和
Expression
列:
对于非功能键部分,
Column_name
表示由键部分索引的列,并且
Expression
是
NULL
。
对于功能键部分,
Column_name
列是
NULL
并
Expression
指示关键部分的表达式。
表中还提供了有关表索引的信息
INFORMATION_SCHEMA
STATISTICS
。
请参见
第25.26节“INFORMATION_SCHEMA STATISTICS表”
。
有关隐藏索引的扩展信息仅可使用
SHOW
EXTENDED INDEX
;
它不能从
STATISTICS
表中
获得
。
您可以使用
mysqlshow -k
db_name
tbl_name
命令
列出表的索引
。
显示主要状态
此语句提供有关主服务器的二进制日志文件的状态信息。
它需要
SUPER
或
REPLICATION CLIENT
特权。
例:
MySQL的> SHOW MASTER STATUS\G
*************************** 1。排******************** *******
文件:master-bin.000002
位置:1307
Binlog_Do_DB:测试
Binlog_Ignore_DB:手动,mysql
Executed_Gtid_Set:3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5
1排(0.00秒)
使用全局事务ID时,
Executed_Gtid_Set
显示已在主服务器上执行的事务的GTID集。
这与
gtid_executed
此服务器上
的
系统变量
的值相同,也与
此服务器
Executed_Gtid_Set
的输出中
的值相同
SHOW SLAVE STATUS
。
显示开放表格 [{FROM | 在}db_name
] [喜欢'pattern
'| 在哪里expr
]
SHOW OPEN TABLES
列出
TEMPORARY
表缓存中当前打开
的非
表。
请参见
第8.4.3.1节“MySQL如何打开和关闭表”
。
该
FROM
子句(如果存在)将显示的表限制为
db_name
数据库中
存在的表
。
该
LIKE
子句(如果存在)指示要匹配的表名。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
SHOW OPEN TABLES
输出有以下列:
Database
包含表的数据库。
Table
表名。
In_use
表的锁表或锁请求的数量。
例如,如果一个客户端使用获取锁定为一个表
LOCK TABLE t1 WRITE
,
In_use
将是1,如果其他客户端的问题
LOCK TABLE t1 WRITE
,而表保持锁定时,客户端将阻塞等待锁,但是锁定请求会导致
In_use
为2。如果计数零,表已打开但当前未使用。
声明
In_use
也增加了
HANDLER
...
OPEN
,减少了
HANDLER
...
CLOSE
。
Name_locked
表名是否已锁定。 名称锁定用于执行诸如删除或重命名表之类的操作。
如果您没有表的权限,则它不会显示在输出中
SHOW OPEN TABLES
。
显示插件
SHOW
PLUGINS
显示有关服务器插件的信息。
SHOW PLUGINS
输出
示例
:
MySQL的> SHOW PLUGINS\G
*************************** 1。排******************** *******
名称:binlog
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
*************************** 2.排******************** *******
名称:CSV
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
*************************** 3。排******************** *******
名称:记忆
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
****************************排******************** *******
姓名:MyISAM
状态:ACTIVE
类型:存储引擎
库:NULL
许可证:GPL
...
SHOW
PLUGINS
输出有以下列:
Name
用于在诸如
INSTALL PLUGIN
和之类的
语句中引用插件的名称
UNINSTALL PLUGIN
。
Status
该插件的状态,一
ACTIVE
,
INACTIVE
,
DISABLED
,
DELETING
,或
DELETED
。
Type
该类型的插件,如
STORAGE
ENGINE
,
INFORMATION_SCHEMA
,或
AUTHENTICATION
。
Library
插件共享库文件的名称。
这是用于在诸如
INSTALL PLUGIN
和之类的
语句中引用插件文件的名称
UNINSTALL PLUGIN
。
此文件位于
plugin_dir
系统变量
指定的目录中
。
如果库名是
NULL
,则插件编译在中,无法卸载
UNINSTALL PLUGIN
。
License
插件的许可方式(例如
GPL
)。
对于安装的插件
INSTALL
PLUGIN
,
Name
和
Library
值也会在
mysql.plugin
系统表中
注册
。
有关构成所显示信息基础的插件数据结构的信息
SHOW
PLUGINS
,请参见
第29.2节“MySQL插件API”
。
插件信息也可从
INFORMATION_SCHEMA
.PLUGINS
表中获得。
请参见
第25.18节“INFORMATION_SCHEMA PLUGINS表”
。
显示特权
SHOW
PRIVILEGES
显示MySQL服务器支持的系统权限列表。
显示的权限包括所有静态权限和所有当前注册的动态权限。
MySQL的> SHOW PRIVILEGES\G
*************************** 1。排******************** *******
特权:改变
上下文:表
评论:改变表格
*************************** 2.排******************** *******
特权:改变常规
背景:功能,程序
注释:更改或删除存储的函数/过程
*************************** 3。排******************** *******
特权:创造
上下文:数据库,表,索引
注释:创建新数据库和表
****************************排******************** *******
特权:创建例程
上下文:数据库
注释:使用CREATE FUNCTION / PROCEDURE
****************************排******************** *******
权限:创建临时表
上下文:数据库
注释:使用CREATE TEMPORARY TABLE
...
SHOW GRANTS
声明
显示属于特定用户的权限
。
有关
更多信息
,
请参见
第13.7.6.21节“SHOW GRANTS语法”
。
显示程序代码 proc_name
此语句是MySQL扩展,仅适用于已使用调试支持构建的服务器。
它显示命名存储过程的内部实现的表示。
类似的语句
SHOW
FUNCTION CODE
显示有关存储函数的信息(请参见
第13.7.6.19节“显示函数代码语法”
)。
要使用任一语句,您必须具有全局
SELECT
特权。
如果命名例程可用,则每个语句都会生成结果集。
结果集中的每一行对应
于例程中的
一个
“
指令
”
。
第一列是
Pos
从0开始的序数。第二列是
Instruction
包含SQL语句(通常从原始源更改)或者只对存储例程处理程序有意义的指令。
mysql>DELIMITER //
mysql>CREATE PROCEDURE p1 ()
- >BEGIN
- >DECLARE fanta INT DEFAULT 55;
- >DROP TABLE t2;
- >LOOP
- >INSERT INTO t3 VALUES (fanta);
- >END LOOP;
- >END//
查询正常,0行受影响(0.00秒) MySQL的>SHOW PROCEDURE CODE p1//
+ ----- + ---------------------------------------- + | Pos | 说明| + ----- + ---------------------------------------- + | 0 | 设置fanta @ 0 55 | | 1 | stmt 9“DROP TABLE t2”| | 2 | stmt 5“INSERT INTO t3 VALUES(fanta)”| | 3 | 跳2 | + ----- + ---------------------------------------- + 4行(0.00秒)
在此示例中,不可执行
BEGIN
和
END
语句已消失,对于
语句,仅显示可执行部分(分配默认值的部分)。
对于从源代码中获取的每个语句,都有一个代码字
后跟一个类型(9表示
,5表示
,依此类推)。
最后一行包含一条指令
,意思是
。
DECLARE
variable_name
stmt
DROP
INSERT
jump 2
GOTO instruction #2
显示程序状态 [喜欢'pattern
'| 在哪里expr
]
该语句是MySQL扩展。
它返回存储过程的特征,例如数据库,名称,类型,创建者,创建和修改日期以及字符集信息。
类似的语句
SHOW
FUNCTION STATUS
显示有关存储函数的信息(参见
第13.7.6.20节“显示函数状态语法”
)。
该
LIKE
子句(如果存在)指示要匹配的过程或函数名称。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
MySQL的> SHOW PROCEDURE STATUS LIKE 'sp1'\G
*************************** 1。排******************** *******
Db:测试
名称:sp1
类型:程序
定义者:testuser @ localhost
修改时间:2018-08-08 13:54:11
创建时间:2018-08-08 13:54:11
Security_type:DEFINER
评论:
character_set_client:utf8mb4
collation_connection:utf8mb4_0900_ai_ci
数据库整理:utf8mb4_0900_ai_ci
character_set_client
是
character_set_client
创建例程时系统变量
的会话值
。
collation_connection
是
collation_connection
创建例程时系统变量
的会话值
。
Database
Collation
是与例程关联的数据库的排序规则。
存储的例程信息也可以从
INFORMATION_SCHEMA
PARAMETERS
和
ROUTINES
表中获得。
请参见
第25.16节“INFORMATION_SCHEMA参数表”
和
第25.23节“INFORMATION_SCHEMA ROUTINES表”
。
显示[FULL] PROCESSLIST
SHOW PROCESSLIST
显示正在运行的线程。
如果您有
PROCESS
权限,则可以查看所有主题。
否则,您只能看到自己的线程(即与您正在使用的MySQL帐户关联的线程)。
如果不使用
FULL
关键字,则只在
Info
字段
中显示每个语句的前100个字符
。
SHOW PROCESSLIST
如果您收到
“
太多连接
”
错误消息并想知道发生了什么,
该
语句非常有用
。
MySQL保留一个额外的连接以供具有
CONNECTION_ADMIN
或
SUPER
特权
的帐户使用
,以确保管理员应始终能够连接并检查系统(假设您没有向所有用户提供此特权)。
可以使用
KILL
语句
终止线程
。
请参见
第13.7.7.4节“KILL语法”
。
SHOW PROCESSLIST
输出
示例
:
mysql> SHOW FULL PROCESSLIST \ G. *************************** 1。排******************** ******* Id:1 用户:系统用户 主办: db:NULL 命令:连接 时间:1030455 州:等待主人发送事件 信息:NULL *************************** 2.排******************** ******* Id:2 用户:系统用户 主办: db:NULL 命令:连接 时间:1004 状态:已读取所有中继日志; 等待奴隶 I / O线程更新它 信息:NULL *************************** 3。排******************** ******* Id:3112 用户:replikator 主持人:artemis:2204 db:NULL 命令:Binlog转储 时间:2144 状态:已将所有binlog发送给奴隶; 等待binlog更新 信息:NULL ****************************排******************** ******* Id:3113 用户:replikator 主持人:iconnect2:45781 db:NULL 命令:Binlog转储 时间:2086年 状态:已将所有binlog发送给奴隶; 等待binlog更新 信息:NULL ****************************排******************** ******* Id:3123 网友:stefan 主持人:localhost db:apollon 命令:查询 时间:0 状态:NULL 信息:显示完整的流程列表 5行(0.00秒)
SHOW PROCESSLIST
输出有以下列:
连接标识符。
这是同一类型的在所显示的值
ID
的列
INFORMATION_SCHEMA
PROCESSLIST
表,该
PROCESSLIST_ID
性能图式的列
threads
表,并且通过返回的
CONNECTION_ID()
功能。
发出声明的MySQL用户。
值是
system user
指服务器在内部处理任务而生成的非客户端线程。
这可能是复制从属或延迟行处理程序上使用的I / O或SQL线程。
对于
system user
,
Host
列中
未指定主机
。
unauthenticated user
指的是已与客户端连接关联但尚未对客户端用户进行身份验证的线程。
event_scheduler
指监视预定事件的线程(请参见
第24.4节“使用事件调度程序”
)。
甲
User
的值
system
user
是从不同的
SYSTEM_USER
特权。
前者指定内部线程。
后者区分系统用户和常规用户帐户类别(请参见
第6.2.11节“帐户类别”
)。
发出语句的客户端的主机名(除了
system user
没有主机
的客户端
)。
TCP / IP连接的主机名以
格式
报告,
以便更容易确定哪个客户端正在执行哪些操作。
host_name
:client_port
默认数据库(如果选择了一个);
否则
NULL
。
线程正在执行的命令类型。
有关线程命令的说明,请参见
第8.14节“检查线程信息”
。
此列的值对应于
客户端/服务器协议和
状态变量
的
命令
。
请参见
第5.1.10节“服务器状态变量”
。
COM_
xxx
Com_
xxx
线程处于当前状态的时间(以秒为单位)。 对于从属SQL线程,该值是最后一个复制事件的时间戳与从属机器的实时之间的秒数。 请参见 第17.2.2节“复制实现细节” 。
指示线程正在执行的操作,事件或状态。
有关
State
值的
说明,请
参见
第8.14节“检查线程信息”
。
大多数州对应于非常快速的操作。 如果一个线程在给定状态下停留很多秒,则可能存在需要调查的问题。
对于
SHOW PROCESSLIST
声明中的价值
State
是
NULL
。
线程正在执行的语句,或者
NULL
它是否正在执行任何语句。
语句可能是发送到服务器的语句,如果语句执行其他语句,则可能是最内层语句。
例如,如果
CALL
语句执行正在执行语句的存储过程,则
SELECT
该
Info
值显示该
SELECT
语句。
还可以从
mysqladmin processlist
命令,
INFORMATION_SCHEMA
PROCESSLIST
表和Performance Schema
threads
表中
获取进程信息
(请参见
第4.5.2节“
mysqladmin
- 管理MySQL服务器的客户端”
,
第25.19节“INFORMATION_SCHEMA PROCESSLIST表”
和
第26.12节)。 .17.5,“线程表”
)。
与
INFORMATION_SCHEMA
PROCESSLIST
表和
SHOW PROCESSLIST
语句相比,由于它们需要互斥锁而导致性能损失,因此访问
threads
不需要互斥锁,并且对服务器性能的影响最小。
该
threads
表还显示了有关后台线程的信息,
PROCESSLIST
表中
SHOW PROCESSLIST
没有。
这意味着
threads
可以用来监视其他线程信息源不能的活动。
显示简介[type
[,type
] ...] [FOR QUERYn
] [限制row_count
[偏移offset
]]type
:{ 所有 | BLOCK IO | 上下文切换 | 中央处理器 | IPC | 记忆 | 页面故障 | 资源 | SWAPS }
在
SHOW PROFILE
和
SHOW PROFILES
报表显示剖析,表示当前会话过程中执行的语句资源使用信息。
该
SHOW PROFILE
和
SHOW PROFILES
语句被取消,并将在未来的MySQL版本中删除。
请改用
Performance Schema
;
请参见
第26.19.1节“使用性能模式查询分析”
。
要控制性能分析,请使用
profiling
会话变量,其默认值为0(
OFF
)。
通过设置
profiling
为1或
启用分析
ON
:
MySQL的> SET profiling = 1;
SHOW
PROFILES
显示发送到服务器的最新语句的列表。
列表的大小由
profiling_history_size
会话变量
控制,该
变量的默认值为15.最大值为100.将值设置为0具有禁用分析的实际效果。
除了
SHOW
PROFILE
和
之外
,
所有语句都被分析
SHOW
PROFILES
,因此您不会在配置文件列表中找到这些语句。
格式错误的陈述是分析的。
例如,
SHOW PROFILING
是一个非法语句,如果您尝试执行它会发生语法错误,但它将显示在分析列表中。
SHOW
PROFILE
显示有关单个语句的详细信息。
如果没有该
子句,则输出与最近执行的语句有关。
如果
包含,则
显示语句信息
。
值
对应于
显示
的
值
。
FOR
QUERY
n
FOR QUERY
n
SHOW PROFILE
n
n
Query_ID
SHOW PROFILES
可以给出
该
子句以将输出限制为
行。
如果
给出,
可以添加以将输出
行
开始
到完整的行集。
LIMIT
row_count
row_count
LIMIT
OFFSET
offset
offset
默认情况下,
SHOW PROFILE
显示
Status
和
Duration
列。
这些
Status
值与
State
显示
的
值类似
SHOW PROCESSLIST
,尽管某些状态值的两个语句的解释可能存在一些细微差别(请参见
第8.14节“检查线程信息”
)。
type
可以指定
可选
值以显示特定的其他类型的信息:
ALL
显示所有信息
BLOCK IO
显示块输入和输出操作的计数
CONTEXT SWITCHES
显示自愿和非自愿上下文切换的计数
CPU
显示用户和系统CPU使用时间
IPC
显示发送和接收的消息的计数
MEMORY
目前尚未实施
PAGE FAULTS
显示主要和次要页面错误的计数
SOURCE
显示源代码中的函数名称,以及函数发生的文件的名称和行号
SWAPS
显示交换计数
每个会话启用性能分析。 会话结束时,其分析信息将丢失。
MySQL的>SELECT @@profiling;
+ ------------- + | @@ profiling | + ------------- + | 0 | + ------------- + 1排(0.00秒) MySQL的>SET profiling = 1;
查询正常,0行受影响(0.00秒) MySQL的>DROP TABLE IF EXISTS t1;
查询正常,0行受影响,1警告(0.00秒) MySQL的>CREATE TABLE T1 (id INT);
查询OK,0行受影响(0.01秒) MySQL的>SHOW PROFILES;
+ ---------- + ---------- + -------------------------- + | Query_ID | 持续时间| 查询| + ---------- + ---------- + -------------------------- + | 0 | 0.000088 | SET PROFILING = 1 | | 1 | 0.000136 | DROP TABLE IF EXISTS t1 | | 2 | 0.011947 | CREATE TABLE t1(id INT)| + ---------- + ---------- + -------------------------- + 3组(0.00秒) MySQL的>SHOW PROFILE;
+ ---------------------- + ---------- + | 状态| 持续时间| + ---------------------- + ---------- + | 检查权限| 0.000040 | | 创建表| 0.000056 | | 创建后| 0.011363 | | 查询结束| 0.000375 | | 释放物品| 0.000089 | | 记录慢查询| 0.000019 | | 清理| 0.000005 | + ---------------------- + ---------- + 7行(0.00秒) MySQL的>SHOW PROFILE FOR QUERY 1;
+ -------------------- + ---------- + | 状态| 持续时间| + -------------------- + ---------- + | 查询结束| 0.000107 | | 释放物品| 0.000008 | | 记录慢查询| 0.000015 | | 清理| 0.000006 | + -------------------- + ---------- + 4行(0.00秒) MySQL的>SHOW PROFILE CPU FOR QUERY 2;
+ ---------------------- + ---------- + ---------- + ---- -------- + | 状态| 持续时间| CPU_user | CPU_system | + ---------------------- + ---------- + ---------- + ---- -------- + | 检查权限| 0.000040 | 0.000038 | 0.000002 | | 创建表| 0.000056 | 0.000028 | 0.000028 | | 创建后| 0.011363 | 0.000217 | 0.001571 | | 查询结束| 0.000375 | 0.000013 | 0.000028 | | 释放物品| 0.000089 | 0.000010 | 0.000014 | | 记录慢查询| 0.000019 | 0.000009 | 0.000010 | | 清理| 0.000005 | 0.000003 | 0.000002 | + ---------------------- + ---------- + ---------- + ---- -------- + 7行(0.00秒)
分析仅在某些体系结构上具有部分功能。
对于依赖于
getrusage()
系统调用的
值,
NULL
将在不支持该调用的Windows等系统上返回。
此外,分析是每个进程而不是每个线程。
这意味着除了您自己的服务器之外的服务器上的线程上的活动可能会影响您看到的计时信息。
INFORMATION_SCHEMA
PROFILING
表中
还提供了性能分析信息
。
请参见
第25.20节“INFORMATION_SCHEMA PROFILING表”
。
例如,以下查询是等效的:
显示查询2; 选择状态,格式化(持续时间,6)作为持续时间 来自INFORMATION_SCHEMA.PROFILING WHERE QUERY_ID = 2 ORDER BY SEQ;
显示配置文件
该
SHOW PROFILES
语句与
SHOW PROFILE
显示的分析信息
一起
显示了在当前会话过程中执行的语句的资源使用情况。
有关更多信息,请参见
第13.7.6.30节“显示配置文件语法”
。
该
SHOW PROFILE
和
SHOW PROFILES
语句被取消,并将在未来的MySQL版本中删除。
请改用
Performance Schema
;
请参见
第26.19.1节“使用性能模式查询分析”
。
显示RELAYLOG活动 [IN'log_name
'] [从pos
] [限制[offset
,]row_count
] [channel_option
]channel_option
: FOR CHANNELchannel
显示复制从站的中继日志中的事件。
如果未指定
,则显示第一个中继日志。
该声明对主人没有影响。
需要
特权。
'
log_name
'SHOW RELAYLOG EVENTS
REPLICATION SLAVE
该
LIMIT
子句的语法与
SELECT
语句
相同
。
请参见
第13.2.10节“SELECT语法”
。
发出
SHOW RELAYLOG EVENTS
no with no
LIMIT
子句可能会启动耗费时间和资源的过程,因为服务器会向中心返回中继日志的完整内容(包括修改从站接收的数据的所有语句)。
使用optional
子句可以命名该语句适用的复制通道。
提供
子句将语句应用于特定复制通道。
如果未命名通道且不存在额外通道,则该语句将应用于默认通道。
FOR CHANNEL
channel
FOR CHANNEL
channel
使用多个复制通道时,如果
SHOW RELAYLOG EVENTS
语句没有使用
子句
定义的
通道,则会
生成错误。
有关
更多信息
,
请参见
第17.2.3节“复制通道”
。
FOR CHANNEL
channel
SHOW RELAYLOG EVENTS
显示中继日志中每个事件的以下字段:
Log_name
要列出的文件的名称。
Pos
事件发生的位置。
Event_type
描述事件类型的标识符。
Server_id
发生事件的服务器的服务器ID。
End_log_pos
值
End_log_pos
此事件在主人的二进制日志。
Info
有关事件类型的更多详细信息。 此信息的格式取决于事件类型。
与设置用户和系统变量有关的一些事件不包括在输出中
SHOW RELAYLOG EVENTS
。
要完全了解中继日志中的事件,请使用
mysqlbinlog
。
SHOW SLAVE HOSTS
显示当前向主服务器注册的复制从服务器列表。
SHOW SLAVE HOSTS
需要
REPLICATION SLAVE
特权。
SHOW SLAVE HOSTS
应该在充当复制主服务器的服务器上执行。
该语句显示有关已连接或已连接为复制从属服务器的信息,结果的每一行对应一个从属服务器,如下所示:
mysql> SHOW SLAVE HOSTS
;
+ ------------ + ----------- ------ + + ----------- + ----- --------------------------------- +
| Server_id | 主持人| 港口| Master_id | Slave_UUID |
+ ------------ + ----------- ------ + + ----------- + ----- --------------------------------- +
| 192168010 | iconnect2 | 3306 | 192168011 | 14cb6624-7f93-11e0-b2c0-c80aa9429562 |
| 1921680101 | 雅典娜| 3306 | 192168011 | 07af4990-f41f-11df-a566-7ac56fdaf645 |
+ ------------ + ----------- ------ + + ----------- + ----- --------------------------------- +
Server_id
:从服务器的唯一服务器ID,在从服务器的选项文件中配置,或在命令行中配置
。
--server-id=
value
Host
:带有
--report-host
选项
的从站上指定的从服务器的主机名
。
这可能与操作系统中配置的计算机名称不同。
User
:从服务器用户名as,在带有
--report-user
选项
的从站上指定
。
仅当使用该
--show-slave-auth-info
选项
启动主服务器时,语句输出才包含此列
。
Password
:从服务器密码as,在带有
--report-password
选项
的从站上指定
。
仅当使用该
--show-slave-auth-info
选项
启动主服务器时,语句输出才包含此列
。
Port
:从服务器正在侦听的主服务器上的端口,如带有
--report-port
选项
的从服务器上指定的那样
。
此列中的零表示
--report-port
未设置
从端口(
)。
Master_id
:从服务器正在复制的主服务器的唯一服务器ID。
这是执行的服务器的服务器ID
SHOW
SLAVE HOSTS
,因此为结果中的每一行列出了相同的值。
SHOW SLAVE STATUS [FOR CHANNEL channel
]
此语句提供有关从属线程的基本参数的状态信息。
它需要
SUPER
或
REPLICATION CLIENT
特权。
SHOW SLAVE STATUS
是非阻塞的。
与其同时运行时
STOP
SLAVE
,
SHOW SLAVE STATUS
返回时无需等待
STOP SLAVE
完成关闭从属SQL线程或从属I / O线程(或两者)。
这允许在监视和其他应用程序中使用,其中立即响应
SHOW SLAVE STATUS
比确保它返回最新数据更重要。
如果使用
mysql
客户端
发出此语句
,则可以使用
\G
语句终止符而不是分号来获得更易读的垂直布局:
MySQL的> SHOW SLAVE STATUS\G
*************************** 1。排******************** *******
Slave_IO_State:等待主节点发送事件
Master_Host:localhost
Master_User:repl
Master_Port:13000
Connect_Retry:60
Master_Log_File:master-bin.000002
Read_Master_Log_Pos:1307
Relay_Log_File:slave-relay-bin.000003
Relay_Log_Pos:1508
Relay_Master_Log_File:master-bin.000002
Slave_IO_Running:是的
Slave_SQL_Running:是的
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno:0
Last_Error:
Skip_Counter:0
Exec_Master_Log_Pos:1307
Relay_Log_Space:1858
Until_Condition:无
Until_Log_File:
Until_Log_Pos:0
Master_SSL_Allowed:没有
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master:0
Master_SSL_Verify_Server_Cert:没有
Last_IO_Errno:0
Last_IO_Error:
Last_SQL_Errno:0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id:1
Master_UUID:3e11fa47-71ca-11e1-9e33-c80aa9429562
Master_Info_File:/var/mysqld.2/data/master.info
SQL_Delay:0
SQL_Remaining_Delay:NULL
Slave_SQL_Running_State:从中继日志中读取事件
Master_Retry_Count:10
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:3e11fa47-71ca-11e1-9e33-c80aa9429562:1-5
Executed_Gtid_Set:3e11fa47-71ca-11e1-9e33-c80aa9429562:1-5
Auto_Position:1
Replicate_Rewrite_DB:
CHANNEL_NAME:
Master_TLS_Version:TLSv1.2
Master_public_key_path:public_key.pem
Get_master_public_key:0
性能模式提供了公开复制信息的表。
这与
SHOW SLAVE STATUS
声明中
提供的信息类似
,但以表格形式表示。
有关详细信息,请参见
第26.12.11节“性能模式复制表”
。
以下列表描述了返回的字段
SHOW SLAVE STATUS
。
有关解释其含义的其他信息,请参见
第17.1.7.1节“检查复制状态”
。
Slave_IO_State
从属I / O线程
State
的
SHOW PROCESSLIST
输出
字段的
副本
。
这告诉您线程正在做什么:尝试连接到主服务器,等待主服务器的事件,重新连接到主服务器,等等。
有关可能状态的列表,请参见
第8.14.4节“复制从站I / O线程状态”
。
Master_Host
从属设备连接的主控主机。
Master_User
用于连接到主服务器的帐户的用户名。
Master_Port
用于连接主服务器的端口。
Connect_Retry
连接重试之间的秒数(默认为60)。
这可以使用
CHANGE MASTER
TO
语句
设置
。
Master_Log_File
I / O线程当前正在读取的主二进制日志文件的名称。
Read_Master_Log_Pos
I / O线程读取的当前主二进制日志文件中的位置。
Relay_Log_File
SQL线程当前正在读取和执行的中继日志文件的名称。
Relay_Log_Pos
当前中继日志文件中SQL线程已读取和执行的位置。
Relay_Master_Log_File
包含SQL线程执行的最新事件的主二进制日志文件的名称。
Slave_IO_Running
I / O线程是否已启动并已成功连接到主站。 在内部,此线程的状态由以下三个值之一表示:
MYSQL_SLAVE_NOT_RUN。
从I / O线程未运行。
对于这种状态,
Slave_IO_Running
是
No
。
MYSQL_SLAVE_RUN_NOT_CONNECT。
从I / O线程正在运行,但未连接到复制主机。
对于这种状态,
Slave_IO_Running
是
Connecting
。
MYSQL_SLAVE_RUN_CONNECT。
从I / O线程正在运行,并连接到复制主机。
对于这种状态,
Slave_IO_Running
是
Yes
。
所述的值
Slave_running
系统状态变量对应于该值。
Slave_SQL_Running
SQL线程是否已启动。
Replicate_Do_DB
,
Replicate_Ignore_DB
使用
--replicate-do-db
和
--replicate-ignore-db
选项或
CHANGE REPLICATION
FILTER
语句
指定的任何数据库的名称
。
如果使用该
FOR
CHANNEL
子句,则会显示特定于通道的复制过滤器。
否则,将显示每个复制通道的复制筛选器。
Replicate_Do_Table
,
Replicate_Ignore_Table
,
Replicate_Wild_Do_Table
,
Replicate_Wild_Ignore_Table
与被指定的任何表的名称
--replicate-do-table
,
--replicate-ignore-table
,
--replicate-wild-do-table
,和
--replicate-wild-ignore-table
选项,或
CHANGE REPLICATION
FILTER
声明。
如果使用该
FOR
CHANNEL
子句,则会显示特定于通道的复制过滤器。
否则,将显示每个复制通道的复制筛选器。
Last_Errno
,
Last_Error
这些列是
Last_SQL_Errno
和的
别名
Last_SQL_Error
。
发出
RESET MASTER
或
RESET SLAVE
重置这些列中显示的值。
当从属SQL线程收到错误时,它首先报告错误,然后停止SQL线程。
这意味着有一个小的时间窗口,在此期间
即使
仍然显示
也
SHOW SLAVE STATUS
显示非零值
。
Last_SQL_Errno
Slave_SQL_Running
Yes
Skip_Counter
sql_slave_skip_counter
系统变量
的当前值
。
请参见
第13.4.2.5节“SET GLOBAL sql_slave_skip_counter语法”
。
Exec_Master_Log_Pos
SQL线程已读取并执行的当前主二进制日志文件中的位置,标记要处理的下一个事务或事件的开始。
从现有从站启动新从站时,
可以将此值与
CHANGE MASTER
TO
语句
MASTER_LOG_POS
选项
一起使用
,以便新从站从此点读取。
通过给出的坐标(
Relay_Master_Log_File
,
Exec_Master_Log_Pos
在主服务器的二进制日志)对应于给出的坐标(
Relay_Log_File
,
Relay_Log_Pos
在中继日志)。
来自中继日志的事务序列中已执行的不一致可导致该值为
“
低水位线
”
。
换句话说,保证在该头寸之前出现的交易已经提交,但该头寸之后的交易可能已经提交或未提交。
如果需要纠正这些差距,请使用
START SLAVE
UNTIL SQL_AFTER_MTS_GAPS
。
有关
更多信息
,
请参见
第17.4.1.33节“复制和事务不一致”
。
Relay_Log_Space
所有现有中继日志文件的总组合大小。
Until_Condition
,
Until_Log_File
,
Until_Log_Pos
语句
UNTIL
子句中
指定的值
START SLAVE
。
Until_Condition
有这些价值观:
None
如果没有
UNTIL
指定条款
Master
如果从机正在读取,直到主机二进制日志中的给定位置
Relay
如果从站正在读取,直到其中继日志中的给定位置
SQL_BEFORE_GTIDS
如果从属SQL线程正在处理事务,直到它到达其中列出GTID的第一个事务
gtid_set
。
SQL_AFTER_GTIDS
如果从属线程正在处理所有事务,直到两个线程都处理了最后一个事务
gtid_set
。
SQL_AFTER_MTS_GAPS
如果多线程从属的SQL线程正在运行,直到在中继日志中找不到更多间隙。
Until_Log_File
并
Until_Log_Pos
指明用于定义SQL线程停止执行的坐标的日志文件名称和位置。
有关
UNTIL
子句的
更多信息
,请参见
第13.4.2.6节“START SLAVE语法”
。
Master_SSL_Allowed
,
Master_SSL_CA_File
,
Master_SSL_CA_Path
,
Master_SSL_Cert
,
Master_SSL_Cipher
,
Master_SSL_CRL_File
,
Master_SSL_CRL_Path
,
Master_SSL_Key
,
Master_SSL_Verify_Server_Cert
这些字段显示从站用于连接到主站的SSL参数(如果有)。
Master_SSL_Allowed
有这些价值观:
Yes
如果允许与主服务器建立SSL连接
No
如果不允许与主服务器建立SSL连接
Ignored
如果允许SSL连接但从服务器未启用SSL支持
其他SSL相关的字段的值对应的值
MASTER_SSL_CA
,
MASTER_SSL_CAPATH
,
MASTER_SSL_CERT
,
MASTER_SSL_CIPHER
,
MASTER_SSL_CRL
,
MASTER_SSL_CRLPATH
,
MASTER_SSL_KEY
,和
MASTER_SSL_VERIFY_SERVER_CERT
选项的
CHANGE MASTER TO
说法。
请参见
第13.4.2.1节“更改主语法”
。
Seconds_Behind_Master
该字段表示 奴隶的 “ 迟到 ” :
当从站正在主动处理更新时,此字段显示从站上当前时间戳与主站上当前正在处理的事件上记录的原始时间戳之间的差异。
当从站上当前没有处理任何事件时,该值为0。
本质上,该字段测量从属SQL线程和从属I / O线程之间的时间差(秒)。
如果主站和从站之间的网络连接速度很快,则从站I / O线程非常接近主站,因此该字段很好地近似了从站SQL线程与主站的比较。
如果网络很慢,这
不是
一个很好的近似;
从属SQL线程可能经常遇到慢速读取从属I / O线程,因此
Seconds_Behind_Master
即使I / O线程与主节点相比较晚,也经常显示值0。
换句话说,
此列仅适用于快速网络
。
即使主机和从机没有相同的时钟时间,这个时间差计算仍然有效,前提是从机I / O线程启动时计算的差值从那时起保持不变。
任何更改(包括NTP更新)都可能导致时钟偏差,从而导致计算
Seconds_Behind_Master
可靠性降低。
在MySQL 8.0中,
NULL
如果从属SQL线程未运行,或者SQL线程已消耗所有中继日志且从属I / O线程未运行
,则此字段为
(未定义或未知)。
(在旧版本的MySQL中,此字段是
NULL
从属SQL线程或从属I / O线程未运行或未连接到主服务器。)如果I / O线程正在运行但是中继日志已用完,
Seconds_Behind_Master
则是设为0。
值
Seconds_Behind_Master
基于存储在事件中的时间戳,这些时间戳通过复制保留。
这意味着如果主M1本身是M0的从属,则来自M1的二进制日志的任何来自M0的二进制日志的事件都具有该事件的M0时间戳。
这使MySQL能够
TIMESTAMP
成功
复制
。
然而,问题
Seconds_Behind_Master
是如果M1也从客户端接收直接更新,则该
Seconds_Behind_Master
值随机波动,因为有时来自M1的最后一个事件源自M0,有时是M1上的直接更新的结果。
使用多线程从属时,应记住此值基于
Exec_Master_Log_Pos
,因此可能无法反映最近提交的事务的位置。
Last_IO_Errno
,
Last_IO_Error
导致I / O线程停止的最新错误的错误号和错误消息。
错误号为0,空字符串的消息表示
“
没有错误。
“
如果该
Last_IO_Error
值不为空,则错误值也会出现在从站的错误日志中。
I / O错误信息包括显示最近发生的I / O线程错误的时间戳。
此时间戳使用格式
YYMMDD hh:mm:ss
,并显示在
Last_IO_Error_Timestamp
列中。
发出
RESET MASTER
或
RESET SLAVE
重置这些列中显示的值。
Last_SQL_Errno
,
Last_SQL_Error
导致SQL线程停止的最新错误的错误号和错误消息。
错误号为0,空字符串的消息表示
“
没有错误。
“
如果该
Last_SQL_Error
值不为空,则错误值也会出现在从站的错误日志中。
如果从属是多线程的,则SQL线程是工作线程的协调器。
在这种情况下,该
Last_SQL_Error
字段显示
Last_Error_Message
Performance Mapma
replication_applier_status_by_coordinator
表中
的
列
显示的内容。
修改字段值以表明其他工作线程中可能存在更多故障,这些故障可以在
replication_applier_status_by_worker
显示每个工作线程状态
的
表中
看到
。
如果该表不可用,则可以使用从属错误日志。
replication_applier_status_by_worker
还应使用
日志或
表来了解有关
SHOW SLAVE STATUS
协调器表所
显示的故障的更多信息
。
SQL错误信息包括显示最近发生SQL线程错误的时间戳。
此时间戳使用格式
YYMMDD hh:mm:ss
,并显示在
Last_SQL_Error_Timestamp
列中。
发出
RESET MASTER
或
RESET SLAVE
重置这些列中显示的值。
在MySQL 8.0中,
Last_SQL_Errno
和
Last_SQL_Error
列中
显示的所有错误代码和消息都
对应于
第B.3.1节“服务器错误消息参考”中
列出的错误值
。
在以前的版本中并非总是如此。
(Bug#11760365,Bug#52768)
Replicate_Ignore_Server_Ids
使用
语句
IGNORE_SERVER_IDS
选项
指定的任何服务器标识
CHANGE MASTER TO
,以便从属服务器忽略来自这些服务器的事件。
当删除其中一个服务器时,此选项用于循环或其他多主复制设置。
如果以这种方式设置了任何服务器ID,则会显示一个或多个数字的逗号分隔列表。
如果未设置服务器ID,则该字段为空。
表中
的
Ignored_server_ids
值
slave_master_info
还显示要忽略的服务器ID,但作为以空格分隔的列表,前面是要忽略的服务器ID总数。
例如,如果发出
CHANGE MASTER
TO
包含该
IGNORE_SERVER_IDS = (2,6,9)
选项
的
语句
以告知从属服务器忽略具有服务器ID 2,6或9的主服务器,则该信息如下所示:
Replicate_Ignore_Server_Ids:2,6,9
Ignored_server_ids:3,2,6,9
Replicate_Ignore_Server_Ids
过滤由I / O线程执行,而不是由SQL线程执行,这意味着过滤掉的事件不会写入中继日志。
这与服务器选项所采用的过滤操作不同
--replicate-do-table
,后者适用于SQL线程。
从MySQL 8.0.3开始,如果
SET GTID_MODE=ON
在任何通道设置了现有服务器ID时
发出,
则会发出
弃用警告
IGNORE_SERVER_IDS
。
在启动基于GTID的复制之前,请使用
SHOW_SLAVE_STATUS
检查并清除所涉及的服务器上所有被忽略的服务器ID列表。
您可以通过发出
CHANGE MASTER TO
包含
IGNORE_SERVER_IDS
带有空列表
的
选项
的
语句
来清除
列表。
Master_Server_Id
server_id
来自主人
的
价值。
Master_UUID
server_uuid
来自主人
的
价值。
Master_Info_File
master.info
如果文件而不是表用于从属主信息存储库,则文件
的位置
。
SQL_Delay
从站必须滞后主站的秒数。
SQL_Remaining_Delay
如果
Slave_SQL_Running_State
是
Waiting until MASTER_DELAY seconds after master
executed event
,则此字段包含的剩余延迟秒数。
在其他时候,这个领域是
NULL
。
Slave_SQL_Running_State
SQL线程的状态(类似于
Slave_IO_State
)。
该值与
State
显示的SQL线程
的值相同
SHOW
PROCESSLIST
。
第8.14.5节“复制从属SQL线程状态”
提供了可能状态的列表
Master_Retry_Count
在连接丢失的情况下,从站可以尝试重新连接到主站的次数。
可以使用
语句(首选)或旧
服务器选项(仍然支持向后兼容性)
的
MASTER_RETRY_COUNT
选项
来设置此值
。
CHANGE MASTER
TO
--master-retry-count
Master_Bind
从属绑定的网络接口(如果有)。
这是使用
语句
MASTER_BIND
选项设置的
CHANGE MASTER TO
。
Last_IO_Error_Timestamp
YYMMDD hh:mm:ss
格式
的时间戳
,显示最近的I / O错误发生的时间。
Last_SQL_Error_Timestamp
YYMMDD hh:mm:ss
格式化
的时间戳
,显示最近发生的SQL错误。
Retrieved_Gtid_Set
与此从站接收的所有事务对应的全局事务ID集。 如果未使用GTID,则清空。 有关 更多信息, 请参阅 GTID集 。
这是中继日志中存在或已存在的所有GTID的集合。
Gtid_log_event
收到后
立即添加每个GTID
。
这可能导致部分传输的事务将其GTID包含在集合中。
当所有中继日志由于执行
RESET SLAVE
或
CHANGE MASTER TO
由于
--relay-log-recovery
选项
的影响而
丢失时
,该组将被清除。
何时
relay_log_purge =
1
,始终保留最新的中继日志,并且不清除该组。
Executed_Gtid_Set
在二进制日志中写入的全局事务ID集。
这与
gtid_executed
此服务器上
的全局
系统变量的值以及此服务器
Executed_Gtid_Set
的输出中
的值相同
SHOW MASTER STATUS
。
如果未使用GTID,则清空。
有关
更多信息,
请参阅
GTID集
。
Auto_Position
1如果正在使用自动定位; 否则为0。
Replicate_Rewrite_DB
该
Replicate_Rewrite_DB
值显示指定的任何复制筛选规则。
例如,如果设置了以下复制过滤规则:
CHANGE REPLICATION FILTER REPLICATE_REWRITE_DB =((db1,db2),(db3,db4));
该
Replicate_Rewrite_DB
值显示:
Replicate_Rewrite_DB:(db1,db2),(db3,db4)
有关更多信息,请参见 第13.4.2.2节“更改复制过滤器语法” 。
Channel_name
正在显示的复制通道。 始终存在默认复制通道,可以添加更多复制通道。 有关 更多信息 , 请参见 第17.2.3节“复制通道” 。
Master_TLS_Version
主服务器上使用的TLS版本。 有关TLS版本信息,请参见 第6.3.6节“加密连接协议和密码” 。
Master_public_key_path
包含主服务器所需的公钥的从属端副本的文件的路径名,用于基于RSA密钥对的密码交换。
该文件必须采用PEM格式。
此列适用于使用
sha256_password
或
caching_sha2_password
身份验证插件进行
身份验证的从属
服务器。
如果
Master_public_key_path
给定并指定了有效的公钥文件,则优先于
Get_master_public_key
。
Get_master_public_key
是否向主服务器请求基于RSA密钥对的密码交换所需的公钥。
此列适用于使用
caching_sha2_password
身份验证插件
进行
身份验证的
从属
服务器。
对于该插件,除非请求,否则主服务器不会发送公钥。
如果
Master_public_key_path
给定并指定了有效的公钥文件,则优先于
Get_master_public_key
。
SHOW [GLOBAL | 会话]状态 [喜欢'pattern
'| 在哪里expr
]
SHOW
STATUS
提供服务器状态信息(请参见
第5.1.10节“服务器状态变量”
)。
此声明不需要任何权限。
它只需要连接到服务器的能力。
还可以从以下来源获取状态变量信息:
性能架构表。 请参见 第26.12.14节“性能模式状态变量表” 。
在 中mysqladmin扩展状态 命令。 请参见 第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端” 。
对于
SHOW
STATUS
,
LIKE
子句(如果存在)指示要匹配的变量名称。
WHERE
可以使用
一个
子句来选择使用更一般条件的行,如
第25.42节“扩展显示语句”中所述
。
SHOW
STATUS
接受可选
GLOBAL
或
SESSION
变量范围修饰符:
使用
GLOBAL
修饰符,语句将显示全局状态值。
全局状态变量可以表示服务器本身某些方面的状态(例如,
Aborted_connects
),或者表示与MySQL的所有连接的聚合状态(例如,
Bytes_received
和
Bytes_sent
)。
如果变量没有全局值,则显示会话值。
使用
SESSION
修饰符,语句将显示当前连接的状态变量值。
如果变量没有会话值,则显示全局值。
LOCAL
是...的同义词
SESSION
。
如果不存在修饰符,则默认为
SESSION
。
第5.1.10节“服务器状态变量”中 列出了每个状态变量的范围 。
每次调用
SHOW
STATUS
语句都使用内部临时表并递增全局
Created_tmp_tables
值。
此处显示了部分输出。 您的服务器的名称和值列表可能有所不同。 第5.1.10节“服务器状态变量”中 给出了每个变量的含义 。
MySQL的> SHOW STATUS;
+ -------------------------- + ------------ +
| Variable_name | 价值|
+ -------------------------- + ------------ +
| Aborted_clients | 0 |
| Aborted_connects | 0 |
| Bytes_received | 155372598 |
| Bytes_sent | 1176560426 |
| 连接| 30023 |
| Created_tmp_disk_tables | 0 |
| Created_tmp_tables | 8340 |
| Created_tmp_files | 60 |
...
| Open_tables | 1 |
| Open_files | 2 |
| Open_streams | 0 |
| Opened_tables | 44600 |
| 问题| 2026873 |
...
| Table_locks_immediate | 1920382 |
| Table_locks_waited | 0 |
| Threads_cached | 0 |
| Threads_created | 30022 |
| Threads_connected | 1 |
| Threads_running | 1 |
| 正常运行时间| 80380 |
+ -------------------------- + ------------ +
使用
LIKE
子句,该语句仅显示名称与模式匹配的变量的行:
MySQL的> SHOW STATUS LIKE 'Key%';
+ -------------------- + ---------- +
| Variable_name | 价值|
+ -------------------- + ---------- +
| Key_blocks_used | 14955 |
| Key_read_requests | 96854827 |
| Key_reads | 162040 |
| Key_write_requests | 7589728 |
| Key_writes | 3813196 |
+ -------------------- + ---------- +
显示表状态 [{FROM | 在}db_name
] [喜欢'pattern
'| 在哪里expr
]
SHOW TABLE STATUS
工作喜欢
SHOW
TABLES
,但提供了很多关于每个非
TEMPORARY
表
的信息
。
您还可以使用
mysqlshow --status
db_name
命令
获取此列表
。
该
LIKE
子句(如果存在)指示要匹配的表名。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
此语句还显示有关视图的信息。
SHOW TABLE STATUS
输出有以下列:
Name
表的名称。
Engine
表的存储引擎。 请参见 第15章, InnoDB存储引擎 和 第16章, 备用存储引擎 。
对于分区表,
Engine
显示所有分区使用的存储引擎的名称。
Version
此列未使用。
通过删除
.frm
MySQL 8.0中
的
文件,此列现在报告硬编码值
10
,这是
.frm
MySQL 5.7中使用
的最后一个
文件版本。
Row_format
该行的存储格式(
Fixed
,
Dynamic
,
Compressed
,
Redundant
,
Compact
)。
对于
MyISAM
表格,
Dynamic
对应
myisamchk -dvv
报告的内容
Packed
。
Rows
行数。
某些存储引擎(例如
MyISAM
)存储确切的计数。
对于其他存储引擎,例如
InnoDB
,该值是近似值,并且可以与实际值相差多达40%至50%。
在这种情况下,用于
SELECT COUNT(*)
获得准确的计数。
该
Rows
值是
NULL
对
INFORMATION_SCHEMA
表。
Avg_row_length
平均行长。
Data_length
For
MyISAM
,
Data_length
是数据文件的长度,以字节为单位。
For
InnoDB
,
Data_length
是为聚簇索引分配的大致内存量,以字节为单位。
具体来说,它是聚集索引大小(以页为单位)乘以
InnoDB
页面大小。
有关其他存储引擎的信息,请参阅本节末尾的注释。
Max_data_length
对于
MyISAM
,
Max_data_length
是数据文件的最大长度。
这是在给定数据指针大小的情况下可以存储在表中的数据的总字节数。
未使用
InnoDB
。
有关其他存储引擎的信息,请参阅本节末尾的注释。
Index_length
For
MyISAM
,
Index_length
是索引文件的长度,以字节为单位。
For
InnoDB
,
Index_length
是为非聚簇索引分配的大致内存量,以字节为单位。
具体来说,它是非聚集索引大小(以页为单位)乘以
InnoDB
页面大小
的总和
。
有关其他存储引擎的信息,请参阅本节末尾的注释。
Data_free
已分配但未使用的字节数。
InnoDB
tables报告表所属的表空间的可用空间。
对于位于共享表空间中的表,这是共享表空间的可用空间。
如果您使用多个表空间并且该表具有自己的表空间,则可用空间仅用于该表。
可用空间表示完全空闲的区域中的字节数减去安全边界。
即使可用空间显示为0,只要不需要分配新的扩展区,就可以插入行。
对于NDB Cluster,
Data_free
显示磁盘上为磁盘数据表或磁盘分配但未使用的空间。
(
Data_length
列
报告内存数据资源使用情况
。)
对于分区表,此值仅为估计值,可能不完全正确。
在这种情况下获取此信息的更准确方法是查询
INFORMATION_SCHEMA
PARTITIONS
表,如下例所示:
SELECT SUM(DATA_FREE) 来自INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA ='mydb' AND TABLE_NAME ='mytable';
有关更多信息,请参见 第25.17节“INFORMATION_SCHEMA PARTITIONS表” 。
Auto_increment
下一个
AUTO_INCREMENT
值。
Create_time
创建表时。
Update_time
上次更新数据文件时。
对于某些存储引擎,此值为
NULL
。
例如,
InnoDB
在其
系统表空间中
存储多个表,
并且数据文件时间戳不适用。
即使
文件每次表
模式与每个
InnoDB
在单独的表
.ibd
文件,
改变缓冲
可以延缓写入到数据文件,因此,文件的修改时间是从最后插入的时间不同,更新或删除。
对于
MyISAM
,使用数据文件时间戳;
但是,在Windows上,更新不会更新时间戳,因此值不准确。
Update_time
显示最后一个
UPDATE
,
INSERT
或
DELETE
在
InnoDB
未分区的表上
执行
的时间戳值
。
对于MVCC,时间戳值反映
COMMIT
时间,该时间被视为上次更新时间。
重新启动服务器或从
InnoDB
数据字典缓存中
逐出表时,时间戳不会保留
。
Check_time
上次检查表时。
此时并非所有存储引擎都更新,在这种情况下,值始终为
NULL
。
对于分区
InnoDB
表,
Check_time
总是如此
NULL
。
Collation
表默认排序规则。 输出未显式列出表默认字符集,但排序规则名称以字符集名称开头。
Checksum
实时校验和值(如果有)。
Create_options
使用的额外选项
CREATE
TABLE
。
CREATE TABLE
保留了执行
when时的原始选项,
此处报告的选项可能与活动表设置和选项不同。
对于
InnoDB
表格,
报告
实际
ROW_FORMAT
和
KEY_BLOCK_SIZE
选项。
在MySQL 8.0之前,
Create_options
报告最初提供的
ROW_FORMAT
和
KEY_BLOCK_SIZE
。
有关更多信息,请参见
第13.1.20节“CREATE TABLE语法”
。
Create_options
显示
partitioned
表是否已分区。
它还显示
ENCRYPTION
在创建或更改每个表的文件表空间时指定
的
选项。
此列不显示创建或更改常规表空间时指定的加密选项。
该
表
的
ENCRYPTION
列
INNODB_TABLESPACES
适用于每个表文件和一般表空间。
Comment
创建表时使用的注释(或有关MySQL无法访问表信息的信息)。
对于
NDB
表,此语句的输出显示
Avg_row_length
和
Data_length
列的
适当值,但
BLOB
不考虑列。
对于
NDB
表格,仅
Data_length
包括存储在主存储器中的数据;
在
Max_data_length
与
Data_free
列应用到磁盘的数据。
对于NDB Cluster Disk Data表,
Max_data_length
显示为磁盘数据表或片段的磁盘部分分配的空间。
(
Data_length
列
报告内存数据资源使用情况
。)
对于
MEMORY
表,
Data_length
,
Max_data_length
,和
Index_length
值近似分配内存的实际数量。
分配算法大量保留存储器以减少分配操作的数量。
对于视图,显示的大多数列为
SHOW TABLE STATUS
0或
NULL
除了
Name
表示视图名称,
Create_time
表示创建时间,并
Comment
说
VIEW
。
表中还提供了
INFORMATION_SCHEMA
TABLES
表信息。
请参见
第25.30节“INFORMATION_SCHEMA TABLES表”
。
显示[扩展] [完整]表格 [{FROM | IN}db_name
] [喜欢'pattern
'| 在哪里expr
]
SHOW
TABLES
列出
TEMPORARY
给定数据库
中的非
表。
您也可以使用
mysqlshow
db_name
命令
获取此列表
。
该
LIKE
子句(如果存在)指示要匹配的表名。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
该
LIKE
子句
执行的匹配
取决于
lower_case_table_names
系统变量
的设置
。
可选
EXTENDED
修饰符导致
SHOW
TABLES
列出由失败
ALTER
TABLE
语句
创建的隐藏表
。
这些临时表的名称以逗号开头,
#sql
可以使用删除
DROP
TABLE
。
此语句还列出了数据库中的所有视图。
可选的
FULL
改性剂引起
SHOW
TABLES
显示与的值的第二输出列
BASE TABLE
为一个表,
VIEW
用于一个视图,或
SYSTEM
VIEW
为一个
INFORMATION_SCHEMA
表。
如果您没有基表或视图的权限,则它不会显示在输出
SHOW
TABLES
或
mysqlshow db_name中
。
表中还提供了
INFORMATION_SCHEMA
TABLES
表信息。
请参见
第25.30节“INFORMATION_SCHEMA TABLES表”
。
显示触发器 [{FROM | IN}db_name
] [喜欢'pattern
'| 在哪里expr
]
SHOW
TRIGGERS
列出当前为数据库中的表定义的触发器(默认数据库,除非
FROM
给出
了
子句)。
此语句仅返回您具有该
TRIGGER
权限的
数据库和表的结果
。
该
LIKE
子句(如果存在)指示要匹配的表名(而不是触发器名),并使该语句显示这些表的触发器。
该
WHERE
子句可以使用更一般的条件来选择行,如
第25.42节“扩展到SHOW语句”中所述
。
对于
第24.3节“使用触发器”中
ins_sum
定义的
触发器
,输出
SHOW TRIGGERS
如下所示:
MySQL的> SHOW TRIGGERS LIKE 'acc%'\G
*************************** 1。排******************** *******
触发:ins_sum
事件:插入
表:帐户
声明:SET @sum = @sum + NEW.amount
时间:之前
创建时间:2018-08-08 10:10:12.61
sql_mode:ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,
NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,
NO_ENGINE_SUBSTITUTION
定义者:我@ localhost
character_set_client:utf8mb4
collation_connection:utf8mb4_0900_ai_ci
数据库整理:utf8mb4_0900_ai_ci
SHOW
TRIGGERS
输出有以下列:
Trigger
触发器的名称。
Event
触发事件。
这是触发器激活的关联表上的操作类型。
值为
INSERT
(插入了一行),
DELETE
(删除了一行)或
UPDATE
(一行被修改)。
Table
为其定义触发器的表。
Statement
触发体; 也就是说,触发器激活时执行的语句。
Timing
触发器在触发事件之前还是之后激活。
值是
BEFORE
或
AFTER
。
Created
创建触发器的日期和时间。
这是
TIMESTAMP(2)
触发器
的
值(以百分之几秒为单位)。
sql_mode
创建触发器时生效的SQL模式,以及触发器执行的模式。 有关允许的值,请参见 第5.1.11节“服务器SQL模式” 。
Definer
以
格式
创建触发器的用户的帐户
。
'
user_name
'@'host_name
'
character_set_client
character_set_client
创建触发器时系统变量
的会话值
。
collation_connection
collation_connection
创建触发器时系统变量
的会话值
。
Database Collation
与触发器关联的数据库的排序规则。
INFORMATION_SCHEMA
TRIGGERS
表格中
也提供了触发信息
。
请参见
第25.34节“INFORMATION_SCHEMA TRIGGERS表”
。
SHOW [GLOBAL | 会话]变量 [喜欢'pattern
'| 在哪里expr
]
SHOW
VARIABLES
显示MySQL系统变量的值(请参见
第5.1.8节“服务器系统变量”
)。
此声明不需要任何权限。
它只需要连接到服务器的能力。
系统变量信息也可从以下来源获得:
性能架构表。 请参见 第26.12.13节“性能模式系统变量表” 。
在 中mysqladmin变量 命令。 请参见 第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端” 。
对于
SHOW VARIABLES
,
LIKE
子句(如果存在)指示要匹配的变量名称。
WHERE
可以使用
一个
子句来选择使用更一般条件的行,如
第25.42节“扩展显示语句”中所述
。
SHOW
VARIABLES
接受可选
GLOBAL
或
SESSION
变量范围修饰符:
使用
GLOBAL
修饰符,语句显示全局系统变量值。
这些是用于初始化与MySQL的新连接的相应会话变量的值。
如果变量没有全局值,则不显示任何值。
使用
SESSION
修饰符,语句将显示对当前连接有效的系统变量值。
如果变量没有会话值,则显示全局值。
LOCAL
是...的同义词
SESSION
。
如果不存在修饰符,则默认为
SESSION
。
每个系统变量的范围在 第5.1.8节“服务器系统变量”中 列出 。
SHOW
VARIABLES
受版本相关的显示宽度限制。
对于具有非常长值且未完全显示的变量,请将其
SELECT
用作变通方法。
例如:
SELECT @@ GLOBAL.innodb_data_file_path;
大多数系统变量可以在服务器启动时设置(只读变量,例如
version_comment
异常)。
许多可以在运行时使用该
SET
语句
进行更改
。
请参见
第5.1.9节“使用系统变量”
和
第13.7.5.1节“变量赋值的SET语法”
。
此处显示了部分输出。 您的服务器的名称和值列表可能有所不同。 第5.1.8节“服务器系统变量” 描述了每个变量的含义, 第5.1.1节“配置服务器” 提供了有关调整它们的信息。
MySQL的> SHOW VARIABLES;
+ -------------------------------------------- + ---- -------------------------- +
| Variable_name | 价值|
+ -------------------------------------------- + ---- -------------------------- +
| activate_all_roles_on_login | 关闭|
| auto_generate_certs | ON |
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
| 自动提交| ON |
| automatic_sp_privileges | ON |
| avoid_temporal_upgrade | 关闭|
| back_log | 151 |
| basedir | / usr / |
| big_tables | 关闭|
| bind_address | * |
| binlog_cache_size | 32768 |
| binlog_checksum | CRC32 |
| binlog_direct_non_transactional_updates | 关闭|
| binlog_error_action | ABORT_SERVER |
| binlog_expire_logs_seconds | 2592000 |
| binlog_format | 行|
| binlog_group_commit_sync_delay | 0 |
| binlog_group_commit_sync_no_delay_count | 0 |
| binlog_gtid_simple_recovery | ON |
| binlog_max_flush_queue_time | 0 |
| binlog_order_commits | ON |
| binlog_row_image | 完全|
| binlog_row_metadata | MINIMAL |
| binlog_row_value_options | |
| binlog_rows_query_log_events | 关闭|
| binlog_stmt_cache_size | 32768 |
| binlog_transaction_dependency_history_size | 25000 |
| binlog_transaction_dependency_tracking | COMMIT_ORDER |
| block_encryption_mode | aes-128-ecb |
| bulk_insert_buffer_size | 8388608 |
...
| max_allowed_packet | 67108864 |
| max_binlog_cache_size | 18446744073709547520 |
| max_binlog_size | 1073741824 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| max_connect_errors | 100 |
| max_connections | 151 |
| max_delayed_threads | 20 |
| max_digest_length | 1024 |
| max_error_count | 1024 |
| max_execution_time | 0 |
| max_heap_table_size | 16777216 |
| max_insert_delayed_threads | 20 |
| max_join_size | 18446744073709551615 |
...
| thread_handling | 每个连接一个线程
| thread_stack | 286720 |
| time_zone | 系统|
| 时间戳| 1530906638.765316 |
| tls_version | TLSv1,TLSv1.1,TLSv1.2 |
| tmp_table_size | 16777216 |
| tmpdir | / tmp |
| transaction_alloc_block_size | 8192 |
| transaction_allow_batching | 关闭|
| transaction_isolation | REPEATABLE-READ |
| transaction_prealloc_size | 4096 |
| transaction_read_only | 关闭|
| transaction_write_set_extraction | XXHASH64 |
| unique_checks | ON |
| updatable_views_with_limit | 是的|
| 版本| 8.0.12 |
| version_comment | MySQL社区服务器 - GPL |
| version_compile_machine | x86_64 |
| version_compile_os | Linux |
| version_compile_zlib | 1.2.11 |
| wait_timeout | 28800 |
| warning_count | 0 |
| windowing_use_high_precision | ON |
+ -------------------------------------------- + ---- -------------------------- +
使用
LIKE
子句,该语句仅显示名称与模式匹配的变量的行。
要获取特定变量的行,请使用
LIKE
如下所示
的
子句:
显示变量如'max_join_size'; 显示会话变量类似'max_join_size';
要获取名称与模式匹配的变量列表,请
%
在
LIKE
子句中
使用
通配符
:
显示变量如'%size%'; 显示全球变量如'%size%';
通配符可用于要匹配的模式中的任何位置。
严格来说,因为
_
是一个匹配任何单个字符的通配符,你应该将其转义为
\_
按字面意思匹配它。
实际上,这很少是必要的。
显示警告[限制[offset
,]row_count
] 显示计数(*)警告
SHOW
WARNINGS
是一个诊断语句,显示有关在当前会话中执行语句所产生的条件(错误,警告和注释)的信息。
警告DML语句诸如产生
INSERT
,
UPDATE
和
LOAD
DATA
以及DDL语句如
CREATE
TABLE
和
ALTER
TABLE
。
该
LIMIT
子句的语法与
SELECT
语句
相同
。
请参见
第13.2.10节“SELECT语法”
。
SHOW
WARNINGS
也用于以下
EXPLAIN
,以显示由其生成的扩展信息
EXPLAIN
。
请参见
第8.8.3节“扩展EXPLAIN输出格式”
。
SHOW
WARNINGS
显示有关在当前会话中执行最近的非诊断语句所导致的条件的信息。
如果最新语句在解析期间导致错误,则
SHOW WARNINGS
显示结果条件,而不管语句类型(诊断或非诊断)。
该
SHOW COUNT(*)
WARNINGS
诊断语句显示错误,警告和注意事项的总数。
您还可以从
warning_count
系统变量中
检索此数字
:
显示计数(*)警告; SELECT @@ warning_count;
这些语句的区别在于第一个是不清除消息列表的诊断语句。
第二个,因为它是一个
SELECT
声明被认为是非诊断的并且确实清除了消息列表。
相关的诊断语句
SHOW
ERRORS
仅显示错误条件(不包括警告和注释),并且
SHOW COUNT(*)
ERRORS
语句显示错误总数。
请参见
第13.7.6.17节“显示错误语法”
。
GET
DIAGNOSTICS
可用于检查个别条件的信息。
请参见
第13.6.7.3节“获取诊断语法”
。
这是一个显示数据转换警告的简单示例
INSERT
。
该示例假定禁用严格的SQL模式。
启用严格模式后,警告将成为错误并终止
INSERT
。
MySQL的>CREATE TABLE t1 (a TINYINT NOT NULL, b CHAR(4));
查询OK,0行受影响(0.05秒) MySQL的>INSERT INTO t1 VALUES(10,'mysql'), (NULL,'test'), (300,'xyz');
查询正常,3行受影响,3次警告(0.00秒) 记录:3个重复:0个警告:3 MySQL的>SHOW WARNINGS\G
*************************** 1。排******************** ******* 等级:警告 代码:1265 消息:第1行的列'b'截断数据 *************************** 2.排******************** ******* 等级:警告 代码:1048 消息:列'a'不能为空 *************************** 3。排******************** ******* 等级:警告 代码:1264 消息:第3行的列'a'超出范围值 3组(0.00秒)
所述
max_error_count
系统变量控制错误,警告和音符信息的最大数量的量,服务器存储的信息,因此该消息数
SHOW
WARNINGS
显示。
要更改服务器可以存储的消息数,请更改值
max_error_count
。
max_error_count
仅控制存储的消息数量,而不是计算的消息数量。
即使生成的消息数超过,
值
warning_count
也不受限制
。
以下示例演示了这一点。
该
语句产生三条警告消息(示例禁用严格的SQL模式以防止在单个转换问题后发生错误)。
只存储并显示一条消息,因为
已设置为1,但所有三条都被计算在内(如值所示
):
max_error_count
max_error_count
ALTER
TABLE
max_error_count
warning_count
MySQL的>SHOW VARIABLES LIKE 'max_error_count';
+ ----------------- + ------- + | Variable_name | 价值| + ----------------- + ------- + | max_error_count | 1024 | + ----------------- + ------- + 1排(0.00秒) MySQL的>SET max_error_count=1, sql_mode = '';
查询正常,0行受影响(0.00秒) MySQL的>ALTER TABLE t1 MODIFY b CHAR;
查询正常,3行受影响,3次警告(0.00秒) 记录:3个重复:0个警告:3 MySQL的>SHOW WARNINGS;
+ --------- + ------ + -------------------------------- -------- + | 等级| 代码| 消息| + --------- + ------ + -------------------------------- -------- + | 警告| 1263 | 第1行的列'b'截断数据 + --------- + ------ + -------------------------------- -------- + 1排(0.00秒) MySQL的>SELECT @@warning_count;
+ ----------------- + | @@ warning_count | + ----------------- + | 3 | + ----------------- + 1排(0.01秒)
要禁用消息存储,请设置
max_error_count
为0.在这种情况下,
warning_count
仍指示发生了多少警告,但消息未存储且无法显示。
该
sql_notes
系统变量控制是否说明消息增量
warning_count
和服务器是否将它们存储。
默认情况下,
sql_notes
为1,但如果设置为0,则注释不会递增
warning_count
,服务器不会存储它们:
mysql>SET sql_notes = 1;
mysql>DROP TABLE IF EXISTS test.no_such_table;
查询正常,0行受影响,1警告(0.00秒) MySQL的>SHOW WARNINGS;
+ ------- + ------ + ---------------------------------- - + | 等级| 代码| 消息| + ------- + ------ + ---------------------------------- - + | 注意| 1051 | 未知表'test.no_such_table'| + ------- + ------ + ---------------------------------- - + 1排(0.00秒) mysql>SET sql_notes = 0;
mysql>DROP TABLE IF EXISTS test.no_such_table;
查询正常,0行受影响(0.00秒) MySQL的>SHOW WARNINGS;
空集(0.00秒)
MySQL服务器向每个客户端发送一个计数,指示由该客户端执行的最新语句产生的错误,警告和注释的总数。
从C API,可以通过调用获得此值
mysql_warning_count()
。
请参见
第28.7.7.82节“mysql_warning_count()”
。
在
MySQL的
客户端,您可以启用和禁用使用自动的警告显示
warnings
和
nowarning
分别命令,或它们的快捷键,
\W
和
\w
(参见
第4.5.1.2节,“MySQL客户端命令”
)。
例如:
MySQL的>\W
显示警告已启用。 MySQL的>SELECT 1/0;
+ ------ + | 1/0 | + ------ + | NULL | + ------ + 1排,1警告(0.03秒) 警告(代码1365):除以0 MySQL的>\w
显示警告已禁用。
BINLOG' str
'
BINLOG
是一个内部使用声明。
它由
mysqlbinlog
程序
生成,
作为二进制日志文件中某些事件的可打印表示。
(请参见
第4.6.8节“
mysqlbinlog
- 处理二进制日志文件的实用程序”
。)该
值是一个基本的64位编码字符串,该服务器解码该字符串以确定相应事件指示的数据更改。
此声明需要
或
特权。
'
str
'BINLOG_ADMIN
SUPER
此语句只能执行格式描述事件和行事件。
CACHE INDEX {tbl_index_list
[,tbl_index_list
] ...... |tbl_name
分区(partition_list
) } 在key_cache_name
tbl_index_list
:tbl_name
[{INDEX | KEY}(index_name
[,index_name
] ...)]partition_list
:{partition_name
[,partition_name
] ...... | 所有 }
该
CACHE
INDEX
语句将表索引分配给特定的键缓存。
它仅适用于
MyISAM
表,包括分区
MyISAM
表。
分配索引后,可以根据需要将它们预加载到缓存中
LOAD INDEX INTO
CACHE
。
下面的语句从表中分配指标
t1
,
t2
以及
t3
名为键缓存
hot_cache
:
MySQL的> CACHE INDEX t1, t2, t3 IN hot_cache;
+ --------- + -------------------- + ---------- + ------- --- +
| 表| Op | Msg_type | Msg_text |
+ --------- + -------------------- + ---------- + ------- --- +
| test.t1 | assign_to_keycache | 状态| 好的
| test.t2 | assign_to_keycache | 状态| 好的
| test.t3 | assign_to_keycache | 状态| 好的
+ --------- + -------------------- + ---------- + ------- --- +
语法
CACHE
INDEX
使您可以指定只应将表中的特定索引分配给缓存。
但是,实现将所有表的索引分配给缓存,因此没有理由指定除表名之外的任何内容。
CACHE
INDEX
可以通过使用参数设置语句或服务器参数设置设置其大小来创建语句中
引用的键高速缓存
。
例如:
SET GLOBAL keycache1.key_buffer_size = 128 * 1024;
密钥缓存参数作为结构化系统变量的成员进行访问。 请参见 第5.1.9.5节“结构化系统变量” 。
在为其分配索引或发生错误之前,必须存在密钥缓存:
MySQL的> CACHE INDEX t1 IN non_existent_cache;
ERROR 1284(HY000):未知密钥缓存'non_existent_cache'
默认情况下,表索引分配给在服务器启动时创建的主(默认)密钥缓存。 销毁密钥缓存时,分配给它的所有索引都将重新分配给默认密钥缓存。
索引分配会全局影响服务器:如果一个客户端为给定缓存分配索引,则无论哪个客户端发出查询,此缓存都将用于涉及索引的所有查询。
CACHE
INDEX
分区
MyISAM
表
支持
。
您可以将一个,多个或所有分区的一个或多个索引分配给给定的密钥缓存。
例如,您可以执行以下操作:
CREATE TABLE pt(c1 INT,c2 VARCHAR(50),INDEX i(c1)) ENGINE = MyISAM数据 哈希分区(c1) PARTITIONS 4; SET GLOBAL kc_fast.key_buffer_size = 128 * 1024; SET GLOBAL kc_slow.key_buffer_size = 128 * 1024; CACHE INDEX pt PARTITION(p0)IN kc_fast; CACHE INDEX pt PARTITION(p1,p3)IN kc_slow;
上一组语句执行以下操作:
创建一个包含4个分区的分区表;
这些分区自动命名
p0
,... ,
p3
;
此表有一个以
i
列
命名的索引
c1
。
创建名为
kc_fast
和的
2个密钥缓存
kc_slow
分配为分区的索引
p0
的
kc_fast
键缓存和用于分区的索引
p1
和
p3
到
kc_slow
键缓存;
剩余分区(
p2
)
的索引
使用服务器的默认密钥缓存。
如果您希望将表中所有分区的索引分配给
pt
名为的单个密钥缓存
kc_all
,则可以使用以下两个语句之一:
CACH指数pt PARTITION(ALL)in kc_all; CACHE INDEX pt IN kc_all;
刚刚显示的两个语句是等效的,发出任何一个语句都具有完全相同的效果。
换句话说,如果您希望将分区表的所有分区的索引分配给相同的密钥缓存,则该
PARTITION (ALL)
子句是可选的。
将多个分区的索引分配给密钥缓存时,分区不必是连续的,您无需按任何特定顺序列出其名称。 未明确分配给密钥缓存的任何分区的索引会自动使用服务器默认密钥缓存。
分区
MyISAM
表
也支持索引预加载
。
有关更多信息,请参见
第13.7.7.5节“LOAD INDEX INTO CACHE语法”
。
FLUSH [NO_WRITE_TO_BINLOG | LOCAL] {flush_option
[,flush_option
] ...... |tables_option
}flush_option
:{ 二进制日志 | 发动机日志 | 错误日志 | 一般日志 | HOSTS | 日志 | 特权 | OPTIMIZER_COSTS | 继电器日志[FOR CHANNELchannel
] | 慢日志 | 状态 | USER_RESOURCES }tables_option
:{ TABLES | 表格tbl_name
[,tbl_name
] ...... | 带读锁的表格 | TABLEStbl_name
[,tbl_name
] ......阅读锁定 | TABLEStbl_name
[,tbl_name
] ......出口 }
该
FLUSH
语句有几种变体形式,用于清除或重新加载各种内部高速缓存,刷新表或获取锁。
要执行
FLUSH
,您必须拥有该
RELOAD
权限。
特定刷新选项可能需要其他权限,如稍后所述。
无法
FLUSH
在存储的函数或触发器中
发出
语句。
但是,您可以
FLUSH
在存储过程中
使用
,只要不从存储的函数或触发器调用它们。
请参见
第C.1节“存储程序的限制”
。
默认情况下,服务器将
FLUSH
语句
写入
二进制日志,以便它们复制到复制从属服务器。
要禁止记录,请指定可选
NO_WRITE_TO_BINLOG
关键字或其别名
LOCAL
。
FLUSH LOGS
,
FLUSH BINARY LOGS
,
FLUSH TABLES
WITH READ LOCK
(带或不带表列表),并
没有写入到二进制日志在任何情况下,因为如果复制到从它们会造成问题。
FLUSH
TABLES
tbl_name
... FOR
EXPORT
该
FLUSH
语句导致隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
所述
中mysqladmin
实用程序提供了一个命令行界面一些刷新操作,使用诸如命令
flush-hosts
,
flush-logs
,
flush-privileges
,
flush-status
,和
flush-tables
。
请参见
第4.5.2节“
mysqladmin
- 管理MySQL服务器的客户端”
。
向
SIGHUP
服务器
发送
信号会导致发生几次与各种形式的
FLUSH
语句
类似的刷新操作
。
请参见
第5.1.16节“服务器对信号的响应”
。
该
RESET
声明是相似
FLUSH
。
有关
将
语句与复制一起
使用的信息
,
请参见
第13.7.7.6节“RESET语法”
RESET
。
以下列表描述了允许的
FLUSH
语句
flush_option
值。
有关
FLUSH
TABLES
变体的
描述
,请参见
FLUSH TABLES语法
。
关闭并重新打开服务器正在写入的任何二进制日志文件。 如果启用了二进制日志记录,则二进制日志文件的序列号相对于前一个文件递增1。
关闭并重新打开已安装存储引擎的任何可刷新日志。
这会导致
InnoDB
将其日志刷新到磁盘。
关闭并重新打开服务器正在写入的任何错误日志文件。
关闭并重新打开服务器正在写入的任何常规查询日志文件。
清空主机缓存和
host_cache
公开缓存内容
的性能模式
表,并取消阻止任何被阻止的主机。
请参见
第8.12.4.2节“DNS查找优化和主机缓存”
。
如果某些主机更改了IP地址,或者
对于来自合法主机的连接发生
错误消息,请刷新主机缓存
。
(参见
第B.4.2.5节“主机'host_name'被阻止”
。)当
连接到MySQL服务器时,当给定主机连续发生错误时,MySQL认为出现了问题,并阻止主机进一步连接请求。
刷新主机缓存会启用来自主机的进一步连接尝试。
默认值为
100.要避免此错误消息,请启动服务器并将其
设置为较大的值。
Host
'
host_name
' is blockedmax_connect_errors
max_connect_errors
max_connect_errors
关闭并重新打开服务器正在写入的任何日志文件。 如果启用了二进制日志记录,则二进制日志文件的序列号相对于前一个文件递增1。 如果启用了中继日志记录,则中继日志文件的序列号相对于前一个文件递增1。
FLUSH LOGS
对用于常规查询日志或慢查询日志的表没有影响(请参见
第5.4.1节“选择常规查询日志和慢查询日志输出目标”
)。
重新读取成本模型表,以便优化程序开始使用存储在其中的当前成本估算。 服务器会向错误日志写入警告,以查找任何无法识别的条目。 (有关这些表的信息,请参见 第8.9.5节“优化程序成本模型” 。)此操作仅影响在刷新后开始的会话。 现有会议继续使用开始时的当前成本估算。
从
mysql
系统数据库中
的授权表重新加载特权
,并清除
caching_sha2_password
身份验证插件
使用的内存高速缓存
。
作为此操作的一部分,服务器将读取
global_grants
包含动态权限分配
的
表,并注册其中发现的任何未注册权限。
服务器在内存中缓存信息的结果
GRANT
,
CREATE USER
,
CREATE SERVER
,和
INSTALL PLUGIN
语句。
该内存不能由相应的释放
REVOKE
,
DROP
USER
,
DROP
SERVER
,和
UNINSTALL PLUGIN
语句,所以执行导致缓存报表的多个实例的服务器上,将有内存使用的增加。
可以释放此缓存的内存
FLUSH PRIVILEGES
。
FLUSH
RELAY LOGS [FOR CHANNEL
channel
]
关闭并重新打开服务器正在写入的任何中继日志文件。 如果启用了中继日志记录,则中继日志文件的序列号相对于前一个文件递增1。
该
子句使您可以命名该语句适用的复制通道。
执行
以刷新特定复制通道的中继日志。
如果未命名通道且不存在额外的复制通道,则该语句将应用于默认通道。
如果未命名通道且存在多个复制通道,则该语句将应用于所有复制通道。
有关更多信息,请参见
第17.2.3节“复制通道”
。
FOR CHANNEL
channel
FLUSH
RELAY LOGS FOR CHANNEL
channel
关闭并重新打开服务器正在写入的任何慢查询日志文件。
此选项将会话状态从所有活动会话添加到全局状态变量,重置所有活动会话的状态,并重置从断开连接的会话聚合的帐户,主机和用户状态值。 请参见 第26.12.14节“性能模式状态变量表” 。 调试查询时,此信息可能有用。 请参见 第1.7节“如何报告错误或问题” 。
将所有每小时用户资源重置为零。
这使已达到每小时连接,查询或更新限制的客户端能够立即恢复活动。
FLUSH USER_RESOURCES
不适用于由
max_user_connections
系统变量
控制的最大同时连接的限制
。
请参见
第6.2.20节“设置帐户资源限制”
。
FLUSH TABLES
刷新表,并根据使用的变量获取锁。
声明中
TABLES
使用的
任何
变体
FLUSH
必须是唯一使用的选项。
FLUSH
TABLE
是...的同义词
FLUSH
TABLES
。
此处的说明指示表通过关闭它们以不同的方式
InnoDB
刷新,这会将表内容刷新到磁盘但保持打开状态。
这仍然允许在表打开时复制表文件,只要其他活动不修改它们即可。
关闭所有打开的表,强制关闭所有正在使用的表,并刷新预准备的语句缓存。 有关 预 准备语句高速缓存的信息,请参见 第8.10.3节“高速缓存准备语句和存储程序” 。
FLUSH TABLES
有活动时不允许
LOCK TABLES ...
READ
。
要刷新和锁定表,请
改用。
FLUSH
TABLES
tbl_name
... WITH READ
LOCK
FLUSH
TABLES
tbl_name
[,
tbl_name
] ...
使用一个或多个以逗号分隔的表名列表,此语句
FLUSH
TABLES
与没有名称的
情况类似
,只是服务器只刷新命名表。
如果命名表不存在,则不会发生错误。
关闭所有打开的表并使用全局读锁锁定所有数据库的所有表。
如果您具有可以及时拍摄快照的Veritas或ZFS等文件系统,则这是一种非常方便的备份方式。
使用
UNLOCK
TABLES
即可解除锁定。
FLUSH TABLES WITH
READ LOCK
获得全局读锁定,而不是表锁,所以它不会受到相同的行为
LOCK TABLES
,并
UNLOCK
TABLES
相对于表锁定和隐式的提交:
UNLOCK
TABLES
仅当当前已锁定任何表时,才会隐式提交任何活动事务
LOCK TABLES
。
由于后一语句不获取表锁,因此
不会发生
UNLOCK
TABLES
后续
提交
FLUSH
TABLES WITH READ LOCK
。
开始事务会导致获取的表锁
LOCK TABLES
被释放,就像您已执行一样
UNLOCK
TABLES
。
开始事务不会释放获取的全局读锁
FLUSH
TABLES WITH READ
LOCK
。
FLUSH TABLES WITH
READ LOCK
不会阻止服务器将行插入日志表(请参见
第5.4.1节“选择常规查询日志和慢查询日志输出目标”
)。
FLUSH
TABLES
tbl_name
[,
tbl_name
] ... WITH READ
LOCK
此语句刷新并获取指定表的读锁定。
该语句首先获取表的独占元数据锁,因此它等待打开这些表的事务完成。
然后,语句从表缓存中刷新表,重新打开表,获取表锁(如
LOCK TABLES ...
READ
),并将元数据锁从独占降级为共享。
在语句获取锁并降级元数据锁之后,其他会话可以读取但不能修改表。
由于此语句获取表锁,因此
LOCK TABLES
除了
RELOAD
使用任何
FLUSH
语句
所需
的
权限
之外
,还必须具有
每个表的
权限
。
此语句仅适用于现有基
TEMPORARY)
表
(非
表。如果名称引用基表,则使用该表。如果引用
TEMPORARY
表,则忽略
该
表。如果名称适用于视图,
ER_WRONG_OBJECT
则会发生错误。否则,发生
ER_NO_SUCH_TABLE
错误。
使用
UNLOCK
TABLES
释放锁,
LOCK TABLES
以释放锁和收购其他的锁,或
START
TRANSACTION
释放锁,并开始一个新的事务。
此
FLUSH TABLES
变体使表能够在单个操作中刷新和锁定。
它为
FLUSH TABLES
有活动时不允许
的限制提供了一种解决方法
LOCK TABLES ...
READ
。
此语句不执行隐式
UNLOCK
TABLES
,因此如果在有活动时使用该语句,则会导致错误,
LOCK TABLES
或者在未首先释放获取的锁定的情况下再次
使用该语句时会导致错误
。
如果打开了刷新的表
HANDLER
,则会隐式刷新处理程序并丢失其位置。
FLUSH
TABLES
tbl_name
[,
tbl_name
] ... FOR
EXPORT
此
FLUSH TABLES
变体适用于
InnoDB
表格。
它确保已将对指定表的更改刷新到磁盘,以便在服务器运行时可以创建二进制表副本。
声明的作用如下:
它获取指定表的共享元数据锁。 只要其他会话具有已修改这些表或为其保存表锁的活动事务,该语句就会阻塞。 获取锁后,该语句将阻止尝试更新表的事务,同时允许只读操作继续。
它检查表的所有存储引擎是否支持
FOR EXPORT
。
如果没有,则发生
ER_ILLEGAL_HA
错误并且语句失败。
该语句通知存储引擎每个表以使表准备好导出。 存储引擎必须确保将所有挂起的更改写入磁盘。
该语句将会话置于锁定表模式,以便在
FOR EXPORT
语句完成
时不会释放先前获取的元数据锁
。
该
FLUSH
TABLES ... FOR EXPORT
声明要求您拥有
SELECT
每个表
的
权限。
由于此语句获取表锁,因此
LOCK
TABLES
除了
RELOAD
使用任何
FLUSH
语句
所需
的
权限
之外
,还必须具有
每个表的
权限
。
此语句仅适用于现有的基(非
TEMPORARY
)表。
如果名称引用基表,则使用该表。
如果它引用
TEMPORARY
表,则忽略它。
如果名称适用于视图,
ER_WRONG_OBJECT
则会发生错误。
否则,
ER_NO_SUCH_TABLE
会发生错误。
InnoDB
支持
FOR
EXPORT
具有自己的
.ibd
文件
文件的表(即,在
innodb_file_per_table
启用设置的情况下
创建的表
)。
InnoDB
确保在
FOR EXPORT
语句
通知
任何更改已刷新到磁盘时。
这允许在
FOR
EXPORT
语句生效
时生成表内容的二进制副本,
因为该
.ibd
文件是事务一致的,并且可以在服务器运行时复制。
FOR
EXPORT
不适用于
InnoDB
系统表空间文件或
InnoDB
具有
FULLTEXT
索引的
表
。
FLUSH
TABLES ...FOR EXPORT
分区
InnoDB
表
支持
。
通知时
FOR EXPORT
,
InnoDB
将某些类型的数据写入磁盘,这些数据通常保存在内存中或表空间文件外的单独磁盘缓冲区中。
对于每个表,
InnoDB
还会生成一个
与该表位于同一数据库目录中的
文件
。
该
table_name
.cfg.cfg
文件包含稍后将表空间文件重新导入相同或不同服务器所需的元数据。
当
FOR EXPORT
语句完成,
InnoDB
将有刷新所有
脏页
表中的数据文件。
在刷新之前合并
任何
更改缓冲区
条目。
此时,表已锁定且处于静止状态:表在磁盘上处于事务一致状态,您可以将
.ibd
表空间文件与相应
.cfg
文件
一起
复制,
以获得这些表的一致快照。
有关将复制的表数据重新导入MySQL实例的过程,请参见 第15.6.3.7节“将表空间复制到另一个实例” 。
完成表后,使用
UNLOCK
TABLES
释放锁,
LOCK TABLES
释放锁并获取其他锁,或
START
TRANSACTION
释放锁并开始新事务。
虽然这些语句中的任何一个在会话中都有效,但尝试使用会
FLUSH
TABLES ... FOR EXPORT
产生错误:
FLUSH TABLES ...阅读锁定 FLUSH TABLES ...出口 LOCK TABLES ...阅读 LOCK TABLES ...写
虽然
FLUSH
TABLES ... FOR EXPORT
在会话中有效,但尝试使用这些语句中的任何一个都会产生错误:
带读锁的冲洗表 FLUSH TABLES ...阅读锁定 FLUSH TABLES ...出口
杀[连接| QUERY]processlist_id
与
mysqld的
每个连接都
在一个单独的线程中运行。
你可以用
语句
杀死一个线程
。
KILL
processlist_id
可以从
表的
列,
输出
列和Performance Schema
表
的
ID
列
确定线程进程列表标识符
。
函数
返回当前线程的值
。
INFORMATION_SCHEMA
PROCESSLIST
Id
SHOW
PROCESSLIST
PROCESSLIST_ID
threads
CONNECTION_ID()
KILL
允许使用可选
CONNECTION
或
QUERY
修饰符:
KILL
CONNECTION
KILL
与没有修饰符
相同
:它终止
processlist_id
连接正在执行的任何语句后终止
与给定关联
的连接。
KILL
QUERY
终止连接当前正在执行的语句,但保持连接本身不变。
查看哪些线程可以被杀死的能力取决于
PROCESS
权限:
杀死线程和语句的能力取决于
CONNECTION_ADMIN
和
SUPER
特权:
没有
CONNECTION_ADMIN
或者
SUPER
,你只能杀死你自己的线程和语句。
使用
CONNECTION_ADMIN
或者
SUPER
,您可以终止所有线程和语句,除了影响使用该
SYSTEM_USER
权限
执行的线程或语句之外
,您自己的会话还必须具有该
SYSTEM_USER
权限。
您还可以使用 mysqladmin processlist 和 mysqladmin kill 命令来检查和终止线程。
使用时
KILL
,为线程设置特定于线程的kill标志。
在大多数情况下,线程可能需要一些时间才能死掉,因为只在特定的时间间隔检查kill标志:
在
SELECT
操作
期间
,for
ORDER BY
和
GROUP BY
循环,在读取行块之后检查标志。
如果设置了kill标志,则语句将中止。
ALTER
TABLE
制作表副本的操作会定期检查从原始表中读取的每个复制行的kill标志。
如果设置了kill标志,则语句将中止,并删除临时表。
该
KILL
语句返回时无需等待确认,但kill flag check会在相当短的时间内中止操作。
中止操作以执行任何必要的清理也需要一些时间。
在
执行
期间
UPDATE
或
DELETE
操作
期间
,在每个块读取之后以及每个更新或删除的行之后检查终止标志。
如果设置了kill标志,则语句将中止。
如果您不使用事务,则不会回滚更改。
GET_LOCK()
中止和返回
NULL
。
如果线程在表锁处理程序(状态
Locked
:)中,表锁将快速中止。
如果线程正在等待写入调用中的可用磁盘空间,则写入将中止,并显示 “ 磁盘已满 ” 错误消息。
在
表
上
执行
REPAIR TABLE
或
OPTIMIZE TABLE
操作会
MyISAM
导致表被破坏且无法使用。
对此类表的任何读取或写入都会失败,直到您再次优化或修复它(不中断)。
LOAD INDEX INTO CACHEtbl_index_list
[,tbl_index_list
] ......tbl_index_list
:tbl_name
[PARTITION(partition_list
)] [{INDEX | KEY}(index_name
[,index_name
] ...)] [IGNORE LEAVES]partition_list
:{partition_name
[,partition_name
] ...... | 所有 }
该
LOAD INDEX INTO
CACHE
语句将表索引预加载到由显式
CACHE
INDEX
语句
分配给它的密钥缓存中,否则加载
到默认密钥缓存中。
LOAD
INDEX INTO
CACHE
仅适用于
MyISAM
表,包括分区
MyISAM
表。
此外,可以为一个,多个或所有分区预加载分区表上的索引。
所述
IGNORE LEAVES
改性剂导致要预装只为索引的非叶结点的块。
IGNORE LEAVES
分区
MyISAM
表
也支持
。
以下语句预加载表的索引节点(索引块),
t1
并且
t2
:
MySQL的> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
+ --------- + -------------- + ---------- + ---------- +
| 表| Op | Msg_type | Msg_text |
+ --------- + -------------- + ---------- + ---------- +
| test.t1 | preload_keys | 状态| 好的
| test.t2 | preload_keys | 状态| 好的
+ --------- + -------------- + ---------- + ---------- +
此语句预加载所有索引块
t1
。
它仅为非叶节点预加载块
t2
。
语法
LOAD
INDEX INTO CACHE
使您可以指定只预加载表中的特定索引。
但是,实现会将所有表的索引预加载到缓存中,因此没有理由指定除表名之外的任何内容。
可以在分区
MyISAM
表的
特定分区上预加载索引
。
例如,在以下两个语句中,第一个预加载
p0
分区表
分区
的
索引
pt
,而第二个预加载分区
p1
和
p3
同一个表
的索引
:
负荷指数进入CACHE pt PARTITION(p0); 负荷指数进入CACHE pt PARTITION(p1,p3);
要为表中的所有分区预加载索引
pt
,可以使用以下两个语句之一:
负荷指数进入CACHE pt PARTITION(全部); LOAD INDEX INTO CACHE pt;
刚刚显示的两个语句是等效的,发出任何一个语句都具有完全相同的效果。
换句话说,如果您希望为分区表的所有分区预加载索引,则该
PARTITION (ALL)
子句是可选的。
在为多个分区预加载索引时,分区不需要是连续的,您无需按任何特定顺序列出其名称。
LOAD
INDEX INTO
CACHE ... IGNORE LEAVES
除非表中的所有索引具有相同的块大小,否则将失败。
要确定表的索引块大小,请使用
myisamchk -dv
并检查
Blocksize
列。
重置reset_option
[,reset_option
] ......reset_option
:{ 主 | 奴隶 }
该
RESET
语句用于清除各种服务器操作的状态。
您必须具有
RELOAD
执行权限
RESET
。
有关
RESET
PERSIST
删除持久性全局系统变量
的
语句的
信息
,请参见
第13.7.7.7节“重置PERSIST语法”
。
RESET
充当
FLUSH
声明
的更强版本
。
请参见
第13.7.7.3节“FLUSH语法”
。
该
RESET
语句导致隐式提交。
请参见
第13.3.3节“导致隐式提交的语句”
。
以下列表描述了允许的
RESET
语句
reset_option
值:
RESET MASTER
删除索引文件中列出的所有二进制日志,将二进制日志索引文件重置为空,并创建新的二进制日志文件。
RESET SLAVE
使从属服务器忘记其在主二进制日志中的复制位置。 还通过删除任何现有的中继日志文件并开始新的日志文件来重置中继日志。
重置持有人[[如果存在] system_var_name
]
RESET
PERSIST
从
mysqld-auto.cnf
数据目录中
的
选项文件中
删除持久化的全局系统变量设置
。
删除持久化系统变量会导致
mysqld-auto.cnf
在服务器启动时
不再初始化变量
。
有关保持系统变量和
mysqld-auto.cnf
文件的
更多信息
,请参见
第5.1.9.3节“持久系统变量”
。
所需的权限
RESET
PERSIST
取决于要删除的系统变量的类型:
对于动态系统变量,此语句需要
SYSTEM_VARIABLES_ADMIN
或
SUPER
特权。
对于只读系统变量,此语句需要
SYSTEM_VARIABLES_ADMIN
和
PERSIST_RO_VARIABLES_ADMIN
特权。
请参见 第5.1.9.1节“系统变量权限” 。
根据变量名和
IF
EXISTS
子句是否存在,
RESET PERSIST
语句具有以下形式:
要从中删除所有持久变量
mysqld-auto.cnf
,请在
RESET PERSIST
不命名任何系统变量的情况下
使用
:
重置持有人;
如果
mysqld-auto.cnf
包含两种
变量,则必须具有删除动态和只读系统变量的权限
。
要从中删除特定的持久变量
mysqld-auto.cnf
,请在语句中对其进行命名:
重置持有人system_var_name
;
这包括插件系统变量,即使当前未安装插件也是如此。 如果文件中不存在该变量,则会发生错误。
要从文件中删除特定的持久变量
mysqld-auto.cnf
,但如果文件中不存在该变量,则产生警告而不是错误
IF EXISTS
,请在以前的语法中
添加一个
子句:
如果存在,重置持续system_var_name
;
RESET
PERSIST
不受
persisted_globals_load
系统变量
值的影响
。
RESET
PERSIST
影响性能模式
persisted_variables
表
的内容,
因为表内容对应于
mysqld-auto.cnf
文件
的内容
。
另一方面,因为
RESET PERSIST
不更改变量值,所以在
variables_info
重新启动服务器之前
,它对Performance Schema
表
的内容没有影响
。
有关
RESET
清除其他服务器操作状态的语句变体的
信息
,请参见
第13.7.7.6节“RESET语法”
。
重新开始
该语句停止并重新启动MySQL服务器。
它需要
SHUTDOWN
特权。
一种用途
RESTART
是当不可能或不方便获得对服务器主机上的MySQL服务器的命令行访问权以重新启动它。
例如,
SET
PERSIST_ONLY
可以在运行时使用以对系统变量进行配置更改,这些变量只能在服务器启动时设置,但仍必须重新启动服务器才能使这些更改生效。
该
RESTART
语句提供了一种在客户端会话中执行此操作的方法,无需在服务器主机上进行命令行访问。
执行
RESTART
语句后,客户端可能会丢失当前连接。
如果启用了自动重新连接,则在服务器重新启动后将重新建立连接。
否则,必须手动重新建立连接。
成功的
RESTART
操作要求
mysqld
在具有监视进程的环境中运行,以检测为重新启动目的而执行的服务器关闭:
这些平台为
RESTART
语句
提供必要的监视支持
:
Windows,当 mysqld 作为Windows服务或独立启动 时 。 ( mysqld forks,一个进程充当另一个进程的监视器,充当服务器。)
Unix和类Unix系统使用systemd或 mysqld_safe 来管理 mysqld 。
要配置监视环境,以便
mysqld
启用该
RESTART
语句:
这是在 bash shell中 实现的最小示例 :
#!/斌/庆典
export MYSQLD_PARENT_PID = $$
export MYSQLD_RESTART_EXIT = 16
而真实; 做
斌/ mysqld的 mysqld options here
如果[$?-ne $ MYSQLD_RESTART_EXIT]; 然后
打破
科幻
DONE
在Windows上,用于实现的分叉
RESTART
使得确定要附加的服务器进程以进行调试更加困难。
为了缓解这种情况,
--gdb
除了为设置调试环境所做的其他操作外,还要
使用
抑制分叉来
启动服务器
。
在非调试设置中,
--no-monitor
可以仅用于抑制分支监视过程的唯一目的。
对于服务器开始无论是
--gdb
或
--no-monitor
,执行
RESTART
导致服务器只是退出无需重新启动。
该
DESCRIBE
和
EXPLAIN
语句是同义词,或者用于获取有关表结构或查询执行计划的信息。
有关更多信息,请参见
第13.7.6.5节“显示列语法”
和
第13.8.2节“EXPLAIN语法”
。
{EXPLAIN | 描述| DESC}tbl_name
[col_name
|wild
] {EXPLAIN | 描述| DESC} [explain_type
] {explainable_stmt
| 用于连接connection_id
}explain_type
:{ 格式=format_name
}format_name
:{ 传统 | JSON | 树 }explainable_stmt
:{ SELECT语句 | DELETE语句 | INSERT语句 | REPLACE声明 | 更新声明 }
该
DESCRIBE
和
EXPLAIN
语句是同义词。
实际上,
DESCRIBE
关键字更常用于获取有关表结构的信息,而
EXPLAIN
用于获取查询执行计划(即,MySQL将如何执行查询的说明)。
以下讨论
根据这些用途使用
DESCRIBE
和
EXPLAIN
关键字,但MySQL解析器将它们视为完全同义。
DESCRIBE
提供有关表中列的信息:
MySQL的> DESCRIBE City;
+ ------------ + ---------- + ------ + ------ + --------- + - -------------- +
| 领域| 输入| 空| 钥匙| 默认| 额外的|
+ ------------ + ---------- + ------ + ------ + --------- + - -------------- +
| Id | int(11)| 没有| PRI | NULL | auto_increment |
| 名称| char(35)| 没有| | | |
| 国家| char(3)| 没有| UNI | | |
| 区| char(20)| 是的| MUL | | |
| 人口| int(11)| 没有| | 0 | |
+ ------------ + ---------- + ------ + ------ + --------- + - -------------- +
DESCRIBE
是一个快捷方式
SHOW
COLUMNS
。
这些语句还显示视图的信息。
描述
SHOW
COLUMNS
提供了有关输出列的更多信息。
请参见
第13.7.6.5节“显示列语法”
。
默认情况下,
DESCRIBE
显示有关表中所有列的信息。
col_name
,如果给定,则是表中列的名称。
在这种情况下,该语句仅显示指定列的信息。
wild
如果给定,则是一个模式字符串。
它可以包含SQL
%
和
_
通配符。
在这种情况下,语句仅显示名称与字符串匹配的列的输出。
除非字符串包含空格或其他特殊字符,否则无需将字符串括在引号内。
DESCRIBE
提供
该
声明是为了与Oracle兼容。
。
SHOW CREATE TABLE
,
SHOW TABLE STATUS
和
SHOW
INDEX
语句还提供有关表的信息。
请参见
第13.7.6节“显示语法”
。
该
EXPLAIN
语句提供有关MySQL如何执行语句的信息:
EXPLAIN
作品有
SELECT
,
DELETE
,
INSERT
,
REPLACE
,和
UPDATE
语句。
当
EXPLAIN
与可解释语句一起使用时,MySQL会显示优化程序中有关语句执行计划的信息。
也就是说,MySQL解释了它将如何处理语句,包括有关如何连接表以及以何种顺序连接的信息。
有关使用
EXPLAIN
获取执行计划信息的信息,请参见
第8.8.2节“EXPLAIN输出格式”
。
当
EXPLAIN
使用with
而不是可解释的语句时,它显示在命名连接中执行的语句的执行计划。
请参见
第8.8.4节“获取命名连接的执行计划信息”
。
FOR CONNECTION
connection_id
对于可解释的语句,
EXPLAIN
生成可以使用的其他执行计划信息
SHOW WARNINGS
。
请参见
第8.8.3节“扩展EXPLAIN输出格式”
。
EXPLAIN
用于检查涉及分区表的查询。
请参见
第23.3.5节“获取有关分区的信息”
。
该
FORMAT
选项可用于选择输出格式。
TRADITIONAL
以表格格式显示输出。
如果没有
FORMAT
选项,则
这是默认值
。
JSON
format以JSON格式显示信息。
在MySQL 8.0.16及更高版本中,
TREE
提供了树状输出,其中包含比
TRADITIONAL
格式
更精确的查询处理描述
;
目前,它仍在开发中,仅被认为是实验性的。
EXPLAIN
要求
SELECT
访问的任何表或视图
的
权限,包括任何基础视图表。
对于视图,
EXPLAIN
还需要
SHOW VIEW
特权。
借助于
EXPLAIN
,您可以看到应该向表添加索引的位置,以便通过使用索引查找行来更快地执行语句。
您还可以使用
EXPLAIN
检查优化程序是否以最佳顺序连接表。
要给优化器提供一个提示,以使用与
SELECT
语句
中命名表的顺序相对应的连接顺序
,请使用
SELECT STRAIGHT_JOIN
而不是仅仅
开始语句
SELECT
。
(参见
第13.2.10节“SELECT语法”
。)
优化器跟踪有时可以提供与其相辅相成的信息
EXPLAIN
。
但是,优化程序跟踪格式和内容可能会在不同版本之间发生变化。
有关详细信息,请参阅
MySQL内部:跟踪优化程序
。
如果您在认为应该使用索引时遇到问题,请运行
ANALYZE
TABLE
以更新表统计信息,例如密钥的基数,这可能会影响优化程序所做的选择。
请参见
第13.7.3.1节“ANALYZE TABLE语法”
。
MySQL Workbench具有Visual Explain功能,可以直观地显示
EXPLAIN
输出。
请参阅
教程:使用说明来提高查询性能
。
帮助' search_string
'
该
HELP
语句返回MySQL参考手册中的在线信息。
正确的操作要求
mysql
使用帮助主题信息初始化数据库
中的帮助表
(请参见
第5.1.14节“服务器端帮助支持”
)。
该
HELP
语句在帮助表中搜索给定的搜索字符串并显示搜索结果。
搜索字符串不区分大小写。
搜索字符串可以包含通配符
%
和
_
。
这些与操作员执行的模式匹配操作具有相同的含义
LIKE
。
例如,
HELP 'rep%'
返回以
rep
。
开头的主题列表
。
HELP语句了解几种类型的搜索字符串:
在最一般的级别,用于
contents
检索顶级帮助类别的列表:
帮助'内容'
有关给定帮助类别中的主题列表,例如
Data Types
,请使用类别名称:
帮助'数据类型'
有关特定帮助主题(例如
ASCII()
函数或
CREATE TABLE
语句)的帮助,请使用关联的关键字或关键字:
帮助'ascii' 帮助'创建表'
换句话说,搜索字符串匹配类别,许多主题或单个主题。
您无法事先告知给定的搜索字符串是返回单个帮助主题的项目列表还是帮助信息。
但是,您可以
HELP
通过检查结果集中的行数和列数来确定返回
的响应类型
。
以下描述指示结果集可以采用的表单。
使用
您在使用
mysql
客户端
时看到
的熟悉的
“
表格
”
或
“
垂直
”
格式
显示示例语句的输出
,但请注意,
mysql
本身
以不同的方式
重新格式化
结果集。
HELP
空结果集
找不到匹配的搜索字符串。
结果集包含一行有三列
这意味着搜索字符串对帮助主题产生了影响。 结果有三列:
name
:主题名称。
description
:主题的描述性帮助文本。
example
:用法示例或示例。
此列可能为空。
例:
HELP 'replace'
产量:
名称:REPLACE description:语法: REPLACE(STR,from_str均被,to_str) 返回字符串str,其中出现字符串from_str 替换为字符串to_str。REPLACE()执行区分大小写 搜索from_str时匹配。 例如:mysql> SELECT REPLACE('www.mysql.com','w','Ww'); - >'WwWwWw.mysql.com'
结果集包含多行,包含两列
这意味着搜索字符串匹配了许多帮助主题。 结果集指示帮助主题名称:
name
:帮助主题名称。
is_it_category
:
Y
如果名称代表帮助类别,
N
如果不是。
如果不是,则
name
指定为
HELP
语句
参数
的
值
应生成包含命名项描述的单行结果集。
例:
HELP 'status'
产量:
+ ----------------------- + ---------------- + | 名字| is_it_category | + ----------------------- + ---------------- + | 显示| N | | SHOW ENGINE | N | | 显示主要状态| N | | 显示程序状态| N | | SHOW SLAVE STATUS | N | | 显示状态| N | | 显示表状态| N | + ----------------------- + ---------------- +
结果集包含多行,包含三列
这意味着搜索字符串与类别匹配。 结果集包含类别条目:
source_category_name
:帮助类别名称。
name
:类别或主题名称
is_it_category
:
Y
如果名称代表帮助类别,
N
如果不是。
如果不是,则
name
指定为
HELP
语句
参数
的
值
应生成包含命名项描述的单行结果集。
例:
HELP 'functions'
产量:
+ ---------------------- + ------------------------- + ---------------- + | source_category_name | 名字| is_it_category | + ---------------------- + ------------------------- + ---------------- + | 功能| 创造功能| N | | 功能| 降功能| N | | 功能| 位功能| Y | | 功能| 比较运算符| Y | | 功能| 控制流程功能| Y | | 功能| 日期和时间函数| Y | | 功能| 加密功能| Y | | 功能| 信息功能| Y | | 功能| 逻辑运算符| Y | | 功能| 杂项功能| Y | | 功能| 数字函数| Y | | 功能| 字符串函数| Y | + ---------------------- + ------------------------- + ---------------- +
使用 db_name
该
语句告诉MySQL使用
数据库作为后续语句的默认(当前)数据库。
在会话结束或
发出
另一个
语句
之前,数据库仍然是默认值
:
USE
db_name
db_name
USE
使用db1; SELECT COUNT(*)FROM mytable; #从db1.mytable中选择 使用db2; SELECT COUNT(*)FROM mytable; #从db2.mytable中选择
必须在一行中指定数据库名称。 不支持数据库名称中的换行符。
通过
USE
语句
使特定数据库成为缺省值
不会妨碍访问其他数据库中的表。
以下示例
author
从
db1
数据库和数据库中的
editor
表
访问该
表
db2
:
使用db1; SELECT author_name,editor_name FROM author,db2.editor WHERE author.editor_id = db2.editor.editor_id;