主键的定义:列或多列的集合,用于唯一的标识表中的一行。一个表上只允许有一个主键。

我们在数据库中指定主键时,是通过主键约束来定义的。而创建主键约束时,又是需要有相应的索引来配合实现的。所以,本文的目的是总结创建主键约束时,采用不同的方法创建索引后,主键与该索引之间的关系及相互影响。

为配合本文的描述和测试,首先创建如下测试表:

create table test (id number,c1 varchar2(8));

一、 首先,我们来看最常用的创建主键约束及索引的方法:

alter table t1 add constraint pk_test_id primary key (id);

创建完成后,检查相应约束和索引视图中的内容:

SQL> select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     ENABLED

从上可见,我们已经创建了一个名为“PK_TEST_ID”的主键约束,其当前状态为有效状态。

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

PK_TEST_ID  UNIQUE         TEST        VALID

从上可见,数据库同时自动为该主键约束创建了一个同名的唯一索引。

如果这时,我们将主键约束关闭或者删除,又会是什么情况呢?

SQL> alter table test disable constraint pk_test_id;

Table altered.

SQL> select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     DISABLED

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

no rows selected

可见,当我们把主键约束关闭后,其同名的索引被自动删除了。

那如果我们不将主键约束关闭或者删除,而是将自动创建的同名索引关闭或删除,又会是什么情况呢?

SQL> alter table test enable constraint pk_test_id;

Table altered.

SQL> select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     ENABLED

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

PK_TEST_ID  UNIQUE         TEST        VALID

首先,我们先恢复被关闭的主键约束,发现约束的状态已经恢复正常,而且同名的索引也被重建恢复了。现在我们将同名的索引关闭或删除。

SQL> alter index pk_test_id unusable;

Index altered.

SQL>  select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     ENABLED

SQL>  select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

PK_TEST_ID  UNIQUE         TEST        UNUSABLE

可见,当关闭索引后,除了索引的状态变为UNUSABLE外,主键的状态仍是正常状态。但若此时向表中插入数据,则会报错ORA-01502,如下所示:

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

insert into test values(1,'A')

*

ERROR at line 1:

ORA-01502: index 'U1.PK_TEST_ID' or partition of such index is in unusable state

如果这时我们删除索引,也会报错,提示有约束正在使用该索引,而不允许删除。

SQL> drop index pk_test_id;

drop index pk_test_id

*

ERROR at line 1:

ORA-02429: cannot drop index used for enforcement of unique/primary key

从这两个现象,也证明主键约束是通过相应列上的索引来配合完成的。

至此,我们对第一种创建约束和索引的方法做一个总结:当主键约束的索引为创建主键约束时数据库自动创建的话,则关闭或删除约束,会自动删除相应的索引;而关闭相应的索引,虽然不会影响主键的状态,但此时向表中插入数据会报错(删除数据,以及对主键列的更新也会报错);而尝试删除该索引时,也会报错,而不允许删除该索引。

二、创建主键约束时,指定相应的索引的方法。

在创建主键约束时,我们也可以指定索引。方法如下:

SQL> drop table test purge;

Table dropped.

SQL> create table test (id number,c1 varchar2(8));

Table created.

SQL> alter table test add constraint pk_test_id primary key (id) using index (create index ind_test_id on test(id));

Table altered.

前两条SQL是重建测试环境,以避免前面测试的影响。最后一条SQL则是在ID列上指定了主键约束,同时指定创建了在该列上的非唯一索引。

我们通过相关约束和索引视图来查看一下:

SQL>  select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     ENABLED

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

IND_TEST_ID NONUNIQUE      TEST        VALID

注意最后一条索引信息中索引的名称及唯一性与前面自动创建主键索引时的区别。这说明,非唯一索引,也可以用于配合完成主键约束。

如前测试,我们尝试把主键约束关闭或删除,看看是什么情况?

SQL> alter table test disable constraint pk_test_id;

Table altered.

SQL> select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     DISABLED

SQL>  select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

IND_TEST_ID NONUNIQUE      TEST        VALID

可见,除了相应的主键约束失效外,索引并没有受到影响。这与前边自动创建主键索引的情况是不同的。

接下来,我们再尝试关闭或删除相应的索引,是否会影响到相应的主键约束。

SQL> alter table test enable constraint pk_test_id;

Table altered.

SQL> alter index ind_test_id unusable;

Index altered.

SQL> select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     ENABLED

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

IND_TEST_ID NONUNIQUE      TEST        UNUSABLE

可见,关闭索引并没有影响到相应主键约束的状态。但是否也如前面测试那样,不能插入数据呢?

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

insert into test values(1,'A')

