2

次のようなテーブルがあるとします。

CREATE TABLE foo (
  id SERIAL PRIMARY KEY
  , barid integer NOT NULL REFERENCES bar(id) 
  , bazid integer NOT NULL REFERENCES baz(id)
  , startdate timestamp(0) NOT NULL
  , enddate timestamp(0) NOT NULL
);

このテーブルの目的は、テーブル bar と baz の間に擬似的な「1 対多」の関係を提供することですが、この関係は時間の経過とともに変化する可能性があります。

SELECT * FROM bar
JOIN foo on TRUE
  AND foo.barid = bar.id
  AND now() BETWEEN foo.startdate  AND foo.enddate 
JOIN baz on baz.id = foo.bazid

テーブルの特定の行について、barテーブル内の対応する行を見つけたいと考えていますbazが、対応する行は期間によって異なる可能性があるため、現在は別の行を返し、先月は別の行を返す必要があります。

私の質問は次のとおりです。このテーブルのデータの整合性を検証する最良の方法は何ですか? 具体的には、特定のタイムスタンプについて、 のテーブルfooに1 行しかないことを確認する必要がありますfoo.barid。私はトリガーを書くことができることを知っています(今ではこれが私の唯一のオプションのようです)が、誰かがもっと簡単なアイデアを持っているのでしょうか? 何らかの部分インデックスを使おうと思っていたのですが、条件の書き方がわかりません...

4

2 に答える 2

4

foo特定のタイムスタンプの場合、テーブルには1行しかないことを確認する必要がありますfoo.barid

そして、「タイムスタンプ」とは、一定の期間を意味しているようです。

range type除外制約を(追加のモジュールを使用して) の等価性と組み合わせると、完璧な解決策になります。baridbtree_gist

CREATE EXTENSION btree_gist;  -- needed once per database

CREATE TABLE foo (
  fooid  serial PRIMARY KEY
, barid  integer NOT NULL REFERENCES bar(barid) 
, bazid  integer NOT NULL REFERENCES baz(bazid)
, time_range tsrange NOT NULL           -- replaces startdate  & enddate 
, EXCLUDE USING gist (barid WITH =, time_range WITH &&)
);

これには Postgres 9.2以降が必要です。

関連している:

マニュアルには、一致するコード例があります!

于 2013-12-11T08:11:35.990 に答える
0

私のpostgres 9.3への切り替えが延期されたため、あなたが言及した投稿のようなものになりました:

CREATE TABLE foo (
  id SERIAL PRIMARY KEY
  , barid integer NOT NULL REFERENCES bar(id) 
  , bazid integer NOT NULL REFERENCES baz(id)
  , startdate timestamp(0) NOT NULL
  , enddate timestamp(0) NOT NULL
  EXCLUDE USING gist (
    box(
      point(
        -- this is kind of a dirty hack: as extracting epoch from +/- infinity 
        -- gives 0, I need to distinguish one from another
        date_part('epoch'::text, least( startdate , '2222-01-01') )  
        , barid 
      )
      , point(
        -- same thing here
        date_part('epoch'::text, least( enddate , '2222-01-01') ) 
        , barid 
      )
    )  WITH &&
  )
);
于 2013-12-13T10:15:13.320 に答える