第13章SQL语句语法

目录

13.1数据定义语句
13.1.1原子数据定义语句支持
13.1.2 ALTER DATABASE语法
13.1.3 ALTER EVENT语法
13.1.4 ALTER FUNCTION语法
13.1.5 ALTER INSTANCE语法
13.1.6 ALTER LOGFILE GROUP语法
13.1.7更改过程语法
13.1.8 ALTER SERVER语法
13.1.9 ALTER TABLE语法
13.1.10 ALTER TABLESPACE语法
13.1.11 ALTER VIEW语法
13.1.12 CREATE DATABASE语法
13.1.13 CREATE EVENT语法
13.1.14 CREATE FUNCTION语法
13.1.15 CREATE INDEX语法
13.1.16 CREATE LOGFILE GROUP语法
13.1.17创建过程和创建函数语法
13.1.18 CREATE SERVER语法
13.1.19创建空间参考系统语法
13.1.20 CREATE TABLE语法
13.1.21 CREATE TABLESPACE语法
13.1.22 CREATE TRIGGER语法
13.1.23创建视图语法
13.1.24 DROP DATABASE语法
13.1.25 DROP EVENT语法
13.1.26 DROP FUNCTION语法
13.1.27 DROP INDEX语法
13.1.28 DROP LOGFILE GROUP语法
13.1.29 DROP PROCEDURE和DROP FUNCTION语法
13.1.30 DROP SERVER语法
13.1.31 DROP空间参考系统语法
13.1.32 DROP TABLE语法
13.1.33 DROP TABLESPACE语法
13.1.34 DROP TRIGGER语法
13.1.35 DROP VIEW语法
13.1.36 RENAME TABLE语法
13.1.37 TRUNCATE TABLE语法
13.2数据处理语句
13.2.1 CALL语法
13.2.2 DELETE语法
13.2.3 DO语法
13.2.4 HANDLER语法
13.2.5 IMPORT TABLE语法
13.2.6 INSERT语法
13.2.7 LOAD DATA语法
13.2.8 LOAD XML语法
13.2.9 REPLACE语法
13.2.10 SELECT语法
13.2.11子查询语法
13.2.12 UPDATE语法
13.2.13 WITH语法(公用表表达式)
13.3交易和锁定声明
13.3.1 START TRANSACTION,COMMIT和ROLLBACK语法
13.3.2无法回滚的陈述
13.3.3导致隐式提交的语句
13.3.4 SAVEPOINT,ROLLBACK到SAVEPOINT和RELEASE SAVEPOINT语法
13.3.5备份和解锁实例的锁定实例语法
13.3.6 LOCK TABLES和UNLOCK TABLES语法
13.3.7 SET TRANSACTION语法
13.3.8 XA交易
13.4复制语句
13.4.1控制主服务器的SQL语句
13.4.2用于控制从属服务器的SQL语句
13.4.3用于控制组复制的SQL语句
13.5准备好的SQL语句语法
13.5.1 PREPARE语法
13.5.2 EXECUTE语法
13.5.3 DEALLOCATE PREPARE语法
13.6复合语句语法
13.6.1 BEGIN ... END复合语句语法
13.6.2语句标签语法
13.6.3 DECLARE语法
13.6.4存储程序中的变量
13.6.5流量控制声明
13.6.6游标
13.6.7条件处理
13.7数据库管理声明
13.7.1账户管理声明
13.7.2资源组管理声明
13.7.3表维护声明
13.7.4组件,插件和用户定义的功能语句
13.7.5 SET语法
13.7.6 SHOW语法
13.7.7其他行政声明
13.8效用声明
13.8.1 DESCRIBE语法
13.8.2 EXPLAIN语法
13.8.3 HELP语法
13.8.4 USE语法

本章介绍 MySQL支持 SQL 语句 的语法

13.1数据定义语句

13.1.1原子数据定义语句支持

MySQL 8.0支持原子数据定义语言(DDL)语句。 此功能称为 原子DDL 原子DDL语句将与DDL操作关联的数据字典更新,存储引擎操作和二进制日志写入组合到单个原子事务中。 即使服务器在操作期间停止,也会提交事务,并将适用的更改保留到数据字典,存储引擎和二进制日志中,或者回滚事务。

通过在MySQL 8.0中引入MySQL数据字典,可以实现Atomic DDL。 在早期的MySQL版本中,元数据存储在元数据文件,非事务性表和存储引擎特定的字典中,这需要中间提交。 MySQL数据字典提供的集中式事务元数据存储消除了这一障碍,使得将DDL语句操作重组为原子事务成为可能。

