postgresql----数据库表约束----UNIQUE

四、UNIQUE ---- 唯一约束

唯一键可以是单个字段,也可以是多个字段的组合,设置唯一约束后,INSERT或UPDATE时如果表中唯一键字段中已存在该数据,则拒绝该行数据的INSERT或UPDATE。但是数据库中NULL并不等于NULL,所以唯一键中如果没有NOT NULL约束,则可以在唯一键中INSERT或UPDATE任意多个NULL。

1.创建测试表

唯一约束为组合键(a,b),即a和b的组合必须是唯一的。

create table tbl_unique(
a int not null,
b int,
c varchar(10) not null default ‘catch u‘,
constraint uk_tbl_unique_a_b unique(a,b)
);

向tbl_unique表中写入数据(1,,1,‘test‘)

test=# insert into tbl_unique (a,b,c) values(1,1,‘test‘);
INSERT 0 1

再次写入(a,b)组合(1,1)时,则会返回错误。

test=# insert into tbl_unique (a,b,c) values(1,1,‘u see‘);
ERROR:  duplicate key value violates unique constraint "uk_tbl_unique_a_b"
DETAIL:  Key (a, b)=(1, 1) already exists.

那么唯一键中出现NULL呢?唯一键中可以写入任意多个NULL!

test=# insert into tbl_unique (a) values(2);
INSERT 0 1
test=# insert into tbl_unique (a) values(2);
INSERT 0 1
test=# insert into tbl_unique (a) values(2);
INSERT 0 1
test=# \pset null ‘NULL‘
Null display is "NULL".
test=# select * from tbl_unique ;
 a |  b   |    c
---+------+---------
 1 |    1 | test
 2 | NULL | catch u
 2 | NULL | catch u
 2 | NULL | catch u
(4 rows)

2.唯一键约束删除

test=# alter table tbl_unique drop constraint uk_tbl_unique_a_b ;
ALTER TABLE

3.唯一键约束增加

如果你想向表中增加唯一约束,必须要考虑表中已存在的数据可能存在重复数据。重复的数据有两种理解方式:

方式一:严格意义上的唯一,NULL不等于NULL,即(1,NULL)和(1,NULL)不是重复数据。

方式二:非严格意义上的唯一,NULL等于NULL,即(1,NULL)和(1,NULL)是重复数据。

所以向表中增加唯一约束必须要删除这些重复数据,或者将重复数据删除到唯一。

情况一:删除严格意义上的重复

第一步:清空测试表,写入一些测试数据。

test=# delete from tbl_unique ;
DELETE 4
test=# insert into tbl_unique (a,b) values (1,1),(1,1),(1,1);
INSERT 0 3
test=# insert into tbl_unique (a) values (2),(2),(2);
INSERT 0 3
test=# select * from tbl_unique ;
 a |  b   |    c
---+------+---------
 1 |    1 | catch u
 1 |    1 | catch u
 1 |    1 | catch u
 2 | NULL | catch u
 2 | NULL | catch u
 2 | NULL | catch u
(6 rows)

从结果中看,严格意义上的唯一有1个(1,1,‘catch u‘)和3个(2,NULL,‘catch u‘),删除重复数据即是要删除所有的(1,1,‘catch u‘)。这种情况下只要使用下面的语句删除即可。

delete from tbl_unique where a= 1 and b = 1;

但是如果表中存在成千上万个这种重复数据,这么一条一条的删除岂不显得低级?!

第二步:查询(a,b)存在重复的数据

test=# select a,b from tbl_unique where a is not null and b is not null group by a,b having count(*) > 1;
 a | b
---+---
 1 | 1
(1 row)

第三步:查询所有(a,b)重复的数据

test=# select * from tbl_unique where exists(select null from (select a,b from tbl_unique where a is not null and b is not null group by a,b having count(*) > 1)tbl_temp where tbl_temp.a=tbl_unique.a and tbl_temp.b=tbl_unique.b) ;
 a | b |    c
---+---+---------
 1 | 1 | catch u
 1 | 1 | catch u
 1 | 1 | catch u
(3 rows)

第四步:删除所有(a,b)重复的数据

把上面的语句中select *替换成 delete就可以了。

test=# delete from tbl_unique where exists(select null from (select a,b from tbl_unique where a is not null and b is not null group by a,b having count(*) > 1)tbl_temp where tbl_temp.a=tbl_unique.a and tbl_temp.b=tbl_unique.b) ;
DELETE 3
test=# select * from tbl_unique ;
 a |  b   |    c
---+------+---------
 2 | NULL | catch u
 2 | NULL | catch u
 2 | NULL | catch u
(3 rows)

第五步:增加唯一约束

test=# alter table tbl_unique add constraint uk_tbl_unique_a_b unique (a,b);
ALTER TABLE

情况二:删除非严格意义重复数据

第一步:删除约束,清空数据,写入测试数据

test=# alter table tbl_unique drop constraint uk_tbl_unique_a_b ;
ALTER TABLE
test=# delete from tbl_unique ;
DELETE 3
test=# insert into tbl_unique (a,b) values (1,1),(1,1),(1,1);
INSERT 0 3
test=# insert into tbl_unique (a) values (2),(2),(2);
INSERT 0 3
test=# select * from tbl_unique ;
 a |  b   |    c
---+------+---------
 1 |    1 | catch u
 1 |    1 | catch u
 1 |    1 | catch u
 2 | NULL | catch u
 2 | NULL | catch u
 2 | NULL | catch u
(6 rows)

非严格意义上该表中的数据全部是重复数据,和情况一比只需要把NOT NULL过滤条件去掉即可。

第二步:查询(a,b)重复数据

test=# select a,b from tbl_unique group by a,b having count(*) > 1;
 a |  b
---+------
 2 | NULL
 1 |    1
(2 rows)

第三步:查询所有(a,b)重复数据

test=# select * from tbl_unique where exists(select null from (select a,b from tbl_unique group by a,b having count(*) > 1)tbl_temp where (tbl_temp.a=tbl_unique.a and tbl_temp.b=tbl_unique.b) or (tbl_temp.a is null and tbl_unique.a is null) or (tbl_temp.b is null and tbl_unique.b is null)) ;
 a |  b   |    c
---+------+---------
 1 |    1 | catch u
 1 |    1 | catch u
 1 |    1 | catch u
 2 | NULL | catch u
 2 | NULL | catch u
 2 | NULL | catch u
(6 rows)

第四步:删除所有(a,b)重复数据

同样把上面语句的select * 替换成delete即可。

test=# delete from tbl_unique where exists(select null from (select a,b from tbl_unique group by a,b having count(*) > 1)tbl_temp where (tbl_temp.a=tbl_unique.a and tbl_temp.b=tbl_unique.b) or (tbl_temp.a is null and tbl_unique.a is null) or (tbl_temp.b is null and tbl_unique.b is null)) ;
DELETE 6
test=# select * from tbl_unique ;
 a | b | c
---+---+---
(0 rows)

第五步:增加唯一键约束

test=# alter table tbl_unique add constraint uk_tbl_unique_a_b unique (a,b);
ALTER TABLE

如果表中没有主键或NOT NULL的唯一键,那么可以利用表的OID属性,将表的oid列显示出来,该列类似主键的功能。利用该列,可以将重复数据删除到只剩一条,先使用下面的SQL语句,修改表的属性。

test=# alter table tbl_unique set with oids;
ALTER TABLE

情况三:将严格意义上重复数据删除到只有一条

第一步:删除表约束,清空表,写入测试数据

test=# alter table tbl_unique drop constraint uk_tbl_unique_a_b ;
ALTER TABLE
test=# delete from tbl_unique ;
DELETE 0
test=# insert into tbl_unique (a,b) values (1,1),(1,1),(1,1);
INSERT 0 3
test=# insert into tbl_unique (a) values (2),(2),(2);
INSERT 0 3
test=# select oid,* from tbl_unique ;
  oid  | a |  b   |    c
-------+---+------+---------
 16399 | 1 |    1 | catch u
 16400 | 1 |    1 | catch u
 16401 | 1 |    1 | catch u
 16402 | 2 | NULL | catch u
 16403 | 2 | NULL | catch u
 16404 | 2 | NULL | catch u
(6 rows)

严格意义上的重复数据是3条(1,1,‘catch u‘),现在要将三条的重复数据,删除到只剩一条。

第二步:查询重复数据的最小oid

