Oracle主键约束、唯一键约束、唯一索引的区别

时间:2022-01-23 10:39:10

一般,我们看到术语“索引”和“键”交换使用,但实际上这两个是不同的。索引是存储在数据库中的一个物理结构,键纯粹是一个逻辑概念。键代表创建来实施业务规则的完整性约束。索引和键的混淆通常是由于数据库使用索引来实施完整性约束。

接下来我们看看数据库中的主键约束、唯一键约束和唯一索引的区别。

SQL> select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

PL/SQL Release 11.2.0.1.0 - Production

CORE 11.2.0.1.0 Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production

SQL> create table test (

2 id int,

3 name varchar2(20),

4 constraint pk_test primary key(id))

5 tablespace users;

Table created.

SQL> select constraint_name, constraint_type from user_constraints;

CONSTRAINT_NAME C

------------------------------ -

PK_TEST P

在test表中,我们指定了ID列作为主键,Oracle数据库会自动创建一个同名的唯一索引:

SQL> select index_name, index_type, uniqueness, tablespace_name

2 from user_indexes

3 where table_owner='SCOTT'

4 and table_name = 'TEST';

INDEX_NAME INDEX_TYPE UNIQUENES TABLESPACE_NAME

-------------------- -------------------- --------- ------------------------------

PK_TEST NORMAL UNIQUE USERS

此时,如果我们再试图在ID列上创建一个唯一索引,Oracle会报错,因为该列上已经存在一个唯一索引:

SQL> create unique index idx_test_uk on test(id);

create unique index idx_test_uk on test(id)

*

ERROR at line 1:

ORA-01408: such column list already indexed

即使创建非唯一索引也不行:

SQL> create index idx_test_id on test(id);

create index idx_test_id on test(id)

*

ERROR at line 1:

ORA-01408: such column list already indexed

那么唯一键约束的情况是怎样的呢?

SQL> drop table test purge;

Table dropped.

SQL> create table test(

2 id int,

3 name varchar2(20),

4 constraint uk_test unique(id));

Table created.

SQL> select constraint_name, constraint_type from user_constraints;

CONSTRAINT_NAME C

------------------------------ -

UK_TEST U

查看此时的索引情况:

SQL> select index_name, index_type, uniqueness, tablespace_name

2 from user_indexes

3 where table_owner='SCOTT'

4 and table_name = 'TEST';

INDEX_NAME INDEX_TYPE UNIQUENES TABLESPACE_NAME

-------------------- -------------------- --------- ------------------------------

UK_TEST NORMAL UNIQUE USERS

Oracle同样自动创建了一个同名的唯一索引,而且也不允许再在此列上创建唯一索引或非唯一索引。

我们知道,主键约束要求列值非空(NOT NULL),那么唯一键约束是否也要求非空呢?

SQL> insert into test values(1, 'Sally');

1 row created.

SQL> insert into test values(null, 'Tony');

1 row created.

SQL> insert into test values(null, 'Jack');

1 row created.

SQL> select * from test;

ID NAME

---------- --------------------

1 Sally

Tony

Jack

从实验结果来看,唯一键约束并没有非空要求。

接下来我们看看唯一索引对列值的非空要求有什么不同。

SQL> drop table test purge;

Table dropped.

SQL> create table test(

2 id int,

3 name varchar2(20));

Table created.

SQL> create unique index idx_test_id on test (id);

Index created.

SQL> insert into test values(1, 'Sally');

1 row created.

SQL> insert into test values(null, 'Tony');

1 row created.

SQL> insert into test values(null, 'Jack');

1 row created.

SQL> select * from test;

ID NAME

---------- --------------------

1 Sally

Tony

Jack

通过实验,我们看出唯一索引与唯一键约束一样对列值非空不做要求。

如果我们让主键约束或者唯一键约束失效,Oracle自动创建的唯一索引是否会受到影响?

SQL> drop table test purge;

Table dropped.