原子DDL功能在本节的以下主题中描述:

支持的DDL语句

原子DDL功能支持表和非表DDL语句。 与表相关的DDL操作需要存储引擎支持,而非表DDL操作则不需要。 目前,只有 InnoDB 存储引擎支持原子DDL。

  • 受支持的表DDL语句包括 CREATE ALTER DROP 对数据库,表,表和索引,以及语句 TRUNCATE TABLE 声明。

  • 支持的非表DDL语句包括:

    • CREATE DROP 语句,以及(如果适用) ALTER 存储程序,触发器,视图和用户定义函数(UDF)的语句。

    • 账户管理语句: CREATE ALTER DROP ,,如果适用, RENAME 报表用户和角色,以及 GRANT REVOKE 报表。

原子DDL功能不支持以下语句:

原子DDL特性

原子DDL语句的特征包括以下内容:

  • 元数据更新,二进制日志写入和存储引擎操作(如果适用)将合并为单个事务。

  • 在DDL操作期间,SQL层没有中间提交。

  • 适用时:

    • 数据字典,例程,事件和UDF高速缓存的状态与DDL操作的状态一致,这意味着更新高速缓存以反映DDL操作是成功完成还是回滚。

    • DDL操作中涉及的存储引擎方法不执行中间提交,并且存储引擎将自身注册为DDL事务的一部分。

    • 存储引擎支持DDL操作的重做和回滚,这在DDL操作的 Post-DDL 阶段执行。

  • DDL操作的可见行为是原子的,这会更改某些DDL语句的行为。 请参阅 DDL语句行为中的更改

注意

原子或其他DDL语句隐式结束当前会话中处于活动状态的任何事务,就好像您 COMMIT 在执行语句之前 完成了 一样。 这意味着DDL语句不能在另一个事务中,在事务控制语句中执行 START TRANSACTION ... COMMIT ,或者与同一事务中的其他语句结合使用。

DDL语句行为的变化

本节介绍由于引入原子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秒)
    
    注意

    由于行为的这种变化, DROP VIEW MySQL 5.7主服务器上 的部分完成 操作在MySQL 8.0从服务器上复制时失败。 要避免此故障情形,请 IF EXISTS DROP VIEW 语句中 使用 语法 以防止对不存在的视图发生错误。

  • 不再允许部分执行帐户管理声明。 帐户管理语句对所有命名用户成功或回滚,如果发生错误则无效。 在早期的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 阶段

  1. 准备 :创建所需对象并将DDL日志写入 mysql.innodb_ddl_log 表中。 DDL日志定义了如何前滚和回滚DDL操作。

  2. 执行 :执行DDL操作。 例如,为 CREATE TABLE 操作 执行创建例程

  3. 提交 :更新数据字典并提交数据字典事务。

  4. 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事务。

查看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

13.1.2 ALTER DATABASE语法

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 设置。 有关更多信息,请参阅 为架构和常规表空间定义加密默认值

13.1.3 ALTER EVENT语法

