【问题标题】:Enforcing a unique relationship over multiple columns where one column is nullable在其中一列可以为空的多列上强制执行唯一关系
【发布时间】:2020-06-05 14:21:42
【问题描述】:

给定表格

ID  PERSON_ID  PLAN  EMPLOYER_ID  TERMINATION_DATE  
1         123   ABC          321        2020-01-01
2         123   DEF          321            (null)
3         123   ABC          321            (null)
4         123   ABC          321            (null)

我想排除第 4 个条目。 (第 3 个条目显示此人已被重新雇用,因此是新关系。我只显示相关字段)

我的第一次尝试是简单地在 PERSON_ID / PLAN / EMPLOYER_ID / TERMINATION_DATE 上创建一个唯一索引,认为 DB2 for IBMi 认为空值在唯一索引中是相等的。我显然错了……

  1. 有没有办法强制这些列的唯一性,或者,
  2. 是否有更好的方法来计算终止日期的值? (从技术上讲,null 不正确;我认为它更真/假,但业务逻辑需要一个日期)

编辑

根据 7.3 的文档:

独一无二

防止表包含两个或多个具有相同索引键值的行。 使用 UNIQUE 时,一列的所有空值都被视为相等。例如,如果键是可以包含空值的单个列,则该列只能包含一个空值。当更新表的行或插入新行时,会强制执行该约束。 在执行 CREATE INDEX 语句期间也会检查约束。如果表中已包含具有重复键值的行,则不会创建索引。

不为空的唯一性

防止表包含具有相同索引键值的两行或多行,其中列的所有空值不被视为相等。允许列中有多个空值。否则,这与 UNIQUE 相同。

所以,我看到的行为更像是 UNIQUE WHERE NOT NULL。当我为这个表生成 SQL 时,我看到了

  ADD CONSTRAINT TERMEMPPLANSSN 
  UNIQUE( TERMINATION_DATE , EMPLOYERID , PLAN_CODE , SSN ) ; 

(注意这是显示真实的字段名称,而不是我在示例中使用的名称)


编辑 2

底线,约束!== 索引。当我返回并创建一个实际的 index 时,我得到了想要的行为。

【问题讨论】:

  • 您的 DB2 for IBM i 版本是什么?我的 7.4 不允许我在 (PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE):SQLCODE=-803 上插入具有现有第 3 条和唯一索引的第 4 条记录。 When UNIQUE is used, all null values for a column are considered equal
  • 我认为这是版本 - v7r3m0
  • 规则必须与 7.3 相同。请提供一个包含可空列的唯一索引的可重现示例,该示例允许一列中有多个空值,而其他列的值相同。
  • @MarkBarinstein 感谢您的关注。你需要的不仅仅是我刚刚添加的内容吗
  • 我得到您的要求“排除第 4 个条目”,因为如果表已经包含第 3 行,则不允许插入第 4 行(TERMINATION_DATE 为 NULL)。表中已经存在具有相同列值的第 3 行,因此,唯一索引(不是 UNIQUE 约束 - DB2 不允许对可空列进行 UNIQUE 约束)应该满足这样的要求。 UNIQUE WHERE NOT NULL 仅允许您控制 NOT NULL 值的唯一性。 IE。它会阻止您插入另一行 TERMINATION_DATE = '2020-01-01' 和其他 3 个与第一行相同的列值。

标签: db2 db2-400 unique-index


【解决方案1】:
CREATE TABLE PERSON 
(
  ID INT NOT NULL
, PERSON_ID INT NOT NULL
, PLAN CHAR(3) NOT NULL
, EMPLOYER_ID INT
, TERMINATION_DATE DATE
);

INSERT INTO PERSON (ID, PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE)
VALUES 
  (1, 123, 'ABC', 321, DATE('2020-01-01'))
, (2, 123, 'DEF', 321, CAST(NULL AS DATE))
, (3, 123, 'ABC', 321, CAST(NULL AS DATE))
WITH NC;

--- 不允许:---

INSERT INTO PERSON (ID, PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE) VALUES 
(4, 123, 'ABC', 321, CAST(NULL AS DATE))
or
(4, 123, 'ABC', 321, DATE('2020-01-01'))

你可以:

CREATE UNIQUE INDEX PERSON_U1 ON PERSON 
(PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE);

--- 不允许:---

INSERT INTO PERSON (ID, PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE) VALUES 
(4, 123, 'ABC', 321, DATE('2020-01-01'))

但允许多个:

(X, 123, 'ABC', 321, CAST(NULL AS DATE))
(Y, 123, 'ABC', 321, CAST(NULL AS DATE))
...

你可以:

CREATE UNIQUE WHERE NOT NULL INDEX PERSON_U2 ON PERSON 
(PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多