SQL> create table test(

2 id int,

3 name varchar2(20),

4 constraint uk_test unique(id));

Table created.

SQL> select index_name, index_type, uniqueness from user_indexes;

INDEX_NAME INDEX_TYPE UNIQUENES

------------------------------ --------------------------- ---------

UK_TEST NORMAL UNIQUE

SQL> alter table test disable constraint uk_test;

Table altered.

SQL> select index_name, index_type, uniqueness from user_indexes;

no rows selected

当主键约束或者唯一键约束失效时,Oracle会删除隐式创建的唯一索引。

如果我们先创建唯一索引,再创建主键或者唯一键约束,情况又会怎样呢?

SQL> drop table test purge;

Table dropped.

SQL> create table test(

2 id int,

3 name varchar2(20));

Table created.

SQL> create unique index idx_test_id on test (id);

Index created.

SQL> select index_name, index_type, uniqueness

2 from user_indexes

3 where table_owner = 'SCOTT'

4 and table_name = 'TEST';

INDEX_NAME INDEX_TYPE UNIQUENES

------------------------------ --------------------------- ---------

IDX_TEST_ID NORMAL UNIQUE

SQL> alter table test add constraint uk_test unique (id);

Table altered.

SQL> select index_name, index_type, uniqueness

2 from user_indexes

3 where table_owner = 'SCOTT'

4 and table_name = 'TEST';

INDEX_NAME INDEX_TYPE UNIQUENES

------------------------------ --------------------------- ---------

IDX_TEST_ID NORMAL UNIQUE

SQL> select constraint_name, constraint_type

2 from user_constraints

3 where table_name = 'TEST';

CONSTRAINT_NAME C

------------------------------ -

UK_TEST U

SQL> alter table test disable constraint uk_test;

Table altered.

SQL> select constraint_name, constraint_type, status

2 from user_constraints

3 where table_name = 'TEST';

CONSTRAINT_NAME C STATUS

------------------------------ - --------

UK_TEST U DISABLED

SQL> select index_name, index_type, uniqueness, status

2 from user_indexes

3 where table_owner = 'SCOTT'

4 and table_name = 'TEST';

INDEX_NAME INDEX_TYPE UNIQUENES STATUS

------------------------------ --------------------------- --------- --------

IDX_TEST_ID NORMAL UNIQUE VALID

实验结果表明,先创建的唯一索引不受约束失效的影响。

总结如下:

(1)主键约束和唯一键约束均会隐式创建同名的唯一索引,当主键约束或者唯一键约束失效时,隐式创建的唯一索引会被删除;

(2)主键约束要求列值非空,而唯一键约束和唯一索引不要求列值非空;

(3)相同字段序列不允许重复创建索引;

转自:http://langgufu.iteye.com/blog/1745915

