Voir le flux RSS

fsmrel

DB-MAIN - Créer un MLD et le script SQL de définition des tables

Note : 2 votes pour une moyenne de 5,00.
par , 27/03/2016 à 20h49 (6953 Affichages)
_____________________________________________________________________________________________________


On a vu comment créer des entités-types et leurs associations avec DB-MAIN. Il s’agit ici de produire le MLD et le script SQL de définition des tables qui en sont issues.


(1) Situation initiale

Partons du MCD suivant, dont l’objet est la modélisation de commandes de produits par des clients de l’entreprise Dubicobit :





Pour produire un MLD à partir de ce MCD, on crée un clone de celui-ci. Pour cela, le MCD étant ouvert, dans la barre de menus on choisit « Product » et on clique sur « Copy product » :





Cette action provoque l’ouverture d’une fenêtre « Schema Properties » dans laquelle est repris le nom du MCD, avec un numéro de version + 1 (malgré les apparences, car il ne faudrait pas prendre un tiret pour un signe moins...) :





On modifie le nom du nouveau schéma, par exemple en remplaçant "Clients_MCD" par "Clients_MLD" :





Après qu’on a fait «OK », le clone Clients_MLD du MCD Clients_MCD est créé :





Après avoir cliqué sur l’ovale « Clients_MLD », on a accès au diagramme clone :





Pour obtenir une représentation graphique à la DB-MAIN du MLD, dans la barre de menus on choisit « Transform » et on clique sur « Relational model » :





(2) Représentation graphique

Au résultat, la représentation graphique a changé, la notation des associations est du type « Connect to columns », particulièrement pénible, mais on fera avec, le MLD n’étant finalement ici qu’un intermédiaire servant à la production du script SQL de création des tables :





Ce résultat est hybride. En effet, y figurent toujours des entités-types, avec leurs attributs et leurs identifiants, mais les associations ont été remplacées par des références, symbolisées par des flèches.

Une référence peut être vue comme une contrainte référentielle de la théorie relationnelle, une clé étrangère.

En ce sens, l’entité-type COMMANDE a hérité de l’attribut ClientId, identifiant de CLIENT, et à partir de cet attribut, l’AGL a défini une référence, une contrainte entre les deux entités-types : l’attribut ClientId de l’entité-type COMMANDE fait référence à l’attribut ClientId de l’entité-type CLIENT : une commande ne pourra exister que si les valeurs prises par l’attribut ClientId de l’entité-type COMMANDE sont d’abord des valeurs prises par l’attribut ClientId de l’entité-type CLIENT (on a une application de la restriction {ClientId} de COMMANDE dans la restriction {ClientId} de CLIENT). En plus de la flèche connectant CLIENT et COMMANDE, cette contrainte référentielle (cas particulier de la contrainte d’inclusion) est symbolisée par le mickey « ref: ClientId » dans le cartouche du bas.

L’entité-type LIGNE_CDE est porteuse de deux contraintes référentielles, l’une connectant LIGNE_CDE et PRODUIT, l’autre connectant LIGNE_CDE et COMMANDE. La 2e contrainte est symbolisée non pas par le mickey « ref: ClientId », mais par le mickey « equ: ClientId », traduisant la cardinalité 1,N du MCD : la projection de COMMANDE sur {CommandeId} doit être égale à la projection de LIGNE_CDE sur {CommandeId}. On a affaire à une injection.

Le cartouche du bas de chaque entité-type est pollué par le mickey « acc » : l’AGL anticipe sur le Modèle physique des données. Ainsi, chaque identifiant et chaque référence affublés de ce mickey donneront lieu à une instruction CREATE INDEX lors de la génération du script SQL. On peut bien sûr décocher la case « access key » correspondante :





(3) Toilettage avant production du script SQL

Avant de passer à la production du script SQL, dans la mesure où l’on s’est imposé des règles de codage du nom des contraintes, on aura modifié ces noms en conséquence. Ainsi, DB-MAIN propose de nommer les contraintes de clé primaire en concaténant la chaîne de caractères "ID" et le nom de l’entité-type, ce qui va peut-être à l’encontre de nos propres normes.

Exemple de l’entité-type CLIENT. La contrainte de clé primaire a pour nom ID_CLIENT :





Conformément à nos propres règles de codage du nom des contraintes, renommons-la par exemple en CLIENT_PK, nom qui sera celui de la contrainte dans l’instruction CREATE TABLE en SQL :





Même principe pour les clés alternatives. Par exemple l’AGL a donné le nom SID_CLIENT_1 à la clé alternative {ClientSiret}, renommons-la par exemple ainsi : CLIENT_SIRET_AK. Même principe pour la clé alternative {ClientIban}.

Cela vaut pour les clés étrangères. Ainsi, la contrainte référentielle liant CLIENT et COMMANDE a été nommée FKPASSER_CDE par l’AGL :





On peut préférer renommer cette contrainte en COMMANDE_CLIENT_FK :





(4) Production du script SQL

