2010-06-16 8 views
4

Je suis en train de concevoir un modèle de données pour une page de ville locale, plus comme des exigences pour cela.Question de schéma de base de données

Donc 4 tables: Pays, État, Ville, quartier.

Les relations de vie réelle sont: Le pays possède plusieurs États qui possèdent plusieurs villes et qui doivent plusieurs quartiers.

Dans le modèle de données: est-ce que nous les relions de la même manière à FK ou relions-les à chacun d'eux? Comme dans chaque tableau, il y aura même un identifiant de pays, un identifiant d'état, un ID de ville et un ID de voisinage, chacun d'entre eux étant connecté à chacun d'entre eux? Autre sage pour atteindre le voisinage du pays nous devons joindre 2 autres tables entre?

Il y a plus de tableaux que je dois maintenir pour addess IP des villes, latitude/longitude, etc.

Répondre

5

La chose la plus proche, il est à une norme de l'industrie est la suivante: chaque table dépendante est liée par une clé étrangère son parent immédiat:

create table country 
(country_id number not null 
, country_name varchar2(30) 
, constraint country_pk primary key (country_id) 
) 
/
create table state 
(state_id number not null 
, state_name varchar2(30) 
, country_id number not null 
, constraint state_pk primary key (state_id) 
, constraint state_country_fk foreign key (country_id) 
     references country(country_id) 
) 
/
create table city 
(city_id number not null 
, city_name varchar2(30) 
, state_id number not null 
, constraint city_pk primary key (city_id) 
, constraint city_state_fk foreign key (state_id) 
     references state(state_id) 
) 
/
create table neighbourhood 
(neighbourhood_id number not null 
, neighbourhood_name varchar2(30) 
, city_id number not null 
, constraint neighbourhood_pk primary key (neighbourhood_id) 
, constraint neighbourhood_city_fk foreign key (city_id) 
     references city(city_id) 
) 
/

Une autre approche, qui a largement tombé en disgrâce, est de définir les clés primaires des tables de l'enfant en tant que clés composés y compris les clés de la table parent immédiat:

create table state 
(country_id number not null 
, state_id number not null 
, state_name varchar2(30) 
, constraint state_pk primary key (country_id, state_id) 
, constraint state_country_fk foreign key (country_id) 
     references country(country_id) 
) 
/
create table city 
(country_id number not null 
, state_id number not null 
, city_id number not null 
, city_name varchar2(30) 
, constraint city_pk primary key (country_id, state_id, city_id) 
, constraint city_state_fk foreign key (country_id, state_id) 
     references state(country_id, state_id) 
) 
/
create table neighbourhood 
(country_id number not null 
, state_id number not null 
, city_id number not null 
, neighbourhood_id number not null 
, neighbourhood_name varchar2(30) 
, constraint neighbourhood_pk primary key (country_id, state_id, city_id, neighbourhood_id) 
, constraint neighbourhood_city_fk foreign key (country_id, state_id, city_id) 
     references city(country_id, state_id, city_id) 
) 
/

Cette approche est déconseillée parce qu'à court terme elle crée des jointures excessivement lourdes et à long terme elle crée des dégâts horribles quand les clés changent. Les clés primaires ne sont pas censées changer, mais les pondérer crée du sens. Par conséquent, lorsque les données du système changent - disons qu'il y a une réorganisation des limites de l'État - les modifications apportées à un ensemble de villes doivent être répercutées dans la table de voisinage, et tous les autres enfants. Yuck.

Votre proposition est une version alternative de ceci:

create table state 
(state_id number not null 
, state_name varchar2(30) 
, country_id number not null 
, constraint state_pk primary key (state_id) 
, constraint state_country_fk foreign key (country_id) 
     references country(country_id) 
) 
/
create table city 
(city_id number not null 
, city_name varchar2(30) 
, country_id number not null 
, state_id number not null 
, constraint city_pk primary key (city_id) 
, constraint city_country_fk foreign key (country_id) 
     references country(country_id) 
, constraint city_state_fk foreign key (state_id) 
     references state(state_id) 
) 
/
create table neighbourhood 
(neighbourhood_id number not null 
, neighbourhood_name varchar2(30) 
, country_id number not null 
, state_id number not null 
, city_id number not null 
, constraint neighbourhood_pk primary key (neighbourhood_id) 
, constraint neighbourhood_country_fk foreign key (country_id) 
     references country(country_id) 
, constraint neighbourhood_state_fk foreign key (state_id) 
     references state(state_id) 
, constraint neighbourhood_city_fk foreign key (city_id) 
     references city(city_id) 
) 
/

