Ave,

Envoyé par
escartefigue
Ce quator n'est pas irréductible : vu qu'on ne peut pas être membre sur deux périodes chevauchantes, le trio {EticienId, StructureId, EtreMembreDebut} suffit comme identifiant

Exact, j’avais l’intention de modifier en ce sens, puis je suis passé aux autres discussions en attente...
Cela dit, pour des raisons évidentes de symétrie l’attribut EtreMembreFin peut réclamer être clé candidate au même titre que l’attribut EtreMembreDebut. En passant à SQL :
Table EtreMembre :
1 2 3 4 5 6 7
| CREATE TABLE EtreMembre
( EticienId INT
, StructureId SMALLINT
, MembreDepuis DATE NOT NULL
, CONSTRAINT EtreMembre_PK PRIMARY KEY(EticienId, StructureId)
, CONSTRAINT EtreMembre_Eticien_FK FOREIGN KEY(EticienId) REFERENCES Eticien(EticienId)
, CONSTRAINT EtreMembre_Structure_FK FOREIGN KEY(StructureId) REFERENCES Structure(StructureId)); |
Table EtreMembreHisto :
1 2 3 4 5 6 7 8 9
| CREATE TABLE EtreMembreHisto
( EticienId INT
, StructureId SMALLINT
, EtreMembreDebut DATE
, EtreMembreFin DATE
, CONSTRAINT EtreMembreHisto_PK PRIMARY KEY(EticienId, StructureId, EtreMembreDebut)
, CONSTRAINT EtreMembreHisto_AK UNIQUE (EticienId, StructureId, EtreMembreFin)
, CONSTRAINT EtreMembreHisto_EtreMembre_FK FOREIGN KEY(EticienId, StructureId) REFERENCES EtreMembre(EticienId, StructureId)
, CONSTRAINT EtreMembreHisto_FinSupDebut CHECK (EtreMembreFin >= EtreMembreDebut)); |
A noter la contrainte EtreMembreHisto_FinSupDebut, qui veut que la date de fin soit ≥ à la date de fin. 
Mais si on rentre dans le cycle des contraintes : non chevauchement des dates par des lignes distinctes au sein d’une même table, antériorité des dates de la table EtreMembreHisto par rapport à la date MembreDepuis portée par la table EtreMembre, etc., il reste du boulot...
Je développe ça au paragraphe 6 (Sixième forme normale) de mon article Bases de données relationnelles et normalisation, basé sur la référence Time and Relational Theory de Date, Darwen et Lorentzos.
Y a des triggers en perspective...
Si encore on disposait de l’instruction CREATE ASSERTION définie dans la norme SQL, ça serait beaucoup plus confortable, car le codage des triggers diffère d’un SGBD à l’autre. Par exemple, pour garantir l’antériorité des dates de la table EtreMembreHisto par rapport à la date MembreDepuis portée par la table EtreMembre :
1 2 3
| CREATE ASSERTION Regle_01 CHECK
(NOT EXISTS (SELECT * FROM EtreMembre AS x JOIN EtreMembreHisto AS y
WHERE x.MembreDepuis <= y.EtreMembreFin)) ; |
Au passage, je rappelle le principe de l’information (Information Principle) défini par Codd, père du Modèle Relationnel de Données :
The entire information content of the database at any given time is represented in one and only one way: namely, as explicit values in attribute position in tuples in relations.
Comme le rappelle Chris Date (page 63 de l’ouvrage cité), la simplicité inhérente au Modèle Relationnel de Données est une conséquence directe de ce principe. Codd a régulièrement rappelé qu’il s’agit du principe fondamental sur lequel repose le Modèle Relationnel de Données.
Quant à elle, avec ses colonnes cachées (hidden columns) la norme SQL viole le principe de l’information et se démarque de la théorie relationnelle, c’est un divorce.
Partager