POSTGRES - 插入只有某些栏填写

POSTGRES - 插入只有某些栏填写

问题描述:

有:POSTGRES - 插入只有某些栏填写

ID start_date end_date  account 
1 2016-06-30 null   123 
1 2017-04-19 null   111 
1 2017-04-26 2017-07-30 789 

想完成:

有没有一种方法来创建一个约束/索引/其他机制,检查:

  1. 如果存在ID和帐户和结束日期为空 - >无能为力
  2. 如果存在ID和帐户和结束日期不为空 - >插入行

所以:

insert into table (ID, start_date, account) values (1,2016-08-01,123) 

- >什么也没有发生

insert into table (ID, start_date, account) values (1,2017-04-26, 789) 

- >插入行

我在想也许CHECK约束与存储函数,将威尔我检查上述或类似的东西?或指数:

create unique index unique_account on table (ID, account) where end_date is null 
+0

您可以通过包装INSERT INTO存储过程实现这一目标。然后拒绝对该表的写入权限。因此,所有的写作都必须通过应用所有必要检查的程序。哦,但你已经在想这个了。 –

+0

我觉得你实际上想要一个强制实现非重叠日期范围的约束(per {id,account})在这种情况下,对于* open *区间使用'+ infinity'会比NULL更实用。 – wildplasser

这是最好的做法

警告:使用触发器在高交易数据库会导致性能问题。

解决方案:我假设你使用PostgreSQL 9.5或以上

直到这一步,你几乎已经完成

create unique index unique_account on table (ID, account) where end_date is null 

所有你必须在PostgreSQL的9.5或以上使用UPSERT查询做

ANS CASE 1:

Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING; 

*我们需要"CONFLICT"的唯一索引。这个查询意味着如果你插入相同的id + acoount + date is null然后"ON CONFLICT"将执行和DO NOTHING

ANS案例2:

Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING; 

*使用相同的查询,我们输入end_date值是考虑789插入会成功。

OUTPUT:

BEFORE: 

stackoverflow=# select * from insert_only; 
id | start_date | end_date | account 
----+------------+------------+--------- 
    1 | 2016-08-01 |   |  123 
    1 | 2017-08-01 |   |  111 
    1 | 2017-04-26 | 2017-07-30 |  789 
    1 | 2016-08-01 | 2016-08-01 |  789 
(4 rows) 

stackoverflow=# Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING; 
INSERT 0 0 

stackoverflow=# Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING; 
INSERT 0 1 

AFTER: 

stackoverflow=# select * from insert_only; 
id | start_date | end_date | account 
----+------------+------------+--------- 
    1 | 2016-08-01 |   |  123 
    1 | 2017-08-01 |   |  111 
    1 | 2017-04-26 | 2017-07-30 |  789 
    1 | 2016-08-01 | 2016-08-01 |  789 
    1 | 2016-08-01 | 2016-08-01 |  789 
(5 rows) 
+1

希望这个解决方案可以帮助你。并且从不在插入时使用触发器来验证这会在将来数据增长为100万时造成麻烦。 –