改变
    [DEFINER = user]
    活动event_name
    [安排时间表schedule]
    [完成[NOT] PRESERVE]
    [重命名new_event_name]
    [ENABLE | 禁用| 禁止在[SLAVE]
    [评论' string']
    [DO event_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节“调用的特性的复制”

13.1.4 ALTER FUNCTION语法

改变功能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节“存储程序二进制日志记录”中所述

13.1.5 ALTER INSTANCE语法

更改实例 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节“加密二进制日志文件和中继日志文件”

  • ALTER INSTANCE RELOAD TLS

    此操作从定义上下文的系统变量的当前值重新配置SSL上下文。 它还会更新反映活动上下文值的状态变量。 此操作需要该 CONNECTION_ADMIN 权限。

    默认情况下, RELOAD TLS 如果配置值不允许创建新的SSL上下文 ,则 操作将回滚并显示错误,并且无效。 先前的上下文值继续用于新连接。

    如果 NO ROLLBACK ON ERROR 给出 了可选 子句并且无法创建新上下文,则不会发生回滚。 而是生成警告,并为新连接禁用SSL。

    ALTER INSTANCE RELOAD TLS 语句不会写入二进制日志(因此不会被复制)。 SSL配置是本地的,取决于所有涉及的服务器上不一定存在的本地文件。

    有关重新配置SSL上下文的其他信息,包括与上下文相关的系统和状态变量,请参阅 加密连接的服务器端运行时配置

13.1.6 ALTER LOGFILE GROUP语法

ALTER LOGFILE GROUP logfile_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集群磁盘数据表”

13.1.7更改过程语法

更改程序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特权”

13.1.8 ALTER SERVER语法

更改服务器   server_name
    选项(option[,option] ...)

更改服务器信息 server_name ,调整 CREATE SERVER 语句中 允许的任何选项 mysql.servers 表中 的相应字段会相应 更新。 此声明需要该 SUPER 权限。

例如,要更新 USER 选项:

ALTER SERVER的选项(USER'sally');

ALTER SERVER 导致隐式提交。 请参见 第13.3.3节“导致隐式提交的语句”

ALTER SERVER 无论正在使用的日志记录格式如何,都不会写入二进制日志。

13.1.9 ALTER TABLE语法

ALTER TABLE tbl_name
    [ alter_specification[,alter_specification] ...]
    [ partition_options]

alter_specificationtable_options
  | 添加[栏目] 
        [第一个| 之后]col_name column_definitioncol_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
  | ADD check_constraint_definition
  | DROP CHECK symbol
  | 更改检查symbol[NOT]强制执行
  | 算法[=] {DEFAULT | INSTANT | INPLACE | COPY}
  | ALTER [COLUMN] col_name{SET DEFAULT literal| DROP DEFAULT}
  | ALTER INDEX index_name{VISIBLE | 无形}
  | 更改[栏目] 
        [第一|后]old_col_name new_col_name column_definitioncol_name
  | [DEFAULT] CHARACTER SET [=] charset_name[COLLATE [=] collation_name]
  | 转换为字符集charset_name[COLLATE collation_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_definitioncol_name
  | ORDER BY col_name[,col_name] ......
  | RENAME COLUMN old_col_nameTO new_col_name
  | 重命名{INDEX | KEY} old_index_namenew_index_name
  | 重命名[TO | AS]new_tbl_name
  | {WITHOUT | WITH}验证
  | 添加分区(partition_definition
  | DROP PARTITION partition_names
  | DISCARD PARTITION { partition_names| ALL} TABLESPACE
  | IMPORT PARTITION { partition_names| ALL} TABLESPACE
  | TRUNCATE PARTITION { partition_names| 所有}
  | COALESCE PARTITION number
  | 重新划分partition_namespartition_definitions
  | partition_nametbl_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
  | 与PARSER parser_name
  | 评论' string'
  | {VISIBLE | 无形}

check_constraint_definition
    [CONSTRAINT [ symbol]] CHECK(expr)[[NOT] ENFORCED]

table_optionstable_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
  | TABLESPACE tablespace_name[STORAGE {DISK | MEMORY}]
  | UNION [=](tbl_name[,tbl_name] ......)

partition_options
    (见CREATE TABLE选项)

ALTER TABLE 改变表的结构。 例如,您可以添加或删除列,创建或销毁索引,更改现有列的类型,或重命名列或表本身。 您还可以更改特征,例如用于表的存储引擎或表注释。

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 表以使用压缩行存储格式:

    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开始,在这些条件适用时更改列字符集:

      • 列数据类型是 CHAR VARCHAR ,一个 TEXT 类型,或 ENUM

      • 该字符集的变化是来自 utf8mb3 utf8mb4 ,或任何字符集 binary

      • 列上没有索引。

    • 从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.

Concurrency Control

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 old_index_name TO new_index_name 重命名索引。 这是标准SQL的MySQL扩展。 表的内容保持不变。 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 TABLE tbl_nameDROP FOREIGN KEY fk_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 TABLE tbl_name
        ADD CONSTRAINT [ symbol] CHECK(expr)[[NOT] ENFORCED];
    

    约束语法元素的含义与for相同 CREATE TABLE 请参见 第13.1.20.7节“检查约束”

  • 删除名为的现有约束 symbol

    ALTER TABLE tbl_name
        DROP CHECK symbol;
    
  • 更改是否 symbol 强制执行 现有约束

    ALTER TABLE tbl_name
        ALTER CHECK symbol[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 TABLE tbl_nameCONVERT TO CHARACTER SET charset_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 TABLE tbl_nameDEFAULT CHARACTER SET charset_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表空间

一个 InnoDB 在自己创建的表 文件的每个表的 表空间可以被丢弃,并使用进口 DISCARD TABLESPACE IMPORT TABLESPACE 选项。 这些选项可用于从备份导入每个表的文件表空间,或者将每个表的文件表空间从一个数据库服务器复制到另一个数据库服务器。 请参见 第15.6.3.7节“将表空间复制到另一个实例”

MyISAM表的行顺序

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节“使用表交换分区和子分区”

13.1.9.1 ALTER TABLE分区操作

与分区相关的子句 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节“分区维护”

13.1.9.2 ALTER TABLE和生成的列

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()

13.1.9.3 ALTER TABLE示例

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;

13.1.10 ALTER TABLESPACE语法

仅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静态数据加密”

13.1.11 ALTER VIEW语法

改变
    [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 特权。

13.1.12 CREATE DATABASE语法

创建{数据库| 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指定数据库特征。 数据库特征存储在数据字典中。

MySQL中的数据库实现为包含与数据库中的表对应的文件的目录。 由于最初创建数据库时没有表,因此该 CREATE DATABASE 语句仅在MySQL数据目录下创建一个目录。 第9.2节“模式对象名称” 中给出了允许的数据库名称的规则 如果数据库名称包含特殊字符,则数据库目录的名称包含这些字符的编码版本,如 第9.2.3节“标识符到文件名的映射”中所述

在MySQL 8.0中不支持通过在 数据目录下手动创建目录(例如,使用 mkdir )来 创建数据库目录

您还可以使用 mysqladmin 程序创建数据库。 请参见 第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端”

13.1.13 CREATE EVENT语法

创建
    [DEFINER = user]
    事件
    [IF NOT EXISTS]
    event_name
    按照时间表 schedule
    [完成[NOT] PRESERVE]
    [ENABLE | 禁用| 禁止在[SLAVE]
    [评论' string']event_body;

schedule
    AT timestamp[+ INTERVAL interval] ......
  | 每个interval
    [开始timestamp[+间隔interval] ...]
    [结束timestamp[+ INTERVAL interval] ...]

intervalquantity{年| 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节“存储的例程语法” 您可以将事件创建为存储例程的一部分,但事件不能由另一个事件创建。

13.1.14 CREATE FUNCTION语法

CREATE FUNCTION 语句用于创建存储函数和用户定义函数(UDF):

13.1.15 CREATE INDEX语法

创建[UNIQUE | FULLTEXT | 空间]索引index_name
    [ index_type]
    ON tbl_namekey_part,...)
    [ index_option]
    [ algorithm_option| lock_option] ......

key_part:{ col_name[(length)] | expr)} [ASC | DESC]

index_option
    KEY_BLOCK_SIZE [=] value
  | index_type
  | 与PARSER parser_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)

如果指定的索引前缀超过最大列数据类型大小, 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 ,目标表保留原始表中的功能键部分。

功能索引实现为隐藏的虚拟生成列,具有以下含义:

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 列,您可以尝试使用以下 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节“空间数据类型” 描述了空间数据类型。)但是,空间列索引的支持因引擎而异。 根据以下规则,空间列上的空间和非空间索引可用。

空间列上的空间索引具有以下特征:

  • 仅适用于 InnoDB MyISAM 表格。 指定 SPATIAL INDEX 其他存储引擎会导致错误。

  • 从MySQL 8.0.12开始,空间列 索引 必须 SPATIAL 索引。 因此, SPATIAL 关键字是可选的,但隐含用于在空间列上创建索引。

  • 仅适用于单个空间列。 无法在多个空间列上创建空间索引。

  • 索引列必须是 NOT NULL

  • 列前缀长度是禁止的。 索引每列的全宽。

  • 不允许使用主键或唯一索引。

在空间列非空间索引(与创建 INDEX UNIQUE PRIMARY KEY )具有以下特征:

  • 允许任何支持空间列的存储引擎除外 ARCHIVE

  • NULL 除非索引是主键,否则 列可以是列

  • SPATIAL 索引 的索引类型 取决于存储引擎。 目前,使用B树。

  • 允许,可以有一个列 NULL 仅值 InnoDB MyISAM MEMORY 表。

指数期权

在关键部件列表之后,可以给出索引选项。 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 索引定义中 子句。

    表13.1每个存储引擎的索引类型

    存储引擎 允许的索引类型
    InnoDB BTREE
    MyISAM BTREE
    MEMORY / HEAP HASH BTREE
    NDB HASH BTREE (见文中注释)

    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进行联机操作”

13.1.16 CREATE LOGFILE GROUP语法

CREATE LOGFILE GROUP logfile_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集群磁盘数据表”

13.1.17创建过程和创建函数语法

创建
    [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_parameterparam_name type

typeAny valid MySQL data type

characteristic
    评论' string'
  | 语言SQL
  | [NOT]决定因素
  | {包含SQL | 没有SQL | 读取SQL数据| 修改SQL DATA}
  | SQL SECURITY {DEFINER | INVOKER}

routine_bodyValid 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中,这些特征仅供参考。 服务器不使用它们来约束允许例程执行的语句类型。

  • CONTAINS SQL 表示该例程不包含读取或写入数据的语句。 如果没有明确给出这些特征,则这是默认值。 这些语句的例子是 SET @x = 1 或者 DO RELEASE_LOCK('abc') ,它们既可以执行但不能读取或写入数据。

  • NO SQL 表示该例程不包含SQL语句。

  • READS SQL DATA 表示例程包含读取数据的语句(例如 SELECT ),但不包含写入数据的语句。

  • MODIFIES SQL DATA 表示该例程包含可能写入数据的语句(例如, INSERT DELETE )。

所述 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节“数据库字符集和排序规则”

13.1.18 CREATE SERVER语法

创建服务器server_name
    外部数据包装wrapper_name
    选项(option[,option] ...)

option
  {主持人character-literal
  | 数据库character-literal
  | 用户character-literal
  | 密码character-literal
  | SOCKET character-literal
  | 所有者character-literal
  | PORT numeric-literal}

此语句创建用于 FEDERATED 存储引擎 的服务器的定义 CREATE SERVER 语句 servers mysql 数据库 表中 创建一个新行 此声明需要该 SUPER 权限。

server_name 应该是唯一的参考服务器。 服务器定义在服务器范围内是全局的,无法将服务器定义限定为特定数据库。 server_name 最大长度为64个字符(超过64个字符的名称被静默截断),并且不区分大小写。 您可以将名称指定为带引号的字符串。

wrapper_name 是一个标识符,可以用单引号引用。

对于每个, option 您必须指定字符文字或数字文字。 字符文字是UTF-8,最大长度为64个字符,默认为空(空)字符串。 字符串文字被静默截断为64个字符。 数字文字必须是0到9999之间的数字,默认值为0。

注意

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 无论正在使用的日志记录格式如何,都不会写入二进制日志。

13.1.19创建空间参考系统语法

创建或替换空间参考系统
     ......srid srs_attribute

创建空间参考系统
    [IF NOT EXISTS]
    srid srs_attribute ...

srs_attribute:{
    名称 'srs_name '
  | 定义'definition '
  | 组织org_name'IDENTIFIED BY org_id
  | 说明'description '
}

sridorg_id32-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 属性值不能为空或开始或空白结束。

  • 属性规范中的字符串值不能包含控制字符,包括换行符。

  • 下表显示了字符串属性值的最大长度。

    表13.6创建空间参考系统属性长度

    属性 最大长度(字符)
    NAME 80
    DEFINITION 4096
    ORGANIZATION 256
    DESCRIPTION 2048

这是一个示例 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 经度

13.1.20 CREATE TABLE语法

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_namecreate_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
    {LIKE old_tbl_name| (LIKE old_tbl_name)}

create_definition
  | {INDEX | KEY} [ ] [ ](,...)col_name column_definitionindex_nameindex_typekey_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_definitiondata_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
  | 与PARSER parser_name
  | 评论'string'
  | {VISIBLE | 无形}

check_constraint_definition
    [CONSTRAINT [ symbol]] CHECK(expr)[[NOT] ENFORCED]

reference_definition
    参考文献tbl_namekey_part,...)
      [匹配完整| 匹配部分| 匹配简单]
      [ON DELETE reference_option]
      [ON UPDATE reference_option]

reference_option
    限制| CASCADE | SET NULL | 没有动作| 默认设置

table_optionstable_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
  | TABLESPACE tablespace_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)}}
    [PARTITIONS num]
    [SUBPARTITION BY
        {[LINEAR] HASH(expr
        | [LINEAR] KEY [ALGORITHM = {1 | 2}](column_list)}
      [SUBPARTITIONS num]
    ]
    [(partition_definition[,partition_definition] ......)]

partition_definition
    划分 partition_name
        [VALUES
            {不到{(expr| value_list)| MAXVALUE}
            |
            IN(value_list)}]
        [[STORAGE] ENGINE [=] engine_name]
        [评论[=]' string']
        [DATA DIRECTORY [=]' data_dir']
        [INDEX DIRECTORY [=]' index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] tablespace_name]
        [(subpartition_definition[,subpartition_definition] ......)]

subpartition_definition
    SUBPARTITION logical_name
        [[STORAGE] ENGINE [=] engine_name]
        [评论[=]' string']
        [DATA DIRECTORY [=]' data_dir']
        [INDEX DIRECTORY [=]' index_dir']
        [MAX_ROWS [=] 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语法”

表克隆和复制

列数据类型和属性

每个表的硬限制为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 列。 例如: