IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Schéma Discussion :

Société d'audiovisuel


Sujet :

Schéma

  1. #61
    Nouveau membre du Club
    Homme Profil pro
    technicien audiovisuel
    Inscrit en
    Mars 2016
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : technicien audiovisuel
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mars 2016
    Messages : 41
    Points : 25
    Points
    25
    Par défaut Une avancée
    Bon,

    grâce a un petit pdf déniché sur un serveur de fac allemande j'ai pu avancer un peu.
    La poule et l'oeuf donc et notre relation OEUF 1-1 pondre 1-N POULE

    Une poule pond 1 ou N oeufs
    Un oeuf est pondu par une et une seule poule

    CREATE TABLE chicken(chickenID INT PRIMARY KEY, nbegg INT);
    CREATE TABLE egg(eggID INT PRIMARY KEY, chickenID INT, taille INT);

    La clé étrangère dans l'oeuf, et on la met en "defferable"

    ALTER TABLE egg
    ADD CONSTRAINT eggREFchicken
    FOREIGN KEY (chickenID) REFERENCES chicken(chickenID)
    INITIALLY DEFERRED DEFERRABLE;

    Et ensuite, toujours en suivant mon lien stackoverflow,
    on fait (modifié par tâtonnement pour que cela fonctionne) un trigger :

    CREATE OR REPLACE FUNCTION check_at_least_one()
    RETURNS TRIGGER AS $$
    DECLARE
    nmany integer;
    BEGIN
    SELECT into nmany count(*) from egg where egg.chickenID=NEW.chickenID;
    IF nmany > 0 THEN
    RETURN NEW;
    END IF;
    RETURN NULL;
    END;
    $$ LANGUAGE plpgsql;

    CREATE TRIGGER at_least_one before INSERT or UPDATE or DELETE ON chicken FOR EACH ROW EXECUTE PROCEDURE check_at_least_one();

    Et enfin :

    BEGIN TRANSACTION;
    INSERT INTO egg VALUES(1, 1, 2);
    INSERT INTO egg VALUES(2, 1, 3);
    INSERT INTO egg VALUES(3, 1, 5);
    INSERT INTO chicken VALUES(1, 3);
    COMMIT;

    Et tout le monde est content !

    Moi aussi et je vais pouvoir avancer un peu.
    NB: je peux comprendre que cela ne soit pas le lieu de ce forum (ce type de post) mais comme le schéma est loin d'être finit peut-être que vous m'excuserez.
    DEL

  2. #62
    Nouveau membre du Club
    Homme Profil pro
    technicien audiovisuel
    Inscrit en
    Mars 2016
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : technicien audiovisuel
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mars 2016
    Messages : 41
    Points : 25
    Points
    25
    Par défaut Point d'étape, besoin de conseil.
    Bonjour,

    Je permets de reposter la MCD auquel j’en suis.
    Même s’il n’est pas terminé, j’aurais besoin d’avoir des conseils (ou une validation)
    sur un point précis. Bien entendu toutes autres remarques et suggestions sont les bienvenues.

    Nom : assimil.jpg