Il évite les clés composées mais vous avez encore que cascade problème de données. En outre, il viole la pratique relationnelle en introduisant des clés étrangères pour des relations qui n'existent pas (il n'y a pas de relation directe entre le voisinage et le pays, elle est implicite à travers les liens intermédiaires). Du côté positif, comme vous l'avez souligné, cela peut être très utile pour exécuter des requêtes qui veulent renvoyer des Quartiers pour un Pays donné. J'ai travaillé sur un système où cela était utile (en fait, il utilisait des clés composées héritées, mais le principe est le même). Cependant, il s'agissait d'un entrepôt de données très spécialisé et même alors, les requêtes que j'exécutais étaient des requêtes d'admin/développeur plutôt que des requêtes d'application. À moins que vous ne traitiez d'énormes quantités de données (des millions de voisinages), je pense que le gain de performance obtenu en ignorant quelques jointures ne vaudrait pas la peine de gérer ces colonnes supplémentaires. En bref, utilisez la première approche: c'est propre et c'est standard.

modifier

« Etat devrait être facultatif, bien que depuis tous les pays ont un état. Puis un pays se connectera avec la ville directement. »

Si vrai, cela change tout.De toute évidence, STATE ne peut pas être utilisé comme clé étrangère d'identification pour CITY. Donc, CITY doit faire référence à COUNTRY à la place. STATE peut être une recherche facultative sur CITY.

Bien que je pense que la plupart des pays ont des sous-divisions équivalentes telles que les comtés ou les départements. Même les micro-États comme Lichtenstein et Saint-Marin ont des municipalités (Monaco a juste celui). Peut-être la seule nation qui ne soit pas la Cité du Vatican. Donc, réfléchissez bien à la possibilité de structurer votre modèle de données pour qu'il prenne en charge un ou deux cas de marge, ou de renforcer les données en injectant un "état" artificiel pour des exceptions telles que le Saint-Siège. Aucune approche n'est entièrement satisfaisante.

« tous ces domaines seront saisie semi-automatique des champs donc pas sûr si qui modifie la structure de la table dans de toute façon? »

Cela ne fait aucune différence.

« Mais qui sait, quelques mois plus tard, nous pouvons découvrir une caractéristique cool que peut avoir besoin le pays pour correspondre avec quartiers aussi. »

Oui mais encore vous ne pouvez pas. XP a un principe puissant appelé YAGNI - You're aren't gonna need it. Fondamentalement, ne pas faire beaucoup de travail et compliquer votre conception pour des besoins futurs putatifs qui pourraient ne jamais arriver.

Et si cela arrive, la première solution serait de rejoindre VOISINAGE et COUNTRY via les tables intermédiaires (ou la table, si vous n'utilisez pas STATE comme référencé pour CITY). Seulement si la performance de cette requête est Teh Suck! et il résiste obstinément à l'accord si vous envisagez de peaufiner le modèle de données.

+0

Eh bien, le système est conçu globalement. Ainsi il maintiendra chaque pays, chaque ville, chaque état et chaque voisinage. Ofcourse nous avons seulement des données sur le pays/ville. Les données de voisinage seront imputées par l'utilisateur car il s'agit d'un site de contenu utilisateur. Donc finalement oui, il y aura des dizaines de millions de quartiers. Il n'y a actuellement aucune exigence d'affaires pour correspondre pays avec voisinage. C'est la ville avec le voisinage et peut-être l'état avec le voisinage si existe. Mais qui sait, quelques mois plus tard, nous pouvons découvrir une fonctionnalité intéressante qui peut avoir besoin de pays pour correspondre à des quartiers aussi. – Thomas

+0

Je ne sais pas si c'est important, mais tous ces champs seront des champs auto-complétés, donc je ne sais pas si cela modifie la structure de la table de toute façon? bt: Merci pour le commentaire et le modèle d'échantillon. – Thomas

+0

Le problème que je vois avec l'exemple de code d'industrie est: L'état devrait être facultatif bien que tous les pays n'aient pas un état. Ensuite, un pays se connectera directement à la ville. – Thomas

Questions connexes