InnoDB和NDB存储引擎支持 FOREIGN KEY 和 REFERENCES 子句,这些存储引擎实现了ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (...) REFERENCES ... (...)。对于其他存储引擎,将解析子句,但忽略它们。
与CREATE TABLE不同,对于ALTER TABLE,ADD FOREIGN KEY会忽略给定的index_name,并使用自动生成的外键名。作为一种解决方案,请使用 CONSTRAINT 子句来指定外键名:
1. ADD CONSTRAINT name FOREIGN KEY (....) ...
重要
MySQL忽略内联REFERENCES规范,其中引用被定义为列规范的一部分。MySQL只接受定义为独立外键规范一部分的REFERENCES子句。
注意
分区的InnoDB表不支持外键。这个限制不适用于NDB表,包括那些通过[LINEAR] KEY显式分区的表。
MySQL Server和NDB Cluster都支持使用ALTER TABLE来删除外键:
1. ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;
在ALTER TABLE ... ALGORITHM=INPLACE中,支持在同一ALTER TABLE语句中添加和删除外键,但是在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_nameibfk”开头的内部生成的外键约束名称和用户定义的外键约束名称,以反映新的表名。InnoDB将以字符串“tbl_nameibfk”开头的外键约束名称解释为内部生成的名称。
在MySQL 8.0.16之前,ALTER TABLE只允许以下有限版本的CHECK约束添加语法,它被解析并忽略:
1. ADD CHECK (expr)
从MySQL8.0.16开始,ALTER TABLE允许添加、删除或更改现有表的CHECK约束:
● 添加新的CHECK约束:
1. ALTER TABLE tbl_name
2. ADD CONSTRAINT [symbol] CHECK (expr) [[NOT] ENFORCED];
约束语法元素的含义与CREATE TABLE相同。
● 删除名为symbol的现有CHECK约束:
1. ALTER TABLE tbl_name
2 DROP CHECK symbol;
● 更改已存在的名为symbol的CHECK约束是否强制执行:
1. ALTER TABLE tbl_name ALTER CHECK symbol [NOT] ENFORCED;
DROP CHECK和ALTER CHECK子句是对标准SQL的MySQL扩展。
从MySQL 8.0.19开始,ALTER TABLE允许更通用的(遵从SQL标准)语法来删除和修改任何类型的现有约束,其中约束类型由约束名称决定:
● 删除已存在的名为 symbol 的约束:
1. ALTER TABLE tbl_name
2. DROP CONSTRAINT symbol;
如果启用了sql_require_primary_key系统变量,尝试删除主键会产生错误。
● 更改已存在的名为symbol的约束是否强制执行:
1. ALTER TABLE tbl_name
2. ALTER CONSTRAINT symbol [NOT] ENFORCED;
SQL标准指定所有类型的约束(主键、唯一索引、外键、检查)都属于同一个命名空间。在MySQL中,每个模式的每个约束类型都有自己的命名空间。因此,每种约束类型的名称对于每个模式都必须是唯一的,但是不同类型的约束可以具有相同的名称。当多个约束具有相同的名称时,DROP CONSTRAINT和ADD CONSTRAINT是不明确的,并且会发生错误。在这种情况下,必须使用特定于约束的语法来修改约束。例如,使用DROP PRIMARY KEY或DROP FOREIGN KEY删除主键或外键。
如果表更改导致违反强制CHECK约束,则会发生错误,并且不会修改表。发生错误的操作示例如下:
● 试图将AUTO_INCREMENT属性添加到CHECK约束中使用的列。
● 试图添加强制CHECK约束或将非强制CHECK约束改为强制约束,而这种更改会使现有行违反约束条件。
● 试图修改、重命名或删除CHECK约束中使用的列,除非该约束也在同一语句中被删除。例外:如果CHECK约束只引用一个列,删除该列将自动删除该约束。
ALTER TABLE tbl_name RENAME new_tbl_name更改内部生成的和用户定义的以字符串“tbl_namechk”开头的CHECK约束名称,以反映新的表名。MySQL将以字符串“tbl_namechk”开头的CHECK约束名称解释为内部生成的名称。
更改字符集
要将表默认字符集和所有字符列(CHAR, VARCHAR, TEXT)更改为新字符集,可以使用如下语句:
1. ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;
该语句还更改所有字符列的排序规则。如果不指定COLLATE子句来指示要使用哪个排序规则,则语句将对字符集使用默认排序规则。如果此排序规则不适用于预期的表用途(例如,如果它将从区分大小写的排序规则更改为不区分大小写的排序规则),请显式指定排序规则。
对于数据类型为VARCHAR或其中一种TEXT类型的列,CONVERT TO CHARACTER SET 会根据需要更改数据类型,以确保新列足够长,可以存储与原始列一样多的字符。例如,TEXT列有两个长度字节,用于存储列中值的字节长度,最大值为65535。对于latin1 TEXT列,每个字符需要一个字节,因此该列最多可存储65535个字符。如果将列转换为utf8,则每个字符可能需要最多三个字节,最大可能长度为3×65535=196605个字节。这个长度不适合TEXT列的长度字节,因此MySQL将数据类型转换为MEDIUMTEXT,MEDIUMTEXT是长度字节可以记录值196605的最小字符串类型。类似地,VARCHAR列可以转换为MEDIUMTEXT。
若要避免对刚才描述的类型进行数据类型更改,请不要使用CONVERT To CHARACTER SET,而应使用MODIFY来更改单个列。例如:
1. ALTER TABLE t MODIFY latin1_text_col TEXT CHARACTER SET utf8;
2. 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操作将不会应用于它们。
如果在CONVERT TO CHARACTER SET操作中默认使用DEFAULT作为字符集名称,则使用由character_set_database系统变量命名的字符集。
警告
CONVERT TO操作在原始字符集和命名字符集之间转换列值。如果有一个某种字符集的列(比如latin1),但是存储的值实际上使用了其他一些不兼容的字符集(比如utf8),这不是您想要的。在这种情况下,您必须对每个这样的列执行以下操作:
1. ALTER TABLE t1 CHANGE c1 c1 BLOB;
2. ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;
这样做的原因是在转换到BLOB列或从BLOB列转换时没有转换。
若要仅更改表的默认字符集,请使用以下语句:
ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;
单词DEFAULT是可选的。默认字符集是如果没有为以后添加到表中的列指定字符集时使用的字符集(例如,ALTER TABLE ... ADD column)。
对于包含外键约束中使用的字符串列的表,不允许进行字符集转换。解决方法是在执行字符集转换之前禁用foreign_key_checks。在重新启用foreign_key_checks之前,必须对涉及外键约束的两个表执行转换。如果在仅转换一个表后重新启用foreign_key_checks,则由于在这些操作期间发生隐式转换,ON DELETE CASCADE或ON UPDATE CASCADE操作可能会损坏引用表中的数据。
导入InnoDB表
使用DISCARD TABLESPACE和IMPORT TABLESPACE子句,可以从备份或另一个MySQL服务器实例导入InnoDB 独立表空间。
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中,因为刚刚列出的选项作用于各个分区。
官方文档:
https://dev.mysql.com/doc/refman/8.0/en/alter-table.html
阅读 4
赞1
在看1
MySQL的SQL语句 - 数据定义语句(6)- ALTER TABLE 语句 (4)
原文:https://blog.51cto.com/15023289/2560864