2016-07-22 15 views
0

In PostgreSQL 9.5 Ich möchte eine Tabelle mit drei Spalten erstellen. Ich würde im Grunde so etwas wiePostgreSQL exklusiv oder auf Spalteneinstellung

create table Foo (
    account varchar not null, 
    team_id integer references team (ident) on delete cascade, 
    league_id integer references league (ident) on delete cascade 
) 

Der Spaß daran ist nun, dass ich möchte, dass sie ENTWEDER team_id ODER league_id, angeben, aber nicht beide. Die Kombination von account plus einer der anderen beiden Spalten ist dann die UNIQUE-Einschränkung.

Ist das möglich?

Antwort

2

sicher zu gehen, nur eine der Spalten zugeführt wird, eine Check-Einschränkung verwenden:

alter table foo add 
    constraint check_team check (not (team_id is not null and league_id is not null)); 

Die oben verhindert jedoch nicht einen Nullwert für beiden Spalten bereitstellt. Wenn Sie sicherstellen möchten, dass genau einer von ihnen zur Verfügung gestellt ist, können Sie verwenden:

alter table foo add 
    constraint check_team check ((team_id is not null or league_id is not null) 
           and not (team_id is not null and league_id is not null)); 

Edit: als Abelisto erwähnt, kann die Prüfung Einschränkung

alter table foo add 
    constraint check_team check ((team_id is null) <> (league_id is null)); 

vereinfacht werden Ich bin nicht sicher über die einzigartige Beschränkung, die Sie einrichten möchten. Wenn z.B. die folgenden zwei Zeilen sollten ('x', 1, null), verhindert werden ('x', null, 1) dann können Sie einen eindeutigen Index wie folgt verwenden:

create unique index on foo (account, coalesce(team_id, league_id)); 

, dass nur richtig funktionieren würde, wenn Sie die Regel durchzusetzen, dass mindestens einer dieser Spalten nicht null sein muss.

Wenn aber wollen Sie das gleiche Team in verschiedenen Spalten erlauben, aber er wollen gleiche team_id oder league_id zweimal für ein Konto zu haben, zu verhindern (das obige Beispiel erlaubt), dann denke ich, Sie eindeutigen Indizes benötigen:

create unique index on foo (account, team_id) where team_id is not null; 
create unique index on foo (account, league_id) where league_id is not null; 
+0

Danke! Ihr zweites Beispiel war genau das, was ich brauchte. – Gargoyle

+0

Eigentlich beantwortet das nur einen Teil der Frage. Jetzt habe ich sichergestellt, dass sie entweder eine Mannschaft oder eine Liga zur Verfügung stellen, aber nicht beide. Wie füge ich jetzt die UNIQUE-Einschränkung hinzu, damit das Paar überprüft wird? Zu Ihrer Frage wären '('x', 1, null)' und '('x', null, 1)' beide OK, da sie sich voneinander unterscheiden. – Gargoyle

+0

Scratch das. Die einzige Bedingung ist, dass alle drei zusammen sind :) – Gargoyle