Db2 在一列可为空的多列上强制执行唯一关系

Db2 在一列可为空的多列上强制执行唯一关系,db2,db2-400,unique-index,Db2,Db2 400,Unique Index,给定桌子 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

给定桌子

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)
我想排除第四个条目。(第三个条目显示此人已被重新雇用,因此是新的关系。我只显示相关字段)

我的第一次尝试是简单地在
个人ID/计划/雇主ID/终止日期
上创建一个唯一索引,认为DB2forIBMI认为空值在唯一索引中是相等的。我显然错了

  • 有没有办法在这些列上强制执行唯一性,或者
  • 是否有更好的方法接近终止日期的价值?(null在技术上不正确;我认为它更正确/错误,但业务逻辑需要一个日期)

  • 编辑 根据7.3的文件:

    独特的

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

    唯一,其中不为NULL

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

    所以,我看到的行为看起来更像是唯一的,而不是NULL。当我为这个表生成SQL时,我看到

      ADD CONSTRAINT TERMEMPPLANSSN 
      UNIQUE( TERMINATION_DATE , EMPLOYERID , PLAN_CODE , SSN ) ; 
    
    (注意,这显示的是真实的字段名,而不是我在示例中使用的字段名)


    编辑2 底线,约束!==指数当我返回并创建一个实际的索引时,我得到了所需的行为

    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;
    
    ---不允许:---

    你可以:

    CREATE UNIQUE INDEX PERSON_U1 ON PERSON 
    (PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE);
    
    CREATE UNIQUE WHERE NOT NULL INDEX PERSON_U2 ON PERSON 
    (PERSON_ID, PLAN, EMPLOYER_ID, TERMINATION_DATE);
    
    ---不允许:---

    但允许多个:

    (X, 123, 'ABC', 321, CAST(NULL AS DATE))
    (Y, 123, 'ABC', 321, CAST(NULL AS DATE))
    ...
    
    你可以:

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

    您的DB2forIBMi版本是什么?我的7.4不允许我在
    (个人ID、计划、雇主ID、终止日期)
    SQLCODE=-803
    上插入第4条记录和现有的第3条记录和唯一索引。我认为这是V7R3M0版本。规则必须与7.3相同。请提供一个包含可空列的唯一索引的可复制示例,该索引允许一列中有多个空,而其他列的值相同。@MarkBarinstein感谢您的关注。如果表格已经包含1-3行,您是否需要比我刚才添加的更多的内容?我得到了您的要求“排除第4项”,因为要求不允许插入第4行(终止日期为空)。表中已经存在具有相同列值的第3行,因此,惟一索引(非惟一约束-DB2不允许对可为null的列进行惟一约束)应该满足这样的要求
    UNIQUE,其中NOT NULL
    允许您仅控制NOT NULL值的唯一性。也就是说,它阻止您插入另一行
    终止日期='2020-01-01'
    ,其他3行的列值与第一行相同。