J'essaie de comprendre ce truc ahurissant qu'ils appellent Database Design sans grand succès, alors je vais essayer d'illustrer mon problème avec un exemple.
J'utilise MySQL et voici ma question:
Disons que je veux créer une base de données pour contenir ma collection de DVD. Je dispose des informations suivantes que je souhaite inclure:
J'aimerais créer des relations entre ceux-ci pour le rendre plus efficace mais je ne sais pas comment.
Voici ce que je pense pour la conception de la base de données:
Table des films => filmid, titre du film, durée d'exécution, description
Tableau des années => année
Tableau des genres => genre
Table des directeurs => directeur
Table des acteurs => nom_acteur
Mais comment pourrais-je créer des relations entre ces tables?
De plus, j'ai créé un ID unique pour la table Films avec une clé primaire qui s'incrémente automatiquement, dois-je créer un ID unique pour chaque table?
Et enfin, si je devais mettre à jour un nouveau film dans la base de données via un formulaire PHP, comment insérer toutes ces données dans (avec les relations et tout?)
merci pour toute aide que vous pouvez donner, Keith
Vous devez faire une distinction entre les attributs et les entités. Une entité est une chose - généralement un nom. Un attribut ressemble plus à une information descriptive. Dans le jargon de la base de données, entité = table, attribut = champ/colonne.
Avoir une table séparée pour certaines choses, utilisons Director, comme exemple, s'appelle la normalisation. Bien que cela puisse être bon dans certaines circonstances, cela peut être inutile dans d'autres (car cela rend généralement les requêtes plus compliquées - vous devez tout joindre - et c'est plus lent).
Dans ce cas, il n'est pas nécessaire d'avoir une table d'année, car il n'y a pas d'autres attributs d'environ une année, en plus de l'année elle-même, que vous stockeriez. Il est préférable de dénormaliser cela et de stocker l'année dans la table du film elle-même.
Director, par contre, est différent. Peut-être voudrez-vous enregistrer le prénom, le nom, la date de naissance, la date de décès du réalisateur (le cas échéant), etc. Vous ne voulez évidemment pas saisir la date de naissance du réalisateur chaque fois que vous entrez dans un film que cette personne dirige, il est donc logique d'avoir une entité distincte pour un directeur.
Même si vous ne voulez pas stocker toutes ces informations sur le réalisateur (vous voulez juste son nom), avoir une table séparée pour cela (et utiliser une clé de substitution - j'y reviendrai dans une seconde) est utile car il empêche les erreurs typographiques et les doublons - si le nom d'une personne est mal orthographié ou saisi différemment (premier, dernier vs dernier, premier), alors si vous essayez de trouver d'autres films qu'ils ont réalisés, vous échouerez.
L'utilisation d'une clé de substitution (clé primaire) pour les tables est généralement une bonne idée. La correspondance d'un entier est beaucoup plus rapide que la correspondance d'une chaîne. Il vous permet également de changer librement le nom, sans vous soucier des clés étrangères stockées dans d'autres tables (l'ID reste le même, vous n'avez donc rien à faire).
Vous pouvez vraiment pousser cette conception assez loin, et il s'agit simplement de déterminer ce que vous voulez pouvoir y stocker.
Par exemple, plutôt que d'avoir un seul réalisateur par film, certains films ont plusieurs réalisateurs ... il y aurait donc une relation plusieurs-à-plusieurs entre les films et les réalisateurs, vous auriez donc besoin d'une table avec par exemple:
films_directors => **filmid, directorid**
Pour aller plus loin, les réalisateurs sont parfois aussi des acteurs, et vice-versa. Ainsi, plutôt que même d'avoir des tables de réalisateur et d'acteur, vous pouvez avoir une seule table de personne et rejoindre cette table en utilisant une table de rôle. La table des rôles occuperait divers postes - par exemple, réalisateur, producteur, star, extra, grip, éditeur ... et cela ressemblerait plus à:
films => **filmid**, title, otherstuff...
people => **personid**, name, ....
roles => **roleid**, role name, ....
film_people => **filmid, personid, roleid**
genre => **genreid**, name, ...
film_genre => **genreid, filmid**
Vous pouvez également avoir un champ role_details dans la table film_people, qui peut contenir des informations supplémentaires en fonction du rôle (par exemple, le nom du rôle joué par l'acteur).
Je montre également le genre comme une relation beaucoup <> multiple, car il est possible qu'un film soit de plusieurs genres. Si vous ne le vouliez pas, au lieu de la table film_genre, les films contiendraient simplement un genreid.
Une fois que cela est configuré, il est facile d'interroger et de trouver tout ce qu'une personne a fait, ou tout ce qu'une personne a fait en tant que réalisateur, ou tous ceux qui ont déjà réalisé un film, ou toutes les personnes impliquées dans un film spécifique. Cela peut continuer encore et encore.
Ce qui suit n'est pas du code MySQL réel. Il semble que ce dont vous avez besoin est plus d'un début conceptuel ici. Voici donc un modèle de ce à quoi votre base de données devrait ressembler.
Pour chaque acteur du film, vous ajouteriez une ligne à l'Index Acteur-Film. Donc, si les acteurs 5 et 13 (les clés primaires de ces acteurs) ont joué dans le film 4 (encore une fois, la clé primaire de ce film), vous auriez deux lignes reflétant ce fait dans votre index: une avec id de film = 4, et acteur id = 5, et un autre avec film id = 4, et acteur id = 13.
J'espère que cela pourra aider.
En outre, cela suppose que chaque film a exactement un réalisateur. Si un film de votre bibliothèque a deux réalisateurs (comme Slumdog Millionaire), vous voudrez séparer l'identifiant du réalisateur de la table des films et créer un index réalisateur-film comme l'indice acteur-film comme ci-dessus.
Voici les tableaux que j'utiliserais:
films (_id_, title, runningtime, description)
genres (_id_, name)
people (_id_, name, birthdate, etc...)
roles (_roleid_, rolename)
filmgenres (_filmid_, _genreid_)
castandcrew (_filmid_, _roleid_, _personid_)
Au lieu d'avoir une table de réalisateurs et d'acteurs, ayez juste une table de personnes. Cela peut également inclure des membres d'équipage (au cas où vous voudriez savoir qui était le 2e Junior Assistant Dolly Grip). Chaque film peut être de n'importe quel nombre de genres (comédie et horreur, par exemple). De plus, les gens peuvent jouer n'importe quel nombre de rôles dans chaque film - il y a un certain nombre d'acteurs/réalisateurs là-bas.
Le tableau des rôles ne signifie pas nécessairement le personnage joué par l'acteur, mais cela pourrait. Cela pourrait être "Réalisateur", "Producteur", "Acteur" ... ou même "Luke Skywalker" si vous vouliez obtenir ce finement ... Je crois qu'IMDB le fait.
J'espère que les noms des champs ci-dessus devraient faire allusion aux clés étrangères, et j'ai mis _underscores_
autour des clés primaires que j'utiliserais.
Vous pouvez télécharger le schéma Imdb ici .
Votre table Films a également besoin de liens vers les tables des genres, des réalisateurs et des acteurs. Étant donné que les acteurs, au moins seront plusieurs à plusieurs (un film listera plus d'un acteur, un acteur sera dans plus d'un film), vous aurez besoin d'une table pour les relier.
Films Table => filmid, filmtitle, runningtime, description, genreid, directorid
Genre Table => genreid, genre
Director Table => directorid, director
Actors Table => actorid,actor_name
FilmActor link table => actorid, filmid (with a record linking each actor to each film)
Toute table qui peut être plusieurs à plusieurs a besoin d'une table de liaison.
J'ai créé un ID unique pour la table Films avec une clé primaire qui s'incrémente automatiquement, dois-je créer un ID unique pour chaque table?
Oui, chaque table doit avoir un identifiant unique. Mais ce n'est pas nécessairement la clé d'incrémentation automatique principale - c'est ce qui rend cette instance particulière unique. Par exemple, pour les films, je pense qu'il est courant d'être le titre + l'année de sortie - bien que vous souhaitiez vérifier auprès d'un cinéphile (un expert du domaine) pour en être sûr. L'incrémentation automatique est une solution de secours - en gros, lorsque vous n'avez vraiment rien d'autre sur quoi vous uniqueifier.
Vous pouvez utiliser une clé d'incrémentation automatique pour faciliter l'utilisation dans les jointures et autres, mais vous devriez quand même avoir une contrainte unique sur les champs d'unicité.
En ce qui concerne la conception réelle, je suggérerais quelque chose comme:
Films => Primary Key(filmid), Unique Constraint(filmtitle, year),
runningtime, description,
Foreign Key(Genre), Foreign Key(DirectorId)
Genre Table => Primary Key(Genre)
Director Table => Primary Key(DirectorId), DirectorName
Actors Table => Primary Key(ActorId), ActorName
Films_Actors => Primary Key(Foreign Key(ActorId), Foreign Key(FilmId))
Pour l'insert, eh bien - franchement, c'est un PITA. Vous devez insérer dans l'ordre inverse (et c'est là que les clés d'incrémentation automatique peuvent être un PITA encore plus grand - si vous pouvez ajouter une date de naissance ou quelque chose dans la table Acteurs et Directeurs, alors une contrainte unique peut le rendre plus facile).
Vous insérez donc Acteur (s), Réalisateur, Film, puis Films_Actors. Idéalement, le tout en une seule transaction. De plus, je suppose que Genre est déjà rempli et qu'il s'agit d'une liste de sélection - il n'est donc pas nécessaire de l'insérer.
Je me rends compte que votre question a déjà reçu une réponse, mais je voulais vous signaler:
http://www.imdb.com/interfaces
IMDB fournit des fichiers de texte plat de leur base de données (moins les clés primaires). Vous pourriez trouver cela utile pour alimenter votre base de données une fois que vous avez commencé, ou vous pouvez l'utiliser dans votre programme/site Web pour vous permettre de rechercher simplement un titre de film à ajouter à votre "Collection de DVD", et d'avoir le reste des informations tiré de ceux-ci.
Parfois les acteurs sont réalisateurs et vice versa, peut-être voulez-vous une table "people"?
Vous n'avez pas vraiment besoin d'un YearTable, et tout ce dont vous avez besoin est des colonnes genre_id, director_id et actor_id dans votre table films.
En outre, vos tables de genre, de réalisateur et d'acteur ont besoin de leurs propres identifiants uniques.
Edit: Ceci, bien sûr, en supposant que vous n'aurez qu'un genre, un réalisateur, et un acteur pour chaque film. Ce n'est probablement pas le cas.
Pour avoir de nombreux acteurs appartenant à de nombreux films, vous aurez besoin d'une table de relations distincte. Vous pouvez l'appeler "moviesActors" (ou actorMovies) et chaque ligne aura un acteur_id et un movie_id pour dire cet acteur était dans ce film.
Chaque table doit avoir une clé primaire unique.
Vous devriez lire sur normalisation de la base de données .
Un tableau annuel est probablement inutile.
Si c'est l'année de sortie, par exemple, l'année peut être stockée dans le film.
S'il y a plusieurs réalisateurs sur un film, alors vous auriez une table séparée qui contiendrait la clé primaire de la table de film et de la table de réalisateur. De même pour toutes les contraintes de clé étrangère qui sont plusieurs-à-un ou plusieurs-à-plusieurs. En particulier, je pense que cela s'appliquerait à l'acteur.