12

Ich habe eine Struktur mit drei Tabellen: tournament, group und team. Die tournament und group Tabellen haben eine one-to-many Beziehung und group und team haben eine one-to-many Beziehung wie unten gezeigt.Wie man den Fremdschlüssel einer anderen Tabelle in einer Beziehung repliziert

table structure

Wie replizieren i den Wert des tournament_id von group Tabelle in die group_tournament_id von team Tisch?

ich suche nach einer Antwort, die dies mit der Aussage erstellen wie

create table team (
    id serial primary key, 
    group_id int references group, 
    group_tournament_id int references group(tournament_id) 
); 

natürlich erreichen wird dies nicht, denn um etwas, das es in diesem Fall tournament_id einzigartig sein, muss das Bezug funktionieren würde ist nicht eindeutig zuzuordnen

ich brauche einen Standardweg über den Wert von tournament_id von group in ‚Team‘ group_tournament_id der Tabelle zu kopieren, wann immer ich group_id inside Team table

einfügen

bearbeiten: nicht mehr brauchen Antwort in Symfony, nur PostgreSQL wäre in Ordnung

+0

Hier haben Sie, wie zu Relationen Entitäten: http: //doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/association-mapping.html, und hier symfony docs über das Mapping: http: //symfony.com/doc/current/book/doctrine.html#add-mapping-information – fito

+1

Ich denke, es würde helfen, wenn Ihre Frage ein wenig genauer wäre in dem, was Sie versuchen zu tun und enthielt etwas Code, den Sie haben könnten versucht. –

+3

Normalerweise sollte die 'team' Tabelle nur' group_id' haben und sollte ** not ** 'turnier_id' haben. Ich verstehe nicht, warum Sie Ihr Schema ent-normalisieren. –

Antwort

5

Sie sollten die Referenz direkt von teams bis tournaments verwenden. Verwenden Sie einen Trigger, um automatisch die entsprechende Referenz von groups. zu erhalten (Beachten Sie jedoch, dass die Referenz nicht erforderlich ist, da Sie in einer Abfrage immer tournament_id von groups erhalten können. Ich nehme an, dass diese Referenz einige Abfragen vereinfachen soll).

Ich habe die Namen von Tabellen und Spalten leicht geändert (group kann kein Name einer Tabelle sein).

Tables:

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); 

Trigger:

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(); 

Test:

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) 
+0

andere Möglichkeiten, dies ohne Trigger zu erreichen? OP fragte Alternativen zu Triggern – Dheeraj

+1

Oh, ja, ich habe die Kopfgeldnote nicht gelesen. Wenn ich es sah, würde ich die Antwort nicht posten. Aber ... was ist los mit einem Auslöser? Dies ist die natürlichste und Standardlösung in solchen Fällen. – klin

3

Sie verwenden identifizieren Beziehungen nur:

enter image description here

Dies erzeugt Schlüssel, die den ganzen Weg "propagieren", so erhalten Sie team.tournament_id, die garantiert auf das gleiche Turnier wie die Elterngruppe zeigen.

Bitte beachte, dass ich group_no verwendet (nicht group_id) als Namenskonvention, um anzuzeigen, nicht die Gruppe allein zu identifizieren, aber in Kombination mit den tournament_id. Dito für team_no.

Dies erschwert jedoch das Einfügen. Sie können die Datenbank nicht mehr dazu veranlassen, die nächste automatisch inkrementierte ID für Ihre Gruppe oder Ihr Team zu generieren (weil Sie sie jetzt mit einer Kombination von Werten und nicht nur mit einem Wert identifizieren), aber Sie können das einfach manuell tun - z.beim Einstecken in group, vergeben Sie SELECT MAX(group_no) + 1 FROM group WHERE tournament_id = ... an die neue group_no, und ähnlich für das Team.

BTW, kann diese zusätzlich-surrogate keys (die id in Ihrem Diagramm) durchgeführt werden, wenn Sie noch brauchen.

1

Sie können ein SELECT verwenden, um einen Wert mit INSERT oder UPDATE zu füttern:

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

Dies ist, was ich bin mit Postgres-IDs für Fremdschlüssel ohne (unconsistent) Doppel Abfrage einfügen lassen (von Gruppen auswählen einfügen in Teams).