主键、唯一键与唯一索引的区别

原文地址:http://blog.sina.com.cn/s/blog_82ee2ee60100xwl4.html

这篇文章的意义已经理解,但是他举得例子不错,保存下来,下次想看的时候可以参考一下。

 

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

 

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

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 (          

  id int,

  name varchar2(20),

  constraint pk_test primary key(id))

  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

  from user_indexes

  where table_owner='SCOTT'

  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(

  id int,

  name varchar2(20),

  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

  from user_indexes

  where table_owner='SCOTT'

  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(

  id int,

  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(

  id int,

  name varchar2(20),

  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(

  id int,

  name varchar2(20));

 

Table created.

 

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

 

Index created.

 

SQL> select index_name, index_type, uniqueness

  from user_indexes

  where table_owner = 'SCOTT'

  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

  from user_indexes

  where table_owner = 'SCOTT'

  and table_name = 'TEST';

 

INDEX_NAME                     INDEX_TYPE                  UNIQUENES

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

IDX_TEST_ID                    NORMAL                      UNIQUE

 

SQL> select constraint_name, constraint_type

  from user_constraints

  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

  from user_constraints

  where table_name = 'TEST';

 

CONSTRAINT_NAME                C STATUS

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

UK_TEST                        U DISABLED

 

SQL> select index_name, index_type, uniqueness, status

  from user_indexes

  where table_owner = 'SCOTT'

  and table_name = 'TEST';

 

INDEX_NAME                     INDEX_TYPE                  UNIQUENES STATUS

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

IDX_TEST_ID                    NORMAL                      UNIQUE    VALID

 

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

 

总结如下:

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

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

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

 

主键索引唯一索引的主要区别在于: 1. **唯一性**: - **主键索引**:一个表仅能有一个主键,其值必须唯一且不可为NULL。这是为了保证每一行数据的唯一标识。 - **唯一索引**:可以有多个,对索引列的要求稍低,允许NULL值,但在该列上有唯一约束。 2. **数量限制**: - **主键**:一个表只允许有一个主键。 - **唯一索引**:可以在多列或多行上创建,不受此限制。 3. **自动增长**: - **主键**:如果指定为主键并且设置了自动增长属性,数据库会自动为其分配连续的数值。 - **唯一索引**:不支持自动增长功能。 4. **索引类型**: - **主键索引**:通常是**聚簇索引**,数据存储基于主键值。 - **唯一索引**:通常是**非聚簇索引**,数据仍然按照行的物理顺序存储,但索引本身是独立的。 5. **外关联**: - **主键**:因为是唯一标识,其他表通过外经常引用主键。 - **唯一索引**:虽然也能用于外参照,但不如主键频繁。 6. **使用场景**: - **主键**:适用于作为行的唯一标识,常用于关系数据库的一对一或多对多关系中。 - **唯一索引**:适合那些只需要保证某个字段或一组字段值的独特性的场景,比如邮箱地址、电话号码等。 在实际操作中,你可以使用SQL语句来创建这些索引,例如: ```sql CREATE TABLE example ( id INT PRIMARY KEY AUTO_INCREMENT, email VARCHAR(255) UNIQUE ); ``` 这里`id`是主键,`email`是唯一索引
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值