Oracle主键约束、唯一键约束、唯一索引的区别的更多相关文章

  1. SQL Server的外键必须引用的是主键或者唯一键(转载)

    问: In SQL Server , I got this error -> "There are no primary or candidate keys in the refere ...

  2. Sql Server中的游标最好只用于有主键或唯一键的表

    游标cursor,我想大多数人都在sql server里面用过.当一个表数据量不太大的时候,游标还是可以用的,毕竟游标是循环一个表中每一行数据的最简便办法.但是如果你用一个游标去循环一个没有主键或唯一 ...

  3. powerdesigner设置主键为自增字段,设置非主键为唯一键并作为表的外键

    转自:https://www.cnblogs.com/CoffeeHome/archive/2014/06/04/3767501.html 这里powerdesigner连接的数据库是以mysql为例 ...

  4. SQL Server的唯一键和唯一索引会将空值(NULL)也算作重复值

    我们先在SQL Server数据库中,建立一张Students表: CREATE TABLE [dbo].[Students]( ,) NOT NULL, ) NULL, ) NULL, [Age] ...

  5. 视图view没有主键,但可以添加唯一索引

    视图没有主键,但可以加上唯一索引 大致可以这样理解:视图是张虚拟的表.视图所对应的数据不进行实际的存储,数据库中只存储视图的定义,对视图的数据进行操作时,系统根据视图的定义去操作与视图相关联的基本表. ...

  6. SQL Server 数据库添加主键,唯一键,外键约束脚本

    -- 声明使用数据库use 数据库;go -- 添加主键(primary key)约束-- 基本语法-- 判断主键约束是否存在,如果存在则删除,不存在则添加if exists(select * fro ...

  7. mysql中主键和唯一键的区别

    区别项 primary key(主键) unique(唯一键约束) 唯一性 可以 可以 是否可以为空 不可以 可以 允许个数 只能有1个 允许多个 是否允许多列组合 允许 允许

  8. 生成主键ID,唯一键id,分布式ID生成器雪花算法代码实现

    工具类:  package com.ihrm.common.utils; import java.lang.management.ManagementFactory; import java.net. ...

  9. Oracle 数据库表中已有重复数据添加唯一键(唯一约束)

    Oracle 数据库表中已有重复数据添加唯一键(唯一约束) 问题描述 以 demo 举例,模拟真实场景. 表 TEST_TABLE 有如下字段和数据:id 是主键,code 没有设置键和索引 ID C ...

随机推荐

  1. block的复习

    main.m // //  main.m //  8A10.Block的复习 // //  Created by huan on 16/2/8. //  Copyright © 2016年 huanx ...

  2. ACM/ICPC 之 DFS范例(ZOJ2412-ZOJ1008)

    通过几道例题简单阐述一下DFS的相关题型 ZOJ2412-Farm Irrigation 直观的DFS题型,稍加变化,记录好四个方向上的通路就能够做出来 题目和接水管类似,问最少要灌溉几次,即求解最少 ...

  3. 分享一个使用APICloud云数据库已上线的商城APP

    本项目盈利模式依赖taobao模块实现淘宝闭环交易,发布销售淘宝联盟产品获取返佣.目前已在应用宝上线安卓版本,先上图. 源码在此: http://community.apicloud.com/bbs/ ...

  4. 【Away3D代码解读】(二):渲染核心流程(简介、实体对象收集)

    我之前解析过Starling的核心渲染流程,相比Away3D而言Starling真的是足够简单,不过幸运的是两者的渲染流程是大体上相似的:Starling的渲染是每帧调用Starling类中的rend ...

  5. Spark运行各个时间段的解释

    package org.apache.spark.ui private[spark] object ToolTips {  val SCHEDULER_DELAY =    ""& ...

  6. 2017年的golang、python、php、c++、c、java、Nodejs性能对比(golang python php c++ java Nodejs Performance)

    2017年的golang.python.php.c++.c.java.Nodejs性能对比 本人在PHP/C++/Go/Py时,突发奇想,想把最近主流的编程语言性能作个简单的比较, 至于怎么比,还是不 ...

  7. 使用jquery实现文本框输入特效:文字逐个显示逐个消失反复循环

    前两天看到某个网站上的输入框有个小特效:文字逐个显示,并且到字符串最大长度后,逐个消失,然后重新循环显示消失,循环显示字符串数组.我对这个小特效有点好奇,于是今天自己尝试用jquery写一个简单的小d ...

  8. Docker学习笔记三 Dockerfile 指令 定制镜像

    本文地址:https://www.cnblogs.com/veinyin/p/10412079.html  镜像是分层存储的,每一层都是独立存在的,修改当前层并不会修改其依赖的上一层,删除某一层也只是 ...

  9. Apache TomEE 入门指南

    介绍 Apache TomEE(发音同“tommy”)是一个新的JavaEE服务器,由Apache软件基金会开发,你大概能够从它的名字猜到,它是从Tomcat而来, 同时加入的JavaEE的特征:To ...

  10. 【转】基于Redis实现延时队列服务

    背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论c.点我达订单 ...