Caveat : Le script SQL est à produire à partir du MLD. En effet, si une génération est possible à partir du MCD, elle sera toutefois incomplète (absence des contraintes référentielles).

Dans la version de DB-MAIN que nous utilisons ici, la liste des SGBD cibles est réduite, on complétera manuellement ce qui manque dans le script (à savoir les paramètres physiques des tables, lesquels sont du ressort du DBA).

Quoi qu’il en soit, une fois le toilettage des noms terminé, on peut passer à la génération du script SQL de création des tables. Pour obtenir la liste des SGBD connus de l’AGL et sélectionner l’un d’entre eux, on passe par la barre de menus :

File > Generate > mon SGBD :





Evidemment, pour produire un script DB2, Oracle, ou MS SQL Server, c’est plutôt moyen, mais rappelons que le paramétrage physique est du ressort du DBA. Ce qui nous intéresse ici au 1er chef est déjà d’avoir, dans le bon ordre, les instructions CREATE TABLE et ALTER TABLE (pour les contraintes référentielles) : DB-MAIN sait faire. Maintenant, à chacun de voir quel choix de SGBD correspond au mieux (ou au moins mal...) pour le code SQL attendu.


Le résultat obtenu figure ci-dessous (on a retenu MySQL). Là encore, il y aura un travail de toilettage à faire. Par exemple, l’attribut ClientSiret de la table CLIENT a pour type BIGINT (DB-MAIN est chiche aux niveaux MCD et MLD quant aux types disponibles...) : on remplacera par DECIMAL(14). Par ailleurs, DB-MAIN a pris l’initiative de suffixer le nom des clés candidates (c'est-à-dire primaires et alternatives) par la chaîne "ID" : on effectuera un remplacement de masse de "PK_ID" par "PK" et de "AK_ID" par "AK". Même principe pour les clés étrangères, remplacer "FK_FK" par "FK".

A signaler qu’en fonction du SGBD, DB-MAIN met — ou ne met pas — en oeuvre une contrainte pour faire respecter la cardinalité 1,N définie dans le MCD, cas ici de l’association entre COMMANDE et LIGNE_CDE (une commande a au moins une ligne de commande) :


alter table COMMANDE add constraint COMMANDE_PK_CHK
    check(exists(select * from LIGNE_CDE
                 where LIGNE_CDE.CommandeId = CommandeId)); 

Bien entendu, les SGBD SQL du jour ne permettent pas que l’on procède ainsi. L’AGL met donc la contrainte en commentaire dans le script.


Script (MySQL) produit par DB-MAIN :



-- *********************************************
-- * SQL MySQL generation
-- *--------------------------------------------
-- * DB-MAIN version: 9.2.b
-- * Generator date: Feb 17 2014
-- * Generation date: Fri Mar 18 16:58:02 2016
-- * LUN file: D:\DBmain\developpez\clients.lun
-- * Schema: Clients_MLD 
-- ********************************************* 


-- Database Section
-- ________________ 

create database Clients_MLD;
use Clients_MLD;


-- Tables Section
-- _____________ 

create table CLIENT (
     ClientId int not null auto_increment,
     ClientNom varchar(32) not null,
     ClientSiret bigint not null,
     ClientIban varchar(27) not null,
     constraint CLIENT_PK_ID primary key (ClientId),
     constraint CLIENT_SIRET_AK_ID unique (ClientSiret),
     constraint CLIENT_IBAN_AK_ID unique (ClientIban));

create table COMMANDE (
     CommandeId int not null,
     CommandeNo char(8) not null,
     CommandeDate date not null,
     ClientId int not null,
     constraint COMMANDE_PK_ID primary key (CommandeId),
     constraint COMMANDE_NO_AK_ID unique (CommandeNo));

create table LIGNE_CDE (
     CommandeId int not null,
     ProduitId int not null,
     Quantite int not null,
     constraint LIGNE_CDE_PK_ID primary key (CommandeId, ProduitId));

create table PRODUIT (
     ProduitId int not null,
     ProduitReference char(12) not null,
     ProduitLibelle varchar(32) not null,
     constraint PRODUIT_PK_ID primary key (ProduitId),
     constraint PRODUIT_REFERENCE_AK_ID unique (ProduitReference));


-- Constraints Section
-- ___________________ 

-- Not implemented
-- alter table COMMANDE add constraint COMMANDE_PK_CHK
--     check(exists(select * from LIGNE_CDE
--                  where LIGNE_CDE.CommandeId = CommandeId)); 

alter table COMMANDE add constraint COMMANDE_CLIENT_FK_FK
     foreign key (ClientId)
     references CLIENT (ClientId);

alter table LIGNE_CDE add constraint LIGNE_CDE_PRODUIT_FK_FK
     foreign key (ProduitId)
     references PRODUIT (ProduitId);

alter table LIGNE_CDE add constraint LIGNE_CDE_COMMANDE_FK
     foreign key (CommandeId)
     references COMMANDE (CommandeId);


-- Index Section
-- _____________ 

create unique index CLIENT_PK_IND
     on CLIENT (ClientId);

create unique index CLIENT_SIRET_AK_IND
     on CLIENT (ClientSiret);

create unique index CLIENT_IBAN_AK_IND
     on CLIENT (ClientIban);

create unique index COMMANDE_PK_IND
     on COMMANDE (CommandeId);

create unique index COMMANDE_NO_AK_IND
     on COMMANDE (CommandeNo);

create index COMMANDE_CLIENT_FK_IND
     on COMMANDE (ClientId);

create unique index LIGNE_CDE_PK_IND
     on LIGNE_CDE (CommandeId, ProduitId);

create index LIGNE_CDE_PRODUIT_FK_IND
     on LIGNE_CDE (ProduitId);

create unique index PRODUIT_PK_IND
     on PRODUIT (ProduitId);

create unique index PRODUIT_REFERENCE_AK_IND
     on PRODUIT (ProduitReference);


Rien n’interdit de reprendre un script avec un outil comme MySQL Workbench, d’effectuer une rétro-conception et, par exemple, de compléter avec les actions de compensation associées aux clés étrangères (CASCADE, RESTRICT, NO ACTION).

Pour visualiser le script directement dans DB-MAIN, cliquer sur le nom du fichier qui a été produit, comme ci-dessous :


Le DDL n’a pas l’air d’être modifiable dans DB-MAIN, la case « lock » reste manifestement cochée quoi qu’on fasse.

________________________________________________________________________________________________________________

Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog Viadeo Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog Twitter Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog Google Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog Facebook Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog Digg Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog Delicious Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog MySpace Envoyer le billet « DB-MAIN - Créer un MLD et le script SQL de définition des tables » dans le blog Yahoo

Commentaires

  1. Avatar de fsmrel
    • |
    • permalink
    Merci pour ton retour.


    Citation Envoyé par CinePhil
    la contrainte CHECK produite mais commentée qui est due à la cardinalité mini de 1 dans l'association entre commande et ligne_commande !
    Pourquoi est-elle commentée et marquée comme non-implémentée ?
    Sous MySQL, ça peut se comprendre puisque MySQL n'a toujours pas, à ma connaissance, implémenté les contraintes CHECK mais sous PostgreSQL qui respecte mieux la norme, je ne comprends pas.
    Dans le cas de PostgreSQL, certaines contraintes peuvent être codées, mais seulement les plus simples. Par exemple :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CREATE TABLE S
    (
        A             integer            NOT NULL
    ,   B             integer            NOT NULL
    , CONSTRAINT S_PK PRIMARY KEY (A)
    , CONSTRAINT S_CHK_01 CHECK (A > B)
    ) ;

    Dans ces conditions, si on tente
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    INSERT INTO S (A, B) VALUES (5, 6) ;

    Alors, à juste titre, on se fait jeter :

    Citation Envoyé par PostgreSQL
    la nouvelle ligne viole la contrainte de vérification « s » de la relation « chk_01 »
    A ceci près que PostgreSQL devrait permuter les éléments entre guillemets :

    la nouvelle ligne viole la contrainte de vérification « chk_01 » de la relation « s »


    En tout cas, dès qu’il y a une fonction ou une sous-requête, PostgreSQL abandonne :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ALTER TABLE S ADD CONSTRAINT CHK_02 CHECK (EXISTS (SELECT 'vrai' FROM S WHERE A = 5)) ;

    =>

    Citation Envoyé par PostgreSQL
    ERREUR: ne peut pas utiliser une sous-requête dans la contrainte de vérification
    Ou encore (avec des approximations orthographiques de sa part) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ALTER TABLE SP ADD CONSTRAINT CHK_03 CHECK (COUNT(*) > 0) ;
    Citation Envoyé par PostgreSQL
    ERREUR: les fonctions d'agrégats ne sont pas autorisés dans les contraintes CHECK
    Autrement dit, comme c’est précisé dans la doc de PostgreSQL, la règle F671 de la norme SQL est laissée de côté (à savoir « Enhanced integrity management ») :

    Citation Envoyé par le père de PostgreSQL
    Subqueries in CHECK intentionally omitted.
    On doit donc laisser les contraintes sous forme de commentaires.


    Citation Envoyé par CinePhil
    Un point négatif : il ne semble pas y avoir de visualisation du script avant sa sauvegarde. Ce serait plus simple de vérifier et corriger le script directement dans DB-Main. Comme ce logiciel semble avoir été fait sur une base de l'AGL Eclipse, il doit pourtant avoir un éditeur intégré.
    Quand tu as choisi le SGBD, DB-MAIN génère d’office le DDL présenté en fin du billet. Pour le visualiser, tu cliques sur le nom du fichier, comme précisé dans l’image que je viens d’ajouter. Pour le modifier, ça n’a pas l’air possible, il y a bien une case « lock », mais elle ne semble pas pouvoir être décochée (et la doc est muette). Soit tu reviens sur le MLD, soit tu modifies hors DB-MAIN...