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
postgresql----数据库表约束----UNIQUE的更多相关文章
- postgresql数据库primary key约束/not null约束/unique约束及default值的添加与删除、列的新增/删除/重命名/数据类型的更改
如果在建表时没有加primary key约束.not null约束.unique约束.default值,而是创建完表之后在某个字段添加的话 1.primary key约束的添加与删除 给red_pac ...
- PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库
最近准备下PostgreSQL数据库开发的相关知识,本文把总结的PPT内容通过博客记录分享,本随笔的主要内容是介绍PostgreSQL数据库的基础信息,以及如何在我们的开发框架中使用PostgreSQ ...
- 数据库并发事务控制四:postgresql数据库的锁机制二:表锁 <转>
在博文<数据库并发事务控制四:postgresql数据库的锁机制 > http://blog.csdn.net/beiigang/article/details/43302947 中后面提 ...
- ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库
前段时间在园子里看到了小蝶惊鸿 发布的有关绿色版的Linux.NET——“Jws.Mono”.由于我对.Net程序跑在Linux上非常感兴趣,自己也看了一些有关mono的资料,但是一直没有时间抽出时间 ...
- TPC-H生成.tbl文件导入postgresql数据库的坑
数据库project好好的不用主流的MySQL和Microsoft server而要求用听都没听过的postgresql (当然,可能你三个都没听过) 这里的坑主要是把生成的那八张.tbl的表导入pg ...
- PowerDesigner反向工程PostgreSQL数据库
1. 环境准备: a) 安装PowerDesigner,以PowerDesigner15.1为例 b) 安装java jdk,以jdk-7-windows-i586为例 ...
- 视频教程--ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库
说好的给园子里的朋友们录制与<ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库> 这篇博客相对应的视频,由于一个月一来没有时 ...
- Enterprise Architect的共享Respository设置,postgresql数据库
Enterprise Architect有一个很实用的共享,在设计UML图的时候,可以连接到一个数据库服务器,将所有的画图数据共享在上面,所有连到这个server的人,都可以看到 别人的图,图中的元素 ...
- PostgreSQL数据库基本配置
一.安装 首先安装PostgreSQL客户端: sudo apt-get install postgresql-client 然后,安装PostgreSQL服务器: sudo apt-get inst ...
- C#访问PostGreSQL数据库的方法 http://www.jb51.net/article/35643.htm
这次的项目中的一个环节要求我把PostGreSQL数据取出来,然后放到SqlServer里,再去处理分析. http://www.jb51.net/article/35643.htm - 我对Post ...
随机推荐
- android tab之间滑动切换界面功能
1. onTouchListener(); //捕捉touch事件,比如说onDown 需要将可滑动的控件加上两个方法:(1)view.setOnTouch ...
- BCM_GPIO驱动测试
在写内核驱动的时候,最好先在uboot上,进行裸板测试,验证寄存器,再移植到内核中,这样可以熟悉寄存器,也排除内核中的一些干扰. /********************************** ...
- 第三百零六节,Django框架,models.py模块,数据库操作——创建表、数据类型、索引、admin后台,补充Django目录说明以及全局配置文件配置
Django框架,models.py模块,数据库操作——创建表.数据类型.索引.admin后台,补充Django目录说明以及全局配置文件配置 数据库配置 django默认支持sqlite,mysql, ...
- IoC是一个很大的概念,可以用不同的方式实现。
IoC是一个很大的概念,可以用不同的方式实现.其主要形式有两种: ◇ 依赖查找:容器提供回调接口和上下文条件给组件.EJB和Apache Avalon 都使用这种方式.这样一来,组件就必须使用容器提供 ...
- e643. 以匿名类处理事件
If an event handler is specific to a component (that is, not shared by other components), there is n ...
- (转)引用---FFMPEG解码过程
视频播放过程 首先简单介绍以下视频文件的相关知识.我们平时看到的视频文件有许多格式,比如 avi, mkv, rmvb, mov, mp4等等,这些被称为容器(Container), 不同的容器格式规 ...
- c++ vector init操作
1) string str[n]={"hello", ...}; vector<string> strArray(str,str+n); 2) vector<st ...
- 【Java面试题】50 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
1.对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址.大小以及使用情况. 通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象.通过这种方式确定哪些对象是"可达的&q ...
- memcached +mysql+php 例子
<?php header("content-type:text/html;charset=utf-8"); $memcachehost = '127.0.0.1'; $mem ...
- Unity3D面试——真实的面试,unity3d面试
本来想写一个系列的,一半是抨击现在面试之水,要人之奸,用大哥的话说,要走新手是做螺丝钉和抹布用的.另一半是对出出学校的或者是自废武功转3d的朋友们提供一个比较有价值的参考.不过我时间实在仓促.没有保证 ...