1.1.1 唯一约束
唯一约束保证在一列中或者一组列中保存的数据在表中所有行间是唯一的。
写成一个列约束的语法是:
CREATE TABLE products (
product_no integer UNIQUE,
name text,
price numeric
);
写成一个表约束的语法是:
CREATE TABLE products (
product_no integer,
name text,
price numeric,
UNIQUE (product_no)
);
要为一组列定义一个唯一约束,把它写作一个表级约束,列名用逗号分隔:
CREATE TABLE example (
a integer,
b integer,
c integer,
UNIQUE (a, c)
);
这指定这些列的组合值在整个表的范围内是唯一的,但其中任意一列的值并不需要是(一般也不是)唯一的。
我们可以通常的方式为一个唯一索引命名:
CREATE TABLE products (
product_no integer CONSTRAINT must_be_different UNIQUE,
name text,
price numeric
);
增加一个唯一约束会在约束中列出的列或列组上自动创建一个唯一B-tree索引。
通常,如果表中有超过一行在约束所包括列上的值相同,将会违反唯一约束。
但是在这种比较中,两个空值被认为是不同的。
1.1.2 主键
主键 = 非空 + 唯一(会创建唯一索引)
表中主键只能有一个,但是可以利用 非空+唯一实现多个主键的效果
一个主键约束表示可以用作表中行的唯一标识符的一个列或者一组列。
这要求那些值都是唯一的并且非空。因此,下面的两个表定义接受相同的数据:
CREATE TABLE products (
product_no integer UNIQUE NOT NULL,
name text,
price numeric
);
CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
);
主键也可以包含多于一个列,其语法和唯一约束相似:
CREATE TABLE example (
a integer,
b integer,
c integer,
PRIMARY KEY (a, c)
);
增加一个主键将自动在主键中列出的列或列组上创建一个唯一B-tree索引。并且会强制这些列被标记为NOT NULL。
一个表最多只能有一个主键(可以有任意数量的唯一和非空约束,它们可以达到和主键几乎一样的功能,但只能有一个被标识为主键)。
关系数据库理论要求每一个表都要有一个主键。方便定位数据。
1.1.3 外键
一个外键约束指定一列(或一组列)中的值必须匹配出现在另一个表中某些行的值。我们说这维持了两个关联表之间的引用完整性。
例如我们有一个使用过多次的产品表:
CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
);
让我们假设我们还有一个存储这些产品订单的表。我们希望保证订单表中只包含真正存在的产品的订单。因此我们在订单表中定义一个引用产品表的外键约束:
CREATE TABLE orders (
order_id integer PRIMARY KEY,
product_no integer REFERENCES products (product_no),
quantity integer
);
现在就不可能创建包含不存在于产品表中的product_no值(非空)的订单。
我们说在这种情况下,订单表是引用表而产品表是被引用表。相应地,也有引用和被引用列的说法。
CREATE TABLE orders (
order_id integer PRIMARY KEY,
product_no integer REFERENCES products,
quantity integer
);
因为如果缺少列的列表,则被引用表的主键将被用作被引用列。
一个外键也可以约束和引用一组列。照例,它需要被写成表约束的形式。下面是一个例子:
CREATE TABLE t1 (
a integer PRIMARY KEY,
b integer,
c integer,
FOREIGN KEY (b, c) REFERENCES other_table (c1, c2)
);
当然,被约束列的数量和类型应该匹配被引用列的数量和类型。
CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
);
CREATE TABLE orders (
order_id integer PRIMARY KEY,
shipping_address text,
...
);
CREATE TABLE order_items (
product_no integer REFERENCES products ON DELETE RESTRICT,
order_id integer REFERENCES orders ON DELETE CASCADE,
quantity integer,
PRIMARY KEY (product_no, order_id)
);
限制删除或者级联删除是两种最常见的选项。RESTRICT阻止删除一个被引用的行。
CASCADE指定当一个被引用行被删除后,引用它的行也应该被自动删除。
还有其他两种选项:SET NULL和SET DEFAULT。这些将导致在被引用行被删除后,引用行中的引用列被置为空值或它们的默认值。
一个外键所引用的列必须是一个主键或者被唯一约束所限制。这意味着被引用列总是拥有一个索引(位于主键或唯一约束之下的索引),因此在其上进行的一个引用行是否匹配的检查将会很高效。
由于从被引用表中DELETE一行或者UPDATE一个被引用列将要求对引用表进行扫描以得到匹配旧值的行,在引用列上建立合适的索引也会大有益处。
1.1.4 排他约束
排他约束保证如果将任何两行的指定列或表达式使用指定操作符进行比较,至少其中一个操作符比较将会返回否或空值。语法是:
CREATE TABLE circles (
c circle,
EXCLUDE USING gist (c WITH &&)
);
增加一个排他约束将在约束声明所指定的类型上自动创建索引。