2017-07-05 15 views
0

を記入されている場合にのみ: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とアカウントが存在し、終了日がnullの場合 - >何もしない
  2. IDとアカウントが存在し、終了日がnullでない場合 - >だから、

行を挿入:

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

- > INSERT ROW - >何も

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

あなたは、ストアドプロシージャへの挿入をラップすることにより、それを達成することができます。そして、テーブルへの書き込みアクセスを拒否します。したがって、すべての書き込みは、必要なすべてのチェックを適用する手順を経なければなりません。ああ、あなたはすでにそれについて考えていた。 –

+0

私はあなたが実際には重複しない日付範囲({id、account}に従う)を強制するという気持ちを持っています。その場合、* open *間隔に '+ infinity'を使用する方がNULLよりも実用的でしょう。 – wildplasser

答えて

0

これは、ベストプラクティス

WARNINGです:非常にトランザクションデータベースに使用トリガーは、パフォーマンスの問題が発生します。

ソリューション:私はあなたがあなたがしなければならないのは、PostgreSQL 9.5または

UPSERTクエリを使用しているあなたは、ほぼ

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

を行って、この段階までのPostgreSQL 9.5または

上を使用すると仮定

ANSケース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; 

*挿入が成功するアカウント789に同じクエリ我々入力end_date値を使用します。

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万人のように成長しているときに将来的にトラブルを引き起こす可能性のある検証のために挿入にトリガーを使用しないでください。 –

関連する問題