您好,欢迎访问一九零五行业门户网

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

一般,我们看到术语“索引”和“键”交换使用,但实际上这两个是不同的。 索引是存储在数据库中的一个物理结构,键纯粹是一个逻辑概念。键代表创建来实施业务规则的完整性约束。索引和键的混淆通常是由于数据库使用索引来实施完整性约束。 接下来我们看看数
一般,我们看到术语“索引”和“键”交换使用,但实际上这两个是不同的。索引是存储在数据库中的一个物理结构,键纯粹是一个逻辑概念。键代表创建来实施业务规则的完整性约束。索引和键的混淆通常是由于数据库使用索引来实施完整性约束。
接下来我们看看数据库中的主键约束、唯一键约束和唯一索引的区别。
sql> select * fromv$version;
banner
--------------------------------------------------------------------------------
oracle database 11g enterpriseedition 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 tabletest (          
  2  id int,
  3  namevarchar2(20),
  4  constraintpk_testprimarykey(id))
  5  tablespaceusers;
table created.
sql> selectconstraint_name, constraint_type from user_constraints;
constraint_name               c
-------------------------------
pk_test                       p
在test表中,我们指定了id列作为主键,oracle数据库会自动创建一个同名的唯一索引:
sql> selectindex_name, index_type, uniqueness, tablespace_name
  2  fromuser_indexes
  3  wheretable_owner='scott'
  4  and table_name ='test';
index_name          index_type          uniquenes tablespace_name
---------------------------------------- ---------------------------------------
pk_test             normal              unique   users
此时,如果我们再试图在id列上创建一个唯一索引,oracle会报错,因为该列上已经存在一个唯一索引:
sql> create uniqueindex idx_test_uk on test(id);
create unique index idx_test_uk ontest(id)
                                       *
error at line 1:
ora-01408: such column list alreadyindexed
即使创建非唯一索引也不行:
sql> create indexidx_test_id on test(id);
create index idx_test_id ontest(id)
                                *
error at line 1:
ora-01408: such column list alreadyindexed
那么唯一键约束的情况是怎样的呢?
sql> drop table testpurge;
table dropped.
sql> create tabletest(
  2  id int,
  3  namevarchar2(20),
  4  constraintuk_testunique(id));
table created.
sql> selectconstraint_name, constraint_type from user_constraints;
constraint_name               c
-------------------------------
uk_test                       u
查看此时的索引情况:
sql> selectindex_name, index_type, uniqueness, tablespace_name
  2  fromuser_indexes
  3  wheretable_owner='scott'
  4  and table_name ='test';
index_name          index_type          uniquenes tablespace_name
---------------------------------------- ---------------------------------------
uk_test             normal              unique   users
oracle同样自动创建了一个同名的唯一索引,而且也不允许再在此列上创建唯一索引或非唯一索引。
我们知道,主键约束要求列值非空(not null),那么唯一键约束是否也要求非空呢?
sql> insert intotest values(1, 'sally');
1 row created.
sql> insert intotest values(null, 'tony');
1 row created.
sql> insert intotest values(null, 'jack');
1 row created.
sql> select * fromtest;
id name
------------------------------
        1 sally
          tony
          jack
从实验结果来看,唯一键约束并没有非空要求。
接下来我们看看唯一索引对列值的非空要求有什么不同。
sql> drop table testpurge;
table dropped.
sql> create tabletest(
  2  id int,
  3  namevarchar2(20));
table created.
sql> create uniqueindex idx_test_id on test (id);
index created.
sql> insert intotest values(1, 'sally');
1 row created.
sql> insert intotest values(null, 'tony');
1 row created.
sql> insert intotest values(null, 'jack');
1 row created.
sql> select * fromtest;
id name
------------------------------
        1 sally
          tony
          jack
通过实验,我们看出唯一索引与唯一键约束一样对列值非空不做要求。
如果我们让主键约束或者唯一键约束失效,oracle自动创建的唯一索引是否会受到影响?
sql> drop table testpurge;
table dropped.
sql> create tabletest(
  2  id int,
  3  namevarchar2(20),
  4  constraint uk_testunique(id));
table created.
sql> selectindex_name, index_type, uniqueness from user_indexes;
index_name                    index_type                 uniquenes
--------------------------------------------------------- ---------
uk_test                       normal                     unique
sql> alter tabletest disable constraint uk_test;
table altered.
sql> selectindex_name, index_type, uniqueness from user_indexes;
no rows selected
当主键约束或者唯一键约束失效时,oracle会删除隐式创建的唯一索引。
如果我们先创建唯一索引,再创建主键或者唯一键约束,情况又会怎样呢?
sql> drop table testpurge;
table dropped.
sql> create tabletest(
  2  id int,
  3  namevarchar2(20));
table created.
sql> create uniqueindex idx_test_id on test (id);
index created.
sql> selectindex_name, index_type, uniqueness
  2  fromuser_indexes
  3  where table_owner ='scott'
  4  and table_name ='test';
index_name                    index_type                 uniquenes
--------------------------------------------------------- ---------
idx_test_id                   normal                     unique
sql> alter tabletest add constraint uk_test unique (id);
table altered.
sql> selectindex_name, index_type, uniqueness
  2  fromuser_indexes
  3  where table_owner ='scott'
  4  and table_name ='test';
index_name                    index_type                 uniquenes
--------------------------------------------------------- ---------
idx_test_id                   normal                     unique
sql> selectconstraint_name, constraint_type
  2  fromuser_constraints
  3  where table_name ='test';
constraint_name               c
-------------------------------
uk_test                       u
sql> alter tabletest disable constraint uk_test;
table altered.
sql> selectconstraint_name, constraint_type, status
  2  fromuser_constraints
  3  where table_name ='test';
constraint_name               c status
------------------------------ ---------
uk_test                       u disabled
sql> selectindex_name, index_type, uniqueness, status
  2  fromuser_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)相同字段序列不允许重复创建索引;
其它类似信息

推荐信息