根据我对文档的理解,以下定义是等价的:
create table foo (
id serial primary key,
code integer,
label text,
constraint foo_uq unique (code, label));
create table foo (
id serial primary key,
code integer,
label text);
create unique index foo_idx on foo using btree (code, label);
然而,Postgres 9.4手册中的注释说:
向表中添加唯一约束的首选方法是ALTER table…添加约束。使用索引来强制惟一的约束
可以被认为是一个不应该被认为是实现细节的实现吗
直接访问。
(编辑:此说明已从Postgres 9.5的手册中删除。)
仅仅是风格的问题吗?选择其中一个变量的实际后果是什么(例如在性能方面)?
我在医生里读到:
ADD table_constraint [ NOT VALID ]
This form adds a new constraint to a table using the same syntax as CREATE TABLE, plus the option NOT VALID, which is currently only allowed for foreign key constraints. If the constraint is marked NOT VALID, the potentially-lengthy initial check to verify that all rows in the table satisfy the constraint is skipped. The constraint will still be enforced against subsequent inserts or updates (that is, they'll fail unless there is a matching row in the referenced table). But the database will not assume that the constraint holds for all rows in the table, until it is validated by using the VALIDATE CONSTRAINT option.
所以我认为这就是你所说的“部分唯一性”通过添加一个约束。
以及,关于如何确保唯一性:
Adding a unique constraint will automatically create a unique B-tree index on the column or group of columns listed in the constraint. A uniqueness restriction covering only some rows cannot be written as a unique constraint, but it is possible to enforce such a restriction by creating a unique partial index.
Note: The preferred way to add a unique constraint to a table is ALTER TABLE … ADD CONSTRAINT. The use of indexes to enforce unique constraints could be considered an implementation detail that should not be accessed directly. One should, however, be aware that there’s no need to manually create indexes on unique columns; doing so would just duplicate the automatically-created index.
因此,我们应该添加约束,它创建一个索引,以确保唯一性。
我怎么看这个问题?
“约束”的目的是在语法上确保这一列应该是唯一的,它建立了一个法律,一个规则;而“索引”是语义上的,关于“如何实现,如何实现唯一性,在实现时唯一性意味着什么”。所以,Postgresql实现它的方式是非常符合逻辑的:首先,你声明一个列应该是唯一的,然后,Postgresql为你添加一个唯一索引的实现。
SELECT a.phone_number,count(*) FROM public.users a
Group BY phone_number Having count(*)>1;
SELECT a.phone_number,count(*) FROM public.retailers a
Group BY phone_number Having count(*)>1;
select a.phone_number from users a inner join users b
on a.id <> b.id and a.phone_number = b.phone_number order by a.id;
select a.phone_number from retailers a inner join retailers b
on a.id <> b.id and a.phone_number = b.phone_number order by a.id
DELETE FROM
users a
USING users b
WHERE
a.id > b.id
AND a.phone_number = b.phone_number;
DELETE FROM
retailers a
USING retailers b
WHERE
a.id > b.id
AND a.phone_number = b.phone_number;
CREATE UNIQUE INDEX CONCURRENTLY users_phone_number
ON users (phone_number);
验证:
insert into users(name,phone_number,created_at,updated_at) select name,phone_number,created_at,updated_at from users