ユーザ間の一致を記録するテーブルを作成したい。すべてのマッチは1v1なので、常に2人のユーザーが試合に出ています。そのうちの1人は勝者でなければならず、もう1人は敗者でなければなりません。postgresqlテーブル制約が不正な挿入を拒否しない
CREATE TABLE IF NOT EXISTS matches (
match_id bigserial PRIMARY KEY,
user_1_id bigint NOT NULL REFERENCES users(user_id),
user_2_id bigint NOT NULL REFERENCES users(user_id),
winner_id bigint REFERENCES users(user_id),
loser_id bigint REFERENCES users(user_id),
tied boolean,
CONSTRAINT check_winner_loser_tied CHECK (
(user_1_id != user_2_id) AND
(
(winner_id = user_1_id AND loser_id = user_2_id AND tied = FALSE) OR
(winner_id = user_2_id AND loser_id = user_1_id AND tied = FALSE) OR
(tied = TRUE AND winner_id = NULL AND loser_id = NULL)
)
)
);
あなたが上見ることができるように、私はしかし、私はまだ、テーブルに例を無効なデータを挿入することができるよ、私は上記の条件を強制するためにテーブル制約を追加しました:
INSERT INTO matches (user_1_id, user_2_id, winner_id, loser_id, tied)
VALUES (1, 2, 1, 2, TRUE); -- can't be winner & loser if it's a tie!
さらに:
INSERT INTO matches (user_1_id, user_2_id, winner_id, loser_id, tied)
VALUES (1, 2, NULL, NULL, FALSE); -- must be a winner & loser if no tie!
私は間違っていますか?
さらに詳しい情報:SELECT version();
はPostgreSQL 9.6.3 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit
を返します。
で、この新しいものは 'winner_id = NULL'本当であってはなりません、winner_idではなくNULL' IS'てみてください。 – dnoeth
@dnoethありがとう、それは第1のケース(勝者と敗者との同値=真)を解決するのに役立ちました!ただし、2番目のケースは引き続き可能です(tie = false、null winner&null loser)。 – kfedorov91
2番目のケースで失敗する理由はわかりませんが、データモデルは少し複雑です。 'winner_id'、' loser_id'、 'tied'を3つの値(0,1,2)の単純な列に置き換えてみませんか?0 =タイ、1 =第1ユーザが勝ち、第2 =ユーザが勝った。 – dnoeth