Mysql 8.0 第13章 SQL语句的语法 (第1节)

8 篇文章 2 订阅
7 篇文章 0 订阅

内容太多,按小节开。下一节,请见 13.2节
翻译居多,译者附加了自己的例子,感觉的翻译不准的地方,已经附加了原文!

13.1 数据定义语句(DDL)

13.1.2 修改数据库语法

原文
在这里插入图片描述
ALTER DATABASE允许你修改一个数据库的字符集( 需要ALTER权限 ),要查某看个数据库的字符集文件db.opt,可以在mysql服务器的data目录下相应的数据库文件夹内看到。

ALTER SCHEMAALTER DATABASE的同义词。
  CHARACTER SET部分决定了数据库所使用的字符集,COLLATE决定数据库的校对字符集,关于这两个字符集请见第10章。可以使用SQL命令SHOW CHARACTER SETSHOW COLLATION来查看mysql服务器所支持的这两个字符集分别都有什么。
  如果你修改了这两个字符集,使用了这个数据库的的存储例程就要删除并重新建立,以便它使用新的字符集( 在存储例程中,如果未明确指定字符集或排序规则,则具有字符数据类型的变量将使用数据库缺省值, 详情参见章节13.7.6 )


13.1.3 修改事件语法

原文
在这里插入图片描述
  在不删除某一事件的基础上,ALTER EVENT用来修改此事件的一些属性。它里面的一些特性的用法和含义,如ON SCHEDULE已在章节13.1.13 中讲过。
  任何具有EVENT权限的用户都可以执行ALTER EVENT操作,执行ALTER EVENT成功的用户就会成为此事件的DEFINER。修改一个不存在的事件会报1517错误。

1.部分用法
(1)可以使用RENAME TO重命名原事件的名字
(2)关闭一个事件可以使用ALTER EVENT myevent DISABLE;
(3)可以把一个事件移动到新的数据库,使用RENAME TO db_name.event_name

2.注意事项
(1)你在ALTER EVENT中修改的选项会覆盖原事件的相应属性,未修改的属性会保留。:
(2)在创建或修改事件内嵌套 创建或修改事件不会报错,但是执行的时候会有错误,别这么使用。


13.1.3 修改函数语法

原文 P1865
在这里插入图片描述
  ALTER FUNCTION用来修改存储函数的某些属性,你可以修改多个属性,但有些属性不能修改那就是存储函数的主体和参数。如果想要主体和参数的更改,必须使用DROP FUNCTION name删除函数和CREATE FUNCTION name重新创建函数。
  使用这个方法,你还要有ALTER ROUTINE权限(该权限自动授予函数的创建者),如果启用了二进制日志记录,则ALTER FUNCTION 语句可能还需要该 SUPER特权。
  更多此方法的关键字请见章节13.1.14 创建函数语法


13.1.7 修改PROCEDURE语法

原文
在这里插入图片描述
  ALTER PROCEDURE用来修改存储过程的某些属性,你可以修改多个属性,但有些属性不能修改那就是存储过程的主体和参数。如果想要主体和参数的更改,必须使用DROP PROCEDURE name删除函数和CREATE PROCEDURE name重新创建函数。
  使用这个方法,你还要有ALTER ROUTINE权限(该权限自动授予函数的创建者)。
  更多此方法的关键字请见章节13.1.14 创建函数语法


13.1.12 创建数据库语法

原文
在这里插入图片描述
CREATE DATABASE用来创建一个指定名字的数据库,你需要CREATE权限,CREATE SCHEMACREATE DATABASE的同义词。

如果数据库存在且您未指定IF NOT EXISTS则会发生错误 。

CREATE DATABASE在具有活动的LOCK TABLES语句的会话中不允许。

create_specificationoptions指定数据库字符集。数据库字符集存储在对应数据库的数据目录内。CHARACTER SET子句指定默认数据库字符集。该 COLLATE子句指定默认的数据库排序规则。第10章,字符集,排序规则,Unicode 中讨论了字符集和排序规则名称。

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

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

你也可以用mysql提供的工具mysqladmin来建立数据库。请参见第4.5.2节“ mysqladmin - 管理MySQL服务器的客户端”。


13.1.13 创建事件语法

原文
在这里插入图片描述

  使用此语句将创建并调度一个新的事件,如果你的事件调度器(Event Scheduler)没有设置为ON状态,这个新的事件不会执行,关于事件调度器请见章节 第24.4.2节“事件调度程序配置”。

使用CREATE EVENT,你需要有 与事件关联的数据库的EVENT权限,还可能要SET_USER_ID 或者 SUPER权限,这却决于 DEFINER如何定义,稍后会讲到。

1.主要构成
创建一个新事件的语法最少需要三个部分:
第一部分CREATE EVENT 给出了新事件的名字(需要唯一,不超过64个字符,大小写不敏感)
第二部分ON SCHEDULE决定了事件执行的时间间隔
第三部分DO决定了事件要执行的SQL语句

CREATE EVENT
这里有个例子, 定义了一个名为myevent的事件,一小时之后把mytable表中的所有mycol列的值都+1:
在这里插入图片描述
一个事件与某个数据库关联,如果你在event_name上没给出数据库,会绑定到当前的数据库,如果你想显示指定关联的数据库,可以这么做schema_name.event_name

DEFINER部分指定了事件执行时候检查其执行权限的用户是谁,默认是当前执行创建事件的用户,如果你指定了值,此值必须是msyql用户之一,其形式可以是'user_name'@'host_name', CURRENT_USER, CURRENT_USER()这三种之一。

如果指定了DEFINER子句,下面这些规则确定有效的DEFINER用户值:

  • 如果你没有 SET_USER_IDSUPER特权,则唯一允许的user值是您自己的帐户,无论是字面指定还是使用 CURRENT_USER。您无法将定义者设置为其他帐户。
  • 如果您具有SET_USER_IDSUPER权限,则可以指定任何语法上有效的帐户名称。如果该帐户不存在,则会生成警告。
  • 虽然可以使用不存在的DEFINER帐户创建事件,但 如果该帐户不存在,则会在事件执行时发生错误。

更多事件安全的问题请见 章节23.6 存储程序和视图的访问控制。
在一个事件中,CURRENT_USER() 函数返回用于在事件执行时检查权限的用户,即DEFINER用户。有关事件中用户信息的审核,请参见 第6.3.13节“基于SQL的MySQL帐户活动审核” 。

IF NOT EXISTS和你创建数据库里的同义词的意思一样,如果当前事件已经存在,则不会创建新的事件,只是会有个警告信息而已。

ON SCHEDULE
ON SCHEDULE 用来确定event_body事件的定义时间,频率和持续时间。有两种形式,你可以任选其一:
a. AT timestamp
AT timestamp表明是一次性事件,timestamp必须是一个日期时间值,不能只有日期而没有时间,你可以指定其为 DATETIME类型或者TIMESTAMP类型。如果你指定的日期时间是过去的,会生成一条警告信息,例如:
在这里插入图片描述
无论是出于何种原因让CREATE EVENT语句无效,语句都会失败并出现错误。
您可以使用CURRENT_TIMESTAMP 指定当前日期和时间。在这种情况下,事件一旦创建就会起作用。
要创建一个事件,该事件发生在将来某个时间点 - 例如“ 从现在起三周 ” - 可以使用optional子句 + INTERVAL interval。interval由两部分组成,一个整数和一个时间单位,它遵循的语法和函数DATE_ADD()中使用的时间间隔保持一致(参见 第12.7节“日期和时间函数”。时间单位也相同,除了在定义事件时,不能使用任何涉及微秒的单位)。对于某些区间类型,可以使用复杂的时间单位,比如2分10秒可以写成+ INTERVAL '2:10' MINUTE_SECOND(等价于+ INTERVAL 2 MINUTE + INTERVAL 10 SECOND)。

b.Every
Every表明是重复性事件,可以使用interval部分,不能用 + INTERVAL
EVERY '2:10' MINUTE_SECOND 表明每2分10秒执行一次该事件。
  Every选项还有两个附加参数 STARTSENDS 其意思很明确,指定事件开始和结束的时间,如果不指定STARTS参数,它等价于取事件创建完毕的时间。一个使用例子:
EVERY 12 HOUR STARTS CURRENT_TIMESTAMP INTERVAL 30 MINUTE ENDS CURRENT_TIMESTAMP + INTERVAL 4 WEEK
不使用ENDS部分,事件会无限执行下去。
它表明从30分钟以后开始到4周以后结束,期间每12小时执行一次事件。
  如果一个重复性事件没有在其周期内完成,可能会导致同一时间内有多个事件实例进程在运行,如果你想避免这种行为可以使用保护机制,例如GET_LOCK()方法或者 给行、表上锁

ON SCHEDULE 里面还可以用mysql函数或用户变量来存储时间间隔(下图所示),但是不能用存储函数或用户自定义的函数来存时间间隔,表引用也不行.
在这里插入图片描述
还有一种情况也不允许在ON SCHEDULE中使用,我不知道怎么翻译 :
在这里插入图片描述
ON SCHEDULE部分的时间表现值由会话中的变量time_zone来决定,也就是说,用于事件调度的时区,它在事件执行时会生效。这些时间会转换为UTC格式并和事件的时区一起存储在mysql.event表中。这使得事件执行能够按照其定义执行,而不管服务器 后续的时区或夏令时的更改。有关事件时间如何表示的更多内容,请参见第24.4.4节“事件元数据”。另请参见 第13.7.6.18节“显示事件语法”和第25.9节“INFORMATION_SCHEMA事件表”。

DO
DO语句包含了事件要指定的动作(一系列SQL语句),例如:
在这里插入图片描述

2.可用部分
(1)通常,一旦事件过期,它会立即被删除(默认为ON COMPLETION NOT PRESERVE),如果你想在事件结束后保留这个事件对象,可以增加ON COMPLETION PRESERVE字段
(2)事件创建完毕是否马上启用取决于ENABLEDISABLE选项,默认是ENABLE,这在你修改事件语句的时候很有用( 13.1.3, “ALTER EVENT Syntax”),第三个参数DISABLE ON SLAVE不太明白(原文:DISABLE ON SLAVE is set for the status of an event on a replication slave to indicate that the event was created on the master and replicated to the slave, but is not executed on the slave See Section 17.4.1.16, “Replication of Invoked Features”)
(3)使用COMMENT 'string',你还可以为事件提供一个注释说明,长度在64位以内,引号引起。

3.注意事项
(1)服务器的 sql_mode变量会影响事件当时的创建、修改和执行,事件开始执行时就不会理会当前服务器的sql_mode
(2)创建事件中的SQL语句可以是修改事件的语句,但是事件执行的时候会失败。
(3)创建事件中的SQL语句可以是select或show语句,但是其查询结果不会显示,你可以用SELECT ... INTO或者INSERT INTO ... SELECT等语句存储结果。
(4)DO中的语句默认使用当前数据库,如果指定其他数据库要加点(db_name.tbl_name)。
(5)创建事件中的SQL语句如果很长,你可以用BEGIN ...END来包裹。例子如下(使用了delimiter来重新定义结束符):
在这里插入图片描述
可以使用更复杂的复合语句,例如存储例程中使用的语句。此示例使用局部变量,错误处理程序和流控制构造:
在这里插入图片描述
(5)无法给事件传递参数或者从事件传递参数,但是可以在事件中调用带参数的存储过程。
在这里插入图片描述
(6)如果事件的定义者(difiner)有足够的权限来设定全局系统变量(第 5.1.8.1 系统变量权限),他定义的事件就可以滥用或设定全局变量,请小心使用。
(7)通常,在存储例程中有效的任何语句都可以用于事件执行的操作语句。有关存储例程中允许的语句的更多信息,请参见 第24.2.1节“存储的例程语法” 。您可以将事件创建为存储例程的一部分,但事件不能由另一个事件创建。

4.自定义例子
事件:

CREATE DEFINER='bbs'@'localhost' EVENT bbs_blog.addopt on SCHEDULE  EVERY 10 SECOND STARTS CURRENT_TIMESTAMP + INTERVAL '1:10' MINUTE_SECOND ENDS CURRENT_TIMESTAMP + INTERVAL 2 MINUTE + INTERVAL 10 SECOND on COMPLETION PRESERVE COMMENT 'testevent' DO UPDATE bbs_blog.test set sid=sid+1 WHERE id=2;

  这里定义了一个事件 bbs_blog.addopt其作用是在1分10秒后到2分10
之间每10秒将bbs_blog数据库的表test中id为2的记录sid字段+1,将此事件存储在mysql数据库的event表中并提供了注释说明。

问题:
  1分10秒后sid没有增加,直到事件区间结束也没有增加。
解决:
  (1)设置事件调度器为打开状态
  show VARIABLES like '%event_scheduler%'; 结果是OFF
  打开:set global event_scheduler=ON;
  (2)在event表中删除对应的事件,并再次创建事件
  DELETE from mysql.event where name='addopt1';


13.1.14 创建函数语法

CREATE FUNCTION被用来创建存储函数和用户自定义函数(UDF)

  • 有关创建存储函数的内容,请见章节13.1.17 创建存储过程和创建函数的语法
  • 有关创建用户自定义函数的内容,请见章节13.7.4.1 创建用户自定义函数的语法

13.1.15 创建索引语法

原文
在这里插入图片描述
  CREATE INDEX用来向现有表添加索引。通常,你在用CREATE TABLE建表的时候就能创建索引了,详情见13.1.20 创建表的语法。对于InnoDB表,此指南尤其重要,其中主键决定数据文件中行的物理布局。
  CREATE INDEXALTER TABLE语句都可以用来创建索引,用法互通,可以看13.1.9 修改表的语法。CREATE INDEX不能用来创建主键(PRIMARY KEY),可以用 ALTER TABLE来代替。更多关于索引的信息,请见 8.3.1 Mysql如何使用索引。
  InnoDB引擎支持虚拟列上的二级索引。有关更多信息,请参见 第13.1.20.9节“二级索引和生成的列”。当innodb_stats_persistent变量开启后,在InnoDB表上创建索引后运行语句ANALYZE TABLE name可以查看表的索引结构 。
  索引的组成形式是(key_part1, key_part2, ...)这样的,一个索引可以是多个key_part组成,这样的索引,它的键是这些key_part联合组成的。例如(col1,col2,col3)表示指定了一个多列组成的索引,其中的列组成为col1,col2,col3。
  key_part 结束之前,可以指定排序规则ASCDESC,分别用于指定索引值是升序或降序排列,默认都是升序的,两个排序方式都不能用在HASH索引上面。MySQL 8.0.12 中, ASC和DESC不是允许用在空间索引(SPATIAL INDEX)上面的。
下面对CREATE INDEX语法按照如下部分进行介绍:

a. 列前缀

对于字符串类型的列,可以使用列的前一部分值来创建索引,使用col_name(length)语法指定索引前缀的长度。

  • 可以在CHAR, VARCHAR, BINARY类型的列上指定前缀,可以不指定 。
  • BLOBTEXT 类型的列必须指定前缀 。此外, 只能在InnoDB/MyISAMBLACKHOLE表中为BLOBTEXT列创建索引,其它类型的表不可以。
  • 前缀的长度限制以字节为单位。然而,该长度 在你使用CREATE TABLE、ALTER TABLE或CREATE INDEX语句时被解释为非二进制字符串(CHAR,VARCHAR,TEXT)的字符数 或者 被解释为二进制字符串(BINARY,VARBINARY,BLOB)的字节数。因此, 为使用多字节字符集的非二进制字符串列指定前缀长度时,请考虑此问题。这里有个网友的例子放在b小节之前。

  存储引擎的类型决定了是否支持前缀索引这个特性和前缀索引的长度限定。NDB存储引擎不支持前缀这一属性 21.1.6.6,而InnoDB表使用了 REDUNDANT/COMPACT行格式的话,它支持索引的前缀长度为767字节,而使用了DYNAMIC/COMPRESSED行格式的话 能达到3072字节;对于MyISAM表,前缀限定长度为1000字节以内。NDB存储引擎不支持前缀(见第22.1.6.6,“在NDB Cluster不支持或缺失的功能”)。
  从MySQL 5.7.17开始,如果指定的索引前缀长度超过指定的列数据类型的最大长度,则按CREATE INDEX如下方式处理索引:
  (1) 对于非唯一索引,要么发生错误(如果启用了严格的SQL模式),要么索引长度减少到最大列数据类型大小,并产生警告(如果未启用严格SQL模式)
  (2) 对于唯一索引,无论SQL模式如何都会发生错误,因为减少索引长度可能会导致插入的数据不唯一。
