【问题标题】:Unique value Constraint with multiple columns across the table, not the combination in Oracle具有跨表多列的唯一值约束,而不是 Oracle 中的组合
【发布时间】:2020-08-23 09:12:47
【问题描述】:

在 oracle 中有没有一种方法可以强制两列之间的唯一性?

不是两列组合之间的唯一性,而是两列之间跨表的值。

参考资料:

Unique value constraint across multiple columns

示例数据,不应允许:

id | phone1 | phone2
1  | 111    | 111

id | phone1 | phone2
1  | 111    | NULL
2  | 111    | NULL  

id | phone1 | phone2
1  | 111    | NULL
2  | NULL   | 111 

Unique constraint on combination of two columns?

我的 Oracle 版本:

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

【问题讨论】:

  • 请提供样本数据以及允许和不允许的示例。
  • 我添加了参考资料,其中包含我正在寻找的样本。
  • 那么,phone1 不能与phone2 相同,并且任何值在两列中都应该是唯一的?
  • 没错。请查看上面的第 2 和第 3 个案例以获取更多信息。总之,这两个字段(phone1 和 phone2)的值在表中的两列值中应该是唯一的。

标签: sql oracle multiple-columns unique-constraint


【解决方案1】:

我会使用check() 约束来确保每一行的唯一性,以及跨行唯一性的唯一索引:

create table mytable (
    id int, 
    phone1 int, 
    phone2 int,
    check (phone1 <> phone2)
);

create unique index myidx on mytable(
    greatest(coalesce(phone1, phone2), coalesce(phone2, phone1)),
    least(coalesce(phone1, phone2), coalesce(phone2, phone1))
);

这种方法的好处是它还可以防止插入像 (111, 222) 和 (222, 111) 这样的元组。

Demo on DB Fiddle:

insert into mytable values(1, 111, 111);
ORA-02290: 违反检查约束 (FIDDLE_SMBYKTEIHNNVOHKZSCYK.SYS_C0020876)
begin
    insert into mytable values(1, 111, null);
    insert into mytable values(1, 111, null);
end;
/
ORA-00001: 违反了唯一约束 (FIDDLE_SMBYKTEIHNNVOHKZSCYK.MYIDX) ORA-06512: 在第 3 行
begin
    insert into mytable values(1, 111, null);
    insert into mytable values(1, null, 111);
end;
/
ORA-00001: 违反了唯一约束 (FIDDLE_SMBYKTEIHNNVOHKZSCYK.MYIDX) ORA-06512: 在第 3 行
begin
    insert into mytable values(1, 111, 222);
    insert into mytable values(1, 222, 111);
end;
/
ORA-00001: 违反了唯一约束 (FIDDLE_SMBYKTEIHNNVOHKZSCYK.MYIDX) ORA-06512: 在第 3 行

【讨论】:

  • 您的greatest/least 构造基本上是对元组进行排序,对吧?
  • @wolφi:是的,确实如此。这是为了防止“镜像”元组(我回答中的最后一个用例)。
  • 你有什么手机??? ;-) 是的,当然它适用于字母数字...
【解决方案2】:

我会结合检查约束和函数上的唯一索引来解决它:

CREATE TABLE t(id NUMBER, phone1 NUMBER, phone2 NUMBER);
ALTER  TABLE t ADD CONSTRAINT c1 CHECK (phone1 <> phone2);
CREATE UNIQUE INDEX u ON t(COALESCE(phone1, phone2));

案例 1 有效:

INSERT INTO t VALUES (1, 111, 111);
ORA-02290: check constraint (C1) violated

案例 2 也有效:

INSERT INTO t VALUES (1, 111, NULL);
INSERT INTO t VALUES (2, 111, NULL);
ORA-00001: unique constraint (U) violated

案例 3:

INSERT INTO t VALUES (1, 111, NULL);
INSERT INTO t VALUES (2, NULL, 111);
ORA-00001: unique constraint (WFL.U) violated

但是,这不受保护:

INSERT INTO t VALUES (1, 111, 222);
INSERT INTO t VALUES (2, 222, 111);

【讨论】:

  • 知道了。但最后一个很重要。
  • 好的,那是 GMB 解决方案的 +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
相关资源
最近更新 更多