test=# select min(oid) from tbl_unique where a is not null and b is not null group by a,b;
  min
-------
 16399
(1 row)

第三步:查询oid不是最小的重复数据

test=# select oid,* from tbl_unique where oid not in(select min(oid) from tbl_unique where a is not null and b is not null group by a,b) and a is not null and b is not null;
  oid  | a | b |    c
-------+---+---+---------
 16400 | 1 | 1 | catch u
 16401 | 1 | 1 | catch u
(2 rows)

第四步:删除oid不是最小的重复数据

把上面的SQL语句中select替换成delete即可。

test=# delete from tbl_unique where oid not in(select min(oid) from tbl_unique where a is not null and b is not null group by a,b) and a is not null and b is not null;
DELETE 2
test=# select oid,* from tbl_unique ;
  oid  | a |  b   |    c
-------+---+------+---------
 16399 | 1 |    1 | catch u
 16402 | 2 | NULL | catch u
 16403 | 2 | NULL | catch u
 16404 | 2 | NULL | catch u
(4 rows)

第五步:增加唯一键约束

test=# alter table tbl_unique add constraint uk_tbl_unique_a_b unique (a,b);
ALTER TABLE

情况四:将非严格意义上重复数据删除到只有一条

第一步:删除唯一约束,清空表,写入测试数据

test=# alter table tbl_unique drop constraint uk_tbl_unique_a_b ;
ALTER TABLE
test=# delete from tbl_unique ;
DELETE 4
test=# insert into tbl_unique (a,b) values (1,1),(1,1),(1,1);
INSERT 0 3
test=# insert into tbl_unique (a) values (2),(2),(2);
INSERT 0 3
test=# select oid,* from tbl_unique ;
  oid  | a |  b   |    c
-------+---+------+---------
 16407 | 1 |    1 | catch u
 16408 | 1 |    1 | catch u
 16409 | 1 |    1 | catch u
 16410 | 2 | NULL | catch u
 16411 | 2 | NULL | catch u
 16412 | 2 | NULL | catch u
(6 rows)

第二步:查询重复数据的最小oid

test=# select min(oid) from tbl_unique group by a,b;
  min
-------
 16410
 16407
(2 rows)

第三步:查询oid不是最小的重复数据

test=# select oid,* from tbl_unique where oid not in(select min(oid) from tbl_unique group by a,b);
  oid  | a |  b   |    c
-------+---+------+---------
 16408 | 1 |    1 | catch u
 16409 | 1 |    1 | catch u
 16411 | 2 | NULL | catch u
 16412 | 2 | NULL | catch u
(4 rows)

第四步:删除oid不是最小的重复数据

把上面的SQL语句中select替换成delete即可。

test=# delete from tbl_unique where oid not in(select min(oid) from tbl_unique group by a,b);
DELETE 4
test=# select oid,* from tbl_unique ;
  oid  | a |  b   |    c
-------+---+------+---------
 16407 | 1 |    1 | catch u
 16410 | 2 | NULL | catch u
(2 rows)

第五步:增加唯一键约束

test=# alter table tbl_unique add constraint uk_tbl_unique_a_b unique (a,b);
ALTER TABLE
时间: 2024-11-06 07:47:55

postgresql----数据库表约束----UNIQUE的相关文章

PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库

最近准备下PostgreSQL数据库开发的相关知识,本文把总结的PPT内容通过博客记录分享,本随笔的主要内容是介绍PostgreSQL数据库的基础信息,以及如何在我们的开发框架中使用PostgreSQL数据库,希望大家多多提意见. 1.PostgreSQL数据库介绍 PostgreSQL是以加州大学伯克利分校计算机系开发的 POSTGRES,现在已经更名为PostgreSQL.它具有很多不错的特点: 开源:PostgreSQL 是一个自由的对象-关系数据库服务器(数据库管理系统),它在灵活的 B

数据库并发事务控制四:postgresql数据库的锁机制二:表锁

在博文<数据库并发事务控制四:postgresql数据库的锁机制 > http://blog.csdn.net/beiigang/article/details/43302947 中后面提到: 常规锁机制可以参考pg的官方手册,章节和内容见下面 13.3. Explicit Locking http://www.postgresql.org/docs/9.4/static/explicit-locking.html 这节分为:表锁.行锁.页锁.死锁.Advisory锁(这个名字怎么翻译好???

