Oracle数据库中违反唯一约束的处理

数据库 Oracle
根据NULL的定义,NULL表示的是未知,因此两个NULL比较的结果既不相等,也不不等,结果仍然是未知。

根据NULL的定义,NULL表示的是未知,因此两个NULL比较的结果既不相等,也不不等,结果仍然是未知。根据这个定义,多个NULL值的存在应该不违反唯一约束。

实际上Oracle也是如此实现的:

SQL> CREATE TABLE T (ID NUMBER);

表已创建。

SQL> ALTER TABLE T ADD UNIQUE (ID);

表已更改。

SQL> INSERT INTO T VALUES (1);

已创建 1 行。

SQL> INSERT INTO T VALUES (1);

INSERT INTO T VALUES (1)

*第 1 行出现错误:

ORA-00001: 违反唯一约束条件 (YANGTK.SYS_C007300)

SQL> INSERT INTO T VALUES (NULL);

已创建 1 行。

SQL> INSERT INTO T VALUES (NULL);

已创建 1 行。

SQL> INSERT INTO T VALUES (NULL);

已创建 1 行。

但是当唯一约束为复合字段时,则情况发生了变化。根据Oracle文档的描述,对于复合字段的唯一约束,不为空字段的值是不能重复的。也就是说,如果两个字段构成了一个唯一约束,其中一个字段为空,那么另一个字段的值不能出现重复。

SQL> DROP TABLE T PURGE;

表已删除。

SQL> CREATE TABLE T (ID NUMBER, ID2 NUMBER);

表已创建。

SQL> ALTER TABLE T ADD UNIQUE (ID, ID2);

表已更改。

SQL> INSERT INTO T VALUES (1, 1);

已创建 1 行。

SQL> INSERT INTO T VALUES (1, NULL);

已创建 1 行。

SQL> INSERT INTO T VALUES (2, NULL);

已创建 1 行。

SQL> INSERT INTO T VALUES (1, NULL);

INSERT INTO T VALUES (1, NULL)

*第 1 行出现错误:

ORA-00001: 违反唯一约束条件 (YANGTK.SYS_C007301)

SQL> INSERT INTO T VALUES (NULL, NULL);

已创建 1 行。

SQL> INSERT INTO T VALUES (NULL, NULL);

已创建 1 行。

SQL> INSERT INTO T VALUES (NULL, NULL);

已创建 1 行。

对于全部为NULL的情况,仍然和单字段唯一约束一样,不会造成重复,但是对于部分为NULL的情况,就如上面例子所示,只要其中不为NULL的部分发生了重复,Oracle就认为约束发生了重复。

而这似乎和NULL的定义有所冲突,第一次看concept的时候一直没有搞明白Oracle为什么这么实现,不过这次再看concept的时候,已经想明白了。

由于Oracle的唯一约束是依赖索引实现的,而Oracle的BTREE索引又是不存储NULL值的,所以键值全部为NULL的记录不会记录在索引中,因此也就不会违反唯一约束了,而对于部分为NULL的记录,索引是要记录数值的,因此一旦键值中非NULL部分发生了冲突,Oracle就认为违反了的唯一约束。

Oracle在这里还是选择了自己的方便的方法来实现,而没有完全真正的根据NULL的定义去实现唯一约束。

【编辑推荐】

  1. Oracle数据库文件恢复与备份思路
  2. 数据库管理中使用存储过程的5个好处
  3. Oracle数据库管理脚本浅析
责任编辑:book05 来源: IT专家网
相关推荐

2011-08-18 11:18:25

Oracle唯一约束唯一索引

2010-10-19 16:26:46

SqlServer唯一

2010-10-19 16:34:10

SqlServer唯一

2010-11-12 14:39:36

Sql Server唯

2010-11-12 14:45:19

Sql Server唯

2011-05-26 10:30:12

Oracle数据库约束

2010-09-24 17:08:03

SQL Server唯

2011-08-10 16:01:11

OracleConstraint

2011-05-26 13:36:40

Oracle数据库时间处理

2011-08-10 15:38:12

ConstraintOracle

2010-11-22 15:00:01

Mysql分区表

2010-11-12 14:29:46

Sql Server创

2009-05-18 13:18:54

字符Oracle字符串

2011-05-26 14:43:49

ORACLE数据库异常处理

2011-03-17 14:09:25

Oracle数据库字符

2010-04-09 14:37:08

Oracle数据库

2010-04-07 14:22:46

2010-04-30 14:39:03

Oracle数据库

2010-01-05 09:24:42

MySQL外键约束

2009-09-02 18:52:38

Oracle数据库并行
点赞
收藏

51CTO技术栈公众号