diff --git a/app/pages/+data.ts b/app/pages/+data.ts index 3472ac3..873d355 100644 --- a/app/pages/+data.ts +++ b/app/pages/+data.ts @@ -22,9 +22,7 @@ export async function data(pageContext: PageContext) { }); let cachePathname = urlParsed.pathname.replace(/\/$/, "").replace(/^\//, ""); - if (cachePathname === "") { - cachePathname = "index"; - } + if (cachePathname === "") cachePathname = "index"; const doc = docCache.get(cachePathname); @@ -41,7 +39,7 @@ export async function data(pageContext: PageContext) { docs: docCache.orderByLastEdit({ limit: 2, includedBasePaths: ["docs", "certifications"], - excludedFileNames: [cachePathname], + excludedFileNames: [cachePathname, "docs", "certifications"], }), }; } diff --git a/app/pages/docs/merise/dictionnaire-de-donnees/DictionnaryTable.tsx b/app/pages/docs/merise/dictionnaire-de-donnees/DictionnaryTable.tsx index 76041ce..063aac8 100644 --- a/app/pages/docs/merise/dictionnaire-de-donnees/DictionnaryTable.tsx +++ b/app/pages/docs/merise/dictionnaire-de-donnees/DictionnaryTable.tsx @@ -1,87 +1,336 @@ -export default function DictionnaryTable() { +import { For } from "solid-js"; + +type DataTable = { + tableName: string; + hiddenInBasic?: boolean; + documentName: string; + columns: DataColumn[]; + primaryKeys?: string[]; + foreignKeys?: string[]; +}; + +type DataColumnType = + | "Alphanumérique" + | "Alphabétique" + | "Numérique" + | "Date" + | "Logique"; + +type DataColumn = { + name: string; + logical: string; + dbmsType: string; + dbmsLength?: number; + length?: string | number; + type: DataColumnType; + hiddenInTechnical?: boolean; + hiddenInBasic?: boolean; + dbmsConstraints: string[]; + constraints?: string[]; +}; + +const data: DataTable[] = [ + { + tableName: "musician", + documentName: "Musicien", + primaryKeys: ["id_musician"], + columns: [ + { + name: "code musicien", + logical: "id_musician", + dbmsType: "SERIAL", + type: "Numérique", + hiddenInBasic: true, + dbmsConstraints: ["NOT_NULL", "UNIQUE"], + }, + { + name: "Nom", + logical: "lastname", + dbmsType: "VARCHAR", + type: "Numérique", + length: 30, + dbmsLength: 30, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + { + name: "Prénom", + logical: "firstname", + dbmsType: "VARCHAR", + type: "Numérique", + length: 30, + dbmsLength: 30, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + { + name: "Instruments", + logical: "instruments", + dbmsType: "VARCHAR[]", + type: "Alphabétique", + length: 30, + dbmsLength: 30, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + { + name: "Adresse e-mail", + logical: "email", + dbmsType: "VARCHAR", + type: "Alphanumérique", + length: 50, + dbmsLength: 50, + dbmsConstraints: ["NOT_NULL", "UNIQUE"], + constraints: ["Obligatoire", "Unique"], + }, + { + name: "Mot de passe", + logical: "password", + dbmsType: "VARCHAR", + type: "Alphanumérique", + length: "> 12", + dbmsLength: 32, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + ], + }, + { + tableName: "musician_participates_event", + documentName: "", + hiddenInBasic: true, + primaryKeys: ["id_musician", "event_id"], + foreignKeys: ["id_musician", "event_id"], + columns: [ + { + name: "", + logical: "event_id", + dbmsType: "SERIAL", + type: "Numérique", + dbmsConstraints: ["NOT_NULL"], + }, + { + name: "Lieu", + logical: "location", + dbmsType: "VARCHAR", + type: "Alphabétique", + dbmsLength: 30, + dbmsConstraints: ["NOT_NULL"], + }, + { + name: "Date et heure", + logical: "datetime", + dbmsType: "TIMESTAMP", + type: "Alphabétique", + dbmsLength: 30, + dbmsConstraints: ["NOT_NULL"], + }, + ], + }, + { + tableName: "event", + documentName: "", + hiddenInBasic: true, + primaryKeys: ["id_event"], + columns: [ + { + name: "", + logical: "id_event", + dbmsType: "SERIAL", + type: "Numérique", + dbmsConstraints: ["NOT_NULL", "UNIQUE"], + }, + { + name: "Lieu", + logical: "location", + dbmsType: "VARCHAR", + type: "Alphabétique", + dbmsLength: 30, + dbmsConstraints: ["NOT_NULL"], + }, + { + name: "Date et heure", + logical: "datetime", + dbmsType: "TIMESTAMP", + type: "Alphabétique", + dbmsLength: 30, + dbmsConstraints: ["NOT_NULL"], + }, + ], + }, + { + tableName: "concert", + documentName: "Concert", + primaryKeys: ["id_concert"], + foreignKeys: ["event_id"], + columns: [ + { + name: "code concert", + logical: "id_concert", + dbmsType: "SERIAL", + type: "Numérique", + hiddenInBasic: true, + dbmsConstraints: ["NOT_NULL", "UNIQUE"], + }, + { + name: "Date et heure", + logical: "datetime", + dbmsType: "TIMESTAMP", + type: "Date", + hiddenInTechnical: true, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + { + name: "Lieu", + logical: "location", + dbmsType: "VARCHAR", + type: "Alphabétique", + hiddenInTechnical: true, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + { + name: "Tarif", + logical: "price", + dbmsType: "MONEY", + type: "Numérique", + dbmsConstraints: [], + constraints: ["Obligatoire"], + }, + { + name: "", + logical: "event_id", + dbmsType: "SERIAL", + type: "Numérique", + hiddenInBasic: true, + dbmsConstraints: ["NOT_NULL"], + }, + ], + }, + { + tableName: "rehearsal", + documentName: "Répétition", + primaryKeys: ["id_rehearsal"], + foreignKeys: ["event_id"], + columns: [ + { + name: "code répétition", + logical: "id_rehearsal", + dbmsType: "SERIAL", + type: "Numérique", + hiddenInBasic: true, + dbmsConstraints: ["NOT_NULL", "UNIQUE"], + }, + { + name: "Date et heure", + logical: "datetime", + dbmsType: "TIMESTAMP", + type: "Date", + hiddenInTechnical: true, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + { + name: "Lieu", + logical: "location", + dbmsType: "VARCHAR", + type: "Alphabétique", + hiddenInTechnical: true, + dbmsConstraints: ["NOT_NULL"], + constraints: ["Obligatoire"], + }, + { + name: "", + logical: "event_id", + dbmsType: "SERIAL", + type: "Numérique", + hiddenInBasic: true, + dbmsConstraints: ["NOT_NULL"], + }, + ], + }, +]; + +type DictionnaryTableProps = { + isTechnical?: boolean; +}; + +export default function DictionnaryTable(props: DictionnaryTableProps) { return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nom de la donnéeFormatLongueurContraintesDocument
NomAlphabétique30ObligatoireMusicien
PrénomAlphabétique30ObligatoireMusicien
InstrumentsAlphabétique30ObligatoireMusicien
Adresse e-mailAlphanumérique50Obligatoire, uniqueMusicien
Mot de passeAlphanumérique> 12ObligatoireMusicien
Date et heure de concertDate-ObligatoireConcert
Lieu de concertAlphabétique50ObligatoireConcert
TarifNumérique--Concert
Date et heure de répétitionDate-ObligatoireRépétition
Lieu de répétitionAlphabétique50ObligatoireRépétition
+ props.isTechnical || !table.hiddenInBasic)} + > + {(table) => ( + + + + + + + + + + + + props.isTechnical + ? !column.hiddenInTechnical + : !column.hiddenInBasic, + )} + > + {(column) => ( + + + + + + + )} + + + + + + + + {props.isTechnical && ( + + {table.primaryKeys && table.primaryKeys.length > 0 && ( + <> + + + + )} + {table.foreignKeys && table.foreignKeys.length > 0 && ( + <> + + + + )} + + )} + +
+ {props.isTechnical ? "Colonne" : "Nom de la donnée"} + {props.isTechnical ? "Type" : "Format"}LongueurContraintes
{props.isTechnical ? column.logical : column.name}{props.isTechnical ? column.dbmsType : column.type} + {props.isTechnical + ? column.dbmsLength || "-" + : column.length || "-"} + + {props.isTechnical + ? column.dbmsConstraints?.join(", ") || "-" + : column.constraints?.join(", ") || "-"} +
+ {props.isTechnical ? "Table" : "Document"} + + {props.isTechnical ? table.tableName : table.documentName} +
+ Clé primaire + ({table.primaryKeys.join(", ")}) + Clé(s) étrangère(s) + {table.foreignKeys.join(", ")}
+ )} +
); } diff --git a/app/pages/docs/merise/mcd/+Page.mdx b/app/pages/docs/merise/mcd/+Page.mdx index ab7ec9b..f91d63c 100644 --- a/app/pages/docs/merise/mcd/+Page.mdx +++ b/app/pages/docs/merise/mcd/+Page.mdx @@ -50,9 +50,9 @@ On a ici un MCD qui représente trois **entités** : Chacune de ces entités a plusieurs **attributs** qui lui sont propres : -- **Entité 1** : code identité 1, attribut 2, attribut 3 -- **Entité 2** : code identité 2, attribut 2, attribut 3 -- **Entité 3** : code identité 3, attribut 2, attribut 3 +- **Entité 1** : code entité 1, attribut 2, attribut 3 +- **Entité 2** : code entité 2, attribut 2, attribut 3 +- **Entité 3** : code entité 3, attribut 2, attribut 3 Dans le MCD, un attribut en gras est un attribut **unique**. @@ -72,6 +72,7 @@ Ici, on a : - **Entité 1** 0,N - Contenir - 0,N **Entité 2** - **Entité 1** 1,1 - Posséder - 0,N **Entité 3** +- **Entité 3** 0,N - Diriger - 0,1 **Entité 3** Mais qu'est-ce que ça veut dire tout ça ? @@ -93,6 +94,8 @@ Toujours dans l'exemple précédent, on comprend donc que : - **Entité 2** peut être contenue entre 0 et N **Entité 1** - **Entité 1** doit posséder 1 et 1 seule **Entité 3** - **Entité 3** peut être possédée entre 0 et N **Entité 1** +- **Entité 3** peut diriger entre 0 et N **Entité 3** +- **Entité 3** peut être dirigée par 0 ou 1 **Entité 3** La plupart du temps, nous allons retrouver les valeurs suivantes : @@ -109,6 +112,22 @@ Toujours dans l'exemple précédent, on comprend donc que : Si la valeur n'est pas connue à l'avance ou qu'aucune limite n'est nécessaire, on utilisera alors **N**. +## Les relations réflexives + +En regardant notre exemple, on se rend compte que l'entité **Entité 3** est reliée à elle-même par une relation. +C'est ce qu'on appelle une **relation réflexive**. + +C'est un cas particulier qui va nous permettre de créer une relation entre une entité et elle-même, +sans avoir à créer une nouvelle entité. + +### Situation concrète + +Prenons un exemple concret avec une entité **Catégorie**. +Si l'on souhaite qu'une catégorie puisse regrouper plusieurs sous-catégories _(et que ces sous-catégories puissent elles-mêmes regrouper d'autres sous-catégories)_, +on va créer une relation réflexive entre la catégorie et elle-même. + +De cette manière, on va pouvoir créer une hiérarchie entre les catégories. + ## Retour sur notre dictionnaire de données Maintenant que l'on sait comment fonctionne un MCD, on va pouvoir retourner sur notre dictionnaire de données pour le formaliser en MCD. diff --git a/app/pages/docs/merise/mld/+Page.mdx b/app/pages/docs/merise/mld/+Page.mdx index bc9e1c3..a4a6c36 100644 --- a/app/pages/docs/merise/mld/+Page.mdx +++ b/app/pages/docs/merise/mld/+Page.mdx @@ -4,4 +4,215 @@ description: Plongez dans le MLD et MRD de Merise pour transformer votre modèle tags: [Backend, Merise, BDD, MCD, MLD, MPD, SQL] --- -En cours de rédaction... +import Callout from "@/components/Callout"; + +Dans cet article, on va parler du **MLD** _(Modèle Logique de Données)_ et du **MRD** _(Modèle Relationnel de Données)_. + +Le MLD est la suite normale et directe du MCD dans le processus Merise. Son but est de transformer le MCD en un modèle qui pourra être implémenté dans une base de données relationnelle. + +On parlera plus tard du MRD, mais globalement : c'est la même chose que le MLD ! + +## 🤔 Qu'est-ce que le MLD ? + +Le **MLD** est un schéma qui va nous permettre de représenter les données que l'on a récupérées dans le MCD, mais en ajoutant des détails techniques. + +Il va nous permettre de représenter les différentes données que l'on a, regroupée dans une **table**, ainsi que les relations entre elles au travers de **clés étrangères**, de **clés primaires** et de **tables de jointure**. + +Contrairement au MCD, le MLD n'est pas destiné à être compris par le client. + +## 🔍 Exemple de MLD + +Reprenons le premier exemple de MCD, dans l'article précédent : + +![Exemple de MCD](/images/merise/mcd-basic.webp) + +On a ici un MCD qui représente trois **entités** : + +- **Entité 1** +- **Entité 2** +- **Entité 3** + +À partir de ce MCD, on va pouvoir créer un MLD. +Voici à quoi il ressemble : + +![Exemple de MLD](/images/merise/mld-basic.webp) + +On a ici un MLD qui représente trois **tables** : +- **table_1** +- **table_2** +- **table_3** + +Mais surtout : on a ajouté des **clés primaires**, des **clés étrangères** et une **table de jointure** ! + +Pour le moment ça semble bizarre voire magique, on va prendre le temps de décortiquer tout ça. + +## Transformation du MCD en MLD + +Comme dit plus tôt, le MLD découle directement du MCD. +Il va donc reprendre les mêmes **entités** et **attributs** que le MCD, mais en ajoutant des détails techniques. + + + À partir du MLD, on va commencer à parler de **table** et de **colonne**. + On parlera aussi de **clé primaire** et de **clé étrangère** ! + + +Pour pouvoir le transformer en MLD, il y a plusieurs éléments à prendre en compte : + +- Attributs : + - Les **attributs** qui sont en gras et soulignés _(discriminants)_ dans le MCD, deviennent des **clés primaires** dans le MLD. + - Les **attributs** qui sont en gras _(attributs uniques)_ deviennent des **colonnes uniques** dans le MLD. + - Les **attributs** qui ne sont pas en gras deviennent des **colonnes** dans le MLD. +- Relations : + - On supprime les **relations** du MCD pour laisser place à des **clés étrangères** dans le MLD. + - Est-ce que la cardinalité maximale est de **1** ou de **N** ? + - Est-ce que la relation est dite **réflexive** ? + +Commençons par les **entités** et leurs **attributs**, on verra les cardinalités après 😉 + +## Convertir les entités et attributs + +Pour cette étape, ça va être très simple ! +On vient reprendre notre MCD correspondant à la gestion d'un groupe de musique : + +![MCD final](/images/merise/mcd-4.webp) + +Les seules choses que nous avons à faire sont : + +- Remplacer les **entités** par des **tables** +- Remplacer les **attributs** par des **colonnes** + + + Dans le MLD, on ne précise pas encore les types de données des colonnes. + On serait tenté de le faire dès maintenant, mais ce serait ne pas respecter la méthode Merise et l'intérêt du MLD. + + On le fera plus tard, dans le **MPD** _(Modèle Physique de Données)_ ! + + +Voici donc les tables et colonnes que l'on obtient : + +![Exemple de MLD sans relations](/images/merise/mld-1.webp) + +Pour l'instant, on a juste remplacé les **entités** par des **tables** et les **attributs** par des **colonnes**. Il nous reste plus qu'à ajouter les **clés primaires** et les **clés étrangères** ! + +## Convertir les relations + +Pour convertir les relations, il faut d'abord se poser la question de la cardinalité maximale de chaque relation. + +Il y a deux possibilités : + +- **One to Many** _(1,N)_ +- **Many to Many** _(N,N)_ + +Un troisième cas existe, dans le cas où la relation est réflexive _(une entité se relie à elle-même)_. + +### ➡️ One to Many + +Dans le cas d'une relation **One to Many**, on va ajouter une **clé étrangère** dans la table qui est du côté de la relation **One** _(1)_. + +Dans notre cas, on a une relation **One to Many** entre **Événement** et l'héritage _(**Concert** et **Répétition**)_. + + + Effectivement, aucune cardinalité n'est présente entre l'héritage et l'entité générique ! + Dans ce cas précis, on considère que l'héritage est une relation **One to Many**. + + C'est-à-dire : + + - **Événement** peut être spécialisé par **Concert** ou **Répétition** _(**0,2** de manière implicite)_ + - **Concert** doit spécialiser un et un seul **Événement** _(**1,1** de manière implicite)_ + - **Répétition** doit spécialiser un et un seul **Événement** _(**1,1** de manière implicite)_ + + +On va donc ajouter une **clé étrangère** dans les tables **concert** et **rehearsal** qui va faire référence à la **clé primaire** de la table **event**. + +![Exemple de MLD avec relation One to Many](/images/merise/mld-2.webp) + +Et là : tu remarqueras que les **clés étrangères** sont en italique et sont préfixées par un `#` ! + +On constate également que des flèches sont apparues entre les tables. +Ces flèches nous permettent de visualiser le sens de la relation entre les tables, en partant de la table contenant la **clé étrangère** vers la table contenant la **clé primaire**. + +### 🔀 Many to Many + +Pour cette deuxième possibilité, il est impossible de stocker une clé étrangère dans l'une des deux tables. +Il faut alors créer une **table de jointure** qui va faire le lien entre les deux tables. + +Cette table se caractérise par : + +- **Son nom** : + - Généralement composé des deux tables qu'elle relie, séparées par un `_` _(ex: `table_1_table_2`)_ + - Peut aussi être un nom plus explicite, comme `table_1_action_table_2` +- **Ses colonnes** : + - Deux colonnes qui vont faire référence aux **clés primaires** des deux tables qu'elle relie + - Les potentielles autres colonnes qui sont spécifiques à la relation + +![Exemple de MLD avec relation Many to Many](/images/merise/mld-3.webp) + +Ici, nous avons une relation **Many to Many** entre les tables **musician** et **event**. +Une table de jointure a donc été créée, qui s'appelle `musician_participates_event`. + +Cette table contient deux colonnes qui font référence aux **clés primaires** des tables **musician** et **event**. + + + Il n'est pas nécessaire d'ajouter une clé primaire dans la table de jointure. + + Pour rendre unique chaque enregistrement, on viendra _(plus tard !)_ créer une **clé unique** sur les deux colonnes qui fait référence aux **clés primaires** des tables qu'elle relie. + + C'est ce qu'on appelle une **clé composite**. + + +### 🔄 Relations réflexives + +Dans notre situation, nous n'avons pas de relation réflexive. +Mais le premier exemple donné sur cet article possède une relation réflexive sur l'entité **Entité 3**. + +Pas besoin de revenir tout en haut de l'article, je te le remets juste ici : + +![Exemple de MCD](/images/merise/mcd-basic.webp) + +Dans cet exemple, on retrouve une relation réflexive entre l'entité **Entité 3** et elle-même. +Cette relation est définie avec une cardinalité **0,1** - **0,N**. + +On appliquera la même logique que pour une relation **One to Many** que l'on a vu plus haut. +On retrouvera donc une **clé étrangère** dans la table **table_3** qui va faire référence à la **clé primaire** de la même table. + +![Exemple de MLD avec relation réflexive](/images/merise/mld-4.webp) + +### 🎉 MLD final + +Et voilà, on a terminé notre MLD ! +Oui, pour de vrai 😁 + +Voici à quoi il ressemble : + +![Exemple de MLD final](/images/merise/mld-5.webp) + +## MLD et MRD + +Le MLD et le MRD sont deux choses différentes, mais qui se ressemblent beaucoup. + +Le MLD est un modèle **logique** de données, qui est un schéma **graphique**. +Le MRD, lui, est un modèle **relationnel** de données, qui est un schéma **textuel**. + +Les informations présentes seront les mêmes, seule la forme change. + + + Le MRD n'est pas obligatoire, mais il permet une représentation plus linéaire. + À toi de voir si tu souhaites le faire ou non, mais il est souvent plus simple à lire ! + + +Pour notre MLD final, voici à quoi il ressemblerait en MRD : + +musician(**id_musician**, lastname, firstname, instruments, **email**, password) +musician_participates_event(_#id_musician_, _#id_event_) +event(**id_event**, datetime, location) +concert(**id_concert**, price, _#event_id_) +rehearsal(**id_rehearsal**, _#event_id_) + +## Conclusion + +Par rapport au MCD, le MLD est beaucoup plus rapide à réaliser. _(en même temps, tous les choix ont été faits avant !)_ + +Ce schéma permet de visualiser les relations entre les différentes tables de manière simple et efficace, sans avoir à se soucier des détails techniques. + +Mais pour le moment, on n'a pas encore parlé des types de données des colonnes, ni des index à créer sur les tables... +Rendez-vous pour la prochaine et dernière étape : le **MPD** _(Modèle Physique de Données)_ ! 🚀 \ No newline at end of file diff --git a/app/pages/docs/merise/mpd/+Page.mdx b/app/pages/docs/merise/mpd/+Page.mdx index a8e6ce7..074c27e 100644 --- a/app/pages/docs/merise/mpd/+Page.mdx +++ b/app/pages/docs/merise/mpd/+Page.mdx @@ -4,4 +4,139 @@ description: Apprenez à créer le MPD dans Merise, la dernière étape pour con tags: [Backend, Merise, BDD, MCD, MLD, MPD, SQL] --- -En cours de rédaction... +import DictionnaryTable from "../dictionnaire-de-donnees/DictionnaryTable"; +import Callout from "@/components/Callout"; +import tabs from "./tabs"; + +Prêt·e pour la dernière étape de la méthodologie Merise ? 🎉 +Alors sans plus tarder, accueillons comme il se doit le **MPD** _(Modèle Physique de Données)_ ! + +## 🤔 Qu'est-ce que le MPD ? + +Le **MPD** est la dernière étape de la méthodologie Merise. +Il reprend les éléments du MLD en ajoutant les derniers **détails techniques** nécessaires +pour implémenter le modèle dans un **SGBD** _(Système de Gestion de Base de Données)_. + +**Ces détails techniques sont** : + +- Le type de données de chaque colonne _(ex: `VARCHAR`, `INT`, `DATE`, etc.)_ +- La taille de chaque colonne _(ex: `VARCHAR(255)`, `INT(11)`, etc.)_ +- Les contraintes d'intégrité _(ex: `NOT NULL`, `UNIQUE`, etc.)_ +- Les clés étrangères _(ex: `FOREIGN KEY`, `REFERENCES`, etc.)_ + +## 🔍 Exemple de MPD + +À partir du **MLD** _(et **MRD** si existant)_ et du **dictionnaire de données**, on va pouvoir créer le MPD. + +Faisons la transition de l'exemple de MLD basique que l'on a vu précédemment : + +![Exemple de MLD](/images/merise/mld-basic.webp) + +En prenant en considération que l'application va être développée avec **PostgreSQL**, on prendra soin d'utiliser +les **types de données** et les **contraintes d'intégrité** qui lui sont propres. + +Voici à quoi il ressemble : + +![Exemple de MPD](/images/merise/mpd-basic.webp) + +Avec ce schéma, il est facile d'identifier les différentes tables, leurs colonnes, les types de données, +les contraintes d'intégrité, ainsi que les clés primaires et étrangères qui relient les tables entre elles. + +Une fois le MPD créé, il est possible de le traduire en **SQL** pour créer les tables dans le SGBD. +Voici un exemple de code SQL pour créer les tables correspondantes au MPD ci-dessus : + + + +## 📊 Dictionnaire de données + +Tu te souviens du **dictionnaire de données** que l'on a créé lors du brief avec le client ? Juste avant de passer au MCD ? +Il est maintenant possible de le mettre jour avec les informations du SGBD utilisé ! + +Bien entendu ce n'est pas obligatoire, mais c'est une bonne source d'informations pour +les développeurs et les administrateurs de la base de données 😉 + +Pour rappel, voici le dictionnaire de données **non technique** que nous avions fait : + + + +En ajoutant les informations techniques, il devient : + + + +Ça en fait du beau monde ! 😅 + +Il est important de noter que le dictionnaire de données doit être mis à jour à chaque fois qu'une modification +est apportée au modèle de données ainsi qu'à la base de données. + +Maintenant, il est temps de réaliser le **MPD** à partir du **MLD** et du **dictionnaire de données** ! + +## 🛠️ Outils pour créer le MPD + +Bien que j'ai recommandé d'utiliser [Looping](https://looping.fr/) pour créer les schémas de données, +il ne permet pas de créer le MPD. + +Il n'est pas pour autant à mettre à la poubelle, car il permet de créer le MCD et le MLD très facilement, ainsi que +le LDD _(Langage de Définition de Données)_ dont on va parler un peu plus tard ! + +Divers outils en ligne permettent de générer des schémas graphiques de bases de données. +Cependant, ils ne sont pas tous adaptés à la création de MPD. + +La plupart du temps, on retrouvera des outils qui permettent de réaliser des ERD _(Entity Relationship Diagram)_. +La différence dans ces outils est qu'ils se basent davantage sur une syntaxe de type **UML** _(Unified Modeling Language)_. + + + En général, les outils qui utilisent une syntaxe de type UML utilisent des **losanges** pour représenter les relations entre les entités. + Dans le cas de Merise, on utilise des **lignes** et **flèches basiques** pour représenter les relations entre les entités/tables. + + Il est aussi possible que tu tombes sur des "pattes de poulet" _(comme dirait une consœur jurée)_ ou **crow's foot notation** + qui est une autre façon de représenter les relations entre les entités/tables. + + C'est joli, **mais c'est pas Merise** ! 😅 + + +De mon côté, j'utilise [DrawDB](https://drawdb.app/) qui est un outil en ligne gratuit et open-source. +Il permet de créer des schémas de bases de données avec la possibilité de configurer l'apparence des lignes de relation, +ainsi que de générer un diagramme à partir d'un fichier SQL. + +## 🔨 Création du MPD + +Pour créer le MPD, il va juste falloir t'armer de patience selon la taille de ton MLD et de ton outil. + +Dans ton outil, tu devras indiquer les types de données et les contraintes d'intégrité pour chaque colonne de chaque table. +Mais ça tombe bien, on a déjà fait le plus gros du travail avec le MLD et le dictionnaire de données ! + +À la fin, on se retrouve avec un schéma qui ressemble à ça : + +![Exemple de MPD](/images/merise/mpd-1.webp) + +## 📜 Préparation du LDD + +Dernière ligne droite : le **LDD** _(Langage de Définition de Données)_ ! + +Le **LDD** correspond tout simplement à la création des tables dans le SGBD, par l'utilisation des commandes SQL +comme `CREATE TABLE`, `ALTER TABLE`, `DROP TABLE`, etc. + +Il est possible de le créer à partir de [DrawDB](https://drawdb.app/) en exportant le schéma au format SQL, mais également +depuis [Looping](https://looping.fr/) ! + +De notre côté, voici à quoi ressemble le LDD pour le MPD ci-dessus : + + + +Et voilà, on en a fini avec le MPD ! 🎉 + +## Conclusion + +Ça y est, on peut souffler un bon coup ! 🍹☀️ + +Non seulement on a créé le **MPD**, mais on a également mis à jour le **dictionnaire de données** avec les informations techniques +tout en préparant le **LDD** pour créer les tables dans le SGBD. +On peut le dire : on est des pros de la méthodologie Merise ! 😎 + +... ou presque ! Merise va plus loin que la simple modélisation de bases de données. +Mais ça, je t'invite à le découvrir par toi-même 😉 + +Si tu souhaites aller plus loin dans la méthodologie Merise, je te recommande de lire la +[quatrième édition du guide pratique Merise](https://www.editions-eni.fr/livre/merise-guide-pratique-4e-edition-modelisation-des-donnees-et-des-traitements-manipulations-avec-le-langage-sql-conception-d-une-application-mobile-android-ou-ios-9782409046667) +aux Éditions ENI. +Il a été écrit par [Jean-Luc Baptiste](https://www.editions-eni.fr/jean-luc-baptiste) qui maîtrise le sujet sur le bout des doigts. \ No newline at end of file diff --git a/app/pages/docs/merise/mpd/tabs.tsx b/app/pages/docs/merise/mpd/tabs.tsx new file mode 100644 index 0000000..4478867 --- /dev/null +++ b/app/pages/docs/merise/mpd/tabs.tsx @@ -0,0 +1,125 @@ +import { Snippet } from "@/components/Snippet"; + +const sqlExampleSnippets = [ + { + name: "Exemple de LDD", + codeLanguage: "sql", + withLineNumbers: true, + code: `CREATE TABLE "table_1" ( + "id_table_1" INTEGER NOT NULL UNIQUE, + "column_2" VARCHAR(50) NOT NULL, + "column_3" VARCHAR(50) NOT NULL, + "table_3_id" INTEGER NOT NULL, + PRIMARY KEY("id_table_1") +); +CREATE INDEX "table_1_index_0" +ON "table_1" ("id_table_3"); + +CREATE TABLE "table_3" ( + "id_table_3" INTEGER NOT NULL UNIQUE GENERATED BY DEFAULT AS IDENTITY, + "column_2" VARCHAR(50) NOT NULL, + "column_3" VARCHAR(50) NOT NULL, + "table_3_id" INTEGER, + PRIMARY KEY("id_table_3") +); +CREATE INDEX "table_3_index_0" +ON "table_3" ("id_table_3"); + +CREATE TABLE "table_2" ( + "id_table_2" INTEGER NOT NULL UNIQUE GENERATED BY DEFAULT AS IDENTITY, + "column_2" VARCHAR(50) NOT NULL, + "column_3" VARCHAR(50) NOT NULL, + PRIMARY KEY("id_table_2") +); +CREATE INDEX "table_2_index_0" +ON "table_2" ("id_table_2"); + +CREATE TABLE "table_1_contains_table_2" ( + "table_1_id" INTEGER NOT NULL, + "table_2_id" INTEGER NOT NULL, + PRIMARY KEY("table_1_id", "table_2_id") +); +CREATE UNIQUE INDEX "table_1_contains_table_2_index_0" +ON "table_1_contains_table_2" ("table_1_id", "table_2_id"); + +ALTER TABLE "table_1" +ADD FOREIGN KEY("table_3_id") REFERENCES "table_3"("id_table_3") +ON UPDATE NO ACTION ON DELETE NO ACTION; + +ALTER TABLE "table_3" +ADD FOREIGN KEY("id_table_3") REFERENCES "table_3"("table_3_id") +ON UPDATE NO ACTION ON DELETE NO ACTION; + +ALTER TABLE "table_1" +ADD FOREIGN KEY("id_table_1") REFERENCES "table_1_contains_table_2"("table_1_id") +ON UPDATE NO ACTION ON DELETE NO ACTION; + +ALTER TABLE "table_1_contains_table_2" +ADD FOREIGN KEY("table_2_id") REFERENCES "table_2"("id_table_2") +ON UPDATE NO ACTION ON DELETE NO ACTION;`, + }, +]; + +const sqlBandManagerSnippets = [ + { + name: "LDD final", + codeLanguage: "sql", + withLineNumbers: true, + code: `CREATE TABLE "musician" ( + "id_musician" SERIAL NOT NULL, + "lastname" VARCHAR(30) NOT NULL, + "firstname" VARCHAR(30) NOT NULL, + "instruments" VARCHAR[] NOT NULL, + "email" VARCHAR(50) NOT NULL, + "password" CHAR(64) NOT NULL, + PRIMARY KEY("id_musician") +); + +CREATE TABLE "event" ( + "id_event" SERIAL NOT NULL, + "datetime" TIMESTAMP NOT NULL, + "location" VARCHAR(30) NOT NULL, + PRIMARY KEY("id_event") +); + +CREATE TABLE "concert" ( + "id_concert" SERIAL NOT NULL, + "price" MONEY, + "event_id" SERIAL NOT NULL, + PRIMARY KEY("id_concert") +); + +CREATE TABLE "rehearsal" ( + "id_rehearsal" SERIAL NOT NULL, + "event_id" SERIAL NOT NULL, + PRIMARY KEY("id_rehearsal") +); + +CREATE TABLE "musician_participates_event" ( + "musician_id" SERIAL NOT NULL, + "event_id" SERIAL NOT NULL, + PRIMARY KEY("musician_id", "event_id") +); + +ALTER TABLE "concert" +ADD FOREIGN KEY("event_id") REFERENCES "event"("id_event") +ON UPDATE NO ACTION ON DELETE NO ACTION; + +ALTER TABLE "rehearsal" +ADD FOREIGN KEY("event_id") REFERENCES "event"("id_event") +ON UPDATE NO ACTION ON DELETE NO ACTION; + +ALTER TABLE "musician" +ADD FOREIGN KEY("id_musician") REFERENCES "musician_participates_event"("musician_id") +ON UPDATE NO ACTION ON DELETE NO ACTION; + +ALTER TABLE "event" +ADD FOREIGN KEY("id_event") REFERENCES "musician_participates_event"("event_id") +ON UPDATE NO ACTION ON DELETE NO ACTION;`, + }, +]; + +export default { + sqlExample: () => , + sqlBandManager: () => , +}; diff --git a/app/public/downloads/merise/band-manager.lo1 b/app/public/downloads/merise/band-manager.lo1 index 9b033b5..65434ca 100644 Binary files a/app/public/downloads/merise/band-manager.lo1 and b/app/public/downloads/merise/band-manager.lo1 differ diff --git a/app/public/downloads/merise/band-manager.loo b/app/public/downloads/merise/band-manager.loo index 9b033b5..65434ca 100644 Binary files a/app/public/downloads/merise/band-manager.loo and b/app/public/downloads/merise/band-manager.loo differ diff --git a/app/public/downloads/merise/example.lo1 b/app/public/downloads/merise/example.lo1 new file mode 100644 index 0000000..aedb229 Binary files /dev/null and b/app/public/downloads/merise/example.lo1 differ diff --git a/app/public/downloads/merise/example.loo b/app/public/downloads/merise/example.loo new file mode 100644 index 0000000..aedb229 Binary files /dev/null and b/app/public/downloads/merise/example.loo differ diff --git a/app/public/images/merise/mcd-basic.webp b/app/public/images/merise/mcd-basic.webp index fcc6e93..4ab4b77 100644 Binary files a/app/public/images/merise/mcd-basic.webp and b/app/public/images/merise/mcd-basic.webp differ diff --git a/app/public/images/merise/mld-1.webp b/app/public/images/merise/mld-1.webp new file mode 100644 index 0000000..325f57e Binary files /dev/null and b/app/public/images/merise/mld-1.webp differ diff --git a/app/public/images/merise/mld-2.webp b/app/public/images/merise/mld-2.webp new file mode 100644 index 0000000..038bb7c Binary files /dev/null and b/app/public/images/merise/mld-2.webp differ diff --git a/app/public/images/merise/mld-3.webp b/app/public/images/merise/mld-3.webp new file mode 100644 index 0000000..cb667b2 Binary files /dev/null and b/app/public/images/merise/mld-3.webp differ diff --git a/app/public/images/merise/mld-4.webp b/app/public/images/merise/mld-4.webp new file mode 100644 index 0000000..c3310e5 Binary files /dev/null and b/app/public/images/merise/mld-4.webp differ diff --git a/app/public/images/merise/mld-5.webp b/app/public/images/merise/mld-5.webp new file mode 100644 index 0000000..2dfa5ad Binary files /dev/null and b/app/public/images/merise/mld-5.webp differ diff --git a/app/public/images/merise/mld-basic.webp b/app/public/images/merise/mld-basic.webp new file mode 100644 index 0000000..3afc6a0 Binary files /dev/null and b/app/public/images/merise/mld-basic.webp differ diff --git a/app/public/images/merise/mpd-1.webp b/app/public/images/merise/mpd-1.webp new file mode 100644 index 0000000..a09b8e8 Binary files /dev/null and b/app/public/images/merise/mpd-1.webp differ diff --git a/app/public/images/merise/mpd-basic.webp b/app/public/images/merise/mpd-basic.webp new file mode 100644 index 0000000..917ae75 Binary files /dev/null and b/app/public/images/merise/mpd-basic.webp differ