唯一日期字段postgresql默认值

时间:2017-03-27 20:04:50

标签: postgresql date unique

我有一个date列,我想在填充后保持唯一,但如果未填充date字段,则希望忽略该字段。

在MySQL中,完成此操作的方法是将date列设置为“not null”并为其指定默认值'0000-00-00' - 这允许唯一索引中的所有其他字段即使尚未填充date列,也要“检查”。

这在PosgreSQL中不起作用因为'0000-00-00'不是有效日期,所以你不能将它存储在日期字段中(这对我来说很有意义)。

乍一看,离开字段nullable似乎是一种选择,但这会产生问题:

=> create table uniq_test(NUMBER bigint not null, date DATE, UNIQUE(number, date));
CREATE TABLE
=> insert into uniq_test(number) values(1);
INSERT 0 1
=> insert into uniq_test(number) values(1);
INSERT 0 1
=> insert into uniq_test(number) values(1);
INSERT 0 1
=> insert into uniq_test(number) values(1);
INSERT 0 1
=> select * from uniq_test;
 number | date 
--------+------
      1 | 
      1 | 
      1 | 
      1 | 
(4 rows)

NULL显然“不等于它自己”,所以它不计入约束。

如果我仅在number字段上添加其他唯一约束,则仅检查number而不是date,因此我不能拥有两个具有不同日期的数字。

我可以选择一个“有效日期”(但在工作范围之外)的默认日期来解决这个问题,并且可以(实际上)为当前项目侥幸逃脱,但实际上我可能会遇到这种情况。在接下来的几年中遇到这样的事实并非显而易见,因为它是“很久以前”或“未来”,日期是非实际日期。

'0000-00-00'机制对我的好处恰恰在于这个日期不是真实的,因此表示一个非填充的条目(其中'非填充'是有效的唯一性属性)。当我在互联网上四处寻找解决方案时,我发现的大部分内容都是“只使用NULL”,“存储零是愚蠢的。”

TL; DR 是否存在PostgreSQL最佳做法,需要在包含日期字段的唯一约束中包含“未填充”作为可能的值?

2 个答案:

答案 0 :(得分:2)

不清楚你想要什么。这是我的猜测:

create table uniq_test (number bigint not null, date date);

create unique index i1 on uniq_test (number, date)
where date is not null;

create unique index i2 on uniq_test (number)
where date is null;

对于非空日期将存在唯一约束,对于空日期将存在另一个约束,从而有效地将(number, date)元组转换为不同的值。

检查partial index

答案 1 :(得分:0)

这不是最佳做法,但你可以这样做:

t=# create table so35(i int, d date);
CREATE TABLE
t=# create unique index i35 on so35(i, coalesce(d,'-infinity'));
CREATE INDEX
t=# insert into so35 (i) select 1;
INSERT 0 1
t=# insert into so35 (i) select 2;
INSERT 0 1
t=# insert into so35 (i) select 2;
ERROR:  duplicate key value violates unique constraint "i35"
DETAIL:  Key (i, (COALESCE(d, '-infinity'::date)))=(2, -infinity) already exists.
STATEMENT:  insert into so35 (i) select 2;