2016-04-19 21 views
1

With constraints on rangesは、既存のテーブルに重複する値を追加することを防ぎます。たとえば、次のroom_reservationテーブルでは、競合する時間に部屋が予約されていないことを確認します。Postgresql - 範囲の制約 - 2つのテーブル

CREATE EXTENSION btree_gist; 
CREATE TABLE room_reservation (
    room text, 
    during tsrange, 
    EXCLUDE USING GIST (room WITH =, during WITH &&) 
); 

私たちがここに必要とするのは、部屋とフィールドの間にまた別のテーブルを考えて、予約中にそのテーブル内のレコードを検討することです。

具体的なシナリオは試験管理です。 invigilation table(部屋の予約)とクラスのタイムテーブルもあります。 invigilationレコードを追加したら、他のinvigilationレコードと一致しないようにし、その時間にその部屋には講義がないことを確認する必要があります。

答えて

1

これは、1つの除外制約では実行できません。代わりに、あるテーブル(例:invigilation)に除外制約を使用してから、同じテーブルでBEFORE INSERTトリガーを使用して、2番目のテーブルに競合があるかどうかを確認する必要があります(例:rooms)。クラスは、その後invigilationの挿入は失敗します部屋に予定されている場合

CREATE FUNCTION check_no_class() RETURNS trigger AS $$ 
BEGIN 
    PERFORM * FROM rooms 
    WHERE room = NEW.room 
    AND during && NEW.during; 
    IF FOUND THEN 
    RETURN NULL; 
    ELSE 
    RETURN NEW; 
    END IF; 
END; $$ LANGUAGE plpgsql; 

CREATE TRIGGER check_rooms 
BEFORE INSERT ON invigilation 
FOR EACH ROW EXECUTE PROCEDURE check_no_class(); 

:最初のテーブル上のトリガ機能は、第二のテーブルの上に簡単な範囲チェックを行うだろう。

+0

ありがとう@パトリック! invigilationテーブルの更新に基づいてもう1つのトリガーを追加しようとしました(つまり、現在のinvigilationレコードが新しいものに更新されました)。これを行うために、別のトリガー(check_rooms_2)を作成し、2行目を「更新前に更新する」だけに変更しました。しかし、これはうまくいかなかったようですね! – banbar

+0

再度テストすると、更新が受け入れられます(つまり、レコードは青で強調表示されません)。ただし、競合する更新プログラムの場合は、invigilation表がリフレッシュされると、表は最初の内容に戻ります。 – banbar

関連する問題