我正在尝试解决以下问题。
CREATE TABLE leagues (
id SERIAL PRIMARY KEY,
name TEXT,
...
);
CREATE TABLE players (
id SERIAL PRIMARY KEY,
first_name TEXT,
last_name TEXT,
...
);
CREATE TABLE league_members (
league_id INTEGER REFERENCES leagues (id),
player_id INTEGER REFERENCES players (id),
PRIMARY KEY (league_id, player_id)
);
CREATE TABLE games (
id SERIAL PRIMARY KEY,
league_id INTEGER REFERENCES leagues (id),
winner INTEGER REFERENCES players (id),
loser INTEGER REFERENCES players (id)
);
在游戏表中,是否存在我可以使用的约束,以确保赢家和输家都是同一联盟的成员?
例如:
球员表:
---- id ---- first_name ----
1 "John"
2 "Joe"
3 "Jill"
联赛表:
---- id ---- name ----
1 "League 1"
2 "League 2"
league_members表:
---- id ---- league_id ---- player_id ----
1 1 1
2 1 2
3 2 3
我想确保在游戏桌中以下内容会导致错误:
INSERT INTO games (league_id, winner, loser) VALUES (1,1,3);
这不应该被允许,因为玩家3不在联赛1中。现在我只是在联盟成员表上运行此查询:
SELECT count(*) FROM league_members WHERE league_id = 1 AND (player_id = 1 OR player_id = 3);
并且他们确保计数为2,这意味着两个玩家都是id为1的联盟成员。如果计数为2,那么我允许插入游戏表,否则我不会。有没有办法做到这一点,但让数据库处理约束,以便我在尝试插入游戏表之前不必进行额外的查询?
谢谢!
答案 0 :(得分:2)
一些外键应该保持正确:
CREATE TABLE games (
id SERIAL PRIMARY KEY,
league_id INTEGER REFERENCES leagues (id),
winner INTEGER REFERENCES players (id),
loser INTEGER REFERENCES players (id),
constraint FK_League_Winner FOREIGN KEY (league_id,winner)
REFERENCES league_members (league_id,player_id),
constraint FK_League_Loser FOREIGN KEY (league_id,loser)
REFERENCES league_members (league_id,player_id)
);
由于这两个密钥都在此表中共享league_id
列,因此不会出现成员来自不同联盟的情况。