如何在一对多关系中复制另一个表的外键

时间:2016-01-13 14:38:22

标签: postgresql database-design one-to-many table-relationships postgresql-9.6

我有三个表结构:tournamentgroupteamtournamentgroup表格具有一对多关系,而groupteam有一个一对一许多关系,如下所示。

table structure

如何将tournament_id的{​​{1}}值复制到group表的group_tournament_id

我正在寻找一个能够使用像

这样的创建语句来实现这个目标的答案
team

当然这不起作用,因为为了引用它必须是唯一的东西,在这种情况下,tournament_id不是唯一的

当我插入create table team ( id serial primary key, group_id int references group, group_tournament_id int references group(tournament_id) ); 团队tournament_id时,我需要一种标准方式将group的值从group_tournament_id复制到'团队'表的group_id inside

编辑:不再需要在symfony中回答,只需postgreSQL就可以了

3 个答案:

答案 0 :(得分:5)

您应该直接使用teamstournaments的引用。使用触发器从groups.自动获取相应的引用(请注意,引用不是必需的,因为在查询中始终可以从tournament_id获取groups。我假设此引用是简化一些查询。)

我稍微修改了表和列的名称(group不能是表的名称)。

表:

create table tournaments (
    tournament_id serial primary key);

create table groups (
    group_id serial primary key,
    tournament_id int references tournaments);

create table teams (
    team_id serial primary key, 
    group_id int references groups, 
    tournament_id int references tournaments);

触发:

create or replace function before_insert_or_update_on_teams()
returns trigger language plpgsql as $$
begin
    new.tournament_id = (
        select tournament_id
        from groups
        where group_id = new.group_id
        limit 1);
    return new;
end $$;

create trigger before_insert_or_update_on_teams
before insert or update on teams
for each row execute procedure before_insert_or_update_on_teams();

测试:

insert into tournaments values (default), (default);
insert into groups values (default, 2);
insert into teams values (default, 1, null);

select * from teams;

 team_id | group_id | tournament_id 
---------+----------+---------------
       1 |        1 |             2
(1 row)

答案 1 :(得分:3)

您可以使用识别关系:

enter image description here

这会生成传播的密钥"一直向下,所以你得到delete,保证指向与父组相同的锦标赛。

请注意,我使用team.tournament_id(不是group_no)作为命名惯例,表示它不能单独识别该组,而是与group_id结合使用。同上tournament_id

但这使插入变得复杂。您不能再让数据库为您的组或团队生成下一个自动递增的ID(因为您现在使用值的组合识别它,而不仅仅是一个值),但您可以轻松地手动执行 - 例如插入team_no时,将group分配给新的SELECT MAX(group_no) + 1 FROM group WHERE tournament_id = ...,并为该小组分配类似内容。

顺便说一下,如果你还需要它,可以另外surrogate keys(图表中的group_no)。

答案 2 :(得分:1)

您可以使用SELECT通过INSERTUPDATE提供值:

INSERT INTO "teams" ("group_id", "tournament_id")
SELECT $1, "groups"."tournament_id"
  FROM "groups" WHERE ("groups"."id" = $1)
RETURNING "id"

这是我用来让Postgres在没有(不一致的)双重查询的情况下插入外键的ID(从组中选择,插入到团队中)。