Sql POSTGRES-仅在填写特定列时插入
拥有:Sql POSTGRES-仅在填写特定列时插入,sql,database,postgresql,Sql,Database,Postgresql,拥有: 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 insert into table (ID, start_date, account) values (1,2016-08-01,123) Insert into insert_only (ID, start_da
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
insert into table (ID, start_date, account) values (1,2016-08-01,123)
Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING;
Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING;
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)
想要实现的目标:
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
insert into table (ID, start_date, account) values (1,2016-08-01,123)
Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING;
Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING;
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)
是否有办法创建约束/索引/其他机制来检查:
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
insert into table (ID, start_date, account) values (1,2016-08-01,123)
Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING;
Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING;
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)
->什么也没发生
insert into table (ID, start_date, account) values (1,2017-04-26, 789)
->插入行
我在想,可能是一个带有存储函数的检查约束,它将检查上述内容或类似的内容?或索引:
create unique index unique_account on table (ID, account) where end_date is null
这是最佳实践 警告:在高度事务数据库中使用触发器将导致性能问题 解决方案:我假设您使用PostgreSQL 9.5或更高版本 直到这一步你几乎完成
create unique index unique_account on table (ID, account) where end_date is null
您只需在PostgreSQL 9.5或更高版本中使用UPSERT
query即可
ANS案例1:
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
insert into table (ID, start_date, account) values (1,2016-08-01,123)
Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING;
Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING;
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)
*我们需要“冲突”
的唯一索引。此查询意味着,如果您插入相同的id+account+date为空
,则“冲突时”
将执行且不执行任何操作
ANS案例2:
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
insert into table (ID, start_date, account) values (1,2016-08-01,123)
Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING;
Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING;
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)
*使用相同的查询,我们输入账户的end\u date
值789
插入将成功
输出:
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
insert into table (ID, start_date, account) values (1,2016-08-01,123)
Insert into insert_only (ID, start_date, account) values (1,'2016-08-01',123) ON CONFLICT DO NOTHING;
Insert into insert_only (ID, start_date, end_date,account) values (1,'2016-08-01','2016-08-01',789) ON CONFLICT DO NOTHING;
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)
可以通过将insert包装到存储过程中来实现这一点。然后拒绝对表的写访问。因此,所有写入操作都必须通过应用所有必要检查的过程。哦,但你已经考虑过了。我感觉你实际上想要一个约束来强制执行非重叠的日期范围(每个{id,account})。在这种情况下,使用
+无限
作为开放区间比空区间更实用。希望这个解决方案对你有所帮助。永远不要在insert中使用触发器进行验证,当您的数据增长到100万时,这将在将来造成麻烦。