五.PRIMARY KEY ---- 主鍵約束
主鍵可以是單個字段,也可以是多個字段的組合。主鍵約束其實是UNIQUE和NOT NULL約束的組合,即主鍵必須是唯一,且各字段都是NOT NULL的。
1.創建測試表
create table tbl_primary( a int not null, b int, c int, constraint pk_tbl_primary_a_b primary key (a,b) );
其中(a,b)是組合主鍵,即a和b的組合必須是唯一的,且a是not null,b也是not null的,雖然表定義中沒有明確b是not null的,但是因為b是主鍵的一部分,增加主鍵時會給b增加not null約束。
測試例
test=# insert into tbl_primary (a,b,c) values (1,1,1); INSERT 0 1 test=# insert into tbl_primary (a,b,c) values (1,2,1); INSERT 0 1 test=# insert into tbl_primary (a,b,c) values (1,1,1); ERROR: duplicate key value violates unique constraint "pk_tbl_primary_a_b" DETAIL: Key (a, b)=(1, 1) already exists. test=# insert into tbl_primary (a,c) values (1,5); ERROR: null value in column "b" violates not-null constraint DETAIL: Failing row contains (1, null, 5).
2.刪除主鍵約束
test=# alter table tbl_primary drop constraint pk_tbl_primary_a_b ; ALTER TABLE
3.增加主鍵約束
向已存在的表中增加主鍵約束就必須考慮已存在的數據不是唯一的,或者有可能是NULL,此時增加主鍵約束就會失敗,所以增加主鍵約束之前先刪除這些臟數據。
如果你看了前一節增加唯一約束前刪除臟數據,那么這一節簡直就是小kiss。
對主鍵來說臟數據包括2個部分:NULL和重復數據,刪除NULL數據比較簡單,使用下面的SQL語句即可
test=# delete from tbl_primary where a is null or b is null;
NULL數據刪除后,下面主要講如何刪除重復數據,和UNIQUE處理方式相同,有兩種處理方式:
一、將重復數據刪除到只剩一條
二、將重復數據全部刪除
方式一 將重復數據刪除到只剩一條
第一步:利用表的oids屬性,修改表的屬性
test=# alter table tbl_primary set with oids; ALTER TABLE
第二步:刪除主鍵約束,清空表,寫入測試數據
test=# alter table tbl_primary drop constraint pk_tbl_primary_a_b ; ALTER TABLE test=# delete from tbl_primary where a is null or b is null; DELETE 0 test=# insert into tbl_primary (a,b) values (1,1),(1,1),(1,1),(2,2),(2,2); INSERT 0 5 test=# select oid,* from tbl_primary ; oid | a | b | c -------+---+---+------ 16423 | 1 | 1 | 1 16424 | 1 | 2 | 1 16425 | 1 | 1 | NULL 16426 | 1 | 1 | NULL 16427 | 1 | 1 | NULL 16428 | 2 | 2 | NULL 16429 | 2 | 2 | NULL (7 rows)
第三步:查詢重復數據中最小oid
test=# select min(oid) from tbl_primary group by a,b; min ------- 16428 16423 16424 (3 rows)
第四步:查詢oid不是最小的重復數據
test=# select oid,* from tbl_primary where oid not in (select min(oid) from tbl_primary group by a,b); oid | a | b | c -------+---+---+------ 16425 | 1 | 1 | NULL 16426 | 1 | 1 | NULL 16427 | 1 | 1 | NULL 16429 | 2 | 2 | NULL (4 rows)
第五步:刪除oid不是最小的重復數據
將上面語句中的SELECT替換成DELETE即可
test=# delete from tbl_primary where oid not in (select min(oid) from tbl_primary group by a,b); DELETE 4 test=# select oid,* from tbl_primary ; oid | a | b | c -------+---+---+------ 16423 | 1 | 1 | 1 16424 | 1 | 2 | 1 16428 | 2 | 2 | NULL (3 rows)
第六步:增加主鍵
test=# alter table tbl_primary add constraint pk_tbl_primary_a_b primary key(a,b); ALTER TABLE
方式二 將重復數據全部刪除
第一步:刪除主鍵約束,清空表,寫入測試數據
alter table tbl_primary drop constraint pk_tbl_primary_a_b ; ALTER TABLE test=# delete from tbl_primary; DELETE 8 test=# insert into tbl_primary (a,b) values (1,1),(1,1),(1,1),(2,2),(2,2); INSERT 0 5 test=# select * from tbl_primary ; a | b | c ---+---+------ 1 | 1 | NULL 1 | 1 | NULL 1 | 1 | NULL 2 | 2 | NULL 2 | 2 | NULL (5 rows)
第二步:查詢重復的數據
test=# select a,b from tbl_primary group by a,b having count(*)>1; a | b ---+--- 2 | 2 1 | 1 (2 rows)
第三步:查詢所有的重復數據
test=# select * from tbl_primary where exists (select null from (select a,b from tbl_primary group by a,b having count(*)>1) tbl_temp where tbl_primary.a=tbl_temp.a and tbl_primary.b=tbl_temp.b); a | b | c ---+---+------ 1 | 1 | NULL 1 | 1 | NULL 1 | 1 | NULL 2 | 2 | NULL 2 | 2 | NULL (5 rows)
第四步:刪除所有的重復數據
將上面SQL語句中select替換成delete即可。
test=# delete from tbl_primary where exists (select null from (select a,b from tbl_primary group by a,b having count(*)>1) tbl_temp where tbl_primary.a=tbl_temp.a and tbl_primary.b=tbl_temp.b); DELETE 5
第五步:增加主鍵約束
test=# alter table tbl_primary add constraint pk_tbl_primary_a_b primary key(a,b); ALTER TABLE