是否存在SQL表约束以确保两列之间存在关系?

时间:2017-01-20 06:53:43

标签: sql postgresql

我正在尝试解决以下问题。

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,那么我允许插入游戏表,否则我不会。有没有办法做到这一点,但让数据库处理约束,以便我在尝试插入游戏表之前不必进行额外的查询?

谢谢!

1 个答案:

答案 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列,因此不会出现成员来自不同联盟的情况。