【问题标题】:Is null equal to null in Oracle database?Oracle数据库中的null等于null吗?
【发布时间】:2021-10-06 01:40:29
【问题描述】:

我试图使用 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

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

【问题讨论】:

  • 您的索引有一个case,但没有else。当case 的结果不是 1 时,Oracle 是否为它分配了 0?似乎当该行不活动时,它将是0,导致两行带有 (15, 0)。你的问题的标题是关于 NULL 的,但我没有看到 NULL 进入方程(?)。
  • 我希望on phone (case when active=1 then client_id end) 能够跨数据库引擎工作。我现在没有时间验证并写下答案,但如果没有人超过我,我会在以后尝试这样做。
  • @HardCode - 默认的else 值是null(不仅在Oracle 中,而且我相信在SQL 标准中)。所以从这个角度来看,OP的尝试很好。问题是不同的 - 这是 MT0 在他的回答中解释的。
  • null 永远不会等于 null

标签: sql oracle indexing


【解决方案1】:

你可以使用:

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

sqlfiddle here

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

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

来自 Oracle Unique constraint documentation

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

【讨论】:

  • 你说的太对了。谢谢你。我应该实现为部分索引(正如你提到的)。
  • 但是它仍然困扰着我“...会导致索引中的重复值...”。那么(15, null) 不应该等于另一个(15, null)。 PostgreSQL 似乎表现正确:sqlfiddle.com/#!17/815f55。但是,DB2 的行为方式与 Oracle 相同:dbfiddle.uk/…
  • @TheImpaler - 在 Oracle 中,null 有时等于 null。当您按列分组时,该列为null 的所有行都会组合在一起。如果您选择不同的 ,即使 不止一次是 null,您也会在输出中得到一个 null。类似地,在确定“唯一”时,null 在行中等于自身。当索引(或条件)位于 single 列时,您看不到这一点,因为 Oracle 选择 - 无论出于何种原因 - 将 null 完全排除在考虑之外。
  • @TheImpaler 添加了指向 Oracle 文档的链接。
猜你喜欢
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 2013-05-28
  • 2010-12-22
  • 2023-04-09
  • 2011-03-13
相关资源
最近更新 更多