首页 > 解决方案 > Oracle数据库中的null等于null吗?

问题描述

我试图使用 Oracle 中的唯一索引强制每个客户端只使用一部活动电话,但无法使其正常工作。这在 PostgreSQL 和 DB2 中完美运行,但在 Oracle 中似乎不起作用。

这是示例:

create table phone (
  client_id number(6) not null,
  active number(1) not null check (active in (0, 1)),
  value varchar2(15)
);

insert into phone (client_id, active, value) values (10, 0, '1111');
insert into phone (client_id, active, value) values (10, 1, '3333');
insert into phone (client_id, active, value) values (15, 0, '5555');
insert into phone (client_id, active, value) values (15, 1, '6666');
insert into phone (client_id, active, value) values (15, 0, '7777'); -- offending row

当我尝试创建索引时:

create unique index ix1 on phone (client_id, case when active = 1 then active end);

似乎Oracle不喜欢它,因为重复的索引条目:

错误:ORA-01452:无法创建唯一索引;发现重复键
SQLState: 72000

如果我删除了有问题的数据行,则可以创建索引。

标签: sqloracleindexing

解决方案


您可以使用:

create unique index ix1 on phone (case active when 1 then client_id end);

sqlfiddle在这里

所有列都为;时,UNIQUE索引不会存储行。但是,在您的情况下,基于函数的索引会产生两个值之一,因此该行将被索引,这将导致索引中出现重复值。NULLNULL

更改它以使输出是从activeclient_id列派生的单个值意味着active = 0将导致表达式NULL输出的CASE行并且这些行不会包含在索引中,并且只会检查活动行的重复项。

来自 Oracle Unique 约束文档

为了满足唯一约束,表中的任何两行都不能具有相同的唯一键值。但是,由单个列组成的唯一键可以包含空值。为了满足复合唯一键,表或视图中的任何两行都不能在键列中具有相同的值组合。在所有键列中包含空值的任何行都会自动满足约束。但是,包含一个或多个键列的空值以及其他键列的相同值组合的两行违反了约束。


推荐阅读