概述
演示唯一约束怎样创建、删除、禁用和使用唯一性约束,已经多种数据库的差异。
什么是唯一约束
唯一性约束指表中一个字段或者多个字段联合起来可以唯一标识一条记录的约束, 字段中,可以包括空值。
唯一性约束能够在创建表时或使用ALTER TABLE语句创建。
唯一约束与唯一索引的区别
唯一约束和唯一索引,都可以实现列数据的唯一,列值可以有null。
创建唯一约束,会自动创建一个同名的唯一索引,该索引不能单独删除,删除约束会自动删除索引。唯一约束是通过唯一索引来实现数据的唯一。
创建一个唯一索引,这个索引就是独立,可以单独删除。
如果表的一个字段,要作为另外一个表的外键,这个字段必须有唯一约束(或是主键),如果只是有唯一索引,就会报错。
唯一约束和主键的区别
主键(Primary Key):全部组成主键的列都不能包括空值。
唯一性约束(Unique Constraint):假设唯一性约束由多列组成,当中的部分列能够包括空值。
主键和唯一性约束自动建立了同名唯一性索引。
一个表只能有一个主键,但可以有多个约束。
KingbaseES的唯一约束
单列约束
kingbase=# createtable t1 (c1 int, c2 int);
CREATETABLE
kingbase=# altertable t1 addconstraint t1_u1 unique (c1);
ALTERTABLE
kingbase=# insertinto t1 values (1, 1);
INSERT01
kingbase=# insertinto t1 values (1, 2);
错误: 重复键违反唯一约束"t1_u1"
描述: 键值"(c1)=(1)" 已经存在
kingbase=# insertinto t1 values (null, 2);
INSERT01
kingbase=# insertinto t1 values (null, 3);
INSERT01
kingbase=# select*from t1;
c1 | c2
----+----1|1|2|3
(3 行记录)
KingbaseES的单列唯一约束,不检查null值的数据。
多列约束
kingbase=# createtable t1 (c1 int, c2 int);
CREATETABLE
kingbase=# altertable t1 addconstraint t1_u1 unique (c1, c2);
ALTERTABLE
kingbase=# insertinto t1 values (1, 1);
INSERT01
kingbase=# insertinto t1 values (1, 1);
错误: 重复键违反唯一约束"t1_u1"
描述: 键值"(c1, c2)=(1, 1)" 已经存在
kingbase=# insertinto t1 values (null, 2);
INSERT01
kingbase=# insertinto t1 values (null, 2);
INSERT01
kingbase=# insertinto t1 values (3, null);
INSERT01
kingbase=# insertinto t1 values (3, null);
INSERT01
kingbase=# insertinto t1 values (null, null);
INSERT01
kingbase=# insertinto t1 values (null, null);
INSERT01
kingbase=# select*from t1 ;
c1 | c2
----+----1|1|2|23|3|||
(7 行记录)
KingbaseES的多列唯一约束,不检查含有null值的数据。如果某个约束列是null值,则不能保证记录的唯一。
使用唯一索引建立约束
kingbase=# createtable t1 (c1 int, c2 int);
CREATETABLE
kingbase=# createunique index t1_c1 on t1 (c1);
CREATE INDEX
kingbase=# select indexrelid,indexrelid::regclass::text from pg_index where indrelid='t1'::regclass;
indexrelid | indexrelid
------------+------------
212572| t1_c1
(1 行记录)
kingbase=# altertable t1 addconstraint t1_u1 uniqueusing index t1_c1;
注意: ALTERTABLE/ADDCONSTRAINTUSING INDEX 会把索引 "t1_c1" 重命名为 "t1_u1"
ALTERTABLE
kingbase=# select indexrelid,indexrelid::regclass::text from pg_index where indrelid='t1'::regclass;
indexrelid | indexrelid
------------+------------
212572| t1_u1
(1 行记录)
kingbase=# drop index t1_c1;
错误: 索引 "t1_c1" 不存在
kingbase=# drop index t1_u1;
错误: 无法删除 索引 t1_u1, 因为 在表 t1上的约束t1_u1 需要它
提示: 您也可以删除 在表 t1上的约束t1_u1 代替.
kingbase=# altertable t1 dropconstraint t1_u1;
ALTERTABLE
kingbase=# select indexrelid,indexrelid::regclass::text from pg_index where indrelid='t1'::regclass;
indexrelid | indexrelid
------------+------------
(0 行记录)
已存在唯一索引,被用于唯一约束之后,索引名会被修改为约束名。唯一索引同时不能单独被删除,删除唯一约束的同时,删除其使用的索引。
外键
kingbase=# createtable t1 (c1 int, c2 int);
CREATETABLE
kingbase=# altertable t1 addconstraint t1_u1 unique (c1);
ALTERTABLE
kingbase=# createunique index t1_c2 on t1 (c2);
CREATE INDEX
kingbase=# createtable t2 (c1 int, c2 int);
CREATETABLE
kingbase=# altertable t2 addconstraint fk_c1 foreign key(c1) references t1(c1);
ALTERTABLE
kingbase=# altertable t2 addconstraint fk_c2 foreign key(c2) references t1(c2);
错误: there isnouniqueconstraint matching given keys for referenced table "t1"
kingbase=#
外键,只能参考唯一约束,不能参考唯一索引。