PostgreSQL 数据库错误状态编号解释[附带列表

PostgreSQL 服务器发出的所有消息都赋予了五个字符的错误代码, 这些代码遵循 SQL 的 "SQLSTATE" 代码的习惯.需要知道发生了什么错误条件的应用通常应该测试错误代码,而不是查看文本错误信息.这些错误 代码轻易不会随着 PostgreSQL 的版本更新而修改,并且一般也不会随着错误信息的本地化而发生修改. 请注意有些,但不是全部,PostgreSQL 生成的错误代码是由 SQL 标准定义的: 有些标准没有定义的错误条件是我们发明的或者是从其它数据库借来的. 根据标准,

PowerDesigner反向工程PostgreSQL数据库

1. 环境准备: a)         安装PowerDesigner,以PowerDesigner15.1为例 b)         安装java jdk,以jdk-7-windows-i586为例 c)         下载postgressql jdbc驱动jar包,以postgresql-8.1-415.jdbc2.jar为例 2. 远程连接PostgreSQL数据库 a)         打开PowerDesigner b)         新建一个空白物理数据模型 点击PowerDe

PostgreSQL数据库内核分析 笔记(这本书没有怎么很好的看,主要就是一些数据结构、概念和流程的文字介绍)

PostgreSQL数据库内核分析 跳转至: 导航. 搜索 目录 1系统概述 2体系结构 3存储管理 4索引 5查询编译 6查询执行 7事务处理与并发控制 8数据库安全 9附录A 用Eclipse开发和调试 系统概述 初始化数据库:./initdb --no-locale -D ../data ./pg_ctl start -D ../data 数据库命令:initdb createuser dropuser createdb dropdb pg_dump pg_restore pg_ctl v

安装PostgreSQL数据库(Linux篇) [转]

from marsprj 0.编译环境 Linux: CentOS 5.5 gcc: 4.1.2 1. 安装PostgreSQL 1) 解压postgresql-9.1.7.tar.bz2 #tar jxvf postgresql-9.1.7.tar.bz2 2) 进入解压后的postgresql-9.1.7目录 #cd postgresql-9.1.7 3) 编译postgresql源码 #./configure --prefix=/opt/pgsql-9.1.7 #make #make in

[SQL]远程使用PostgreSQL Studio可视化查看PostgreSQL数据库

1.下载 前往官网地址下载最新的PostgreSQL Studio,我下载的是 pgstudio_1.2-bin .zip,因为我的电脑里面没有tomcat. 如果电脑里有配置好tomcat,可以下载pgstudio_1.2.zip,解压之后是一个war包. 下载地址:http://www.postgresqlstudio.org/download/ 2.解压 将压缩文件解压,可以看到如下目录: 3.运行 在bin目录下运行,启动tomcat: ./catalina.sh run 4.查看 浏览

metasploit连接postgresql数据库

metasploit 连接postgresql数据库: 1.打开postgresql服务:services postgresql start 2.进入postgresql中,设置默认用户密码.创建新用户.设置新用户权限.创建数据库: sudo -u postgres psql#进入postgresql默认的用户 alter user postgres with password '密码'; #设置默认用户的登录密码 create user '用户名' wiht password '密码' noc

postgresql数据库psql控制台操作命令

登录postgresql数据库控制台 psql 数据库名 登录成功显示 [zpf@kevin ~]$ psql postgres psql (9.4.1) Type "help" for help. postgres=# 创建数据库用户xxx CREATE USER xxx WITH PASSWORD 'xxxxxx'; 创建数据库yyy并指定全部者为xxx CREATE DATABASE yyy OWNER xxx; 将对数据库yyy的全部操作权限赋给用户xxx,否则xxx仅仅能登录

ubuntu 下搭建一个python3的虚拟环境(用于django配合postgresql数据库开发)

#安装python pip  (在物理环境中安装) sudo apt-get install python-pip       sudo apt-get install python3-pipsudo pip install --upgrade pipsudo pip3 install --upgrade pip 备注说明: python-pip 是python2版本的包管理工具   , python3-pip是python3版本的包管理工具 ,  如果你创建了一个python2的虚拟环境 ,当