Bonsoir passant13,
Pour être plus à l’aise, je bascule vers Looping (gratuit) qui permet de représenter des MCD aussi bien que des diagrammes de classes. 
Le diagramme de classes ci-dessous :
 
est issu du MCD :
  
 
Je rappelle que les cardinalités (multiplicités) du MCD sont inversées par rapport à celles du diagramme de classes.
La cardinalité 1,1(R) portée par la patte connectant COMMUNE et COM_DEP se lit : la commune C est identifiée relativement au département D, ce qui veut dire qu’au stade SQL, la clé primaire de la table COMMUNE sera la paire {departementId, communeId}. En plus, l’identification relative a donné lieu à une composition UML. 
	
		
			
			
				
					
 Envoyé par 
passant13
					
				 
				J'ai rajouté les id sauf pour la table Commune ou le contexte permet d'utiliser la chaîne Commune comme clé primaire. (une particularité du système considéré)
			
		 
	 
 Utiliser des propriétés  naturelles   (par exemple Commune) pour les clés primaires a causé des ravages dans le passé et ça n’est pas fini. L’attribut CommuneId du MCD (ou idCommune, peu importe le mode de nommage) est artificiel, et donnera lieu en SQL à la clé primaire de la table COMMUNE, tandis que le code de la commune (communeCodeInsee ci-dessus) fera l’objet d’une  clé alternative   (contrainte "UNIQUE" en SQL). L’attribut communeId étant  artificiel,  il s’en suit qu’il ne doit avoir aucune valeur sémantique, il est donc  invariant  et garantit la validité des liens entre les tables SQL (clés étrangères référençant les clés primaires). Les valeurs des identifiants artificiels n’ont pas  à être utilisées par les applications, lesquelles, pour accéder aux données useront des clés alternatives telles que {departementNumero}, {communeCodeInsee}, {lieuCode}, etc.  
	
		
			
			
				
					
 Envoyé par 
passant13
					
				 
				Le cœur du problème c'est qu'on peut avoir deux lieux identiques (dont le nom est identique) situés dans deux communes différentes.
			
		 
	 
 Dans les diagrammes ci-dessus, un lieu détermine une commune, ce qui n’interdit aucunement que le même nom de lieu existe pour deux communes différentes. Exemple :
COMMUNE {departementId   communeId   communeCodeInsee   ...}
         5               1           30189              ...
         5               4           30028              ...
LIEU {departementId    communeId   lieuId   lieuCode   lieuNom   ...}
      5                1           1        C0041      Canet     ...
      5                4           1        C0178      Canet     ...
 Les attributs soulignés sont les éléments de la clé primaire des tables.
	
		
			
			
				
					
 Envoyé par 
passant13
					
				 
				J'en suis arrivé provisoirement à ce schéma et ca ne va toujours pas !
			
		 
	 
 Il faut faire disparaître l’attribut #Commune de la classe Lieu, il sera accessible en SQL par une requête de jointure entre les tables COMMUNE et lieu. Exemple :
SELECT communeCodeInsee 
FROM   LIEU AS x JOIN COMMUNE AS y ON x.departementId = y.departementId
                                  AND x.communeId = y.communeId
WHERE  lieuCode = 'C0041'
;
 Vous observerez qu’on ne se sert absolument pas des valeurs des attributs artificiels departementId, communeId, on n’utilise que les valeurs des attributs naturels (lieuCode dans cet exemple).
En passant, à partir de cette de cette requête vous pouvez concevoir  une vue SQL (qui n’est jamais qu’une table virtuelle) :
CREATE VIEW LIEU_COMMUNE (communeCodeInsee, lieuCode, lieuNom) 
AS
    SELECT communeCodeInsee, lieuCode, lieuNom 
    FROM   LIEU AS x JOIN COMMUNE AS y ON x.departementId = y.departementId
                                 AND x.communeId = y.communeId
;  On obtient le résultat en accédant à la vue :
SELECT communeCodeInsee 
FROM   LIEU_COMMUNE
WHERE  lieuCode = 'C0041'
;
 L’emploi des vues plutôt que des tables devrait vous faciliter la vie pour les formulaires et compagnie.
 
On reviendra plus tard sur l’histoire des sites Web.
Annexe : 
Code SQL généré par Looping, hors Web  (notez la présence de "UNIQUE")
CREATE TABLE DEPARTEMENT(
   departementId INTEGER,
   departementNumero VARCHAR(3) NOT NULL UNIQUE,
   departementNom VARCHAR(32) NOT NULL UNIQUE,
   PRIMARY KEY(departementId)
);
CREATE TABLE COMMUNE(
   departementId INTEGER,
   communeId INTEGER,
   communeCodeInsee VARCHAR(6) NOT NULL UNIQUE,
   communeNom VARCHAR(48) NOT NULL,
   PRIMARY KEY(departementId, communeId),
   FOREIGN KEY(departementId) REFERENCES DEPARTEMENT(departementId)
);
CREATE TABLE LIEU(
   departementId INTEGER,
   communeId INTEGER,
   lieuId INTEGER,
   lieuCode VARCHAR(8) NOT NULL UNIQUE,
   lieuNom VARCHAR(48) NOT NULL,
   PRIMARY KEY(departementId, communeId, lieuId),
   FOREIGN KEY(departementId, communeId) REFERENCES COMMUNE(departementId, communeId)
);
CREATE TABLE HOTEL(
   hotelId INTEGER,
   hotelCode VARCHAR(8) NOT NULL UNIQUE,
   hotelNom VARCHAR(48) NOT NULL,
   departementId INTEGER NOT NULL,
   communeId INTEGER NOT NULL,
   lieuId INTEGER NOT NULL,
   PRIMARY KEY(hotelId),
   FOREIGN KEY(departementId, communeId, lieuId) REFERENCES LIEU(departementId, communeId, lieuId)
); 
  
						
					
Partager