下面的例子(name是非二进制字符串):
CREATE INDEX part_of_name ON customer (name(10));
  如果name列中前10个字符大部分都不相同,则使用此索引前缀来执行的查找速度 不应该比使用整个name列创建的索引慢 。此外,相较前两种情况来说,使用索引前缀可以使索引文件更小,这可以节省大量磁盘空间并且还可能 加快 INSERT操作。
例子:
在这里插入图片描述

b. 方法索引 Functional Key Parts (>= 8.0.13)

一个” 普通 ”索引 索引列值或者列值的前缀。例如,在下表中,给定t1行的索引条目包括完整 col1值和col2由前10个字符组成的值的前缀 :
在这里插入图片描述
MySQL 8.0.13及更高版本支持索引使用表达式和方法,而不是列或列前缀值。使用方法可以让索引的值不直接存储在表中。例子:
在这里插入图片描述
具有多列的索引可以混用方法索引和非方法索引,方法索引可以使用ASCDESC

方法索引必须遵守以下规则。如果索引定义包含不允许的构造,则会发生错误。

  • 在索引定义中,将表达式括在括号内,以将它们与列或列前缀区分开来。例如,这是允许的;
    INDEX ((col1 + col2), (col3 - col4))
  • 这会产生错误; 表达式未括在括号内:
    INDEX (col1 + col2, col3 - col4)
  • 方法索引不能仅由列名组成。例如,这是不允许的:
    INDEX ((col1), (col2))
    相反,非方法索引可以这么写,不带括号:
    INDEX (col1, col2)
  • 方法索引的表达式不能引用列前缀。有关解决方法,请参阅本节后面 SUBSTRING()/ CAST()的讨论。
  • 方法索引不能用于外键。

使用CREATE TABLE ... LIKE创建的新表会保留原表中的方法索引
方法索引实现为隐藏的虚拟生成列,具有以下含义:

  • 每个方法索引都计入表列总数的限制; 请参见 第C.10.4节“表列数和行大小的限制” 。

  • 方法索引继承适用于生成列的所有限制。例子:
    ① 对于方法索引,仅允许生成列允许的功能。
    ② 不允许使用子查询,参数,变量,存储函数和用户定义的函数。

有关限制的更多信息,请参见 第13.1.20.8节“创建表和生成的列”和 第13.1.9.3节“更改表和生成的列”。

包含方法索引的索引可以使用UNIQUE。但是,主键不能包含方法索引。主键需要存储生成的列,但方法索引实现为虚拟生成列,而不是存储生成的列。

SPATIAL索引和FULLTEXT索引不能使用方法索引。

如果表中不包含主键,InnoDB 则会自动将第一个UNIQUE NOT NULL索引提升为主键。UNIQUE NOT NULL索引不支持方法索引。

如果存在重复索引,则非方法索引会发出警告。包含方法的索引没有此功能。
要删除方法索引引用的列,必须首先删除索引。否则,会发生错误。

虽然非方法索引支持前缀长度规范,但这对于非方法索引是不可能的。解决方案是使用 SUBSTRING()(或 CAST(),如本节后面所述)。如果在查询中查找方法索引(此方法索引使用了SUBSTRING()方法),那么WHERE子句部分必须包含 SUBSTRING(),并且参数与方法索引中的参数一致。在以下示例中,只有第二个 SELECT能够使用索引,因为这是SUBSTRING()与方法索引中的函数参数匹配 :
在这里插入图片描述
方法索引中支持其它索引无法索引的值,例如JSON 值。但是,必须正确地完成这一操作才能达到预期的效果。例如,此语法不起作用:
在这里插入图片描述
语法失败,因为:

  • ->> 操作符转变成 JSON_UNQUOTE(JSON_EXTRACT(...))
  • JSON_UNQUOTE()返回数据类型为LONGTEXT的值,因此为隐藏生成的列分配相同的数据类型。
  • MySQL不能索引 LONGTEXT(因为LONGTEXT没有指定前缀长度),并且方法索引中不允许使用前缀长度。

要索引JSON列,您可以尝试使用以下CAST()函数:
在这里插入图片描述
为隐藏的生成列分配 VARCHAR(30) 数据类型,可以对其进行索引。但是这种方法在尝试使用索引时会产生一个新问题:

  • CAST()返回带有排序规则( utf8mb4_0900_ai_ci,服务器默认排序规则 )的字符串。
  • JSON_UNQUOTE()返回带有排序规则(utf8mb4_bin)的字符串 (硬编码)。

因此,前面的表定义中的索引表达式。与以下查询中的WHERE子句表达式之间存在排序规则不匹配 :
在这里插入图片描述

上面的结果是,不使用索引,因为查询中的表达式和索引不同。为了支持这种方案的方法索引有效,可以使用优化器寻找一个索引时自动去除 CAST(),并且满足条件为索引表达式的排序规则匹配查询表达式。对于使用了方法索引的索引,以下两个解决方案中的任何一个都有效(尽管它们在某种程度上有所不同):

  • 解决方案1.为索引表达式分配与以下JSON_UNQUOTE()相同的排序规则:
    在这里插入图片描述
    ->> 操作符的作用跟前面一致,只有 JSON_UNQUOTE()返回utf8mb4_bin类的字符串。因此比较区分大小写,所以只有一行匹配:
    在这里插入图片描述
  • 解决方案2.在查询中指定完整表达式:
    在这里插入图片描述
    CAST()返回带有排序规则utf8mb4_0900_ai_ci的字符串 ,因此比较不区分大小写且两行匹配:
    在这里插入图片描述
    请注意,虽然优化器支持自动剥离使用索引生成的 CAST()列,但以下方法不起作用,因为它会生成带有和不带索引的不同结果(Bug#27337092):
    在这里插入图片描述

b. 唯一索引 Unique Indexes

一个UNIQUE索引创建一种约束使得该列上的所有值都必须是不同的,如果你添加了相同的值则会发生错误。如果为唯一索引中的列指定前缀值 ,那么这些前缀也要唯一。如果某一列允许字段为空(NULL),那么唯一索引允许有多个NULL
如果表有一列是主键PRIMARY KEY 或有一个索引 UNIQUE NOT NULL ,它俩的列数据类型都是整数,则可以在SELECT语句中使用 _rowid 来引用那个索引列 ,如下所示:

  • 如果某列是PRIMARY KEY且列值是整数,则 _rowid 指向 PRIMARY KEY列。如果 PRIMARY KEY 列值不只是整数,则_rowid不能使用。
    select _rowid from blog.auth_user;
  • 此外, _rowid引用第一个UNIQUE NOT NULL索引列(列值是整数)。如果第一个 UNIQUE NOT NULL索引列的值非整数,_rowid则不能使用。
    在这里插入图片描述
    上面的例子诠释了第二点的意思,使用select _rowid from tsgk.ss1就会返回和select phone from tsgk.ss1一样的值。

c. 全文索引 Full-Text Indexes

  仅InnoDB和 MyISAM表支持全文索引 ,并且索引列的数据类型只能是 CHAR, VARCHAR 和 TEXT。索引发生在整个列上所以 不支持列前缀索引,如果指定了前缀的长度,则忽略任何前缀长度。有关操作的详细信息,请参见 第12.9节“全文搜索功能”。

d. 空间索引 Spatial Indexes

MyISAM, InnoDB, NDB和 ARCHIVE存储引擎支持空间索引,对应的列数据类型 如POINTGEOMETRY(第11.5节“空间数据类型”),但是,对于空间列索引的支持因存储引擎而异。在空间列上定义的空间索引和非空间索引遵循以下规则。

(1)空间列上使用空间索引(使用SPATIAL INDEX创建空间索引)具有以下特征:

* 仅适用于MyISAM和 InnoDB表。在其他存储引擎上指定`SPATIAL INDEX`会导致错误。
* 索引列必须是非空的(NOT NULL)。
* 从MySQL 8.0.12开始,空间列的索引必须是SPATIAL索引。因此,SPATIAL关键字是可选的,但隐式地用于在空间列上创建索引。
* 仅适用于单个空间列。无法在多个空间列上创建空间索引。
* 索引列必须是NOT NULL。
* 索引前缀长度设定是禁止的,索引使用列的全宽。
* 不允许使用主键或唯一索引。

(2)在空间列上使用非空间索引(使用 INDEX,UNIQUE或 PRIMARY KEY创建)具有以下特征:

* 除了 ARCHIVE,允许任何支持空间列的存储引擎使用。
* 除了主键列不能为空,其他列可以为空
* 非空间索引的索引的类型取决于存储引擎。目前,都是的形式都是使用B树。
* 仅在InnoDB, MyISAM和 MEMORY表中,允许列值为空 

e. 索引的参数

下面给出了索引的可选参数。 index_option部分的值可以是下面介绍的:

KEY_BLOCK_SIZE [=] value
对于MyISAM表, KEY_BLOCK_SIZE 可以选择指定用于索引key的块的大小(以字节为单位)。该值被视为提示(原文The value is treated as a hint); 如有必要,可以使用不同的大小。为单个索引指定的KEY_BLOCK_SIZE值将影响整张表的 KEY_BLOCK_SIZE值。
InnoDB表的索引级别不支持KEY_BLOCK_SIZE。请参见第13.1.20节“建表语法”

index_type
某些存储引擎允许您在创建索引时指定索引类型。例如下面的例子使用了B树:
在这里插入图片描述
下表中显示了不同存储引擎支持的允许索引类型值。如果列出了多个索引类型,则在没有给出索引类型说明符时,第一个是默认值。表中未列出的存储引擎表示不支持这种索引类型。
在这里插入图片描述
  index_type部分不能用于全文索引FULLTEXT INDEX(MySQL 8.0.12之前)或空间索引 SPATIAL INDEX。全文索引类型的实现依赖于存储引擎,空间索引的类型实现为R树。
如果指定的索引类型对给定的存储引擎无效,但引擎可以使用另一种索引类型而不影响查询结果,则引擎将使用替代类型。解析器识别 RTREE为类型名称。从MySQL 8.0.12开始,仅允许SPATIAL 索引使用RTREE。在8.0.12之前,RTREE不能为任何存储引擎指定。

  B树索引在 NDB存储引擎中被实现为T树索引。
注意

  • 对于NDB表中列的索引,USING只能为唯一索引或主键指定。 USING HASH阻止创建有序的索引; 否则,在NDB表上创建唯一索引或主键会导致即创建有序索引又会创建哈希索引,每种索引都对同一列进行索引。
  • 对于NDB表的唯一索引如果包含一个或多个NULL列,哈希索引只能用于查找包含文字的值,这意味着 IS [NOT] NULL条件会对表进行完整扫描,对于这种情况的一种解决方法是在这样的表上再创建一个有序索引; 也就是说,避免在创建索引时使用USING HASH
  • ON tbl_name之前使用index_type选项已经废弃了,在将来的MySQL版本中将删除对此选项的支持。如果在完整语句的前和后的位置都给出了一个 index_type选项,则后面的选项会生效。

下表显示了各个支持****选项的存储引擎支持关于索引的特性:
在这里插入图片描述
InnoDB和MyISAM是完全一样的。
note 1:
如果使用USING HASH 组织了隐式地创建有序索引。

WITH PARSER parser_name
此选项只能用于 FULLTEXT索引。如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引相关联。InnoDB和MyISAM支持全文解析器插件。有关详细信息,请参阅全文分析器插件和 第29.2.4.4节“编写全文分析器插件”。

COMMENT 'string’
索引说明是可以包含最多1024个字符的可选注释。
索引页的中 MERGE_THRESHOLD 可以被配置为针对单独的索引,通过在创建索引的 index_option COMMENT部分进行指定。
例如:
在这里插入图片描述
当进行删除行或者在更新操作中 缩短行的值的时候,如果索引页的页面完全百分比低于MERGE_THRESHOLD的设定,InnoDB尝试将索引页与相邻索引页合并。默认MERGE_THRESHOLD值为50。
通过使用使用CREATE TABLEALTER TABLE语句,MERGE_THRESHOLD也可以定义在索引级别和表级别定义 。有关更多信息,请参见 第14.8.12节“配置索引页的合并阈值”。

VISIBLE, INVISIBLE
指定索引可见性。默认情况下,索引是可见的。优化程序不使用不可见索引。索引可见性的规范适用于除主键之外的索引(显式或隐式)。有关更多信息,请参见 第8.3.12节“不可见索引” 。

f. 表复制和加锁选项

ALGORITHMLOCK 影响表的复制和索引被修改时并发读取和写入数据的水平。它们与ALTER TABLE声明的部分具有相同的含义 。有关更多信息,请参见第13.1.9节“修改语法”。

NDB Cluster以前支持在 CREATE INDEX时在线操作,现在不支持。NDB Cluster现在支持ALGORITHM=INPLACE使用与标准MySQL服务器相同的语法进行在线操作。有关更多信息,请参见 第13.1.9.2节“NDB簇中的ALTER TABLE联机操作”(这段翻译很别扭,自己理解下 NDB Cluster formerly supported online CREATE INDEX operations using an alternative syntax that is no longer supported. NDB Cluster now supports online operations using the same ALGORITHM=INPLACE syntax used with the standard MySQL Server. See Section 13.1.8.2, “ALTER TABLE Online Operations in NDB Cluster”, for more information.)。


13.1.16 创建过程和创建函数的语法

原文
在这里插入图片描述
这些语句被用来创建存储例程(stored routines)。默认情况下,例程与当前数据库关联,为了与指定的数据库进行关联,你可以使用db_name.sp_name来给它起个名字。
CREATE FUNCTION还被用来支持用户自定义函数(UDF),UDF算是一种扩展的存储函数,存储函数与UDF共享其命名空间。
要调用存储过程,请使用CALL语句(章节13.2.1 CALL语法);要调用存储函数,请在表达式中引用它。函数在表达式求值完毕返回一个值。


译者实例:
(1)定义一个存储过程

delimiter /
create definer=current_user procedure 
test_sp(in p1 int,out version_p varchar(25),inout total int) 
comment 'test-sp' 
language sql 
not deterministic 
READS SQL DATA
sql security definer
begin
	select version() into version_p;
    select count(*) from t_data into total;
    select count(*) from t_data where id>p1;
end/
delimiter ;

(2)调用一个存储过程

mysql> select count(*) from t_data;
		-> 5051639
mysql> call test_sp(@p1,@version,@total);
mysql> select @p1,@version,@total;
+---------+----------+---------+
| @p1     | @version | @total  |
+---------+----------+---------+
| 4000000 | 8.0.13   | 5051639 |
+---------+----------+---------+		

1.可用部分
(1)DEFINER 和 SQL SECURITY部分指定了一个安全的上下文(此上下文用来检查例程执行时的权限)
(2)IN OUT INOUT这三个选项用在创建一个过程中,代表参数的性质。IN表示传递给过程的参数,OUT代表从过程中返回的参数(被初始化为NULL),INOUT表示参数可以由调用者和过程共同修改,调用者做初始值,过程可以修改参数值并返回给调用者。
  对于每个OUTINOUT参数,你可以通过CALL在调用过程中传递参数并获取结果;如果从其他的存储过程或函数中调用一个过程,也可以将常规的参数或局部常规变量作为OUT 或INOUT参数进行传递;如果你在触发器中调用一个过程,可以使用NEW.col_name作为一个INOUT参数。
(3)RETURNS部分是创建函数才能用的,而且是必须有的一部分。它指定了函数返回的类型,函数体必须 包含RETURN xxx语句 如果RETURN部分返回的类型和RETURNS不一样,它会被强制转化为适合的类型。比如,RETURNS中返回一个枚举或集合的值,RETURN返回了一个整数,强制转换后是一个枚举或集合成员的值对应的字符串。下面是一个创建函数的例子:
在这里插入图片描述
(3)routine_body部分包含了一个SQL例程语句,可以是简单的SELECT语句,也可以是大量复合的语句,多条语句可以用 BEGIN ...END包裹 ,复合语句请见章节 13.6
(4)COMMENT部分是MySQL扩展,是一个用于描述存储例程的说明,可以通过 SHOW CREATE PROCEDURE nameSHOW CREATE FUNCTION name来查看。
(5)LANGUAGE特性表示例程是用什么程序语言编写的。服务器忽略了这个特性,仅支持SQL语言的例程。
(6)一个例程如果输入相同参数总能获得相同结果,那他就是确定性的 DETERMINISTIC,否则就是不确定性的 NOT DETERMINISTIC,默认的参数就是 NOT DETERMINISTIC,你可以显示地指定 DETERMINISTIC。
(7){ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } 这几个特征提供了关于例程使用数据的性质的信息,在msyql中这些特征只供参考不会被用来约束和影响一个例程的各种操作。

  • CONTAINS SQL 表明例程语句不包含数据的读写操作,这个是默认值
  • NO SQL 表示该例程不包含SQL语句。
  • READS SQL DATA表示例程包含读取数据的语句(例如 SELECT),但不包含写入数据的语句。
  • MODIFIES SQL DATA表示该例程包含可能写入数据的语句(例如, INSERT或 DELETE)。

(8)SQL SECURITY选项可以是 DEFINERINVOKER以指定的安全上下文; 也就是说,例程是使用DEFINER子句中指定的帐户的权限执行,还是使用调用它的用户权限执行。此帐户必须具有访问与例程关联的数据库的权限。默认值为 DEFINER(也就是SQL SECURITY DEFINER)。调用例程的用户必须具有该EXECUTE特权,如果例程想在DEFINER环境下运行,当前用户需要是DEFINER指定的用户。
(9) DEFINER部分用来指定例程执行的用户并检查权限,此例程可能需要在后面有SQL SECURITY DEFINER这一部分,如果指定DEFINER子句,则这些规则可以用来确定有效的DEFINER用户值:

  • 如果您没有SUPER 权限,则唯一允许的user 值是您自己的帐户,无论是字面指定还是使用CURRENT_USER。您无法将定义者设置为其他帐户。
  • 如果您具有SUPER 权限,则可以指定任何语法上有效的帐户名称。如果该帐户不存在,则会生成警告。
  • 尽管可以使用不存在的帐户创建例程, 但如果SQL SECURITY值为 DEFINER但定义者帐户不存在,则会在例程执行时发生错误。

下面是一个例子,让我们来理解一下DIFINERSQL SECURITY XXX的性质
在这里插入图片描述
a.无论哪个用户定义了该过程,都会为该过程分配DEFINER为用户 admin@localhost
b.无论哪个用户调用该过程,它都以该帐户admin@localhost的权限执行(因为默认的安全特性是DEFINER,这里的意思是在BEGIN前面默认有个选项SQL SECURITY DIFINER 也就是第(8)条里面讲的)
c.该过程成功或失败取决于调用者是否具有EXECUTE权限并且admin用户具有mysql.user表的SELECT权限。

让我们再看一个例子:
在这里插入图片描述
相较前一个例子,这里多了一个SQL SECURITY INVOKER语句,
a.无论哪个用户定义了该过程,都会为该过程分配DEFINER为用户 admin@localhost
b.无论哪个用户调用它,它都以调用者的权限执行例程
c.该过程成功或失败取决于调用者是否具有EXECUTE权限并且具有mysql.user表的SELECT权限。
(10)服务器处理例程参数的数据类型并检查,或使用DECLARE定义的本地例程变量 ,或者函数的返回值如下所示:

  • 检查分配数据类型不匹配和溢出。转换和溢出问题会导致警告或严格SQL模式中的错误
  • 只能分配标量值?。例如SET x = (SELECT 1, 2)是无效的
  • 对于字符数据类型,如果CHARACTER SET声明中有属性,则使用指定的字符集及其默认排序规则。如果该 COLLATE属性也存在,则使用该排序规则而不是默认排序规则。

如果CHARACTER SETCOLLATE这两个字符集都没有指定,例程创建的时候指定的数据库的对应字符集会被使用,如果你想修改例程中的这两个字符集,你可以使用。

2.注意事项
(1)CREATE PROCEDURECREATE FUNCTION 这两个方法需要CREATE ROUTINE权限,可能还需要SUPERSET_USER_ID权限,具体取决于DEFINER值。如果启用了二进制日志记录,CREATE FUNCTION还需要SUPER 权限。
(2)默认情况下,MySQL会自动把权限 ALTER ROUTINEEXECUTE赋予创建例程的用户,可以通过禁用automatic_sp_privileges系统变量来更改此行为
(3)如果例程名称与内置SQL函数的名称相同,则会发生语法错误,除非你在定义或执行例程的时候在例程名字和括号之间多加个空格。所以避免使用内置SQL函数名或已有的你自己的存储例程名字。
(4)sql_mode变量有一个选项IGNORE_SPACE(忽略函数名和括号之间的空格),这个选项只对MySQL内置函数有效,对存储例程无效(无论选项是否开启,都允许例程名和括号之间有空格)。
(5)括号内的是参数列表,参数大小写不敏感,空参数列表可以这么表示()。当你创建一个过程时,列表中参数默认都是IN类型,可以在参数前指定OUTINOUT这两种选项;当你创建一个函数时,列表中参数只能IN类型,无法指定另两种选项。
(6)在例程中准备的语句中不能引用例程参数,详情见附录C.1存储程序的限制
在这里插入图片描述
上面的例子是个简单的存储过程,使用了OUT类型的参数res,你可以用select * from mysql.proc where name='myp_add5'来查看这个存储过程。
(7)mysql的 sql_mode变量会影响例程的创建、修改和执行
(8)返回结果集的语句可以在存储过程中使用,但不能在存储的函数中使用。这些情况是禁止的 select语句没有添加 into var_list选项、 SHOW, EXPLAINCHECK TABLE等。
如果函数定义时就能检测到这种禁止情况,会返回一个错误(ER_SP_NO_RETSET)
如果函数运行时才能检测到这种禁止情况,会返回一个错误哦(ER_SP_BADSELECT)
(9)存储例程中使用USE语句不允许,因为你执行一个例程的时候,隐式的调用了USE db_name这条指令(并在例程终止时撤消),这个db_name在你创建的时候已经指定好了。如果在引用了非例程所使用的数据库之外的数据库对象,应该指定准确的那个数据库名。
(10)从调用者的SQL mode切换到例程的SQL mode 发生在 参数计算完毕并且作为结果分配给例程参数 之后。如果你的例程创建在strict模式(STRICT_TRANS_TABLES)下,执行却在nostrict模式下,那么给例程参数分配结果参数的过程就不会发生。如果想在strict模式下分配传递给例程一些表达式,则应调用具有strict模式的例程。
(11)MySQL不会检查确定性是否正确。如果你的例程是不确定的,但是你指定了DETERMINISTIC参数,可能会影响结果和表现,可能会导致Mysql的优化器执行错误的计划;如果你的例程是确定的,但是你指定了NOT DETERMINISTIC参数可能会导致优化器不能用而降低了性能。
(12)如果启用了二进制日志记录,则该DETERMINISTIC 特性会影响MySQL是否接受该例程的定义。详情见章节23.7存储程序的二进制日志记录
(13)一个例程可以包含now()函数或同名函数或rand()函数,它仍然是复制安全( replication-safe)的?对于 NOW()函数,二进制日志包括时间戳并可以正确复制。 RAND()函数只在执行例程期间只调用一次,也可以正确复制。(可以将例程执行的时间戳和随机数种子视为隐式的输入IN参数)
(14)如果更改数据库缺省字符集或排序规则,则必须删除并重新创建使用数据库缺省值的存储例程,以便它们使用新的缺省值

Mysql允许例程 包含DDL(数据定义语言)语句,比如CREATE和DROP,还允许存储过程(不包含存储函数) 使用SQL事物语句比如COMMIT.存储函数不能含有任何包含提交或回滚语句,SQL标准不要求支持这些语句,该标准规定每个DBMS供应商可以决定是否允许它们。


13.1.18 创建SERVER语法

原文
在这里插入图片描述
  此语句使用 FEDERATED存储引擎来创建一个连接到远程数据服务器的连接服务 。CREATE SERVER语句将会在mysql.servers表中创建一个新行 。此语句需要 SUPER特权。

  server_name 是服务的名字(唯一)。服务的定义在服务器范围内是全局的,无法将服务的定义指定为特定数据库(翻译的蹩脚,原文Server definitions are global within the scope of the server, it is not possible to qualify the server definition to a specific database)。 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
例如:
在这里插入图片描述
  请务必指定与服务器建立连接所需的所有选项。用户名,主机名和数据库名是必需的;也可能需要其他选项,例如密码。
  远程服务器上的表可以通过创建好的FEDERATED表来进行连接访问。

有关更多信息,请参见 第15.8节“FEDERATED存储引擎”。
CREATE SERVER 导致隐式提交。请参见 第13.3.3节“导致隐式提交的语句”。
无论正在使用的日志记录格式如何,CREATE SERVER操作都不会写入二进制日志。


13.1.20 创建表的语法

原文
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

CREATE TABLE使用你给的名称创建一个表。您必须拥有CREATE权限。
CREATE TABLE 创建表时,MySQL将存储原始建表语句,包括所有细则和表的选项。有关更多信息,请参见第13.1.20.1节“CREATE TABLE语句保留”。

默认情况下,在当前数据库中创建表,使用InnoDB存储引擎 。如果表已经存在,或者当前没use数据库,或者数据库不存在,则会发生错误。
有关表的物理表示的信息,请参见 第13.1.20.2节“由建表创建的文件”。

下面将从如下主题针对 CREATE TABLE 进行阐述:

1.表名

tbl_name

使用这种形式db_name.tbl_name用以在指定的数据库中创建表。如果数据库存在,无论是否use数据库,都能创建成功。如果使用带引号的标识符,请分别引用数据库和表名。例如:

正确示范: `mydb`.`mytbl`       错误示范: `mydb.mytbl`。

第9.2节 给出了允许的表命名的规则 。

IF NOT EXISTS
如果表已经存在,则防止发生错误。但是,没有验证现有表的结构与CREATE TABLE语句指示的结构是否相同,仅仅看表名 。

2.临时表
  您可以在创建表时使用TEMPORARY关键字。TEMPORARY表只在当前会话中可见,而当会话关闭时自动删除。有关更多信息,请参见 第13.1.20.3节“创建临时表的语法”。

3. 克隆或复制表

LIKE
CREATE TABLE ... LIKE根据另一个表的定义创建一个空表,包括原始表中定义的任何列属性和索引,例如:
CREATE TABLE new_tbl LIKE orig_tbl;
有关更多信息,请参见第13.1.20.4节“CREATE TABLE … LIKE语法”。

[AS] query_expression
要从另一个表创建一个表,请在 CREATE TABLE语句末尾添加一个SELECT语句:
CREATE TABLE new_tbl AS SELECT * FROM orig_tbl;
有关更多信息,请参见 第13.1.20.5节“CREATE TABLE … SELECT语法”。

IGNORE|REPLACE
IGNORE/REPLACE 选项告诉服务器,在使用SELECT复制表时 如何处理使用唯一键却出现重复的行 。
有关更多信息,请参见 第13.1.20.5节“CREATE TABLE … SELECT语法”。

4.列数据类型和属性
理论上,每个表的列数限制为4096,但给定表的有效最大值可能会很小,其取决于第C.10.4节“表的列数和行大小限制”中给出的因素。

data_type
data_type表示列的数据类型。有关可用于指定列数据类型的语法的完整说明,以及有关每种类型的属性的信息,请参见 第11章 数据类型。

  • 某些属性不适用于所有数据类型。 AUTO_INCREMENT 仅适用于整数和浮点类型。在MySQL 8.0.13之前,DEFAULT并不适用于BLOB, TEXT, GEOMETRY,JSON类型。

  • 字符数据类型(CHAR, VARCHAR, TEXT)可以包括 CHARACTER SETCOLLATE属性来指定该列的字符集和排序规则。有关详细信息,请参见第10章,字符集,排序规则,Unicode。CHARSETCHARACTER SET的同义词。例:
    CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);
    MySQL 5.7后 以字符为单位解释字符列定义中的长度。BINARY和 VARBINARY列的长度以字节为 单位。

  • 对于CHAR, VARCHAR, BINARY,VARBINARY列,索引可以使用列值的前缀部分创建,使用col_name(length) 语法来指定一个索引前缀长度。 BLOBTEXT列也可以被索引,而且必须给出前缀长度。对于非二进制字符串类型(CHAR,VARCHAR,TEXT),前缀长度以字符给出,对于二进制字符串类型(BLOB,BINARY,VARBINARY)以字节为单位给出。请参见第13.1.14节“CREATE INDEX语法”

  • JSON列无法被索引。为了解决此限制,创建一个索引列,该列从JSON列中提取标量值。有关详细示例,请参阅 索引生成的列以提供JSON列索引。

只有InnoDB和 MyISAM存储引擎支持索引BLOBTEXT列。例如:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
从MySQL 5.7.17开始,如果指定的索引前缀长度超过指定的列数据类型的最大长度,则CREATE INDEX按如下方式处理索引:
  (1) 对于非唯一索引,要么发生错误(如果启用了严格的SQL模式),要么索引长度减少到最大列数据类型大小,并产生警告(如果未启用严格SQL模式)
  (2) 对于唯一索引,无论SQL模式如何都会发生错误,因为减少索引长度可能会导致插入的数据不唯一。

NOT NULL | NULL
如果既未指定NULL也未指定NOT NULL,则将列视为指定NULL
在MySQL 5.7后,只有InnoDB, MyISAM以及MEMORY 存储引擎支持索引的列有NULL值 。在其他情况下,您必须将索引的列声明为NOT NULL,否则产生错误结果。

DEFAULT
指定列的默认值。有关默认值处理的更多信息,包括列定义不包含显式DEFAULT 值的情况,请参见 第11.7节“数据类型默认值”。
如果启用了NO_ZERO_DATENO_ZERO_IN_DATE SQL模式,并且在该模式下的你提供的默认值日期值不正确,CREATE TABLE 在未启用严格SQL模式时生成警告,如果启用严格模式则生成错误。例如, NO_ZERO_IN_DATE启用后 c1 DATE DEFAULT '2010-00-00'会生成警告。

AUTO_INCREMENT
整数或浮点列可以具有附加属性AUTO_INCREMENT。当您插入值NULL(推荐)或 0 在一个 AUTO_INCREMENT索引列时,该列将设置为下一个序列值。通常是 value+1,这里 value是目前在表中的列的最大值。AUTO_INCREMENT序列以1开始。

在插入行后检索AUTO_INCREMENT值,请使用SQL函数 LAST_INSERT_ID()或C语言API函数mysql_insert_id()。请参见第12.14节“信息函数”和 第27.7.7.38节“mysql_insert_id()”。