*

ERROR at line 1:

ORA-01502: index 'U1.IND_TEST_ID' or partition of such index is in unusable state

果然,当主键约束所依赖的索引不可用时,数据的插入会报错(删除数据,以及对主键列的更新也会报错);而尝试删除该索引时,也会报错,而不允许删除该索引。这一点和前面测试的情况是相同的。

SQL> drop index ind_test_id;

drop index ind_test_id

*

ERROR at line 1:

ORA-02429: cannot drop index used for enforcement of unique/primary key

三、创建主键约束时,已经在相应的主键列上存在索引时的情况

如果表TEST中已经存在了一个ID列上的索引,然后我再在ID列上创建主键约束,又是会是什么情况呢?

和前面一样,我们先重置测试环境。

SQL> drop table test purge;

Table dropped.

SQL> create table test (id number,c1 varchar2(8));

Table created.

然后,我们先创建一个ID列上的索引。

SQL> create index ind_test_id on test(id);

Index created.

接着,我们在ID列上创建主键约束。

SQL> alter table test add constraint pk_test_id primary key (id);

Table altered.

查看约束和索引的情况:

SQL> select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     ENABLED

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

IND_TEST_ID NONUNIQUE      TEST        VALID

我们可以看到,这次创建主键约束时,自动选用了主键列上已经存在的索引,并没有像测试一中那样,去创建一个与主键同名的唯一索引。

我们继续测试关闭或删除约束,是否会影响索引?

SQL> alter table test disable constraint pk_test_id;

Table altered.

SQL> select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     DISABLED

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

IND_TEST_ID NONUNIQUE      TEST        VALID

发现索引并不受影响。

继续测试关闭或删除索引对主键约束的影响。

SQL> alter table test enable constraint pk_test_id;

Table altered.

SQL>  alter index ind_test_id unusable;

Index altered.

SQL>  select constraint_name,constraint_type,table_name,status from user_constraints where table_name='TEST';

CONSTRAINT_NAME CO TABLE_NAME    STATUS

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

PK_TEST_ID  P  TEST     ENABLED

SQL> select index_name,uniqueness,table_name,status from user_indexes where table_name='TEST';

INDEX_NAME  UNIQUENESS     TABLE_NAME       STATUS

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

IND_TEST_ID NONUNIQUE      TEST        UNUSABLE

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

insert into test values(1,'A')

*

ERROR at line 1:

ORA-01502: index 'U1.IND_TEST_ID' or partition of such index is in unusable state

SQL> drop index ind_test_id;

drop index ind_test_id

*

ERROR at line 1:

ORA-02429: cannot drop index used for enforcement of unique/primary key

和此前的测试完全一样,将主键约束所依赖的索引关闭并不会影响主键约束的状态,但修改数据(包括增删改操作,其中修改特指对主键列的修改)是不被允许的。同样,删除索引,也是不被允许的。

至此,我们把前述三大测试总结一下:

1、对于创建主键约束时自动生成的同名唯一性索引的情况:

关闭或删除主键约束,相应的索引会被删除。

2、对于创建主键约束时,使用了非自动创建的索引的情况(在创建主键约束的SQL中指定创建索引或创建主键约束时,主键列上已有索引。):

关闭或删除主键约束,相应的索引并不会被删除,索引状态也不受影响。

3、在任何一种情况下,关闭主键约束所依赖的索引,都会引起数据插入、删除以及对主键列更新操作的报错。

4、在任何一种情况下,删除主键约束所依赖的索引,是不被允许的。

注意:

此外,有一个特例。即,当我们使用第二种方法,即在创建主键约束的同时,使用USING INDEX子句来创建了一个唯一索引时,比如:

alter table test add constraint pk_test_id primary key (id) using index (create unique index ind_test_id_uni on test(id));

如果这时,我关闭或删除主键约束,则该索引会被自动删除。而当我们恢复主键约束时,数据库会自动创建一个与主键同名的唯一性索引。另外,当我们关闭手工创建的唯一索引或删除它时,情况与前述的内容是一样的。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22207394/viewspace-2080449/,如需转载,请注明出处,否则将追究法律责任。