Affichages : 250
Taille : 290,4 Ko

    Cela concerne les entités FILM / TIRAGE et dans une certaine mesure ce qui gravite
    autour de TIRAGE (en vert sur le MCD )

    Je m’explique :

    L’entité FILM concerne la dimension documentée d’un Film.
    Comme je l’ai plusieurs fois expliqué par avant, nous disposons d’un fond de films tournés
    depuis les années de la guerre (en pellicule) jusqu’à aujourd’hui (en vidéo puis en numérique).
    La liaison FILM --- TIRAGE concerne uniquement les films tournés en pellicule et qui ont
    été tirés en pellicule. Cela comprends à la fois le développement qui aboutit au négatif mais
    aussi les différentes copies dont nous avons gardé des éléments.
    Par étapes (schématique - la question des éléments sonores dérivera par la suite):
    1 Tirage du négatif
    2 Tirage d'après négatif d'une copie de travail servant au montage :
    De ce tirage et après montage, on se retrouve avec :
    a/ une ou plusieurs boites contenant les bobines du films monté
    b/ une ou plusieurs boites contenant les chutes et le doubles (en gros les rebus du montage)
    3 Tirage d'un copie zéro
    4 Tirage de copie d'exploitation
    Et la cela se complique :
    Un film peut très bien avoir des tirages de copies qui ne sont pas au même format (SUPPORT)que le
    négatif (et donc la copie de travail ) Par exemple, un film tourné en 16mm peut ( et c'est
    arrivé souvent dans les années 50/60) se retrouver à être tiré en 35mm pour sa diffusion. Cela
    est encore plus vrai pour les films qui font l'objet d'une ressortie longtemps après leur
    première diffusion.

    On a donc tel que je l'entends les règles suivantes :

    Un film (sous entendu tourné en pellicule) est tiré en un ou plusieurs Tirages
    Chaque tirage peut-être réalisé en plusieurs exemplaires
    Un Tirage tire un et un seul film
    Un Tirage est matérialisé par un et un seul support
    Un Tirage est Composer par au moins une Bobine
    Une Bobine est une part ou la totalité d'un tirage
    Un Support peut matérialiser des tirages
    Un Tirage est contenu dans une ou plusieurs boites
    Une Boite est le contenant d'un est un seul Tirage
    Une Boite contient une ou plusieurs Bobines (les petites se nomment bobinots...)
    Une Bobine est contenu dans une et une seule boite

    Si on regarde l'entité DEPOT qui est supertype de DEPOTINA et de LTCPAT (Labo LTC Patrimoine) :
    Un Tirage peut être ou ne pas être déposé
    Un Dépot peut être fait à l'INA ou chez LTC (pas les deux)
    La quantité d'élément déposé n'est pas forcément égale au nombre d'élément tiré d'un film
    On doit par exemple pouvoir répondre à :
    Pour tel film, il existe
    un dépot INA de :
    _ 1 copie 35mm composé de 2 Bobine de 600m
    _ Les NEGATIFS du FILMS composé de :
    4 Bobines IMAGES (en 4 Boites )
    et
    4 Bobines SONS (en 4 Boites )

    Je vous remercie.
    Del

  3. #63
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir Del,


    Je suis obligé de tourner au ralenti. Quoi qu’il en soit, à propos des triggers :

    Un trigger, concept purement SQL, est du code attaché à une table ou une vue, code automatiquement activé quand cette table ou vue est l’objet d’une mise à jour du fait d’un INSERT, UPDATE ou DELETE, et que nous voulons qu’un traitement particulier soit effectué à cette occasion, de façon automatique, transparente. Du temps où les triggers n’existaient pas, ce code était forcément hébergé au sein d’un programme P (ou d’un sous-programme appelé par les autres programmes et sous-programmes), mais le problème était qu’il fallait déclencher soi-même l’exécution de ce programme P : grâce aux triggers, tour devient transparent, en cas de mise à jour, on n’a pas à intervenir pour exécuter le code, qui est désormais embarqué dans un trigger, le SGBD se charge de passer le contrôle au trigger affecté à la table ou vue.

    Un trigger n’a pas pour objet la coercition, aspect négatif des choses, mais la production, aspect positif. Par exemple, si à l’occasion de la création d’un poste, l’attribut quantite de la table POSTE atteint ou dépasse la valeur 10, on peut vouloir déclencher l’émission d’un message comme quoi le soir-même, ça sera champagne pour les équipes associées au poste. Ceci reste transparent pour l’application, puisque le code concerné est « encapsulé » dans le trigger.

    Mais il faut reconnaître que les triggers sont très souvent utilisés pour contrôler l’intégrité des données (aspect coercitif), pallier certaines carences des SGBD SQL ès matière.


    Reprenons votre scénario « 1,N » initial :

    [PERSONNE]--1-N--------( )--------1-1--[ADRESSE]
    [PERSONNE]--1-N--------( )--------1-1--[MAIL]
    [PERSONNE]--1-N--------( )--------1-1--[TELEPHONE]

    Un script de création des tables :

    
    DROP TABLE IF EXISTS TELEPHONE ;
    DROP TABLE IF EXISTS MAIL ;
    DROP TABLE IF EXISTS ADRESSE ;
    DROP TABLE IF EXISTS PERSONNE ;
    
    
    CREATE TABLE PERSONNE
    (
       PersonneId                INT             NOT NULL  
     , PersonneNom               VARCHAR(32)     NOT NULL 
     , CONSTRAINT PERSONNE_PK PRIMARY KEY (PersonneId)
    ) ;
    
    CREATE TABLE ADRESSE
    (
       PersonneId                INT             NOT NULL
     , AdresseId                 INT             NOT NULL   
     , AdresseLibelle            VARCHAR(32)     NOT NULL
     , CONSTRAINT ADRESSE_PK PRIMARY KEY (AdresseId)
     , CONSTRAINT ADRESSE_PERSONNE_FK FOREIGN KEY (PersonneId)
           REFERENCES PERSONNE (PersonneId)
           ON DELETE CASCADE
           DEFERRABLE INITIALLY DEFERRED
    ) ;
    
    CREATE TABLE MAIL
    (
       PersonneId                INT             NOT NULL
     , MailId                    INT             NOT NULL   
     , MailLibelle               VARCHAR(32)     NOT NULL
     , CONSTRAINT MAIL_PK PRIMARY KEY (MailId)
     , CONSTRAINT MAIL_PERSONNE_FK FOREIGN KEY (PersonneId)
           REFERENCES PERSONNE (PersonneId)
           ON DELETE CASCADE
           DEFERRABLE INITIALLY DEFERRED
    ) ;
    
    CREATE TABLE TELEPHONE
    (
       PersonneId                INT             NOT NULL
     , TelephoneId               INT             NOT NULL   
     , TelephoneNo               VARCHAR(24)     NOT NULL
     , CONSTRAINT TELEPHONE_PK PRIMARY KEY (TelephoneId)
     , CONSTRAINT TELEPHONE_PERSONNE_FK FOREIGN KEY (PersonneId)
           REFERENCES PERSONNE (PersonneId)
           ON DELETE CASCADE
           DEFERRABLE INITIALLY DEFERRED
    ) ;
    
    
    Vous noterez que chaque contrainte référentielle (à savoir ADRESSE_PERSONNE_FK, MAIL_PERSONNE_FK, TELEPHONE_PERSONNE_FK) comporte une clause CASCADE, faisant que la suppression d’une personne entraîne celle de ses adresses, de ses courriels, de ses téléphones, ce qui est sémantiquement pertinent, et du point de vue technique évite des arrachages de cheveux... Notez encore la présence systématique de la clause DEFERRABLE INITIALLY DEFERRED, pour signifier au SGBD qu’il attende la fin des transactions pour s’assurer que l’intégrité référentielle est respectée.


    Exemple d’insert :

    
    START TRANSACTION ;
    
    INSERT INTO ADRESSE (PersonneId, AdresseId, AdresseLibelle) VALUES(314116, 1, 'Paris') ; 
    INSERT INTO MAIL (PersonneId, MailId, MailLibelle) VALUES(314116, 1, 'Raoul@Raoul.com') ; 
    INSERT INTO TELEPHONE (PersonneId, TelephoneId, TelephoneNo) VALUES(314116, 1, '0678901234') ; 
    INSERT INTO PERSONNE (PersonneId, PersonneNom) VALUES (314116, 'Raoul') ;
    
    COMMIT ; 
    
    
    Vous noterez que l’insert dans la table PERSONNE suit les autres inserts, sinon, le contrôle de la présence d’une adresse, d’un courriel et d’un téléphone a lieu trop tard, d’où rejet.

    En ce qui concerne le respect de la cardinalité minimale 1 par trigger, la solution proposée pour l’exemple de la poule et de l’œuf est tout à fait satisfaisante.

    Adaptons l’exemple à votre situation.

    On met en œuvre un trigger contrôlant les inserts dans la table PERSONNE :

    
    DROP FUNCTION IF EXISTS PERSONNE_INSERT() CASCADE ;
    
    CREATE FUNCTION PERSONNE_INSERT()
    RETURNS TRIGGER AS $$
    
        DECLARE Erreur VARCHAR ;
        DECLARE thePsnId integer ;
        DECLARE theKountAdresse integer ;
        DECLARE theKountMail integer ;
        DECLARE theKountTelephone integer ;
     
    BEGIN
        thePsnId = NEW.PersonneId ;
    
        SELECT INTO theKountAdresse COUNT(*) FROM ADRESSE WHERE ADRESSE.PersonneId = thePsnId ;
        SELECT INTO theKountMail COUNT(*) FROM MAIL WHERE MAIL.PersonneId = thePsnId ;
        SELECT INTO theKountTelephone COUNT(*) FROM TELEPHONE WHERE TELEPHONE.PersonneId = thePsnId ;
    
        IF theKountAdresse > 0 AND theKountMail > 0 AND theKountTelephone > 0 THEN
             RETURN NEW ;
        ELSE    
            Erreur = '' ;
            IF theKountAdresse = 0 THEN        
                 Erreur = Erreur || 'ADRESSE' ;
             END IF ;
             IF theKountMail = 0 THEN
                 IF LENGTH(Erreur) > 0 THEN
                     Erreur = Erreur || ', ' ;    
                 END IF ;        
                 Erreur = Erreur || 'MAIL' ;
             END IF ;
             IF theKountTelephone = 0 THEN        
                 IF LENGTH(Erreur) > 0 THEN
                     Erreur = Erreur || ', ' ;    
                 END IF ;        
                Erreur = Erreur || 'TELEPHONE' ;
             END IF ;
    
            Erreur = 'Trigger ' || TG_NAME || ' : viol de la cardinalité 1,N. PersonneId = ''' || thePsnId || '''. Motif : ' || Erreur || '.' ;      
            RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
        END IF ;
    END ;
    
     $$ LANGUAGE plpgsql ;
    
     CREATE TRIGGER PERSONNE_INSERT AFTER INSERT ON PERSONNE 
         FOR EACH ROW 
         EXECUTE PROCEDURE PERSONNE_INSERT();
    
    

    Mais il faut aussi s’assurer qu’on ne peut pas supprimer impunément une adresse, un courriel ou un téléphone faisant que la cardinalité 1,N ne serait plus respectée...

    D’où les triggers pour contrôler chaque DELETE :

    
    DROP FUNCTION IF EXISTS ADRESSE_DELETE() CASCADE ;
    DROP FUNCTION IF EXISTS MAIL_DELETE() CASCADE ;
    DROP FUNCTION IF EXISTS TELEPHONE_DELETE() CASCADE ;
    
    CREATE FUNCTION ADRESSE_DELETE()
        RETURNS TRIGGER AS $$
        
        DECLARE theKountAdresse integer ;
        DECLARE theKountPersonne integer ; 
        DECLARE Erreur VARCHAR ;
        DECLARE thePsnId integer ;
    
    BEGIN
        thePsnId = OLD.PersonneId ;
                  
        SELECT INTO theKountPersonne COUNT(*) FROM PERSONNE WHERE PERSONNE.PersonneId = thePsnId ;
        SELECT INTO theKountAdresse COUNT(*) FROM ADRESSE WHERE ADRESSE.PersonneId = thePsnId ; 
    
        IF theKountPersonne > 0 AND theKountAdresse = 0 THEN 
            Erreur = 'Trigger ' || TG_NAME || ' - Association PERSONNE - ADRESSE. PersonneId = ''' || thePsnId || ''' : viol de la cardinalité 1,N.' ;
            RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
        ELSE
            RETURN NULL ;
        END IF ;
    
    END ;
    $$ LANGUAGE plpgsql ;
    
    CREATE TRIGGER ADRESSE_DELETE AFTER DELETE ON ADRESSE
        FOR EACH ROW 
        EXECUTE PROCEDURE ADRESSE_DELETE()
    ;
    
    --------------------------------------------------------------------------------
    
    CREATE FUNCTION MAIL_DELETE()
        RETURNS TRIGGER AS $$
    
        DECLARE theKountMail integer ;
        DECLARE theKountPersonne integer ; 
        DECLARE Erreur VARCHAR ;
        DECLARE thePsnId integer ;
    
     BEGIN
        thePsnId = OLD.PersonneId ;
                  
        SELECT INTO theKountPersonne COUNT(*) FROM PERSONNE WHERE PERSONNE.PersonneId = thePsnId ;  
        SELECT INTO theKountMail COUNT(*) FROM MAIL WHERE MAIL.PersonneId = thePsnId ; 
    
        IF theKountPersonne > 0 AND theKountMail = 0 THEN 
            Erreur = 'Trigger ' || TG_NAME || ' - Association PERSONNE - MAIL. PersonneId = ''' || thePsnId || ''' : viol de la cardinalité 1,N.' ;
            RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
        ELSE
            RETURN NULL ;
        END IF ;
    
    END ;
    $$ LANGUAGE plpgsql ;
    
    CREATE TRIGGER MAIL_DELETE AFTER DELETE ON MAIL
        FOR EACH ROW 
        EXECUTE PROCEDURE MAIL_DELETE()
    ;
    
    --------------------------------------------------------------------------------
    
    CREATE FUNCTION TELEPHONE_DELETE()
        RETURNS TRIGGER AS $$
    
        DECLARE theKountTelephone integer ;
        DECLARE theKountPersonne integer ; 
        DECLARE Erreur VARCHAR ;
        DECLARE thePsnId integer ;
    
     BEGIN
        thePsnId = OLD.PersonneId ;
                  
        SELECT INTO theKountPersonne COUNT(*) FROM PERSONNE WHERE PERSONNE.PersonneId = thePsnId ;  
        SELECT INTO theKountTelephone COUNT(*) FROM TELEPHONE WHERE TELEPHONE.PersonneId = thePsnId ; 
    
        IF theKountPersonne > 0 AND theKountTelephone = 0 THEN 
            Erreur = 'Trigger ' || TG_NAME || ' - Association PERSONNE - TELEPHONE. PersonneId = ''' || thePsnId || ''' : viol de la cardinalité 1,N.' ;
            RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
        ELSE
            RETURN NULL ;
        END IF ;
    
    END ;
    $$ LANGUAGE plpgsql ;
    
    CREATE TRIGGER TELEPHONE_DELETE AFTER DELETE ON TELEPHONE
        FOR EACH ROW 
        EXECUTE PROCEDURE TELEPHONE_DELETE()
    ;
    
    
    Je vous invite à soumettre tel ou tel insert ou delete délictueux...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  4. #64
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut
    Bonsoir Del,


    L’association COMPOSER connectant les entités-types BOBINE et TIRAGE est inessentielle, car redondante, donc dangereuse, elle devrait disparaître. A la question « à quel tirage fait référence telle bobine ? », l’existence des associations CONTENIR associant BOBINE et TIRAGE via BOITE doivent suffire pour assurer la réponse.


    Quelle information contient chacun des attributs depotinaval, ltcpatnum, ltcpatcopienum ?

    Un dépôt peut héberger plusieurs tirages. Selon le MCD, il peut s’agir de tirages de films différents. Qu’en est-il ?
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  5. #65
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut Spécialisation et contraintes de partitionnement
    Bonsoir Del,


    A propos de la spécialisation des entités-types.

    Reprenons cette partie de votre MCD (cf. post #62) :


    Intéressons-nous aux prestations, et situons-nous au niveau de la théorie relationnelle, auquel cas PRESTATION, PRODUCTION et DIFFUSION sont des relvars (variables relationnelles), qu’on déclare de la façon suivante (je ne reprends pas forcément tous les attributs des entités-types, quant à leur type, on n’en sait pas assez, mais en l’occurrence peu importe) :


     
    VAR PRESTATION BASE RELATION
        {
            PrestationId          INT
          , PrestationTitre       VARCHAR 
          , PrestationTerminee    BOOLEAN
        }
        KEY {PrestationId}
    ;
    
    VAR PRODUCTION BASE RELATION
        {
            PrestationId          INT
          , ProductionJour        INT
          , ProductionUpdate      INT
        }
        KEY {PrestationId}
        FOREIGN KEY {PrestationId} REFERENCES PRESTATION {PrestationId} ON DELETE CASCADE
    ;
    
    VAR DIFFUSION BASE RELATION
        {
            PrestationId          INT
          , DiffusionContexte     VARCHAR 
        }
        KEY {PrestationId}
        FOREIGN KEY {PrestationId} REFERENCES PRESTATION {PrestationId} ON DELETE CASCADE
    ;
    
    

    Dans votre MCD, la lettre « P » au sein d’un triangle marque la volonté d’imposer une contrainte de partitionnement : ainsi, une prestation est, au moins et au plus, soit une production, soit une diffusion. Rappelons que le partitionnement représente à la fois l’exclusion et la totalité :

    A) Exclusion : l’ensemble (au sens de la théorie des ensembles) des productions est disjoint de l’ensemble des diffusions (une prestation est soit une production, soit une diffusion, elle ne peut pas être les deux à la fois).

    Toujours dans le cadre de la théorie relationnelle, cette contrainte fait l’objet d’une instruction CONSTRAINT :

    
    CONSTRAINT DELARITA_PRESTATION_EXCLUSION
        IS_EMPTY 
        (
         PRODUCTION {PrestationId} INTERSECT DIFFUSION {PrestationId}
        ) 
    ;
    
    Ce qui se lit : l’intersection (a) de la projection sur l’attribut PrestationId de la relvar PRODUCTION et (b) de la projection sur l’attribut PrestationId de la relvar DIFFUSION doit être égale à l’ensemble vide.

    B) Totalité : il ne peut y avoir de prestation qui ne soit ni une production ni une diffusion. Contrainte correspondante :

    
    CONSTRAINT DELARITA_PRESTATION_INCLUSION
        (
         PRESTATION {PrestationId} = PRODUCTION {PrestationId} UNION DIFFUSION {PrestationId}
        ) 
    ;
    
    Ce qui se lit : La projection sur l’attribut PrestationId de la relvar PRESTATION doit être égale à l’union (a) de la projection sur l’attribut PrestationId de la relvar PRODUCTION et (b) de la projection sur l’attribut PrestationId de la relvar DIFFUSION.


    Dans la théorie relationnelle, les contrôles sont immédiats. Si donc on tentait de créer une production de la façon suivante :


    
    INSERT PRESTATION RELATION {TUPLE {PrestationId         2,
                                       PrestationTitre      'Y a du mou dans la corde à noeuds',
                                       PrestationTerminee   TRUE
                                      }
                               }  ; 
    
    INSERT PRODUCTION RELATION {TUPLE {PrestationId         2
                                       ProductionJour       20,
                                       ProductionUpdate     0
                                      }
                               }  ;
    
    
    Alors on se ferait jeter, car à l’occasion du 1er INSERT, le SGBD conclurait au viol des contraintes. Par référence à ce que j’ai écrit dans le post #47, je rappelle que le SGBD ne déclenche les contrôles qu’après détection d’un point-virgule, en conséquence de quoi en utilisant l’affectation multiple, c'est-à-dire en séparant les INSERT par des virgules, on a toute latitude pour opérer avant déclenchement des contrôles :


    
    INSERT PRESTATION RELATION {TUPLE {PrestationId         2,
                                       PrestationTitre      'Y a du mou dans la corde à noeuds',
                                       PrestationTerminee   TRUE
                                      }
                               }  , 
    
    INSERT PRODUCTION RELATION {TUPLE {PrestationId         2
                                       ProductionJour       20,
                                       ProductionUpdate     0
                                      }
                               }  ;
    
    
    Et tout se passera bien, la contrainte de partitionnement étant respectée.


    Qu’en est-il avec PostgreSQL ? Comme dans le cas de l’exemple précédent (post #63), on va simuler l’affectation multiple et mettre en oeuvre des triggers et des fonctions.

    Commençons par déclarer les tables (sans oublier les « ON DELETE CASCADE » et « INITIALLY DEFERRED » :

    
    DROP TABLE IF EXISTS DIFFUSION CASCADE ;
    DROP TABLE IF EXISTS PRODUCTION CASCADE ;
    DROP TABLE IF EXISTS PRESTATION CASCADE ;
    
    
    CREATE TABLE PRESTATION
    (
       PrestationId              INT             NOT NULL
     , PrestationTitre           VARCHAR(32)     NOT NULL
     , PrestationTerminee        BOOLEAN         NOT NULL
     , CONSTRAINT PRESTATION_PK PRIMARY KEY (PrestationId)
    ) ;
    
    CREATE TABLE PRODUCTION
    (
       PrestationId              INT             NOT NULL
     , ProductionJour            INT             NOT NULL  
     , ProductionUpdate          INT             NOT NULL
     , CONSTRAINT PRODUCTION_PK PRIMARY KEY (PrestationId)
     , CONSTRAINT PRODUCTION_PRESTATION_FK FOREIGN KEY (PrestationId)
           REFERENCES PRESTATION (PrestationId)
           ON DELETE CASCADE        
           INITIALLY DEFERRED 
    ) ;
    
    CREATE TABLE DIFFUSION
    (
       PrestationId              INT             NOT NULL
     , DiffusionContexte         VARCHAR(32)     NOT NULL
     , CONSTRAINT DIFFUSION_PK PRIMARY KEY (PrestationId)
     , CONSTRAINT DIFFUSION_PRESTATION_FK FOREIGN KEY (PrestationId)
           REFERENCES PRESTATION (PrestationId)
           ON DELETE CASCADE
           INITIALLY DEFERRED              
    ) ; 
    
    

    Une transaction pour créer une prestation (diffusion en l’occurrence) :

    
    START TRANSACTION ;
    
    INSERT INTO DIFFUSION (PrestationId, DiffusionContexte) VALUES (1, 'contexte a) ;
    INSERT INTO PRESTATION (PrestationId, PrestationTitre, PrestationTerminee) VALUES (1, 'prestation a (diffusion)', TRUE) ;
    
    COMMIT ;
    
    
    Tout en notant bien que l’insert dans la table DIFFUSION précède l’insert dans la table PRESTATION, sinon la clause DEFERRED est inopérante et le SGBD rouspète (faites l’expérience...). A signaler qu’en relationnel pur, on utilise l’affectation multiple, auquel cas peu importe l’ordre des insertions.


    Pour éviter de coder à chaque fois la paire d’INSERT, on peut préférer utiliser les services d’une fonction.

    Déclarons cette fonction :

    
    CREATE OR REPLACE FUNCTION DELARITA_PRESTATION_DIFFUSION_INSERT(PrestaId INT, PrestaTitre VARCHAR, PrestaTerminee BOOLEAN, DiffusContexte VARCHAR) 
        RETURNS VOID
        AS $$
          BEGIN
              INSERT INTO DIFFUSION (PrestationId, DiffusionContexte) VALUES (PrestaId, DiffusContexte) ;
              INSERT INTO PRESTATION (PrestationId, PrestationTitre, PrestationTerminee) VALUES (PrestaId, PrestaTitre, PrestaTerminee) ;
          END 
           $$    
        LANGUAGE PLPGSQL    
    ;
    
    
    Et créons quelques diffusions (notez l’appel à la fonction non pas par CALL ou EXEC, mais par SELECT, c’est imposé) :

    
    START TRANSACTION ;
    
    SELECT DELARITA_PRESTATION_DIFFUSION_INSERT (1, 'prestation a (diffusion)', TRUE, 'contexte a') ; 
    SELECT DELARITA_PRESTATION_DIFFUSION_INSERT (3, 'prestation c (diffusion)', TRUE, 'contexte c') ; 
    SELECT DELARITA_PRESTATION_DIFFUSION_INSERT (5, 'prestation e (diffusion)', FALSE, 'contexte e') ; 
    
    COMMIT ;
    
    

    Ce qui vaut pour les diffusions vaut pour les productions :


    
    CREATE OR REPLACE FUNCTION DELARITA_PRESTATION_PRODUCTION_INSERT(PrestaId INT, PrestaTitre VARCHAR, PrestaTerminee BOOLEAN, ProdJour INT, ProdUpdate INT) 
        RETURNS VOID
        AS $$
          BEGIN
              INSERT INTO PRODUCTION (PrestationId, ProductionJour, ProductionUpdate) VALUES (PrestaId, ProdJour, ProdUpdate) ;
              INSERT INTO PRESTATION (PrestationId, PrestationTitre, PrestationTerminee) VALUES (PrestaId, PrestaTitre, PrestaTerminee) ;
          END 
           $$    
        LANGUAGE PLPGSQL    
    ;
    
    
    Une transaction :

    
    START TRANSACTION ;
    
    SELECT DELARITA_PRESTATION_PRODUCTION_INSERT (2, 'prestation b (production)', TRUE, 20, 0) ; 
    SELECT DELARITA_PRESTATION_PRODUCTION_INSERT (4, 'prestation d (production)', TRUE, 40, 1) ; 
    SELECT DELARITA_PRESTATION_PRODUCTION_INSERT (6, 'prestation f (production)', FALSE,60, 0) ; 
    
    COMMIT ;
    
    

    Venons-en aux contraintes de partitionnement. Comme on a pu le voir, en relationnel leur mise en oeuvre est simple. Cette fois-ci (à moins que PostgreSQL ne propose des techniques que je connais pas encore), il va falloir en passer par des triggers, chacun d’eux étant affecté à une table (PRESTATION, DIFFUSION, PRODUCTION) et il aussi falloir se poser les bonnes questions en relation avec les opérations effectuées (INSERT, UPDATE, DELETE)...

    Cas de la table PRESTATION

    — Si on effectue un INSERT directement dans cette table et que passe à l’as l’INSERT correspondant dans la table DIFFUSION ou dans la table PRODUCTION, il y aura viol de la règle de totalité.

    — Si on effectue un UPDATE, si celui-ci change la valeur de la clé primaire, il faut rejeter l’opération, sinon on risque de s’embarquer dans une galère pas possible pour garantir la cohérence avec la table DIFFUSION ou PRODUCTION. Et puis, quand on a modélisé proprement, on n’a pas de raison d’avoir à modifier une clé primaire. Si l’UPDATE modifie autre chose que la clé primaire : on donne le feu vert.

    — Si on effectue un DELETE, grâce à la clause ON DELETE CASCADE (cf. CREATE TABLE DIFFUSION et CREATE TABLE PRODUCTION), la prestation diffusion ou production) est totalement supprimée : la contrainte de partitionnement est respectée, donc on donne le feu vert.


    Le trigger (et sa fonction) correspondant :

    
    CREATE OR REPLACE FUNCTION DELARITA_PRESTATION()
        RETURNS TRIGGER
        AS $$ 
        DECLARE Erreur            VARCHAR ; 
        DECLARE theKount          INTEGER ;
        DECLARE thePrestation     INTEGER ;
        DECLARE thePrestationOld  INTEGER ;
        DECLARE theOperation      VARCHAR ;
     
        BEGIN
            thePrestation = NEW.PrestationId ;
            theOperation = UPPER(TG_OP) ;
    
            IF theOperation = 'INSERT' THEN
                theKount = 
                       (SELECT COUNT(*) 
                        FROM
                             (SELECT PrestationId  
                              FROM   DIFFUSION 
                              WHERE  PrestationId = thePrestation
                             UNION
                              SELECT PrestationId  
                              FROM   PRODUCTION 
                              WHERE  PrestationId = thePrestation                          
                             ) as t) ;
                IF theKount = 0                
                    THEN  
                        Erreur = 'Table ' || UPPER(TG_TABLE_NAME) || ' ; ' || 'Trigger ' || UPPER(TG_NAME) 
                           || '. Viol de la contrainte de totalité. Ajout impossible de la prestation de clé ''' 
                           || thePrestation || ''', il manque une production ou une diffusion.' ;
                        RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
                END IF ;
    
                RETURN NEW ;
            ELSE
                thePrestationOld = OLD.PrestationId ;
                IF thePrestationOld = thePrestation THEN
                    RETURN NEW ;
                ELSE
                    Erreur = 'Table ' || UPPER(TG_TABLE_NAME) || ' ; ' || 'Trigger ' || UPPER(TG_NAME) 
                       || '. Remplacement refusé de la clé primaire ''' || thePrestationOld || ''' par ''' || thePrestation || ''' (procéder par DELETE/INSERT de la prestation).' 
                       ; 
                    RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
                END IF ;
            END IF ; 
        END ;
      $$ 
      LANGUAGE PLPGSQL ;
    
    CREATE TRIGGER DELARITA_PRESTATION AFTER INSERT OR UPDATE ON PRESTATION
        FOR EACH ROW EXECUTE PROCEDURE DELARITA_PRESTATION() ;
    
    

    Dès que je peux, je passe aux triggers affectés aux tables DIFFUSION et PRODUCTION.

    Mais déjà, vous constaterez que pour une contrainte qui, en relationnel s’écrit en une ligne, sans avoir à se poser de question sur la nature des opérations, dès qu’on en passe par des triggers, alors il faut envisager toutes les situations, en espérant ne rien avoir oublié...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  6. #66
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 001
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 001
    Points : 30 905
    Points
    30 905
    Billets dans le blog
    16
    Par défaut Des triggers à foison...
    Bonsoir Del,


    Citation Envoyé par fsmrel
    Venons-en aux contraintes de partitionnement. Comme on a pu le voir, en relationnel leur mise en oeuvre est simple. Cette fois-ci (à moins que PostgreSQL ne propose des techniques que je connais pas encore), il va falloir en passer par des triggers, chacun d’eux étant affecté à une table (PRESTATION, DIFFUSION, PRODUCTION), et il aussi falloir se poser les bonnes questions en relation avec les opérations effectuées (INSERT, UPDATE, DELETE)...
    Dans le message précédent, on a vu le cas de la table PRESTATION. Venons-en aux tables DIFFUSION et PRODUCTION. Prenons le cas de la table DIFFUSION, sachant que, mutatis mutandis, ce qui suit vaut évidemment pour la table PRODUCTION.

    — Si on tente un INSERT directement dans la table DIFFUSION, le SGBD le rejettera d’office. En effet, ou bien la valeur p de la clé primaire de la ligne à insérer est égale à celle de la clé primaire d’une diffusion existante (table DIFFUSION), auquel cas on se fera jeter pour viol de l’intégrité d’entité (doublons interdits dans la clé primaire de la table), ou bien p est la valeur d’une clé primaire d’une ligne de la table PRODUCTION, et cette fois-ci le rejet sera la conséquence d’une tentative de viol de la contrainte d’exclusion, garantie par un trigger ad-hoc, tel que celui-ci :


    
    ----------------------------------------------------------------------------------
    
    -- Contrôle de l'exclusion : refus de l'ajout d'une diffusion si une production 
    -- existe déjà ayant même valeur de clé. 
    
    ----------------------------------------------------------------------------------
    
    CREATE OR REPLACE FUNCTION DELARITA_DIFFUSION_EXCLUSION()
          RETURNS TRIGGER
        AS $$ 
        DECLARE Erreur            VARCHAR ; 
        DECLARE theKount          INTEGER ;    
        DECLARE thePrestation     INTEGER ;
        DECLARE theOperation      VARCHAR ;
            
        BEGIN
            thePrestation = NEW.PrestationId ;
            theOperation = UPPER(TG_OP) ;
    
            theKount = 
                       (SELECT COUNT(*) 
                        FROM
                             (SELECT PrestationId  
                              FROM   PRODUCTION 
                              WHERE  PrestationId = thePrestation
                             ) as t) ;
            IF theKount > 0                
               THEN
                    Erreur = 'Table ' || UPPER(TG_TABLE_NAME) || ' ; ' || 'Trigger ' || UPPER(TG_NAME) || ' ; ' || theOperation || ' ; '
                       || 'Viol de la contrainte d''exclusion. '
                       || 'Ajout ou modification impossible de la diffusion de clé ''' || thePrestation 
                       || ''', il y a déjà une production ayant cette clé.' ;
                    RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
            END IF ;
    
            RETURN NEW ;
      
        END ;
      $$ 
      LANGUAGE PLPGSQL ;
    
    CREATE TRIGGER DELARITA_DIFFUSION_EXCLUSION AFTER INSERT OR UPDATE ON DIFFUSION
        FOR EACH ROW EXECUTE PROCEDURE DELARITA_DIFFUSION_EXCLUSION() ;
    
    


    — Si on tente un UPDATE directement dans la table DIFFUSION, on est face aux possibilité suivantes :

    (1) On tente de remplacer la valeur p de la clé primaire de la table par la même valeur p, ce qui en soi est idiot, mais ne gêne pas, on laisse filer ;

    (2) On tente de remplacer la valeur p de la clé primaire par une valeur p’ différente, laquelle n’existe pas en tant que valeur de clé primaire de la table PRESTATION, auquel cas il y a viol de clé étrangère, dont rejet de l’UPDATE par le SGBD ;

    (3) On tente de remplacer la valeur p de la clé primaire par une valeur p’ différente, laquelle existe en tant que valeur de clé primaire de la table DIFFUSION, auquel cas il y a viol de l’intégrité d’entité (doublons interdits dans la clé primaire de la table), donc rejet de l’UPDATE par le SGBD ;

    (4) On tente de remplacer la valeur p de la clé primaire par une valeur p’ différente, laquelle existe en tant que valeur de clé primaire de la table PRODUCTION, auquel cas il y a viol de la contrainte d’exclusion, garantie par le trigger ci-dessus, donc rejet de l’UPDATE ;

    (5) l’UPDATE porte sur des attributs ne participant pas à la clé primaire (attribut DiffusionContexte par exemple) : l’UPDATE est accepté.


    — Si on tente un DELETE directement dans la table DIFFUSION, cela ne dérange pas le SGBD, lequel réalisera l’opération, mais il y aurait alors viol de la contrainte de totalité, puisqu’on aurait une prestation amputée de sa partie diffusion : pour empêcher cela, il faut mettre en œuvre un trigger ad-hoc :


    
    CREATE OR REPLACE FUNCTION DELARITA_DIFFUSION_DELETE()
        RETURNS TRIGGER AS $$
    
        DECLARE thePrestation     INTEGER ;
        DECLARE thePrestationOld  INTEGER ;
        DECLARE theKountSurtype   INTEGER ; 
        DECLARE theKountSousType  INTEGER ;
        DECLARE Erreur            VARCHAR ;
        DECLARE theOperation      VARCHAR ;
    
     BEGIN
        thePrestation = OLD.PrestationId ;
        theOperation = UPPER(TG_OP) ;
                 
        SELECT INTO theKountSurtype COUNT(*) FROM PRESTATION WHERE PRESTATION.PrestationId = thePrestation ;  
        SELECT INTO theKountSousType COUNT(*) FROM DIFFUSION WHERE DIFFUSION.PrestationId = thePrestation ; 
    
        IF theKountSurtype > 0 AND theKountSousType = 0 THEN 
            Erreur = 'Table ' || UPPER(TG_TABLE_NAME) || ' ; ' || 'Trigger ' || UPPER(TG_NAME) || ' ; ' || theOperation || ' ; '
                || ' - PRESTATION - DIFFUSION. PrestationId = ''' || thePrestation 
                || ''' : rejet de la suppression de la diffusion, passer par la suppression la prestation.' ;
            RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
        ELSE
            RETURN NULL ;
        END IF ;
    
    END ;
    $$ LANGUAGE plpgsql ;
    
    CREATE TRIGGER DELARITA_DIFFUSION_DELETE AFTER DELETE ON DIFFUSION
        FOR EACH ROW 
        EXECUTE PROCEDURE DELARITA_DIFFUSION_DELETE()
    ;
    
    
    Voilà pour la table DIFFUSION.


    La table PRODUCTION fait elle aussi de triggers, semblables à ceux qui précèdent.

    Contrôle des ajouts et modifications :


    
    CREATE OR REPLACE FUNCTION DELARITA_PRODUCTION_EXCLUSION()
        RETURNS TRIGGER
        AS $$ 
        DECLARE Erreur            VARCHAR ; 
        DECLARE theKount          INTEGER ;    
        DECLARE thePrestation     INTEGER ;
        DECLARE theOperation      VARCHAR ;
            
        BEGIN
            thePrestation = NEW.PrestationId ;
            theOperation = UPPER(TG_OP) ;
            theKount = 
                       (SELECT COUNT(*) 
                        FROM
                             (SELECT PrestationId  
                              FROM   DIFFUSION 
                              WHERE  PrestationId = thePrestation
                             ) as t) ;
            IF theKount > 0                
               THEN
                    Erreur = 'Table ' || UPPER(TG_TABLE_NAME) || ' ; ' || 'Trigger ' || UPPER(TG_NAME) || ' ; ' || theOperation || ' ; '
                       || 'Viol de la contrainte d''exclusion. '
                       || 'Ajout ou modification impossible de la production de clé ''' || thePrestation 
                       || ''', il y a déjà une diffusion ayant cette clé.' ;
                    RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
            END IF ;
    
            RETURN NEW ;
      
        END ;
      $$ 
      LANGUAGE PLPGSQL ;
    
    CREATE TRIGGER DELARITA_PRODUCTION_EXCLUSION AFTER INSERT OR UPDATE ON PRODUCTION
        FOR EACH ROW EXECUTE PROCEDURE DELARITA_PRODUCTION_EXCLUSION() ;
    
    

    Contrôle des suppressions dans la table PRODUCTION :

    
    CREATE OR REPLACE FUNCTION DELARITA_PRODUCTION_DELETE()
        RETURNS TRIGGER AS $$
    
        DECLARE thePrestation     INTEGER ;
        DECLARE thePrestationOld  INTEGER ;
        DECLARE theKountSurtype   INTEGER ; 
        DECLARE theKountSousType  INTEGER ;
        DECLARE Erreur            VARCHAR ;
        DECLARE theOperation      VARCHAR ;
    
     BEGIN
        thePrestation = OLD.PrestationId ;
        theOperation = UPPER(TG_OP) ;
                 
        SELECT INTO theKountSurtype COUNT(*) FROM PRESTATION WHERE PRESTATION.PrestationId = thePrestation ;  
        SELECT INTO theKountSousType COUNT(*) FROM PRODUCTION WHERE PRODUCTION.PrestationId = thePrestation ; 
    
        IF theKountSurtype > 0 AND theKountSousType = 0 THEN 
            Erreur = 'Table ' || UPPER(TG_TABLE_NAME) || ' ; ' || 'Trigger ' || UPPER(TG_NAME) || ' ; ' || theOperation || ' ; '
                || ' - PRESTATION - PRODUCTION. PrestationId = ''' || thePrestation 
                || ''' : rejet de la suppression de la production, passer par la suppression la prestation.' ;
            RAISE EXCEPTION SQLSTATE '45003' USING MESSAGE = Erreur ;
        ELSE
            RETURN NULL ;
        END IF ;
    
    END ;
    $$ LANGUAGE plpgsql ;
    
    CREATE TRIGGER DELARITA_PRODUCTION_DELETE AFTER DELETE ON PRODUCTION
        FOR EACH ROW 
        EXECUTE PROCEDURE DELARITA_PRODUCTION_DELETE()
    ;
    
    
    Franchement, tout est plus simple en relationnel pur, car on passe au cran supérieur dans l’abstraction : pas besoin de se poser de questions sur les effets des opérations de mise à jour et de programmer des solutions lourdes, on sous-traite tout ça au SGBD. A quand l’équivalent de l’instruction CONSTRAINT ? Certes, on s’en approche avec l’instruction CREATE ASSERTION de la norme SQL, mais avec là encore le boulet du mode DEFERRED dont on pourrait se débarrasser si l’affectation multiple devenait possible. Mais comme disait Kipling, ceci est une autre histoire, je vous renvoie à ce sujet aux ouvrages de C.J. Date, par exemple SQL and Relational Theory , 3rd Edition.

    Cela dit, je ne connais que moyennement PostgreSQL, et les spécialistes de ce SGBD ont peut-être des solutions permettant d’éviter la tambouille des triggers et de passer au cran supérieur dans l’abstraction.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  7. #67
    Nouveau membre du Club
    Homme Profil pro
    technicien audiovisuel
    Inscrit en
    Mars 2016
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : technicien audiovisuel
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mars 2016
    Messages : 41
    Points : 25
    Points
    25
    Par défaut Sensation
    Bonsoir Mr Fsmrel ....
    Vos derniers posts me laisse sans voix.
    C'est une reprise de service à la vitesse d'un départ des 24h du Mans !
    Je regardais en haut, à pinailler sur du détail, et Zou ! z'êtes parti en bas sur le dur !
    Alors donc, pour le travail que vous avez effectué, un immense merci.

    Je vais quand même faire un point sur les entités du haut suite à discussion avec notre documentaliste/archiviste et bien plus...
    Il est en train, avec le patron, de remodeler nos archives.
    1/ Tout ce qui est chez LTC va progressivement (2/3 mois) être rapatrié vers l'INA : l'entité LTCPAT ne servira plus, sauf à garder une trace historique ; peut-être un argument supplémentaire dans l'entité INFOLABO serait suffisante (iltcpatnum) mais qui serait souvent NULL. Du coup l'entité DEPOT disparaitrait.
    2/ Dans le cadre du tri des archives que nous conservons encore chez nous, et qui vont déménager de la même manière, nous allons supprimer les éléments de montage (chutes et doubles) : La règle donnant 1 boite 1-N Bobines va disparaitre. Du coup on peut sans doute supprimer l'entité type Boite et ne conserver seulement la relation Composer.

    Quelle information contient chacun des attributs depotinaval, ltcpatnum, ltcpatcopienum ?
    depotinaval est un boolean, idiotie de ma part vue la relation de spécialisation.
    ltcpatnum est un identifiant donné par le labo
    ltcpatcopienum est le numéro identifiant (naturel/explicite de la bobine)

    Un dépôt peut héberger plusieurs tirages. Selon le MCD, il peut s’agir de tirages de films différents. Qu’en est-il ?
    Je crois la que je m'embrouille et que c'est du à un manque de mise à plat de nouvelles règles liées à cette extension qui n'existait pas au début.
    Un film peut avoir 0 - N tirage (de fait si il concerne une de nos archives ce n'est plus 0 -- N mais 1 -- N.
    Un tirage étant lié à un support, lorsque est réalisé plusieurs copie lors d'un tirage (ex 3 Copies 16mm Son Optique), l'argument tirerquantité de l'association Tirer joue.
    Maintenant, si lors du dépôt, seules 2 de ces copies sont concernées, il faut pouvoir le dire quelque part. Je pensais donc mettre cela dans l'entité Depot.
    L'erreur est donc dans la cardinalité de depôt qui doit être :
    Tirage 0-1 Deposer 1-1 Depot

    Voilà,
    C'est bien peu comme travail de ma part.

    Merci à vous.
    Cordialement
    Del

Discussions similaires

  1. [MySQL] Recherche dans une base de donnée [ Gros soucis ]
    Par milkasoprano dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 24/03/2006, 17h59
  2. problème de recherche dans une base de donnée mysql
    Par Xini28 dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 24/10/2005, 18h00
  3. Recherche dans une base de donnée
    Par genova dans le forum SQLite
    Réponses: 8
    Dernier message: 28/09/2005, 23h16
  4. problème de recherche dans une base de données
    Par bouzid_mehdi dans le forum Bases de données
    Réponses: 2
    Dernier message: 19/07/2005, 06h47
  5. recherche dans une base de donnée+boucle
    Par eric205 dans le forum Bases de données
    Réponses: 8
    Dernier message: 15/03/2005, 21h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo