MySQL的限制和限制/分区的限制和限制/分区键、主键和唯一键

10.1分区键、主键和唯一键

本节讨论分区键与主键和惟一键的关系。控制这种关系的规则可以这样表达:分区表的分区表达式中使用的所有列都必须是该表可能拥有的每个惟一键的一部分。

换句话说,表上的每个惟一键必须使用表的分区表达式中的每一列。(这也包括表的主键,因为根据定义,它是唯一的键。这种特殊情况将在本节稍后讨论。)例如,下面的表创建语句都是无效的:

CREATE TABLE t1 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col2)) PARTITION BY HASH(col3) PARTITIONS 4;CREATE TABLE t2 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1), UNIQUE KEY (col3)) PARTITION BY HASH(col1 + col3) PARTITIONS 4;

在每种情况下,建议的表至少有一个惟一键,该键不包括分区表达式中使用的所有列。

下面的每个语句都是有效的,并且表示了相应的无效表创建语句可以工作的一种方式:

CREATE TABLE t1 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col2, col3)) PARTITION BY HASH(col3) PARTITIONS 4;CREATE TABLE t2 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col3)) PARTITION BY HASH(col1 + col3) PARTITIONS 4;

这个例子显示了在这种情况下产生的错误:

mysql> CREATE TABLE t3 (-> col1 INT NOT NULL, -> col2 DATE NOT NULL, -> col3 INT NOT NULL, -> col4 INT NOT NULL, -> UNIQUE KEY (col1, col2), -> UNIQUE KEY (col3) ->) -> PARTITION BY HASH(col1 + col3) -> PARTITIONS 4;错误1491 (HY000):主键必须包括表的分区功能中的所有列

创建表语句失败是因为col1col3都包含在建议的分区键中,但是这两个列都不是表上两个惟一键的一部分。这显示了一个可能的修复无效表定义:

mysql> CREATE TABLE t3 (-> col1 INT NOT NULL, -> col2 DATE NOT NULL, -> col3 INT NOT NULL, -> col4 INT NOT NULL, -> UNIQUE KEY (col1, col2, col3), -> UNIQUE KEY (col3) ->) -> PARTITION BY HASH(col3) -> PARTITIONS 4;查询OK,受影响0行(0.05秒)

在本例中,是建议的分区键col3是两个惟一键的一部分,表创建语句成功。

下面的表根本不能分区,因为分区键中不能包含同时属于两个唯一键的任何列:

CREATE TABLE t4 (col1 INT NOT NULL, col2 INT NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col3), UNIQUE KEY (col2, col4));

因为根据定义,每个主键都是唯一的键,所以这个限制还包括表的主键(如果它有主键的话)。例如,下面两个语句是无效的:

CREATE TABLE t5 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, PRIMARY KEY(col1, col2)) PARTITION BY HASH(col3) PARTITIONS 4;CREATE TABLE t6 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, PRIMARY KEY(col1, col3), UNIQUE KEY(col2)) PARTITION BY HASH(YEAR(col2)) PARTITIONS 4;

在这两种情况下,主键都不包括分区表达式中引用的所有列。然而,下面两个语句都是有效的:

CREATE TABLE t7 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, PRIMARY KEY(col1, col2)) PARTITION BY HASH(col1 + YEAR(col2)) PARTITIONS 4;CREATE TABLE t8 (col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, PRIMARY KEY(col1, col2, col4), UNIQUE KEY(col2, col1)) PARTITION BY HASH(col1 + YEAR(col2)) PARTITIONS 4;

如果表没有唯一键(包括没有主键),则不适用此限制,只要列类型与分区类型兼容,就可以在分区表达式中使用任何列。

出于同样的原因,您以后不能向已分区的表添加唯一键,除非该键包含表的分区表达式使用的所有列。考虑如下所示创建的分区表:

CREATE TABLE t_no_pk (c1 INT, c2 INT) -> PARTITION BY RANGE(c1) (-> PARTITION p0 VALUES LESS THAN (10), -> PARTITION p1 VALUES LESS THAN (20), -> PARTITION p2 VALUES LESS THAN (30), -> PARTITION p3 VALUES LESS THAN (40) ->);查询OK, 0行受影响(0.12秒)

可以将主键添加到t_no_pk使用任何一种方法ALTER TABLE声明:

#可能PK mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c1);# drop this PK mysql> ALTER TABLE t_no_pk drop PRIMARY KEY;#使用另一个可能的PK mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c1, c2);# drop this PK mysql> ALTER TABLE t_no_pk drop PRIMARY KEY;查询OK, 0行影响(0.09 sec)记录:0重复:0警告:0

但是,下一条语句失败了,因为c1是分区键的一部分,但不是建议的主键的一部分:

mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c2);ERROR 1503 (HY000): PRIMARY KEY必须包含表的分区功能中的所有列

t_no_pk只有c1在其分区表达式中,试图在其上添加唯一键c2就失败。但是,您可以添加一个使用两者的唯一键c1c2

这些规则也适用于希望使用分区的现有非分区表ALTER TABLE……分区的。考虑一个表np_pk创建如下所示:

mysql> CREATE TABLE np_pk (-> id INT NOT NULL AUTO_INCREMENT, -> name VARCHAR(50), -> added DATE, -> PRIMARY KEY (id) ->);查询OK, 0行受影响(0.08秒)

以下ALTER TABLE语句失败并报错,因为添加列不是表中任何唯一键的一部分:

mysql> ALTER TABLE np_pk -> PARTITION BY HASH(TO_DAYS(added)) -> PARTITIONS 4;ERROR 1503 (HY000): PRIMARY KEY必须包含表的分区功能中的所有列

但是,此语句使用id分区列的列是有效的,如下所示:

mysql> ALTER TABLE np_pk -> PARTITION BY HASH(id) -> PARTITIONS 4;查询OK, 0行影响(0.11秒)记录:0重复:0警告:0

在……的情况下np_pk,唯一可以用作分区表达式一部分的列是id;如果希望使用分区表达式中的任何其他列对这个表进行分区,则必须首先修改这个表,要么将所需的列添加到主键,要么完全删除主键。