oracle 主键约束重名,主键及主键索引的关系及相互影响相关推荐

  1. mysql主键约束和外键约束的作用_MySQL中的主键约束和外键约束

    1.主键约束 表通常具有包含唯一标识表中每一行的值的一列或一组列. 这样的一列或多列称为表的主键 (PK),用于强制表的实体完整性. 由于主键约束可保证数据的唯一性,因此经常对标识列定义这种约束. 如 ...

  2. mysql主键约束自动增长_MySQL教程45-MySQL主键自增长

    在 MySQL 中,当主键定义为自增长后,这个主键的值就不再需要用户输入数据了,而由数据库系统根据定义自动赋值.每增加一条记录,主键会自动以相同的步长进行增长. 通过给字段添加 AUTO_INCREM ...

  3. 外键约束的作用以及如何创建外键约束

    外键约束 外键必须是另一个表的主键. 外键的作用: 1.实体完整性,确保每个实体是唯一的(通过主键来实施) 2.域完整性,确保属性值只从一套可选的集合里选择 3.关联完整性,确保每个外键或null或含 ...

  4. php设置外键约束,关于php:禁用教义外键约束

    我在其中一个模型上有关系: /** * @ORM\ManyToOne(targetEntity="Page", cascade="persist") * @OR ...

  5. mysql级联删除外键约束_玩转MySQL的外键约束之级联删除篇

    [IT168 文档]如今,许多关系型数据库管理系统都提供了外键约束这一强大的功能特性,它能够帮助我们自动地触发指定的动作,诸如删掉.更新数据库表的记录等,从而维护各数据库表之间预定义的关系.本文将演示 ...

  6. mysql中主键约束如何关闭_mysql怎么去除主键约束

    我就废话不多说了,大家还是直接看代码吧~create or replace function aa1(a1 integer[],a2 bigint) returns void AS $$declare ...

  7. mysql一对一外键约束_MySQL数据库之-foreign key 外键(一对多、多对多、一对一)、修改表、复制表...

    我们在同一数据库创建的表时候,很多时候会出现相同数据的冗余问题,也就是说几个id会有一个或者同n个相同字段,这样就导致数据表结构数据重复冗余, 冗余还无所谓,关键是如果我要改其中一个相同的字段信息,其 ...

  8. SQL约束(主键约束 primary key、外键约束 foreign key、唯一约束unique 、CHECK约束)

    注意: A.表中有数据不能创建约束 B.视图下设置后,要点击保存(只有保存后在才看的到) c   别忘了,点刷新,才会出来呀! 1.主键约束 primary key 主键是每行的唯一标识符,仅仅通过它 ...

  9. [JavaWeb-MySQL]约束(非空约束,唯一约束,主键约束,外键约束_级联操作)

    约束 * 概念: 对表中的数据进行限定,保证数据的正确性.有效性和完整性. * 分类:1. 主键约束:primary key2. 非空约束:not null3. 唯一约束:unique4. 外键约束: ...

最新文章

  1. win7下构建swarm nodes实现跨host的容器之间的通信
  2. 2017腾讯编程题----素数对
  3. Hibernate事务管理
  4. 世界上最奇特的国界线,万万没想到...
  5. 解决mysql5数据库连接超时问题
  6. 30 友盟项目---体会篇
  7. 利用Jmail发送和接收邮件
  8. [转]Sandboxie 的工作原理
  9. 创建高质量Python工程(1)-如何设计结构清晰的目录结构(转)
  10. 黑苹果固态硬盘_普通电脑也能尝试:MacOS黑苹果+雷电3硬盘盒测试
  11. matlab数细胞实验图片,献给初学者:手把手教你做细胞计数实验
  12. java面向对象编程培训_Java面向对象编程简介
  13. 【模拟电路仿真】LM324加法器电路(激励源与正弦信号源的使用)
  14. 连续翻页浏览器面临的共同问题
  15. 论文笔记:Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering
  16. PCA(主成分分析)获取BoundingBox代码分析
  17. ERP系统容灾方案析投入产出比例与维护管理成本分析
  18. 郭德纲与姜昆在经济学上的区别(转)
  19. 右下角弹出广告 js,漂浮效果(兼容多浏览器)
  20. 苹果的AR真那么高科技?带你见识这些神奇AR应用

热门文章

  1. OpenCV可移植图形工具HighGUI实现图像和视频操作
  2. (Python代码)通过视差图获取图片中不同物体的高度比
  3. C++多态讲解以及常见面试题
  4. 安卓逆向_19( 一 ) --- APK保护策略【APP打开就崩溃 之 霸哥apk过签名校验】
  5. SpringBoot 自带工具类~AopUtils
  6. sql无法写入mysql_无法通过写入mysql数据库pandas.to\u sql使用sqlalchemy,但不能通过没有pandas的sqlalchemy...
  7. python3中实现tar_Python3实现将文件树中所有文件和子目录归档到tar压缩文件的方法...
  8. 获取iOS任意线程调用堆栈(四)符号化实战
  9. JAVA入门级教学之(对象的创建和使用)
  10. JAVA入门级教学之(赋值运算符)