2009-07-14 7 views
-1

Comment puis-je concevoir une base de données avec une table de lecteurs (avec la clé primaire player_id) que je veux associer en deux équipes pour que la base de données puisse appliquer la contrainte l'équipe se compose de exactement deux joueurs et chaque joueur est dans au plus une équipe?Création d'une base de données pour l'appariement des contraintes

Je peux penser à deux solutions, mais les deux ne me plaisent pas.

Une possibilité est d'avoir deux colonnes player1_id et player2_id qui sont uniques clés étrangères pointant vers la player_id colonne dans la table des joueurs. Un contrôle supplémentaire est nécessaire pour qu'aucun joueur ne soit en même temps joueur1 d'une équipe et joueur2 d'une seconde équipe.

L'autre possibilité qui me vient à l'esprit est de se connecter la table des joueurs et la table d'équipe avec une table de composition de l'équipe qui a une unique, clé étrangère à la player_id colonne dans la table des joueurs et une seconde clé étrangère pointant vers la clé primaire de la table d'équipe. Ici, un contrôle doit être ajouté que chaque équipe a exactement deux membres.

Y a-t-il une meilleure conception qui simplifie la vérification des contraintes?

Si c'est important: la base de données que j'utilise est PostgreSQL 8.4 et je préfère ses puissants rule system aux triggers autant que possible.

EDIT: Une solution basée sur la réponse de AlexKuznetsov

Il ne se sent pas encore parfait pour moi, mais je l'aime beaucoup mieux que ce que j'avais avant. J'ai modifié la solution d'Alex car je ne veux pas avoir une clé étrangère des joueurs vers les équipes, car il y a une phase d'application où les joueurs peuvent s'inscrire. Cette définition s'assure que les membres d'une équipe viennent en couple (et seront insérés par paire). Maintenant, les joueurs peuvent être dans au plus une équipe et les équipes peuvent avoir exactement 0 ou exactement 2 joueurs. Pour m'assurer que chaque équipe a des membres, je pourrais ajouter une clé étrangère dans la table d'équipe qui pointe vers l'une de ses deux appartenances. Mais comme Erwin, je ne suis pas un fan de vérification de contrainte différée. Des idées comment améliorer à cet égard? Ou y a-t-il une approche complètement différente et meilleure? PS: Les méthodes fonctionnent également pour les équipes de n> 2 joueurs. Il suffit de remplacer OtherNumberInTeam par NextNumberInTeam avec la valeur (c'est-à-dire la contrainte) NumberInTeam + 1 mod n.

+0

Avez-vous des vues matérialisées postgres? – FerranB

Répondre

1

Je ne sais pas si cela peut fonctionner sur Postgress, mais voici une solution SQL Server:

CREATE TABLE dbo.Teams(TeamID INT NOT NULL PRIMARY KEY); 
GO 
CREATE TABLE dbo.Players(PlayerID INT NOT NULL PRIMARY KEY, 
    TeamID INT NOT NULL FOREIGN KEY REFERENCES dbo.Teams(TeamID), 
    NumberInTeam INT NOT NULL CHECK(NumberInTeam IN (1,2)), 
    TeamMateID INT NOT NULL, 
    TeamMatesNumberInTeam INT NOT NULL, 
-- if NumberInTeam=1 then TeamMatesNumberInTeam must be 2 
-- and vise versa 
    CHECK(NumberInTeam+TeamMatesNumberInTeam = 3), 
    UNIQUE(TeamID, NumberInTeam), 
    UNIQUE(PlayerID, TeamID, NumberInTeam), 
    FOREIGN KEY(TeamMateID, TeamID, TeamMatesNumberInTeam) 
    REFERENCES dbo.Players(PlayerID, TeamID, NumberInTeam) 
); 

INSERT INTO dbo.Teams(TeamID) SELECT 1 UNION ALL SELECT 2; 
GO 

- vous ne pouvez insérer les joueurs dans les paires complètes

INSERT INTO dbo.Players(PlayerID, TeamID, NumberInTeam, TeamMateID, TeamMatesNumberInTeam) 
SELECT 1,1,1,2,2 UNION ALL 
SELECT 2,1,2,1,1; 

Vous pouvez essayez d'insérer un seul joueur, ou de supprimer un joueur d'une équipe, ou d'insérer plus de deux joueurs par équipe - tous échoueront en raison d'un ensemble complet de contraintes.

Remarque: la pratique dans SQL Server consiste à nommer explicitement toutes les contraintes. Je n'ai pas nommé mes contraintes au cas où cela ne serait pas compatible avec Postgres.

0

Cela ressemble à quelque chose qui serait beaucoup plus facile à appliquer dans une interface utilisateur que dans la base de données. Lorsque vous ajoutez des joueurs à des équipes, n'autorisez pas l'ajout de plus de 2 joueurs et n'autorisez que l'ajout de joueurs qui ne font pas partie d'une équipe.

0

La première solution est limitée s'il peut être nécessaire de changer d'équipe avec trois membres. J'aime l'idée de la table teamMemebrs, mais pour imposer vos contraintes, vous ne pourrez jamais insérer un seul enregistrement à la fois. Tous vos inserts devront être l'ensemble des deux.De plus, vous entrez dans la complexité de ce que vous faites quand le joueur A est dans l'équipe A et que vous voulez qu'il soit déplacé dans l'équipe B. Maintenant vous devez trouver quelqu'un pour passer à l'équipe A et ensuite l'ajouter et son partenaire à l'équipe B.

Serait-il préférable de créer et de peupler les équipes mais de les rendre actives uniquement si elles ont deux membres et que chaque membre n'appartient qu'à une seule équipe? Au moins, vous pouvez faire les changements un à la fois. SP vous pouvez déplacer la personne A de l'équipe A à l'équipe B et rendre l'équipe A inactive jusqu'à ce que vous trouviez une autre personne à ajouter.

0

Il me semble qu'avec la conception player1-id player2_id, vous pouvez faire vérifier toutes vos contraintes après une seule insertion dans votre table d'équipe. Dans les équipes + conception d'appartenance à l'équipe, vous vous retrouvez dans la laideur de la vérification des contraintes différées, par-dessus tout le truc de déclenchement/règle que vous auriez à configurer. Incidemment: des systèmes tels que SIRA_PRISE sont construits dans le but explicite de traiter précisément ces types de problèmes d'application de contraintes de façon purement déclarative, c'est-à-dire SANS les tracas des triggers, ou toute autre forme de programmation impliquée. Vous pourriez être intéressé.

Questions connexes