如果启用了NO_AUTO_VALUE_ON_ZERO SQL模式, AUTO_INCREMENT列可以存储0, 而不会产生一个新的序列值(?拗口,原文you can store 0 in AUTO_INCREMENT columns as 0 without generating a new sequence value。请参见第5.1.11节“服务器的SQL模式”。

每个表 只能有一个AUTO_INCREMENT列,此列必须创建索引,并且不能有 DEFAULT值。只有AUTO_INCREMENT列包含正数才会正常工作。插入负数被视为插入一个非常大的正数。这样做是为了避免数字从正到负“ 计算 ”时产生的精度问题, 并确保您不会意外地获得包含0的AUTO_INCREMENT列。

对于MyISAM表,如果有多列组成一个键 ,您可以指定一个AUTO_INCREMENT辅助列。请参见 第3.6.9节“使用AUTO_INCREMENT”。

要使MySQL与某些ODBC应用程序兼容,您可以使用以下查询找到最后插入行的AUTO_INCREMENT值:
SELECT * FROM tbl_name WHERE auto_col IS NULL;
此方法要求 sql_auto_is_null变量未设置为0. 请参见 第5.1.8节“服务器系统变量”。

有关信息InnoDB和 AUTO_INCREMENT请参见 第15.6.1.5,“InnoDBc护理AUTO_INCREMENT”。有关AUTO_INCREMENTMySQL Replication的信息,请参见 第17.4.1.1节“复制和AUTO_INCREMENT”。

COMMENT
可以使用COMMENT选项指定列的注释 ,最多1024个字符。注释由SHOW CREATE TABLESHOW FULL COLUMNS语句可以显示。

COLUMN_FORMAT
在NDB Cluster中,NDB表可以为单独的列使用 COLUMN_FORMAT 指定数据存储格式 。允许的存储格式有FIXEDDYNAMIC以及DEFAULTFIXED用于指定固定宽度存储,DYNAMIC可变宽度存储,DEFAULT宽度是否固定取决于列的数据类型,(可能由ROW_FORMAT说明符覆盖 )。
从MySQL NDB Cluster 7.5.4开始,对于 NDB表,COLUMN_FORMAT 的默认值为FIXED。( 在MySQL NDB Cluster 7.5.1默认情况下为DYNAMIC,,但此更改已恢复为与现有GA版本系列保持向后兼容。)(错误#24487363)
COLUMN_FORMAT目前对使用除以NDB外的存储引擎的表列没有影响 。在MySQL 5.7及更高版本中,COLUMN_FORMAT默认被忽略。

STORAGE
对于NDB表,可以使用STORAGE子句指定列是存储在磁盘上还是存储在内存中。STORAGE DISK使得该列存储在磁盘上,而STORAGE MEMORY使用内存存储。如果使用了此选项,那么你在CREATE TABLE 的时候必须还要包括一个TABLESPACE参数:
在这里插入图片描述
对于NDB表,STORAGE DEFAULT相当于STORAGE MEMORY
STORAGE选项对使用除以NDB外的存储引擎的表没有影响 。STORAGE 仅在与 NDB Cluster一起提供的mysqld的程序中支持该 关键字; 在任何其他版本的MySQL中都无法识别,任何使用该STORAGE关键字的尝试都会导致语法错误。

GENERATED ALWAYS
用于指定生成的列表达式。有关生成的列的信息,请参见 第13.1.20.8节“创建表和生成的列”。
存储生成的列可以被创建索引。InnoDB 支持虚拟生成列上的二级索引 。请参见 第13.1.20.9节“二级索引和生成的列”。

5.索引和外键
有几个关键字适用于创建索引和外键。除了以下描述之外,你最好看下背景知识,请参见第13.1.15节“创建索引语法”和 第13.1.20.6节“使用FOREIGN KEY约束”。

CONSTRAINT symbol

如果给出了该子句,则该值symbol(如果使用在数据库中) 必须是唯一的。重复出现导致错误。如果未使用CONSTRAIN,或者使用了CONSTRAIN关键字但后面不包含symbol,则会自动创建约束的名称。

PRIMARY KEY

唯一索引而且索引所依附的列必须包含 NOT NULL属性。如果没有明确声明为NOT NULL,MySQL会悄悄地声明它。一张表只能有一个 PRIMARY KEYPRIMARY KEY经常写作 PRIMARY,因此不能用作任何其他类型索引的起名。

如果你没有PRIMARY KEY而应用程序要用你表中的PRIMARY KEY,MySQL会返回第一个NOT NULL且是唯一索引的列作为 PRIMARY KEY

在InnoDB表中,让PRIMARY KEY 尽可能短以尽量减少二级索引的存储开销。每个二级索引条目都包含相应行的主键列的副本。(参见 第15.6.2.1节“聚类和二级索引”。)

在创建的表中,PRIMARY KEY在 所有 UNIQUE 索引的前面声明,然后放置余下的非唯一索引。这有助于MySQL优化器确定要使用哪个索引的优先级,并且还可以更快地检测重复的UNIQUE键。

PRIMARY KEY可以是多列索引。但是,您无法为多列索引使用PRIMARY KEY属性指定为一列。这样做只会将单列标记为主键列。您必须使用分开的形式:PRIMARY KEY(key_part, ...)

如果表有PRIMARY KEYUNIQUE NOT NULL索引,而且该列由具有整数类型组成,则可以使用 _rowid来引用SELECT语句中的索引列 ,具体请见 b.唯一索引中所述。

在MySQL中,PRIMARY KEYPRIMARY是同义词。对于其他索引,如果不指定一个名称,该指索引被分配与第一个索引列相同的名称,有一个可选的后缀(_2,_3, …),以使其唯一。您可以使用SHOW INDEX FROM tbl_name来查看表的索引详情 。请参见 第13.7.6.22节“显示索引语法”。

KEY | INDEX
KEY通常是INDEX的同义词 。在创建一列的时候,可以用PRIMARY KEY也可以用KEY来指定索引,这是为了与其他数据库系统兼容而实现的。

UNIQUE
b.唯一索引中所述。

FULLTEXT
c.全文索引中所述。

SPATIAL
d.空间索引中所述。

FOREIGN KEY
MySQL支持外键,它允许您跨表交叉引用相关数据,以及外键约束,这有助于保持这种扩展数据的一致性。有关定义和选项信息,请参阅后面的 reference_definitionreference_option
使用InnoDB存储引擎的创建的 分区表 不支持外键。有关更多信息,请参见 第22.6节“分区的限制和限制”。

CHECK
CHECK部分被解析但被所有存储引擎忽略。请参见 第1.8.2.3节“外键差异”。

key_part
a.列前缀中所述。

index_type
某些存储引擎允许您在创建索引时指定索引类型。index_type的使用方法是 USING type_name,例:
在这里插入图片描述
最好的USING xx位置应该列参数类型定义的最后(右括号之前)。它也可以在列类型后面给出,但不推荐在该位置使用该选项,并且将在未来的MySQL版本中删除此位置放置索引类型。

index_option
index_option values指定索引的其他选项。

  • KEY_BLOCK_SIZE
    e.索引的参数 中所述,有关表级 KEY_BLOCK_SIZE属性的信息,请参阅 后面的 表选项。

  • WITH PARSER
    WITH PARSER部分只能用于FULLTEXT索引,如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引相关联。InnoDB和MyISAM支持全文解析器插件。详情见e.索引的参数 note 1。如果您的 MyISAM表具有关联的全文解析器插件,则可以使用ALTER TABLE将表转换为InnoDB表。

  • COMMENT
    请参见 e.索引的参数 note 1。有关索引的更多信息,请参见第8.3.1节“MySQL如何使用索引”。

reference_definition
有关reference_definition语法详细信息和示例,请参见 第13.1.120.6节“使用FOREIGN KEY约束”。有关InnoDB外键的特定信息,请参见 第15.6.1.6节“InnoDB和FOREIGN KEY约束”。

InnoDB和 NDB表支持 检查外键约束。必须始终显式命名引用表的列。在外键上的ON DELETEON UPDATE操作是可以的。

对于其它存储引擎(除InnoDB和NDB),MySQL服务器解析而忽略CREATE TABLE语句中的 FOREIGN KEYREFERENCES部分。请参见 第1.8.2.3节“外键差异”。

注意事项
对于熟悉ANSI / ISO SQL标准的用户,请注意包括 InnoDB在内,没有存储引擎识别或强制执行MATCH的参照完整性约束定义。使用MATCH子句不会产生指定的效果,也会忽略后面的 ON DELETEON UPDATE子句部分。出于这些原因,MATCH不应该指定。

SQL标准中的MATCH 控制 NULL在与主键进行比较时如何处理复合(多列)外键中的值。InnoDB本质上实现了定义的语义MATCH SIMPLE,允许外键全部或部分NULL。在这种情况下,允许插入包含此类外键的(子表)行,并且该行与引用的(父)表中的任何行都不匹配。可以使用触发器实现其他语义(整段都不对,原文The MATCH clause in the SQL standard controls how NULL values in a composite (multiple-column) foreign key are handled when comparing to a primary key. InnoDB essentially implements the semantics defined by MATCH SIMPLE, which permit a foreign key to be all or partially NULL. In that case, the (child table) row containing such a foreign key is permitted to be inserted, and does not match any row in the referenced (parent) table. It is possible to implement other semantics using triggers.)。

此外,MySQL要求为引用的列创建索引以提高性能。但是,InnoDB 不强制要求声明引用的列为 UNIQUE或 NOT NULL。外键引用了非唯一键
对包含NULL 值的非唯一键或键的外键引用的处理没有为诸如UPDATE或之类的操作定义 DELETE CASCADE(这一句的原文The handling of foreign key references to nonunique keys or keys that contain NULL values is not well defined for operations such as UPDATE or DELETE CASCADE)。建议您使用外键引用的列 同时指定UNIQUE (或PRIMARY)和NOT NULL的属性。

MySQL解析但忽略了“ 内联 REFERENCES规范 ”(在SQL标准中定义),其中引用被定义为列规范的一部分。MySQL使用 REFERENCES部分的条件是 它作为多列组成的FOREIGN KEY 的一部分(原文MySQL accepts REFERENCES clauses only when specified as part of a separate FOREIGN KEY specification.)。

reference_option
有关信息RESTRICT, CASCADE,SET NULL, NO ACTION,SET DEFAULT选项,请参阅 第13.1.20.6,“使用外键约束”。

6.表选项
表选项用于优化表的行为。在大多数情况下,不必指定其中任何一个。除非另有说明,否则这些选项适用于所有存储引擎。这些选项作为表定义的一部分被接受并记住。如果您稍后使用ALTER TABLE让表使用其他存储引擎,此选项可以发挥作用。

ENGINE
使用下表中显示的名称之一为表指定使用的存储引擎。引擎名称用不用引号无所谓。名称'DEFAULT'可以被识别但忽略其作用。

存储引擎描述
InnoDB具有行锁定和外键的事务安全的表。新建表的默认存储引擎就是InnoDB。如果您有MySQL经验但是不熟悉InnoDB,请参见 第15章,InnoDB存储引擎,特别是 第15.1节“InnoDB简介”。
MyISAM二进制便携式存储引擎,主要用于只读或读取占大头的用途。请参见 第16.2节“MyISAM存储引擎”。
MEMORY此存储引擎的数据仅存储在内存中。请参见 第16.3节“MEMORY存储引擎”。
CSV以逗号分隔值格式存储行的表。请参见 第16.4节“CSV存储引擎”。
ARCHIVE归档存储引擎。请参见 第16.5节“ARCHIVE存储引擎”。
EXAMPLE一个示例引擎。请参见第16.9节“示例存储引擎”。
FEDERATED访问远程表的存储引擎。请参见 第16.8节“FEDERATED存储引擎”。
HEAP这是MEMORY同义词。
MERGE将多个MyISAM表用作一个表的集合。也称为MRG_MyISAM。请参见 第16.7节“MERGE存储引擎”。
NDB集群,容错,基于内存的表,支持事务和外键。也称为 NDBCLUSTER。请参见 第22章,MySQL NDB Cluster 8.0。

默认情况下,如果指定的存储引擎不可用,则该语句将失败并显示错误。您可以通过从SQL模式中删除NO_ENGINE_SUBSTITUTION选项来改变此行为 (请参见第5.1.11节“服务器SQL模式”),以便MySQL允许使用默认存储引擎替换指定的引擎。通常在这种情况下,系统变量default_storage_engine的默认值是InnoDB。当 NO_ENGINE_SUBSTITUTION被禁用,如果指定的存储引擎不可用会出现警告。

AUTO_INCREMENT
表中自增键的初始值。在MySQL 5.7后,这个选项在 MyISAM,MEMORY, InnoDB,ARCHIVE 表中有效。要为不支持AUTO_INCREMENT选项的引擎设置第一个自动增量值,请在创建表后插入一个值小于所需值的“ 虚拟 ”行,然后删除虚拟行。

对于支持在 CREATE TABLE语句中使用AUTO_INCREMENT 表选项的引擎,您还可以使用ALTER TABLE tbl_name AUTO_INCREMENT = N 重置此值。该值不能设置为低于当前列中的最大值。

AVG_ROW_LENGTH
表的平均行长度的近似值。您应该只为具有可变大小的行的大表设置此项。

当您创建MyISAM表时,MySQL使用MAX_ROWSAVG_ROW_LENGTH选项的乘积来确定结果表的大小。如果未指定任一选项,则MyISAM默认情况下数据和索引文件的最大大小为256 TB。(如果您的操作系统不支持较大的文件,则表大小受文件大小限制的约束。)如果您想保持指针大小以使索引更小更快而且您不需要大文件,那么可以通过设置myisam_data_pointer_size 系统变量来减少默认指针大小 。(请参见 第5.1.8节“服务器系统变量”。)如果您希望所有表都能够超过默认限制并且愿意让您的表稍微慢一些并且大于必要的值,则可以通过设置此变量来增加默认指针的大小。将值设置为7允许表的大小高达65,536TB。

[DEFAULT] CHARACTER SET
指定表的默认字符集。 CHARSETCHARACTER SET的同义词。如果字符集名称是 DEFAULT,则使用数据库的字符集。

CHECKSUM
如果希望MySQL为所有行维护实时校验值(即,当表更改时MySQL自动更新这个校验值),请将此值设置为1。这使得表更新速度稍慢,但也更容易找到损坏的表。CHECKSUM TABLE语句用来查看校验值(仅限MyISAM)。

[DEFAULT] COLLATE
指定表的默认排序规则。

COMMENT
表的注释,最多2048个字符。
您可以为使用了table_option COMMENT子句表,设置InnoDB MERGE_THRESHOLD的值。请参见 第15.8.11节“为索引页配置合并阈值”。

Setting NDB_TABLE options.
在MySQL NDB Cluster 7.5.2或更高版本,在CREATE TABLEALTER TABLE语句中COMMENT部分还可以指定一到四个 NDB_TABLE选项 NOLOGGING, READ_BACKUP, PARTITION_BALANCE, FULLY_REPLICATED,选项为键值对的组成形式,如果需要指定多个选项用逗号隔开,并且跟在注释的字符串后面的NDB_TABLE=之后。下面是使用此语法的示例语句):
在这里插入图片描述
注释的字符串中不允许使用空格,该字符串不区分大小写。
使用SHOW CREATE TABLE name可以查看注释。注释的文本也可以在Information Schema.TABLES表的TABLE_COMMENT列 。

select `table_comment` from information_schema.`TABLES` where information_schema.`TABLES`.TABLE_NAME='xxx';

NDB表的ALTER TABLE语句 也支持这种注释语法 。请记住,使用ALTER TABLE语句创建表的注释将会替之前有的注释。
NDB表不支持在表注释中 设置MERGE_THRESHOLD选项 (忽略它)。
有关完整的语法信息和示例,请参见 第13.1.20.10节“设置NDB_TABLE选项”。

COMPRESSION
用于InnoDB表的页级压缩的压缩算法 。支持的值包括 Zlib,LZ4,和 None。COMPRESSION 属性是通过透明页面压缩功能引入的。页面压缩仅支持 InnoDB驻留在 file-per-table表空间,并且仅在支持稀疏文件和打孔(support sparse files and hole punching)的Linux和Windows平台上可用。有关更多信息,请参见 第15.9.2节“InnoDB页面压缩”。

CONNECTION
FEDERATED 表 的连接字符串。
注意,旧版本的MySQL使用COMMENT 设置连接字符串。

DATA DIRECTORY, INDEX DIRECTORY

对于InnoDB表,DATA DIRECTORY='directory' 子句允许在数据目录之外创建一个 file-per-table 表空间。表空间数据文件在指定目录中创建,该目录位于与数据库同名的子目录中。 为了使用DATA DIRECTORY,必须启用该变量innodb_file_per_table才能使用该子句。必须指定完整目录路径。有关更多信息,请参见 第15.6.3.6 节“在数据目录外创建表空间”。

创建MyISAM表时,可以使用 DATA DIRECTORY='directory'或者INDEX DIRECTORY='directory' 。它们分别指定放置 MyISAM 表的数据文件和索引文件的位置。与InnoDB表不同,MySQL在使用前两个指令时不会创建与数据库名对应的子目录。文件在指定的分开的目录中创建。

从MySQL 5.7.17开始,使用 DATA DIRECTORYINDEX DIRECTORY选项必须有FILE权限。

重要
分区表将忽略 DATA DIRECTORYINDEX DIRECTORY选项。(Bug#32091)

这些选项仅在您不使用 --skip-symbolic-links 选项时有效。您的操作系统还必须具有可正常工作的线程安全的 realpath() 调用。有关更完整的信息,请参见 第8.12.2.2节“在Unix上使用MyISAM表的符号链接”。

如果MyISAM创建的表没有DATA DIRECTORY选项,则会在对应数据库目录中创建xx.MYD 文件。默认情况下,如果MyISAM找到已经有xx.MYD文件,则会覆盖它。这同样适用于没有使用INDEX DIRECTORY选项创建的表的xx.MYI 文件。要禁止此行为,请使用--keep_files_on_create选项启动服务器 ,在这种情况下,MyISAM不会覆盖现有文件并返回错误。

如果MyISAM使用DATA DIRECTORYINDEX DIRECTORY选项创建表 并且找到现有 .MYD或.MYI文件,则MyISAM始终返回错误。它不会覆盖指定目录中的文件。

重要
在使用DATA DIRECTORYINDEX DIRECTORY的时候,路径里不能包含MySQL数据目录的路径名。包括分区表和单独的表分区。(参见Bug#32167。)

DELAY_KEY_WRITE
如果要延迟表的索引更新,直到关闭表,请将此值设置为1。见系统变量 delay_key_write的描,第5.1.8节,“服务器系统变量”。(仅限MyISAM。)

ENCRYPTION
为了让一个InnoDB表(有file-per-table表空间)启用页级数据加密,可以将ENCRYPTION选项 设置'Y'。选项值不区分大小写。ENCRYPTION选项随InnoDB表空间加密功能一起介绍 , 请参见第15.6.3.9节“InnoDB表空间加密”。为使用ENCRYPTION选项,keyring插件必须安装并配置。

INSERT_METHOD
如果要将数据插入MERGE 表中,则必须指定INSERT_METHOD应插入表中的哪行。 INSERT_METHOD是一个仅对MERGE表有用的选项 。使用值FIRSTLAST将 插入第一个或最后一个表,或使用值NO来防止插入。请参见 第16.7节“MERGE存储引擎”。

KEY_BLOCK_SIZE
对于MyISAM表,KEY_BLOCK_SIZE 可以选择指定用于索引key的块的大小(以字节为单位)。该值被视为提示(原文The value is treated as a hint); 如有必要,可以使用不同的大小。为单个索引指定的KEY_BLOCK_SIZE值将影响整张表的 KEY_BLOCK_SIZE值。

对于InnoDB表, KEY_BLOCK_SIZE指定用于压缩表的 页面大小(以KB为单位)。该 值被视为提示; 如有必要,可以使用不同的大小。只能小于或等于innodb_page_size变量的值。值0表示默认的压缩页面大小,它是innodb_page_size值的一半 。根据innodb_page_size值的具体情况 ,可能的 选项包括包括0,1,2,4,8和16.有关更多信息,请参见 第15.9.1节“InnoDB表压缩”。

为 InnoDB表指定时KEY_BLOCK_SIZE时,Oracle建议开启innodb_strict_mode变量。当 innodb_strict_mode被启用,指定一个无效的 KEY_BLOCK_SIZE值返回一个错误。如果 innodb_strict_mode禁用,则无效的KEY_BLOCK_SIZE值将导致警告,并KEY_BLOCK_SIZE 选项被忽略。

使用命令SHOW TABLE STATUSSHOW CREATE TABLE返回的结果列Create_options用于记录 最初指定的KEY_BLOCK_SIZE选项。

InnoDB只支持表级的KEY_BLOCK_SIZE

KEY_BLOCK_SIZE不支持innodb_page_size使用32KB和64KB 值(KEY_BLOCK_SIZE is not supported with 32KB and 64KB innodb_page_size values)。InnoDB表的压缩不支持这些页面大小。

MAX_ROWS
您计划在表中存储的最大行数。这不是硬限制而是告诉存储引擎,这个表必须能够存储至少这么多行。
重要
从NDB Cluster 7.5.4开始,NDB表使用MAX_ROW来控制表分区的数量 已经废弃。它在以后的版本中仍然受支持以实现向后兼容性,但在将来的版本中可能会被删除。请改用PARTITION_BALANCE; 请参阅上面的 Setting NDB_TABLE options标题。

NDB存储引擎将这个值作为最大。如果您打算创建非常大的NDB Cluster表(含数百万行),你应该使用这个选项 MAX_ROWS = 2 * row,以确保NDB在哈希表(用于存储表主键的哈希)中分配足够的索引槽数(原文 you should use this option to insure that NDB allocates sufficient number of index slots in the hash table used for storing hashes of the table's primary keys by setting MAX_ROWS = 2 * rows),这里 row是您希望插入表中的行数。

MAX_ROWS最大值为4294967295; 更大的值被截断为此值。

MIN_ROWS
您计划在表中存储的最小行数。MEMORY存储引擎使用它作为内存使用的提示。

PACK_KEYS
仅对MyISAM表有效。如果要使用较小的索引,请将此选项设置为1。这通常会使更新变慢并且读取速度更快。将该选项设置为0将禁用所有关键字压缩。将其设置为 DEFAULT告诉存储引擎只压缩长的CHAR, VARCHAR, BINARY,或 VARBINARY列。

如果不使用PACK_KEYS,则默认为压缩字符串,而不是数字。如果您使用 PACK_KEYS=1,也会压缩数字。
在压缩二进制数字关键字时,MySQL使用前缀压缩:

  • 每个关键字需要一个额外的字节来指示前一个关键字中有多少字节与下一个关键字相同。
  • 指向行的指针以高位字节优先的顺序存储在关键字的后面,用于改进压缩效果。

这意味着,如果两个连续行中有许多相同的关键字,则后续的“相同”的关键字通常只占用两个字节(包括指向行的指针)。与此相比,常规情况下,后续的关键字占用storage_size_for_key + pointer_size(指针尺寸通常为4)。但是,只有在许多数字相同的情况下,前缀压缩才有好处。如果所有的关键字完全不同,并且关键字不能含有NULL值,则每个关键字要多使用一个字节。(在这种情况中,储存压缩后的关键字的长度的字节与用于标记关键字是否为NULL的字节是同一字节。)

PASSWORD

此选项不可用。

ROW_FORMAT
定义行用于存储的物理格式。

在禁用了严格模式的情境下使用CREATE TABLE 语句时,如果指定了用于表的存储引擎不支持的行格式,则使用该存储引擎的默认行格式创建表。通过命令SHOW TABLE STATUS查看Row_format列,其值就是某表的实际行格式;这可能与Create_options列中的值不同, 因为原始CREATE TABLE定义在创建表期间有效。SHOW CREATE TABLE 显示的行的物理格式 和 CREATE TABLE中显示的是一样的。

行格式选择因表使用的存储引擎而异。

对于InnoDB表格:

  • 默认行格式由innodb_default_row_format定义,其默认设置为DYNAMIC。如果ROW_FORMAT未定义或者使用了 ROW_FORMAT=DEFAULT,使用默认行格式。
    如果ROW_FORMAT未定义该选项,或者使用了ROW_FORMAT=DEFAULT选项,则重建表的操作也会以静默方式将表的行格式更改为默认的innodb_default_row_format值 。有关更多信息,请参见 第15.10.2节“指定表的行格式”。

  • 为了更有效地让InnoDB存储数据类型,尤其是BLOB 类型,请使用DYNAMIC。有关行格式相关的要求 ,请参见 第15.10.3节“动态和压缩行格式” 。

  • 要为InnoDB 表启用压缩,请指定ROW_FORMAT=COMPRESSED。有关COMPRESSED行格式的要求,请参见 第15.9节“InnoDB表和页面压缩”。

  • 仍然可以通过指定REDUNDANT行格式来使用旧版MySQL中的行格式。

  • 指定非默认 ROW_FORMAT子句时,请考虑启用 innodb_strict_mode 配置选项。

  • ROW_FORMAT=FIXED不受支持。如果 ROW_FORMAT=FIXEDinnodb_strict_mode禁用时指定, 则InnoDB发出警告并设定ROW_FORMAT=DYNAMIC。如果 ROW_FORMAT=FIXEDinnodb_strict_mode启用时指定(默认情况),则InnoDB 返回错误。

  • 有关InnoDB 行格式的其他信息,请参见 第15.10节“InnoDB行存储和行格式”。

对于MyISAM表,该选项值可以是 FIXED(静态的)或DYNAMIC(可变长度)的行格式。 myisampack工具会将类型设置为 COMPRESSED。请参见 第16.2.3节“MyISAM表存储格式”。

对于NDB表,MySQL NDB Cluster 7.5.1及更高版本中ROW_FORMAT 的默认 值为DYNAMIC(以前,它是 FIXED)。

STATS_AUTO_RECALC
为InnoDB表指定是否自动重新计算 persistent statistics(一种特性)。DEFAULT导致表的这种特性的设置由innodb_stats_auto_recalc 配置选项来决定 。此值为1的时候,当表中10%的数据发生更改时,该值会导致重新计算统计信息;此值为0的时候,可防止自动重新计算此表; 在使用了此设置时,调用ANALYZE TABLE 语句以在对表进行实质性更改后重新计算统计信息。有关持久persistent statistics特性的详细信息,请参阅 第15.8.10.1节“配置持久优化器统计信息参数”。

STATS_PERSISTENT
指定是否为InnoDB表启用 持久统计(persistent statistics)。DEFAULT导致表的这种特性的设置由innodb_stats_persistent 配置选项来决定 。该值为1,启用表的持久统计信息;而值为 0将关闭此功能。通过CREATE TABLE或者ALTER TABLE语句启用持久性统计,在将代表性数据加载到表中后,使用ANALYZE TABLE 来计算统计信息。有关持久统计信息功能的详细信息,请参阅 第15.8.10.1节“配置持久优化器统计信息参数”。

STATS_SAMPLE_PAGES
估计样本的索引页个数和统计其它索引列,例如通过使用ANALYZE TABLE后的列。有关更多信息,请参见 第15.6.10.1节“配置持久优化器统计信息参数”。

TABLESPACE
TABLESPACE子句可用于在现有通用表空间,一个file-pertable表空间或系统表空间中创建表。

CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name

您指定的常规表空间必须在使用TABLESPACE子句之前。有关常规表空间的信息,请参见 第15.6.3.3节“常规表空间”。
tablespace_name是一个区分大小写的标识符。它可能是单引号引起的或不引起的。不允许使用正斜杠(“ / ”)。以innodb_”开头的名称保留用于特殊用途。

要在系统表空间中创建表,请指定 innodb_system为表空间名称。

CREATE TABLE tbl_name ... TABLESPACE [=] innodb_system

使用TABLESPACE [=] innodb_system,无论innodb_file_per_table 设置如何,都可以在系统表空间中放置任何未压缩行格式的表 。例如,您可以使用ROW_FORMAT=DYNAMIC创建一个表,并使用TABLESPACE [=] innodb_system将表添加到系统表空间。

要在 file-per-table表空间中创建表,请指定表空间名称为innodb_file_per_table

CREATE TABLE tbl_name ... TABLESPACE [=] innodb_file_per_table

注意
如果innodb_file_per_table已启用,则无需指定 TABLESPACE=innodb_file_per_table。在innodb_file_per_table启用的情况下,InnoDB表默认就在file-per-table表空间中创建 。

CREATE TABLE ... TABLESPACE=innodb_file_per_table 的时候允许使用DATA DIRECTORY,但不允许 与 TABLESPACE选项一起使用。

注意
自MySQL 5.7.24起,不推荐在CREATE TEMPORARY TABLE的时候,使用TABLESPACE = innodb_file_per_tableTABLESPACE = innodb_temporary子句。将未来的MySQL版本中删除。

UNION
用于访问一组相同的 MyISAM表。这仅适用于 MERGE表。请参见 第16.7节“MERGE存储引擎”。

如果想映射到一个MERGE表,你必须有对表SELECT, UPDATE, DELETE的权限。

注意
以前,所有使用的表必须与MERGE表本身在同一个数据库中。此限制不再适用。

7. 创建分区表
partition_options可用于控制 CREATE TABLE创建出来的表的分区。

本节开头介绍的所有partition_options语法并不适用于所有分区类型。。有关每种类型的信息,有关每种可用类型的信息列表,请参阅请参见第23章分区,有关MySQL中分区的工作和使用的更完整信息,以及有关表创建和其他相关语句的其他示例,也可以在23章中查到。

可以从表中修改,合并,添加分区。有关完成这些任务的MySQL语句的基本信息,请参见第13.1.9节“ALTER TABLE语法”。有关更详细的说明和示例,请参见 第23.3节“分区管理”。

PARTITION BY
如果使用,partition_options子句以PARTITION BY开头。该子句包含用于确定分区的函数; 该函数返回一个从1到 num的整数值,其中 num是分区数。(表可能包含的最大用户定义分区数为1024;子区域的数量 - 本节稍后讨论 - 包含在此最大值中。)

注意
PARTITION BY子句中使用 的表达式(expr) 不能引用那些一开始建表中就建好的任何列; 此类引用是特别不允许的,并导致语句失败并出现错误。(缺陷#29444)这个bug可以搜来看看,并自己理解,翻译不能让你理解。

HASH(expr)
Hash一列或多列以创建一个key用于存放和定位行。expr是使用一个或多个列的表达式。这可以是产生单个整数值的任何有效的MySQL表达式(包括MySQL函数)。例如,这些都是有效的PARTITION BY HASH使用方法:
在这里插入图片描述
您不能在PARTITION BY HASH子句中使用其中任何VALUES LESS THANVALUES IN子句。

PARTITION BY HASH使用 expr除以分区数的余数(即模数)。有关示例和其他信息,请参见 第23.2.4节“HASH分区”。

LINEAR关键字需要一个稍微不同的算法。在这种情况下,计算存储行的分区的数量作为一个或多个逻辑AND运算的结果。有关线性散列的讨论和示例,请参见 第23.2.4.1节“线性散列 分区”。

KEY(column_list)

除了MySQL提供哈希函数以保证均匀的数据分布外,此选项类似于上面的HASHcolumn_list 参数是简单的1个或多个表列(最大:16)的列表。此示例显示了一个按KEY分区的简单表,包含4个分区:
在这里插入图片描述
对于按KEY分区的表,可以使用LINEAR关键字来使用线性分区。这与HASH分区的表具有相同的效果。也就是说,使用& 运算符而不是模数找到分区号 (有关详细信息,请参见 第23.2.4.1节“线性哈希分区”和 第23.2.5节“KEY分区”)。此示例使用按KEY的线性分区在5个分区之间分配数据:
在这里插入图片描述
ALGORITHM={1|2}[SUB]PARTITION BY [LINEAR] KEY子句中相同。
ALGORITHM=1使服务器使用与MySQL 5.1相同的密钥散列函数;
ALGORITHM=2表示服务器使用MySQL 5.5及更高版本中的为新分区表实现和使用的密钥散列函数。(使用MySQL 5.5及更高版本中使用的密钥散列函数创建的分区表不能在MySQL 5.1服务器使用。)不指定该选项与使用ALGORITHM=2具有相同的效果。此选项用于在MySQL 5.1和更高版本的MySQL版本之间对[LINEAR] KEY创建的分区表进行升级或降级 ,或用于(MySQL 5.5或更高版本的服务器上)使用KEY或者LINEAR KEY创建的分区表可以在MySQL 5.1服务器上使用。有关更多信息,请参见 第13.1.9.1节“ALTER TABLE分区操作”。

MySQL 5.7(及更高版本)中的 mysqldump工具将此选项写入内联注释中,如下所示:
在这里插入图片描述
这条语句会导致MySQL 5.6.10和更早版本的服务器忽略该选项,否则会导致对应版本中的语法错误。如果您计划在MySQL 5.7服务器上加载转储,在该服务器中将分区或子分区的表用于MySQL 5.6.11之前的服务器,请务必在继续之前查阅 MySQL 5.6中的更改。(如果您正在将包含KEY 由MySQL 5.7实际5.6.11或更高版本服务器组成的分区或子分区表的转储加载到MySQL 5.5.30或更早版本的服务器中,那么此处找到的信息也适用。)

同样在MySQL 5.6.11及更高版本中,ALGORITHM=1SHOW CREATE TABLE以与mysqldump工具相同的方式显示 。ALGORITHM=2 始终从SHOW CREATE TABLE的输出中省略,即使在创建原始表时指定了ALGORITHM=2

您不能在PARTITION BY KEY语句中使用其中任何VALUES LESS THANVALUES IN子句。

RANGE(expr)
在这种情况下,expr使用一组VALUES LESS THAN 中提供的值。使用RANGE分区时,必须使用VALUES LESS THAN中定义的至少一个分区。您不能在RANGE分区内使用VALUES IN。

注意
对于RANGE分区表,VALUES LESS THAN必须使用整数文字值或计算结果为单个整数值的表达式。在MySQL 5.7后,您可以在使用PARTITION BY RANGE COLUMNS越过此限制 ,本节后面会说。

假设您有一个表,您希望在包含年份值的列上进行分区,根据以下方案。

分区号码年范围
01990年及早些时候
11991年至1994年
21995年至1998年
31999年至2002年
42003年至2005年
52006年及以后

实现这种分区方案的表可以通过CREATE TABLE 语句实现:
在这里插入图片描述

PARTITION ... VALUES LESS THAN ... 可以连续使用。VALUES LESS THAN MAXVALUE用于指定 大于其他值中的最大值的 “ 剩余 ”值。

VALUES LESS THAN子句以类似于switch ... case语句中case 部分的执行顺序工作(如在许多编程语言中都有的流程,如C,Java和PHP)。也就是说,条款必须以这样的方式排列,即每个连续的VALUES LESS THAN语句中指定的上限大于前一个的上限,剩余的用MAXVALUE放在最后列在列表中。(官网这个例子 p3 是不是应该写成2003)

RANGE COLUMNS(column_list)
此项是RANGE变体,有助于使用多列上的范围条件(即具有诸如WHERE a = 1 AND b < 10或WHERE a = 1 AND b = 10 AND c < 10 之类的限定)对查询进行分区修剪。它允许您通过使用COLUMNS子句中的列列表和每个分区定义 PARTITION ... VALUES LESS THAN (value_list)子句中的一组列值来指定多列中的值范围 。(在最简单的情况下,此集合由单个列组成。)可以在column_list中引用列,并且最大的value_list值为16。

COLUMNS语句中的column_list中只能包含列的名称; 列表中的每一列必须是以下MySQL数据类型之一:整数类型; 字符串类型; 时间或日期列类型。不许使用的列类型有BLOB,TEXT, SET,ENUM, BIT,空间数据类型也不允许,也不允许使用浮点数类型的列。您也可以不在COLUMNS 子句中使用函数或算术表达式。

分区定义中使用VALUES LESS THAN 的子句必须为COLUMNS() 子句中出现的每个列指定一个文字值; 也就是说,用于每个VALUES LESS THAN子句的值列表 必须包含与COLUMNS子句中列出的列相同数量的值 。尝试到在VALUES LESS THAN中使用更多或更少的值,错误提示Inconsistency in usage of column lists for partitioning....。您不能在VALUES LESS THAN中使用NULL值。除了第一列, MAXVALUE 可以出现多次:
在这里插入图片描述
VALUES LESS THAN中使用的每个值必须与相应列的类型完全匹配; 没有转换。例如,您不能将字符串 '1’用于与使用整数类型的列匹配的值(您必须使用数字 1),也不能将数字 1用于与使用字符串类型的列匹配的值(在此情况下带引号的字符串:‘1’)。

有关更多信息,请参见 第23.2.1节“RANGE分区”和 第23.4节“分区修剪”。

LIST(expr)
当为表分配分区时,此表中某列具有固定的选项时(例如州或国家/地区代码),这非常有用。在这种情况下,可以将属于某个州或国家的所有行分配给单个分区,或者可以为某组州或国家保留分区。它类似于 RANGE,除了可以仅VALUES IN用于指定每个分区的允许值。

VALUES IN与要匹配的值列表一起使用。例如,您可以创建一个分区方案,如下所示:
在这里插入图片描述

使用列表分区时,必须使用VALUES IN定义至少一个分区。您不能在PARTITION BY LIST中使用 VALUES LESS THAN

注意
对于LIST分区的表,VALUES IN使用的值必须仅包含整数值。在MySQL 5.7后,您可以使用LIST COLUMNS,来越过此限制,本节稍后将对此进行介绍。

LIST COLUMNS(column_list)
LIST的变体,有助于使用多列上的比较条件(即具有诸如 WHERE a = 5 AND b = 5或WHERE a = 1 AND b = 10 AND c = 5之类的限制)对查询进行分区修剪。它允许您通过使用COLUMNS子句中的列列表和每个分区定义子句PARTITION ... VALUES IN (value_list)中的一组列值来指定多列中的 值。

LIST COLUMNS(column_list)VALUES IN(value_list)中的使用的列列表 中的数据类型的规则
RANGE COLUMNS(column_list)VALUES LESS THAN(value_list)中的是一样的,只是在VALUES IN子句中MAXVALUE是不允许的,你可能会用NULL

PARTITION BY LIST COLUMNS子句中的VALUES IN内的列表值 和 PARTITION BY LIST 中的列表值有很大的不同。与 PARTITION BY LIST COLUMNS一起使用时,VALUES IN子句中的每个元素都必须是一组列值; 每个集合中的值的数量必须与COLUMNS子句中使用的列数相同,并且这些值的数据类型必须与列的数据类型匹配(并以相同的顺序出现)。在最简单的情况下,该集合由一列组成。column_list组成元素和元素中 可以使用的最大列数value_list为16。

由以下CREATE TABLE语句定义的表提供了使用LIST COLUMNS分区的表的示例 :
在这里插入图片描述

PARTITIONS num
可以选择使用PARTITIONS num指定分区数,其中是num分区数。如果同时使用此子句和任何 PARTITION子句,num则 必须等于使用PARTITION子句声明的任何分区的总数 。

注意
在创建表并使用RANGE或LIST的部分,无论是否使用PARTITIONS子句,您仍必须一个在表定义中包含至少一个PARTITION VALUES子句(参见下文)。

SUBPARTITION BY
可以可选地将分区划分为多个子分区。这可以通过使用可选的SUBPARTITION BY子句来指示 。子分区可以通过HASH或KEY完成。这俩可能是LINEAR类型。这些工作方式与先前针对等效分区类型所述的方式相同。(但不可能通过LIST或RANGE来完成。)

可以使用SUBPARTITIONS关键字后跟整数值来指示子分区的数量 。

会严格检查使用 PARTITIONS或 SUBPARTITIONS子句中使用的值,该值必须符合以下规则:

  • 该值必须是正的非零整数。

  • 不允许前导0。

  • 该值必须是整数文字,并且不能是表达式。例如,PARTITIONS 0.2E+01 是不允许的,即使0.2E+01评估为 ,也是 2。(Bug#15890)

partition_definition
可以使用partition_definition子句单独定义每个分区 。构成本语句的各个部分如下:

PARTITION partition_name
指定分区的逻辑名称。

VALUES
对于range分区,每个分区必须包含一个 VALUES LESS THAN子句; 对于list分区,您必须VALUES IN为每个分区指定一个子句。这用于确定要在此分区中存储哪些行。见第23章分区 分区类型的讨论和语法的例子。

[STORAGE] ENGINE
分区处理程序接受PARTITION和 SUBPARTITION 中指定[STORAGE] ENGINE选项 。目前,可以使用它的唯一方法是将所有分区或所有子分区设置为同一存储引擎,并且尝试为同一表中的分区或子分区设置不同的存储引擎将导致错误 ERROR 1469 (HY000): The mix of handlers in the partitions is not permitted in this version of MySQL. 希望在未来的MySQL版本中解除对分区的限制。

COMMENT
COMMENT子句可用于指定描述分区的字符串。例:
COMMENT = 'Data for the years previous to 1999'
分区注释的最大长度为1024个字符。

DATA DIRECTORY 和 INDEX DIRECTORY
DATA DIRECTORYINDEX DIRECTORY可以用于指示分别存储该分区的数据和索引的目录。无论是data_dir还是 index_dir 必须是系统绝对路径名。

从MySQL 5.7.17开始,您使用 DATA DIRECTORY或INDEX DIRECTORY分区选项必须有FILE权限,例:
在这里插入图片描述
DATA DIRECTORY和INDEX DIRECTORY 与用CREATE TABLE语句的 table_option子句来创建MyISAM表中的选项有相同的意思 。

可以为每个分区指定一个数据目录和一个索引目录。如果未指定,则数据和索引默认存储在表的数据库目录中。

如果NO_DIR_IN_CREATE有效,DATA DIRECTORYINDEX DIRECTORY选项将被忽略。(Bug#24633)

MAX_ROWS 和 MIN_ROWS
可用于分别指定要在分区中存储的最大和最小行数。max_number_of_rowsmin_number_of_rows必须为正整数。与具有相同名称的表级选项一样,这些选项仅作为 服务器的“ 建议 ”而不是硬限制。

TABLESPACE
可用于为分区指定表空间。由NDB Cluster支持。对于InnoDB 表,它可以用于通过TABLESPACE innodb_file_per_table为分区指定一个 file-per-table 表空间 。所有分区必须属于同一存储引擎。

subpartition_definition
分区定义可以可选地包含一个或多个 subpartition_definition子句。这些中的每一个至少包含SUBPARTITION name ,其中 name是子分区的标识符。除了替换PARTITION键字为 SUBPARTITION外 ,子分区定义的语法与分区定义的语法相同。

子分区必须指定HASH或 KEY,可以是 RANGE或LIST 。请参见第23.2.6节“子分区”。

Partitioning by Generated Columns
允许按生成的列进行分区。例如:
在这里插入图片描述
分区将生成的列视为常规列,这使得可以对不允许进行分区的函数进行限制(请参见 第23.6.3节“对函数相关的分区限制”)。前面的示例演示了此技术: EXP()不能直接在PARTITION BY子句中使用,但允许使用EXP()的生成列定义。

13.1.20.1 保留建表语句

使用CREATE TABLE 创建表时,MySQL将存储 原始语句,包括所有规范和表选项。保留这些信息以便在使用ALTER TABLE语句更改存储引擎,排序规则或其他设置时给你指引。这使你可以将表的类型在InnoDB和 MyISAM之间进行选择, 即使两个引擎支持的行格式不同。

因为保留了原始语句的文本,但是由于某些值和选项可能以静默方式重新配置(例如ROW_FORMAT),当前表的定义(可通过DESCRIBE或使用SHOW TABLE STATUS查看)和原始表的定义(可通过SHOW CREATE TABLE查看)会呈现不同的输出。

13.1.20.2 建表语句生成的文件

对于一个在file-per-table表空间或通用表空间中创建的InnoDB表,表数据和关联索引存储在数据库目录中的 ibd文件中。当InnoDB在系统表空间中创建表,表数据和索引存储在 ibdata*文件,表示系统表空间。innodb_file_per_table变量控制是否默认情况下在每个表的文件表空间或系统表空间中创建表。无论innodb_file_per_table设置如何,TABLESPACE 选项都可用于将表放在每个表的文件表空间,通用表空间或系统表空间中 。

对于MyISAM表,存储引擎会创建数据和索引文件。因此,对于每个MyISAM 表如tbl_name,有两个磁盘文件。

文件作用
tbl_name.MYD数据文件
tbl_name.MYI索引文件

第16章,其它存储引擎,描述了每个存储引擎为表示表而创建的文件。如果表名包含特殊字符,则这些特殊字符会重新编码,如 第9.2.3节“标识符到文件名的映射”中所述。

13.1.20.3 创建临时表语法

您可以在创建表时使用TEMPORARY关键字。一个临时表只在当前会话中可见,而当会话关闭时自动删除。这意味着两个不同的会话可以使用相同的临时表名,而不会相互冲突,也不会与现有的同名非临时表冲突。(在删除临时表之前,现有表是隐藏的。)

InnoDB不支持压缩的临时表。当innodb_strict_mode 启用(默认值), 如果在CREATE TEMPORARY TABLE时指定了ROW_FORMAT=COMPRESSED或 KEY_BLOCK_SIZE则返回错误;如果innodb_strict_mode禁用,则发出警告,并使用非压缩行格式创建临时表。 innodb_file_per_table选项不会影响InnoDB 临时表的创建。

CREATE TABLE导致隐式提交,除非与TEMPORARY 关键字一起使用。请参见 第13.3.3节“导致隐式提交的语句”。

TEMPORARY表与数据库(模式)的关系非常松散。删除数据库不会自动删除在该数据库中创建的任何临时表。此外,如果使用CREATE TABLE语句中可以在不存在的数据库中创建 临时表 。在这种情况下,必须使用数据库名称限定对表的所有后续引用。

要创建临时表,您必须具有CREATE TEMPORARY TABLES权限。会话创建临时表后,服务器不会对表执行进一步的权限检查。所述创建会话可以在表上进行任何操作,例如 DROP TABLE, INSERT, UPDATE,或 SELECT。

这种行为的一个含义是,即使当前用户没有创建它们的权限,会话也可以操纵其临时表。假设当前用户没有CREATE TEMPORARY TABLES 权限,但能够执行定义者上下文存储过程,该过程以具有CREATE TEMPORARY TABLES创建临时表的用户的权限执行。该过程执行时,会话使用定义用户的权限。该过程返回后,有效权限将恢复为当前用户的权限,该权限仍然可以看到临时表并对其执行任何操作。

您不能使用CREATE TEMPORY TABLE ... LIKE基于表mysql空间,InnoDB系统表空间(innodb_system)或常规表空间中的表 的定义来创建空表。此类表的表空间定义包括一个TABLESPACE属性,该 属性定义表所在的表空间,并且上述表空间不支持临时表。要根据此类表的定义创建临时表,请改用以下语法:
在这里插入图片描述
从MySQL 8.0.13开始,不推荐在CREATE TEMPORARY TABLE的时候,使用TABLESPACE = innodb_file_per_tableTABLESPACE = innodb_temporary子句。将未来的MySQL版本中删除。

13.1.20.4 CREATE TABLE … LIKE语法

用于CREATE TABLE … LIKE根据另一个表的定义创建一个空表,包括原始表中定义的任何列属性和索引:
在这里插入图片描述
使用与原始表相同的表存储格式版本创建副本。需要原始表上的SELECT权限。

LIKE 仅适用于基表,不适用于视图。

重要
您无法在表被锁定的时候执行CREATE TABLECREATE TABLE ... LIKE
CREATE TABLE ... LIKECREATE TABLE进行相同的检查。这意味着如果当前SQL模式与创建原始表时生效的模式不同,则对于新模式,表定义可能被视为无效,并且语句将失败。

  • 对于CREATE TABLE … LIKE,目标表保留原始表中生成的列信息。
  • 对于CREATE TABLE … LIKE,目标表保留原始表中的表达式默认值。
  • CREATE TABLE … LIKE不保留原始表的任何外键定义或者 任何 DATA DIRECTORYINDEX DIRECTORY表选项。
  • 如果原始表是临时表, CREATE TABLE … LIKE则不保留 TEMPORARY。要创建 临时目标表,请使用 CREATE TEMPORARY TABLE ... LIKE

在mysql表空间, InnoDB系统表空间(innodb_system)或通用表空间中创建的表包含TABLESPACE属性,该属性定义表所在的表空间。CREATE TABLE … LIKE保留TABLESPACE 属性并在原始定义的表空间中创建表,而不管innodb_file_per_table设置如何 。要在创建空表时避免TABLESPACE是上面属性,请改用以下语法:
在这里插入图片描述

13.1.20.5 CREATE TABLE … SELECT语法

你可以通过在 CREATE TABLE 语句末尾添加SELECT语句来创建另一个表:
在这里插入图片描述
MySQL在 SELECT 语句中 为其中的所有元素创建新列。例如:
在这里插入图片描述
这将创建一个MyISAM表,有三列,a,b,和 c。ENGINE选项是CREATE TABLE 声明的一部分,不应在SELECT之后使用; 这会导致语法错误。对于其他CREATE TABLE选项 也是如此,例如 CHARSET。

请注意,SELECT语句中的列 将追加到表的右侧,而不会重叠到表的右侧。采用以下示例:
在这里插入图片描述
对于foo表中的每一行,bar表将插入一行其中包括foo表新列的值和默认值。

在由 CREATE TABLE … SELECT产生的表中,仅在CREATE TABLE语句中出现的列首先出现。在两个部分中或仅在 SELECT中命名的列在之后出现。CREATE TABLE中同名列的数据类型 将会覆盖 SELECT中同名列 的数据类型。(译者提供一个例子)
在这里插入图片描述
test4表中有一个和test2表同名的c列,所以在test4表中c列出现在b列之后,并且c列的定义出现了覆盖的情况。

如果在将数据复制到表时发生任何错误,则会自动删除它而不会创建。

您可以在SELECT 之前使用IGNOREREPLACE指示如何处理唯一键重复出现的行。使用IGNORE,唯一键重复出现的行将被丢弃。使用 REPLACE新行替换具有唯一键重复出现的行。如果既未指定IGNORE也未指定REPLACE,则重复的唯一键值会导致错误。有关更多信息,请参阅 IGNORE关键字和严格SQL模式的比较。

因为SELECT无法始终确定基础语句中行的顺序 ,CREATE TABLE … IGNORE SELECT 和CREATE TABLE … REPLACE SELECT 语句被标记为基于语句的不安全复制。当使用基于语句的模式时,此类语句在错误日志中生成警告,并在使用MIXED模式时使用基于行的格式写入二进制日志 。另请参见 第17.2.1.1节“基于语句和基于行的复制的优点和缺点”。

  • CREATE TABLE SELECT不会自动为您创建任何索引。这样做是为了使声明尽可能灵活。如果要在创建的表中包含索引,则应在SELECT语句之前指定这些索引 :
    在这里插入图片描述
  • 对于CREATE TABLE … SELECT,目标表不保留有关selected-from表中的列是否为生成列的信息。SELECT语句的 一部分无法将值分配给目标表中的生成列。
  • 对于CREATE TABLE … SELECT,目标表确实保留原始表中的表达式默认值。

可能会发生某些数据类型的转换。例如,AUTO_INCREMENT不保留该 属性,VARCHAR列可以成为 CHAR列。保留属性(翻译可能不正确,Retrained attributes)是NULL(或NOT NULL),还有具有这些属性 CHARACTER SET,COLLATION, COMMENT,和DEFAULT的列。

使用CREATE TABLE … SELECT创建表时 ,请确保在查询中为任何函数调用或表达式设置别名。如果不这样做,则该 CREATE语句可能会失败或导致不合需要的列名。
在这里插入图片描述
您还可以在创建的表中显式指定列的数据类型:
在这里插入图片描述
对于CREATE TABLE ... SELECT,如果IF NOT EXISTS给定并且目标表存在,则不会向目标表中插入任何内容,并且不会记录该语句。

为确保二进制日志可用于重新创建原始表,MySQL不允许在CREATE TABLE ... SELECT期间进行并发插入。

您不能在SELECT语句中使用FOR UPDATE,例如CREATE TABLE new_table SELECT ... FROM old_table ... 。如果您尝试这样做,则该语句将失败。

13.1.20.6 使用FOREIGN KEY约束

MySQL支持外键,它允许您跨表交叉引用相关数据,以及 外键约束,这有助于保持这种展开数据的一致性。CREATE TABLE或者ALTER TABLE语句中的外键约束定义的基本语法如下所示:
在这里插入图片描述
index_name表示外键ID。如果子表上已经显式定义了可以支持外键的索引,则忽略index_name值。否则,MySQL会隐式创建一个根据以下规则命名的外键索引:

  • 如果已定义CONSTRAINT symbol,使用它。否则,使用FOREIGN KEY index_name值。

  • 如果既没有CONSTRAINT symbol也没有FOREIGN KEY index_name定义,使用引用外键列的名称所产生的外键索引名。
    FOREIGN KEY index_name值在数据库中必须是唯一的。

外键定义受以下条件限制:

  1. 外键关系涉及 保存主要数据的父表,以及具有指向其父表的相同值的子表。FOREIGN KEY子句在子表中指定。父表和子表必须使用相同的存储引擎。他们不能是临时表。在MySQL 8.0中,创建外键约束需要父表的REFERENCES权限。

  2. 外键和引用键中的相应列必须具有相似的数据类型。整数类型的大小和符号必须相同。字符串类型的长度不必相同。对于非二进制(字符)字符串列,字符集和排序规则必须相同。
    在这里插入图片描述

  3. 如果启用了 foreign_key_checks(默认设置),则在包含外键约束中使用的字符串列的表上不允许进行字符集转换。第13.1.9节“ALTER TABLE语法”中介绍了解决方法 。

  4. MySQL需要外键和引用键上的索引,以便外键检查可以很快并且不需要表扫描。在引用表中,必须有一个索引,其中外键列以相同的顺序列为 第一列。如果索引不存在,则会自动在引用表上创建此索引。如果您创建另一个可用于强制执行外键约束的索引,则可以稍后以静默方式删除此索引。 index_name如果给定,则如前所述使用。

  5. InnoDB允许外键引用任何列或列组。但是,在引用的表中,必须有一个索引,其中引用的列被列为相同顺序的第一列。
    NDB 在被引用为外键的任何列上需要是显式地唯一索引(或主键)。

  6. 不支持外键列上的索引前缀。这样做的一个结果是, BLOB和TEXT 列不能包含在外键中,因为这些列上的索引必须始终包含前缀长度。

  7. 如果给出了CONSTRAINT symbol子句,则该symbol值(如果使用)在数据库中必须是唯一的。重复的symbol 将导致类似于以下的错误:Error Code: 1826. Duplicate foreign key constraint name 'fk'。如果未给出该子句,或者CONSTRAINT关键字 后面不包含symbol,则会自动创建约束的名称。

  8. InnoDB当前不支持具有用户定义分区的表上的外键。这包括父表和子表。
    此限制不适用于NDB表的分区表(KEY或存储引擎LINEAR KEY支持的唯一用户分区类型) ; 这些可能具有外键引用或是此类引用的目标。

  9. 对于NDB表,引用父表的主键上面不支持ON UPDATE CASCADE

本节中的以下主题描述 了FOREIGN KEY约束使用的其他方面:

参考行动

外键的例子

添加外键

删除外键

外键和其他MySQL语句

外键和ANSI / ISO SQL标准

外键元数据

外键错误

13.1.20.6.1 参照完整性

本节介绍外键如何帮助保证 参照完整性。

对于支持外键的存储引擎,如果父表中没有匹配的候选键值,则MySQL拒绝任何 尝试在子表中创建外键值的INSERT或 UPDATE操作。

当UPDATE或或DELETE操作影响父表中具有子表中匹配行的键值时,结果取决于使用ON UPDATE/ ON DELETE子 句子指定的 referential action。MySQL支持的referential action有5个选项。

  1. CASCADE:从父表中删除或更新行,会自动删除或更新子表中的匹配行。ON DELETE CASCADEON UPDATE CASCADE 都支持。在两个表之间,不要定义多个ON UPDATE CASCADE子句,这些 子句作用于父表或子表中的同一列。
      如果两个表上都定义了一个外键关系的 FOREIGN KEY子句,使两个表都成为父和子,FOREIGN KEY子句的ON UPDATE CASCADEON DELETE CASCADE部分必须xxx以便级联操作成功(原文:If a FOREIGN KEY clause is defined on both tables in a foreign key relationship, making both tables a parent and child, an ON UPDATE CASCADE or ON DELETE CASCADE subclause defined for one FOREIGN KEY clause must be defined for the other in order for cascading operations to succeed)。如果 仅为一个FOREIGN KEY子句定义ON UPDATE CASCADEON DELETE CASCADE,则级联操作将失败并显示错误。

注意
级联外键操作不会激活触发器。

  1. SET NULL:从父表中删除或更新行,并将子表中的外键列设置为NULL。ON DELETE SET NULLON UPDATE SET NULL子句都支持。
    如果指定SET NULL操作,请 确保未将子表中的列声明为NOT NULL。

  2. RESTRICT:拒绝父表的删除或更新操作。指定 RESTRICT(或NO ACTION)与省略ON DELETEON UPDATE子句相同。

  3. NO ACTION:标准SQL中的关键字。在MySQL中,相当于RESTRICT。如果引用的表中存在相关的外键值,则MySQL服务器拒绝父表的删除或更新操作。某些数据库系统具有延迟检查,并且NO ACTION是延迟检查。在MySQL中,立即检查外键约束,因此NO ACTION也是RESTRICT。

  4. SET DEFAULT:这个动作由MySQL解析器认可,但 InnoDB和NDB拒绝包含表定义ON DELETE SET DEFAULTON UPDATE SET DEFAULT条款。

对于未指定ON DELETEON UPDATE的,默认操作始终为RESTRICT。

MySQL支持表中一列与另一列之间的外键引用。(列不能有指向自己的自己的外键引用。)在这些情况下,“ 子表记录 ”实际上是指同一个表中的依赖记录。
在这里插入图片描述
在存储生成列上的外键约束不能用ON UPDATE CASCADEON DELETE SET NULLON UPDATE SET NULLON DELETE SET DEFAULT,或ON UPDATE SET DEFAULT

外键约束不能引用虚拟生成列。

有关InnoDB外键和生成列的限制,请参见 第15.6.1.6节“InnoDB和FOREIGN KEY约束”

外键的例子
这是一个通过单列外键关联parent和child表的简单示例 :
在这里插入图片描述
一个更复杂的示例,其中 product_order表具有两个其他表的外键。一个外键引用product表中的两列索引。另一个引用 customer表中的单列索引:
--

13.1.20.6.2 添加外键

您可以使用ALTER TABLE添加新的外键约束到现有表。此语句显示与此语句的外键相关的语法:
--
外键可以是自引用的(引用同一个表)。使用ALTER TABLE向表中添加外键约束时 ,请记住首先创建所需的索引。

13.1.20.6.3 删除外键

您还可以使用ALTER TABLE来删除外键,此处显示语法:

如果FOREIGN KEY子句在创建外键时包含 名称CONSTRAINT,则可以引用该名称以删除外键。否则,在创建外键时在内部生成fk_symbol值。要在删除外键时找出符号值,请使用SHOW CREATE TABLE 语句,如下所示:
在这里插入图片描述

ALTER TABLE语法支持 在同一语句中 添加和删​​除外键 ,适用于ALTER TABLE ... ALGORITHM=INPLACE但不适用于 ALTER TABLE ...ALGORITHM=COPY

在MySQL 8.0中,服务器禁止更改外键列,这可能会导致参照完整性丢失。解决方法是 在更改列定义之前使用ALTER TABLE ... DROP FOREIGN KEY和之后使用ALTER TABLE ... ADD FOREIGN KEY

13.1.20.6.4 外键和其他MySQL语句

FOREIGN KEY … REFERENCES …子句中的表和列标识符可以在反引号中引用。或者,如果启用了ANSI_QUOTES SQL模式,则可以使用双引号(") 。lower_case_table_names系统变量的设置 也被考虑在内。

您可以通过SHOW CREATE TABLE语句输出查看子表的外键定义:
在这里插入图片描述
您还可以通过查询 INFORMATION_SCHEMA.KEY_COLUMN_USAGE表获取有关外键的信息 。

您可以在INFORMATION_SCHEMA数据库的INNODB_FOREIGNINNODB_FOREIGN_COLS表中找到有关InnoDB表使用的外键。

mysqldump工具在转储文件中生成正确的表定义,包括子表的外键。

为了更容易为具有外键关系的表重新加载转储文件,mysqldump会 自动在转储输出中包含一个语句,设置 foreign_key_checks=0.这样可以避免在重新加载转储时必须按特定顺序重新加载表的问题。也可以手动设置此变量:
在这里插入图片描述
这使您可以按任何顺序导入表,如果转储文件包含未正确为外键排序的表。它还加快了导入操作。设置 foreign_key_checks为0,也可以是在LOAD DATA和 ALTER TABLE操作 忽略外键约束有用。但是,即使foreign_key_checks = 0, MySQL不允许创建外键约束,其中列引用不匹配的列类型。另外,如果表具有外键约束, ALTER TABLE则不能用于更改表以使用其他存储引擎。要更改存储引擎,必须先删除任何外键约束。

不能使用DROP TABLE删除一张表(此表为FOREIGN KEY约束引用的表), 除非您这样设置,SET foreign_key_checks = 0。删除表时,也会删除在用于创建该表的语句中定义的任何约束。

如果重新创建已删除的表,则它必须具有符合引用它的外键约束的定义。它必须具有正确的列名和类型,并且必须在引用的键上具有索引,如前所述。如果不满足这些,MySQL将返回错误1005并在错误消息中引用错误150,这意味着未正确形成外键约束。类似地,如果ALTER TABLE 由于错误150而失败,则这意味着对于更改的表将错误地形成外键定义。

对于InnoDB表,您可以通过检查SHOW ENGINE INNODB STATUS输出来获得MySQL服务器中最近的InnoDB外键错误。

MySQL根据需要将元数据锁扩展到由外键约束相关的表。扩展元数据锁可防止冲突的DML和DDL操作在相关表上并发执行。此功能还允许在修改父表时更新外键元数据。在早期的MySQL版本中,子表所拥有的外键元数据无法安全更新。

如果使用LOCK TABLES显式锁定表,则会打开并隐式锁定由外键约束关联的任何表。对于外键检查,对相关表执行共享只读锁(LOCK TABLES READ)。对于级联更新,对操作中涉及的相关表采用无共享写锁(LOCK TABLES WRITE)。

13.1.20.6.5 外键和ANSI / ISO SQL标准

对于熟悉ANSI / ISO SQL标准的用户,请注意,没有存储引擎,包括InnoDB,识别或强制执行MATCH参照完整性约束定义中使用的子句。使用显式 MATCH子句不会产生指定的效果,也会忽略cause ON DELETE 和ON UPDATE子句。出于这些原因,MATCH应该避免指定。

MATCH SQL标准中 的子句控制NULL在与主键进行比较时如何处理复合(多列)外键中的值。MySQL本质上实现了定义的语义MATCH SIMPLE,允许外键全部或部分NULL。在这种情况下,允许插入包含此类外键的(子表)行,并且该行与引用的(父)表中的任何行都不匹配。可以使用触发器实现其他语义。

此外,MySQL要求出于性能原因对引用的列进行索引。然而,该系统并不强制所引用的列是一个要求 UNIQUE或声明NOT NULL。对包含NULL 值的非唯一键或键的外键引用的处理没有为诸如UPDATE或之类的操作定义 DELETE CASCADE。建议您使用仅引用UNIQUE(包括 PRIMARY)和NOT NULL 键的外键。

此外,MySQL解析但忽略了“ 内联 REFERENCES规范 ”(在SQL标准中定义),其中引用被定义为列规范的一部分。MySQL REFERENCES仅在指定为单独FOREIGN KEY 规范的一部分时才接受 子句。对于不支持外键(例如MyISAM)的存储引擎,MySQL Server会解析并忽略外键规范。

13.1.20.6.6 外键元数据

INFORMATION_SCHEMA.KEY_COLUMN_USAGE 表标识了具有约束的键列。特定于InnoDB外键的元数据可在INNODB_SYS_FOREIGNINNODB_SYS_FOREIGN_COLS 表中找到。

13.1.20.6.7 外键错误

如果涉及InnoDB表的外键错误 (通常是MySQL服务器中的错误150),InnoDB可以通过检查SHOW ENGINE INNODB STATUS输出获得有关最新外键错误的信息 。

警告
如果用户拥有所有父表的表级的特权, ER_NO_REFERENCED_ROW_2和 ER_ROW_IS_REFERENCED_2为外键操作错误信息公开有关父表的信息。如果用户没有所有父表的表级权限,则会显示更多通用错误消息(ER_NO_REFERENCED_ROW和 ER_ROW_IS_REFERENCED)。

一个例外是,对于定义为使用DEFINER特权执行的存储程序,评估特权的用户是程序DEFINER子句中的用户 ,而不是调用用户。如果该用户具有表级父表权限,则仍会显示父表信息。在这种情况下,存储的程序创建者有责任通过包括适当的条件处理程序来隐藏信息。

13.1.20.7 列变更时候的静默操作

在某些情况下,MySQL会默默地更改CREATE TABLE或者 ALTER TABLE语句中给出的列规范。这些可能是对数据类型,与数据类型关联的属性或索引规范的更改。

所有更改都受内部行大小65,535字节的限制,这可能会导致某些数据类型更改尝试失败。请参见第C.10.4节“表列数和行大小的限制”

  1. 为PRIMARY KEY列 自动添加NOT NULL

  2. 创建表时, 会自动删除ENUM和 SET成员值的尾随空格 。

  3. MySQL将其他SQL数据库供应商使用的某些数据类型映射到MySQL类型。请参见 第11.10节“使用其他数据库引擎中的数据类型”

  4. 如果包含一个USING子句来指定给定存储引擎不允许的索引类型,但引擎可以使用另一种可用的索引类型而不影响查询结果,则引擎使用可用类型。

  5. 如果未启用严格SQL模式,则会将长度大于65535的VARCHAR列转换为 TEXT,VARBINARY列转换为BLOB 。否则,在这两种情况下都会发生错误。

  6. 为字符数据类型指定CHARACTER SET binary 的属性会导致将列创建为相应的二进制数据类型: CHAR变为 BINARY, VARCHAR变为 VARBINARY, TEXT变为 BLOB。对于 ENUM和 SET数据类型,不会发生这种情况; 它们是按照声明创建的。假设您使用此定义指定表:
    --
    结果表具有以下定义:

    要查看MySQL是否使用了您指定的数据类型以外的数据类型,请在创建或更改表后执行DESCRIBESHOW CREATE TABLE查看。

如果使用myisampack压缩表,则可能会发生某些其他数据类型更改。请参见 第16.2.3.3节“压缩表特性”

13.1.20.8 创建表和Generated Columns(生成列)

CREATE TABLE支持生成列的规范。生成列的值是根据列定义中包含的表达式计算的。

NDB存储引擎 也支持生成列 。

下面的简单示例显示了一个表,该表存储了直角三角形中a边和 b边的长度,并计算了斜边的c长度 sidec(其他边的平方和的平方根):
在这里插入图片描述
从表中选择会产生以下结果:
--
使用triangle表的任何应用程序都可以访问斜边值,而无需指定计算它们的表达式。

生成列的定义具有以下语法:
在这里插入图片描述
AS (expression) 表示生成列并定义用于计算列值的表达式。AS 之前的GENERATED ALWAYS可以使列的生成性质更明确。表达式中允许或禁止的构造将在后面讨论。

VIRTUALSTORED 关键字表示生成列的值的存储方式,其具有用于使用列含义:

  1. VIRTUAL:不存储列值,行被读取的时候进行计算,但在任何BEFORE触发器后 。虚拟列不占用存储空间。

InnoDB支持虚拟列上的二级索引。请参见 第13.1.20.9节“二级索引和生成的列”

  1. STORED:插入或更新行时,将计算和存储列值。存储列需要存储空间并且可以被索引。

如果两个关键字都未指定,则 默认为VIRTUAL。

允许在表中混合使用VIRTUAL和 STORED列。

可以给出其他属性以指示列是否被索引或可以是NULL,或者添加注释。

生成列表达式必须遵守以下规则。如果表达式包含不允许的构造,则会发生错误。

  1. 允许使用文字,确定性的内置函数和运算符。如果给定表中的相同数据,则多个调用产生相同的结果,而不管连接的用户是谁,则函数是确定性的。不确定性函数会导致失败,例如: CONNECTION_ID(), CURRENT_USER(), NOW()。

  2. 不允许使用子查询,参数,变量,存储函数和用户定义的函数。

  3. 生成列的定义可以引用其他生成列,但只能引用表定义中较早出现的生成列。生成列的定义可以引用表中的任何基本(非生成)列,无论其定义是早期还是稍后发生。

  4. AUTO_INCREMENT属性不能在生成的列定义中使用。

  5. 一个AUTO_INCREMENT基本列不能用在生成列的定义中。

  6. 如果表达式求值导致截断或向函数提供不正确的输入,则 CREATE TABLE语句将终止并显示错误,并拒绝DDL操作。

如果表达式求值为与声明的列类型不同的数据类型,则根据通常的MySQL类型转换规则对声明的类型进行隐式强制。请参见 第12.2节“表达式评估中的类型转换”

注意
如果表达式的任何组件依赖于SQL模式,则表的不同用法可能会出现不同的结果,除非在所有使用过程中SQL模式都相同。↑

对于CREATE TABLE ... LIKE,目标表保留原始表中生成列信息。

对于CREATE TABLE ... SELECT,目标表不保留有关selected-from表中的列是否为生成列的信息。SELECT语句的 一部分无法将值分配给目标表中的生成列。

允许按生成列进行分区。请参阅上面的 创建分区表。

在存储生成列上的外键约束不能用 ON UPDATE CASCADE,ON DELETE SET NULL,ON UPDATE SET NULL, ON DELETE SET DEFAULT,ON UPDATE SET DEFAULT

外键约束不能引用虚拟生成列。

有关InnoDB外键和生成列的限制,请参见 第15.6.1.6节“InnoDB和FOREIGN KEY约束”

触发器不能使用NEW.col_name 或OLD.col_name用于引用生成列。

对于INSERT, REPLACE和 UPDATE,如果生成列明确插入,替换或更新,则唯一允许的值为DEFAULT。

视图中生成的列被视为可更新,因为可以为其分配。但是,如果明确更新此类列,则唯一允许的值为 DEFAULT。

生成的列有几个用例,例如:

  1. 虚拟生成列可用作简化和统一查询的方法。可以将复杂条件定义为生成列,并从表上的多个查询引用,以确保它们全部使用完全相同的条件。

  2. 存储生成列可以用作物化缓存,用于复杂的条件,这些条件在运行中计算成本很高。

  3. 生成列可以模拟方法索引:使用生成列的定义功能表达式并对其进行索引。这对于处理无法直接索引的类型列(例如JSON列)非常有用 ; 有关详细示例,请参阅 索引生成的列以提供JSON列索引

对于存储生成列,这种方法的缺点是值存储两次; 一次作为生成列的值,一次作为索引。

  1. 如果生成列已编制索引,则优化程序将识别与列定义匹配的查询表达式,并在查询执行期间根据需要使用列中的索引,即使查询未按名称直接引用该列也是如此。有关详细信息,请参见 第8.3.11节“生成列索引的优化程序使用”

例:

假设一个表t1包含 first_name和last_name 列,并且该应用程序经常使用如下表达式构造全名:

避免编写出表达的一种方法是在t1上创建一个视图 v1,其通过使用表达式简化应用程序来选择 full_name的:
--
生成列还使应用程序可以直接选择 full_name,而无需定义视图:
--

13.1.22 创建触发器的语法

原文
在这里插入图片描述
此语句创建一个新触发器。触发器是与表关联的一个数据库对象,并在表发生特定事件时激活。触发器与名为tbl_name的表相关联,此表必须引用永久表。不能将触发器与临时表或视图相关联 。

触发器名称存在于某一数据库的命名空间中,这意味着所有触发器必须具有唯一名称。不同数据库中的触发器可以具有相同的名称。

本节介绍CREATE TRIGGER语法。有关其他讨论,请参见 第24.3.1节“触发器语法和示例”

CREATE TRIGGER需要与触发器关联的表的TRIGGER权限。该语句可能还需要SET_USER_IDSUPER权限,具体取决于 DEFINER值,如本节后面所述。如果启用了二进制日志记录,则CREATE TRIGGER可能需要该 SUPER特权,如 第24.7节“存储程序的二进制日志记录”中所述。

DEFINER子句确定在触发器激活时检查访问权限时要使用的安全上下文,如本节后面所述。

trigger_time是触发器开始执行的时间。它可以是BEFOREAFTER表示触发器在每行要修改之前或之后激活。

基本列值检查在触发器激活之前发生,因此您无法使用BEFORE触发器将不适合列类型的值转换为有效值。

trigger_event表示激活触发器的操作类型。trigger_event允许这些 值:

  • INSERT:只要在表中插入新行,触发器就会激活; 例如,通过INSERT, LOAD DATA和 REPLACE语句。
  • UPDATE:只要修改了行,触发器就会激活; 例如,通过 UPDATE陈述。
  • DELETE:只要从表中删除行,触发器就会激活; 例如,通过 DELETE和 REPLACE语句。 DROP TABLETRUNCATE TABLE语句不会激活该触发器,因为它们不使用DELETE。删除分区也不会激活 DELETE触发器。

trigger_event不代表激活触发器的特定SQL语句,因为它表示一种表的操作。例如, INSERT触发器不仅被INSERT语句激活而且也被LOAD DATA语句激活,因为两个语句都将行插入表中。

一个可能令人困惑的例子是INSERT INTO ... ON DUPLICATE KEY UPDATE ...语法: BEFORE INSERT触发器为每一行激活,紧跟着是一个AFTER INSERT触发器或者BEFORE UPDATE和AFTER UPDATE触发器,具体取决于行是否有重复的键。

注意:级联外键操作不会激活触发器。

可以为表定义多个具有相同触发事件和开始时间的触发器。例如,您可以为表创建两个触发器BEFORE UPDATE。默认情况下,具有相同触发事件和操作时间的触发器按创建顺序激活。
要影响触发顺序,指定一个trigger_order部分,指示FOLLOWSPRECEDES与现有的触发器,也有同样的触发事件和动作时间的名称。使用时 FOLLOWS,新触发器在现有触发器之后激活;使用时PRECEDES,新触发器在现有触发器之前激活。

trigger_body是触发器激活时要执行的语句。要执行多个语句,请使用 BEGIN … END 复合语句构造。这也使您可以使用存储例程中允许的相同语句。请参见 第13.6.1节“BEGIN … END复合语句语法”。触发器中不允许使用某些语句; 请参见 第C.1节“存储程序的限制”。

在触发器主体中,您可以使用目标表(与触发器关联的表)的别名列 NEWOLD来进行引用某列。 在更新或删除之前,OLD.col_name指的是现有行的列。 NEW.col_name指的是要插入的新行的列或更新后的现有行。

触发器不能将 NEW.col_nameOLD.col_name用于
生成的列。有关生成的列的信息,请参见 第13.1.20.8节“创建表和生成的列”。

服务器的 sql_mode变量会影响触发器当时的创建和执行,事件开始执行时就不会理会当前服务器的sql_mode

DEFINER子句指定在触发器激活时检查访问权限时要使用的MySQL帐户。如果user给出值,它应该指定为MySQL账户 , 或 。默认 值是执行语句的用户 。这与 明确指定相同。 ‘user_name’@'host_name’CURRENT_USERCURRENT_USER()DEFINERCREATE TRIGGERDEFINER = CURRENT_USER
DEFINER部分指定了事件执行时候检查其执行权限的用户是谁,默认是当前执行创建事件的用户,如果你指定了值,此值必须是msyql用户之一,其形式可以是'user_name'@'host_name', CURRENT_USER, CURRENT_USER()这三种之一。

如果指定了DEFINER子句,下面这些规则确定有效的DEFINER用户值:

  • 如果你没有 SET_USER_IDSUPER特权,则唯一允许的user值是您自己的帐户,无论是字面指定还是使用 CURRENT_USER。您无法将定义者设置为其他帐户。
  • 如果您具有SET_USER_IDSUPER权限,则可以指定任何语法上有效的帐户名称。如果该帐户不存在,则会生成警告。
  • 虽然可以使用不存在的DEFINER帐户创建触发器,但在帐户确实存在之前激活此类触发器并不是一个好主意。此行为在权限检查权限的时候是未定义的。

DEFINER在检查触发权限时, MySQL会将用户考虑在内,如下所示:

  • CREATE TRIGGER的时候,发出语句的用户必须有 TRIGGER权限。

  • 在触发器激活时,将针对DEFINER用户检查权限 。该用户必须具有以下权限:
    – 目标表的TRIGGER 的权限。
    – 在触发器主体中引用OLD.col_nameNEW.col_name列,则要有目标表的 SELECT权限 。
    – 如果触发器主体中使用了SET NEW.col_name = value为列赋值,则要有目标表的UPDATE权限 。
    – 无论触发器执行的语句通常需要什么其他权限。

有关触发器安全性的更多信息,请参见 第24.6节“存储程序和视图的访问控制”。

在触发器主体内, CURRENT_USER()函数返回用于在触发器激活时检查权限的帐户。这是DEFINER用户,而不是其操作导致触发器被激活的用户。有关触发器内用户审核的信息,请参见 第6.3.13节“基于SQL的MySQL帐户活动审核”。

如果您使用LOCK TABLES锁定具有触发器的表,则触发器中使用的表也会被锁定,如 第13.3.6.2节“锁定表和触发器”中所述。

有关触发器使用的其他讨论,请参见 第24.3.1节“触发器语法和示例”。

13.1.32 删除表的语法

原文
在这里插入图片描述
DROP TABLE删除一个或多个表。您必须拥有每个表的DROP权限。

小心这个语句!它删除表定义和所有表数据。对于分区表,它会永久删除表定义,其所有分区以及存储在这些分区中的所有数据。它还会删除与已删除表关联的分区定义。

DROP TABLE导致隐式提交,除非与TEMPORARY 关键字一起使用。请参见第13.3.3节“导致隐式提交的语句”。

重要
删除表时,不会自动删除专门为该表授予的权限。必须手动删除它们。请参见 第13.7.1.6节“GRANT语法”。

如果参数列表中指定的任何表不存在,则该语句将失败并显示一个错误,该错误按名称指示它无法删除的不存在的表,并且不进行任何更改。

使用IF EXISTS以删除一个不存在的表时提示错误警告,这个警告可以用SHOW WARNINGS显示。请参见第13.7.6.40节“显示警告语法”。

IF EXISTS对于在特殊情况下删除表也很有用,在这种情况下,数据字典中有条目但没有存储引擎管理的表。(例如,如果在从存储引擎中删除表之后但在删除数据字典条目之前发生异常服务器退出。)

TEMPORARY关键字具有以下效果:

  • 该声明仅删除临时表。
  • 该语句不会导致隐式提交。
  • 没有检查访问权限。一个临时表的可见性只与创建它的会话有关,所以没必要检查。

使用TEMPORARY是确保您不会意外删除非临时表的好方法。

RESTRICTCASCADE 关键字没啥用。允许它们从其他数据库系统中轻松移植。

DROP TABLE并不支持innodb_force_recovery的所有设置。请参见 第15.20.2节“强制InnoDB恢复”。

13.1.34 删除触发器语法

DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
该语句删除了一个触发器。数据库名称是可选的。如果省略了数据库名,则会从默认数据库中删除触发器。DROP TRIGGER 需要与触发器关联的表的TRIGGER权限。

使用IF EXISTS以防止删除一个不存在的触发器错误。请参见 第13.7.6.40节“显示警告语法”。

如果删除表,也会删除表的触发器。

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值