🗄️ Introduction aux

Bases de Données

De la théorie à MySQL

Formation DWWM - 2025-2026

Au programme 📋

  • 🎯 Introduction : Qu'est-ce qu'une BDD ?
  • 📖 Définitions : BDD, SGBD, types
  • 🎨 MCD : Modèle Conceptuel de Données
  • 📊 MLD : Modèle Logique de Données
  • 🔧 MPD : Modèle Physique de Données
  • 🐬 MySQL : Installation et utilisation
  • 💻 SQL : Requêtes de base (CRUD)
  • 🔗 Jointures : Relier les tables
  • 💪 Exercices : Cas pratiques

🎯 Partie 1

Introduction aux Bases de Données

Comprendre les fondamentaux

Qu'est-ce qu'une Base de Données ? 🗄️

Base de Données (BDD)
Ensemble organisé de données structurées et stockées de manière permanente
🤔 Pourquoi une BDD ?
Pour stocker, organiser, rechercher et gérer de grandes quantités de données de façon efficace

Analogie : Une bibliothèque 📚

  • 🏢 Bibliothèque = Base de données
  • 📚 Étagères = Tables
  • 📖 Livres = Enregistrements (lignes)
  • 📄 Fiches = Attributs (colonnes)
  • 🔍 Catalogue = Index

Avant les BDD : Les fichiers plats 📄

Problème : Stocker des données dans des fichiers texte

utilisateurs.txt :
--------------------
1|Marie|Dupont|marie@mail.com|25
2|Jean|Martin|jean@mail.com|30
3|Sophie|Durand|sophie@mail.com|28
❌ Problèmes des fichiers plats :
  • Redondance des données (doublons)
  • Incohérence (modifications partielles)
  • Difficulté de recherche (parcourir tout le fichier)
  • Pas de relations entre fichiers
  • Pas de contrôle d'accès concurrent
  • Pas de sécurité

Avec une BDD : Organisation 🎯

Table : utilisateurs +----+---------+---------+-------------------+-----+ | id | prenom | nom | email | age | +----+---------+---------+-------------------+-----+ | 1 | Marie | Dupont | marie@mail.com | 25 | | 2 | Jean | Martin | jean@mail.com | 30 | | 3 | Sophie | Durand | sophie@mail.com | 28 | +----+---------+---------+-------------------+-----+ Table : commandes +----+------------+------------+--------+ | id | user_id | date | total | +----+------------+------------+--------+ | 1 | 1 | 2024-12-20 | 99.99 | | 2 | 1 | 2024-12-25 | 149.50 | | 3 | 2 | 2024-12-28 | 49.99 | +----+------------+------------+--------+
✅ Avantages :
  • Données structurées et organisées
  • Relations entre tables (user_id → id)
  • Recherche rapide avec index
  • Intégrité des données garantie
  • Accès concurrent géré

Où sont utilisées les BDD ? 🌍

Partout autour de vous !
  • 🛒 E-commerce : Produits, clients, commandes (Amazon, Cdiscount...)
  • 📱 Réseaux sociaux : Utilisateurs, posts, likes (Facebook, Instagram...)
  • 🏦 Banques : Comptes, transactions, historique
  • 🏥 Hôpitaux : Patients, dossiers médicaux, rendez-vous
  • ✈️ Compagnies aériennes : Vols, réservations, passagers
  • 🎓 Écoles : Étudiants, notes, cours
  • 🎬 Netflix : Films, utilisateurs, historique de visionnage
  • 📧 Gmail : Emails, contacts, pièces jointes
  • 🎮 Jeux vidéo : Comptes, scores, inventaires

📖 Partie 2

Définitions : BDD et SGBD

Les concepts de base

Qu'est-ce qu'un SGBD ? 🔧

SGBD = Système de Gestion de Base de Données
(DBMS en anglais : Database Management System)

Logiciel qui permet de créer, gérer et manipuler des bases de données
Architecture Application -> SGBD -> BDD +-------------------+ | APPLICATION | (PHP, Java, Python...) | (votre code) | +--------+----------+ | | Requetes SQL v +-------------------+ | SGBD | (MySQL, PostgreSQL...) | (logiciel) | -> Gere les acces +--------+----------+ -> Optimise les requetes | -> Assure l'integrite v +-------------------+ | BASE DE | (Fichiers sur le disque) | DONNEES | +-------------------+

Rôle du SGBD 🎯

Le SGBD est responsable de :

  1. Stockage : Enregistrer les données sur le disque
  2. Interrogation : Rechercher et récupérer les données (SQL)
  3. Mise à jour : Modifier, ajouter, supprimer
  4. Intégrité : Garantir la cohérence des données
  5. Sécurité : Gérer les droits d'accès
  6. Concurrence : Plusieurs utilisateurs en même temps
  7. Sauvegarde : Backup et restauration
  8. Optimisation : Index, cache, performances
💡 Analogie : Le SGBD est comme un bibliothécaire qui organise les livres, aide à chercher, prête, range, et protège la bibliothèque.

Les différents types de SGBD 📊

Type Exemples Caractéristiques
Relationnel
(SGBDR)
MySQL
PostgreSQL
Oracle
SQL Server
Tables avec relations
Langage SQL
⭐ Le plus utilisé
NoSQL MongoDB
Redis
Cassandra
Documents JSON
Clé-valeur
Très rapide
Graphe Neo4j
ArangoDB
Relations complexes
Réseaux sociaux
Dans ce cours : Focus sur les SGBDR (Relationnel) avec MySQL

MySQL : Le SGBD que nous utiliserons 🐬

MySQL
SGBD relationnel open-source, très populaire pour le web

Pourquoi MySQL ?

  • ✅ Gratuit et open-source
  • ✅ Très utilisé (WordPress, Facebook, Twitter...)
  • ✅ Performant et fiable
  • ✅ Facile à apprendre
  • ✅ Compatible avec PHP, Python, Java...
  • ✅ Grande communauté et documentation

Alternatives similaires :

  • MariaDB : Fork de MySQL (quasi identique)
  • PostgreSQL : Plus avancé, plus complexe
  • SQLite : Léger, sans serveur (mobile)

Vocabulaire de base 📚

Terme Définition Analogie
Base de données Collection de tables Bibliothèque
Table Collection d'enregistrements Étagère
Enregistrement
(ligne / row / tuple)
Une entrée dans la table Un livre
Champ
(colonne / field / attribut)
Une propriété des enregistrements Titre, auteur...
Clé primaire
(Primary Key)
Identifiant unique N° ISBN
Clé étrangère
(Foreign Key)
Référence vers une autre table Référence croisée

🎨 Partie 3

MCD - Modèle Conceptuel

Concevoir la structure de la BDD

Qu'est-ce que le MCD ? 🎨

MCD = Modèle Conceptuel de Données
Représentation abstraite et visuelle des données et de leurs relations
🤔 Pourquoi un MCD ?
Pour réfléchir à la structure AVANT de créer la base de données
C'est le plan architectural de votre BDD

Les 3 composants du MCD :

  1. ENTITÉS : Les "objets" (Client, Produit, Commande...)
  2. ATTRIBUTS : Les propriétés (nom, prix, date...)
  3. RELATIONS : Les liens entre entités (commander, acheter...)

Les ENTITÉS 📦

ENTITÉ = Objet ou concept du monde réel
Représentée par un rectangle
+------------+ +------------+ +------------+ | CLIENT | | PRODUIT | | COMMANDE | +------------+ +------------+ +------------+ +------------+ +------------+ +------------+ | ETUDIANT | | COURS | | PROFESSEUR | +------------+ +------------+ +------------+

Comment identifier les entités ?

  • Cherchez les NOMS dans la description du problème
  • Ce sont des "choses" qui ont une existence propre
  • On peut les compter (plusieurs clients, plusieurs produits...)
Exemple : Site e-commerce
Entités : CLIENT, PRODUIT, COMMANDE, CATÉGORIE, ADRESSE

Les ATTRIBUTS 🏷️

ATTRIBUT = Propriété / Caractéristique d'une entité
Listés sous l'entité
+----------------------+ | CLIENT | +----------------------+ | _id_ | <- Identifiant (souligne) | nom | | prenom | | email | | date_inscription | +----------------------+ +----------------------+ | PRODUIT | +----------------------+ | _id_ | | nom | | description | | prix | | stock | +----------------------+

Règles pour les attributs :

  • Chaque entité a un identifiant unique (souligné)
  • Les attributs sont atomiques (indivisibles)
  • Pas d'attributs calculés (âge → date_naissance)

Les RELATIONS (ASSOCIATIONS) 🔗

RELATION = Lien entre deux ou plusieurs entités
Représentée par un ovale/ellipse
+----------+ +----------+ | CLIENT |------( commander )--------| PRODUIT | +----------+ +----------+ +----------+ +----------+ | ETUDIANT |--------( suivre )---------| COURS | +----------+ +----------+ +----------+ +----------+ | AUTEUR |--------( ecrire )---------| LIVRE | +----------+ +----------+

Comment identifier les relations ?

  • Cherchez les VERBES qui lient les entités
  • Un client commande des produits
  • Un étudiant suit des cours
  • Un auteur écrit des livres

Les CARDINALITÉS 🔢

CARDINALITÉ = Nombre min et max d'occurrences de la relation
Format : (min, max)
(0,n) (0,n) +----------+ +----------+ | CLIENT |------( commander )--------| PRODUIT | +----------+ +----------+ Lecture : <- Un CLIENT peut commander 0 a n produits -> Un PRODUIT peut etre commande par 0 a n clients

Cardinalités courantes :

Notation Signification
0,1 Zéro ou un (optionnel, unique)
1,1 Exactement un (obligatoire, unique)
0,n Zéro ou plusieurs (optionnel, multiple)
1,n Un ou plusieurs (obligatoire, multiple)

Types de relations selon les cardinalités 🔍

1. Relation ONE-TO-ONE (1,1 ↔ 0,1 ou 1,1)

(1,1) (0,1) +----------+ +----------+ | USER |-------( posseder )---------| PROFIL | +----------+ +----------+ Un utilisateur a UN profil Un profil appartient a UN utilisateur

2. Relation ONE-TO-MANY (1,n ↔ 0,n)

(1,1) (0,n) +----------+ +----------+ | CLIENT |-------( passer )-----------| COMMANDE| +----------+ +----------+ Un client passe PLUSIEURS commandes Une commande appartient a UN client

3. Relation MANY-TO-MANY (0,n ↔ 0,n)

(0,n) (0,n) +----------+ +----------+ | ETUDIANT |--------( suivre )----------| COURS | +----------+ +----------+ Un etudiant suit PLUSIEURS cours Un cours est suivi par PLUSIEURS etudiants

Exemple complet : Site E-commerce 🛒

+-------------+ +-------------+ | CLIENT |(1,1) (0,n) | COMMANDE | +-------------+-------(passer)-------+-------------+ | _id_ | | _id_ | | nom | | date | | prenom | | total | | email | | statut | +-------------+ +-------------+ |(1,1) | (contenir) | |(0,n) +-------------+ +-------------+ | PRODUIT |(1,1) (0,n) | LIGNE | +-------------+----(concerner)-------+-------------+ | _id_ | | quantite | | nom | | prix_unit | | prix | +-------------+ | stock | +-------------+ |(0,n) | (appartenir) | |(1,1) +-------------+ | CATEGORIE | +-------------+ | _id_ | | nom | +-------------+

📊 Partie 4

MLD - Modèle Logique

Du MCD vers les tables

Qu'est-ce que le MLD ? 📊

MLD = Modèle Logique de Données
Transformation du MCD en tables avec leurs clés
🤔 Pourquoi le MLD ?
Pour passer de la conception abstraite (MCD) à une structure proche de la BDD réelle

Transformation MCD → MLD :

  1. Chaque ENTITÉ devient une TABLE
  2. Chaque ATTRIBUT devient une COLONNE
  3. L'identifiant devient la CLÉ PRIMAIRE
  4. Les RELATIONS deviennent des CLÉS ÉTRANGÈRES

Notation du MLD 📝

Syntaxe :
NomTable(cle_primaire, attribut1, attribut2, #cle_etrangere)
Legende : _souligne_ = Cle primaire (Primary Key) #hashtag = Cle etrangere (Foreign Key) Exemple : Client(_id_, nom, prenom, email) Commande(_id_, date, total, statut, #id_client)

Explications :

  • Client(id, ...) : id est la clé primaire
  • #id_client : référence vers Client(id)

Règle 1 : Relation ONE-TO-MANY 🔗

Cas : 1,1 ↔ 0,n ou 1,n ↔ 0,n

MCD : (1,1) (0,n) +----------+ +----------+ | CLIENT |-------( passer )-----------| COMMANDE| +----------+ +----------+ MLD : Client(_id_, nom, prenom, email) Commande(_id_, date, total, #id_client) ^ Cle etrangere vers Client
💡 Règle : La clé étrangère va du côté 0,n ou 1,n

Règle 2 : Relation MANY-TO-MANY 🔗🔗

Cas : 0,n ↔ 0,n

MCD : (0,n) (0,n) +----------+ +----------+ | ETUDIANT |--------( suivre )----------| COURS | +----------+ +----------+ MLD : Etudiant(_id_, nom, prenom) Cours(_id_, nom, credits) Suivre(_#id_etudiant_, _#id_cours_, note) +---------------+--------------+ Cle primaire composee
💡 Règle : Créer une TABLE INTERMÉDIAIRE (aussi appelée table de liaison ou table associative)

Règle 3 : Relation ONE-TO-ONE 🔗

Cas : 1,1 ↔ 0,1 ou 1,1 ↔ 1,1

MCD : (1,1) (0,1) +----------+ +----------+ | USER |-------( posseder )---------| PROFIL | +----------+ +----------+ MLD Option 1 : Cle etrangere User(_id_, email, password) Profil(_id_, bio, avatar, #id_user) MLD Option 2 : Tout dans une table User(_id_, email, password, bio, avatar)
💡 Conseil : Si optionnel (0,1), faire 2 tables. Si obligatoire et peu d'attributs, fusionner.

Exemple complet : E-commerce 🛒

MLD complet : Client(_id_, nom, prenom, email, date_inscription) Categorie(_id_, nom, description) Produit(_id_, nom, description, prix, stock, #id_categorie) Commande(_id_, date, total, statut, #id_client) LigneCommande(_#id_commande_, _#id_produit_, quantite, prix_unitaire) +---------------+--------------+ Cle primaire composee

Explications :

  • Produit : #id_categorie → Un produit appartient à UNE catégorie
  • Commande : #id_client → Une commande appartient à UN client
  • LigneCommande : Table intermédiaire (MANY-TO-MANY entre Commande et Produit)

🔧 Partie 5

MPD - Modèle Physique

De la théorie à MySQL

Qu'est-ce que le MPD ? 🔧

MPD = Modèle Physique de Données
Implémentation réelle dans un SGBD spécifique (MySQL, PostgreSQL...)
🤔 Pourquoi le MPD ?
Pour passer du modèle logique au code SQL exécutable

Transformation MLD → MPD :

  1. Définir les TYPES DE DONNÉES (INT, VARCHAR...)
  2. Ajouter les CONTRAINTES (NOT NULL, UNIQUE...)
  3. Créer les INDEX pour les performances
  4. Écrire le code CREATE TABLE

Types de données MySQL 📊

Type Description Exemples
INT Nombre entier 42, -10, 1000
BIGINT Très grand entier 9999999999
DECIMAL(10,2) Nombre décimal précis 99.99, 149.50
FLOAT / DOUBLE Nombre à virgule 3.14159
VARCHAR(255) Texte variable "Marie", "email@..."
TEXT Long texte Articles, descriptions
DATE Date AAAA-MM-JJ 2024-12-30
DATETIME Date + heure 2024-12-30 15:30:00
TIMESTAMP Date auto (création) CURRENT_TIMESTAMP
BOOLEAN Vrai/Faux (0/1) TRUE, FALSE
ENUM Liste de valeurs 'small','medium','large'

Contraintes MySQL 🔒

Contrainte Description Exemple
PRIMARY KEY Clé primaire (unique + not null) id INT PRIMARY KEY
AUTO_INCREMENT Incrémentation auto (1, 2, 3...) id INT AUTO_INCREMENT
NOT NULL Obligatoire (pas de valeur nulle) nom VARCHAR(50) NOT NULL
UNIQUE Valeur unique dans la table email VARCHAR(100) UNIQUE
DEFAULT Valeur par défaut statut VARCHAR(20) DEFAULT 'actif'
FOREIGN KEY Clé étrangère (référence) FOREIGN KEY (id_client) REFERENCES client(id)
CHECK Vérification condition CHECK (age >= 18)

Exemple MPD : Table Client 👤

CREATE TABLE client (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nom VARCHAR(50) NOT NULL,
    prenom VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    telephone VARCHAR(20),
    date_inscription TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Explications ligne par ligne :

  • id INT PRIMARY KEY AUTO_INCREMENT : Identifiant unique auto-incrémenté
  • nom VARCHAR(50) NOT NULL : Texte max 50 caractères, obligatoire
  • email VARCHAR(100) NOT NULL UNIQUE : Email obligatoire et unique
  • telephone VARCHAR(20) : Optionnel (pas de NOT NULL)
  • date_inscription TIMESTAMP DEFAULT CURRENT_TIMESTAMP : Date auto
  • ENGINE=InnoDB : Moteur de stockage (supporte les clés étrangères)
  • CHARSET=utf8mb4 : Encodage UTF-8 (accents + émojis)

Exemple MPD complet : E-commerce 🛒

-- Table Client
CREATE TABLE client (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nom VARCHAR(50) NOT NULL,
    prenom VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    date_inscription TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Table Categorie
CREATE TABLE categorie (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nom VARCHAR(50) NOT NULL UNIQUE,
    description TEXT
);

-- Table Produit
CREATE TABLE produit (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nom VARCHAR(100) NOT NULL,
    description TEXT,
    prix DECIMAL(10,2) NOT NULL,
    stock INT NOT NULL DEFAULT 0,
    id_categorie INT NOT NULL,
    FOREIGN KEY (id_categorie) REFERENCES categorie(id)
);

-- Table Commande
CREATE TABLE commande (
    id INT PRIMARY KEY AUTO_INCREMENT,
    date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    total DECIMAL(10,2) NOT NULL,
    statut ENUM('en_attente', 'validee', 'expediee', 'livree') DEFAULT 'en_attente',
    id_client INT NOT NULL,
    FOREIGN KEY (id_client) REFERENCES client(id)
);

-- Table Ligne de Commande
CREATE TABLE ligne_commande (
    id_commande INT,
    id_produit INT,
    quantite INT NOT NULL,
    prix_unitaire DECIMAL(10,2) NOT NULL,
    PRIMARY KEY (id_commande, id_produit),
    FOREIGN KEY (id_commande) REFERENCES commande(id),
    FOREIGN KEY (id_produit) REFERENCES produit(id)
);

💻 Partie 6

SQL : Les requêtes de base

CRUD : Create, Read, Update, Delete

Qu'est-ce que SQL ? 💬

SQL = Structured Query Language
Langage pour interroger et manipuler les bases de données

Les 4 opérations de base (CRUD) :

Opération SQL Action
Create INSERT Ajouter
Read SELECT Lire
Update UPDATE Modifier
Delete DELETE Supprimer

INSERT - Ajouter des données ➕

INSERT INTO = Ajouter de nouvelles lignes dans une table
🤔 Pourquoi INSERT ?
Pour remplir la base de données : ajouter clients, produits, commandes...
Syntaxe de base :
INSERT INTO nom_table (colonne1, colonne2) VALUES (valeur1, valeur2);

INSERT - Comment ça marche ⚙️

AVANT INSERT : Table : client +----+--------+--------+------------------+ | id | nom | prenom | email | +----+--------+--------+------------------+ | 1 | Martin | Jean | jean@mail.com | +----+--------+--------+------------------+ REQUETE : INSERT INTO client (nom, prenom, email) VALUES ('Dupont', 'Marie', 'marie@mail.com'); APRES INSERT : Table : client +----+--------+--------+------------------+ | id | nom | prenom | email | +----+--------+--------+------------------+ | 1 | Martin | Jean | jean@mail.com | | 2 | Dupont | Marie | marie@mail.com | <- NOUVELLE LIGNE +----+--------+--------+------------------+ ^ id=2 auto-genere (AUTO_INCREMENT)

Explication ligne par ligne :

INSERT INTO client (nom, prenom, email)
--          ^       ^
--          |       Liste des colonnes a remplir
--          Nom de la table
VALUES ('Dupont', 'Marie', 'marie@mail.com');
--      ^         ^        ^
--      |         |        Valeur pour "email"
--      |         Valeur pour "prenom"
--      Valeur pour "nom"

INSERT - Cas pratiques 🎯

1. Insertion simple (le plus courant)

-- Ajouter un nouveau client
INSERT INTO client (nom, prenom, email, password)
VALUES ('Dupont', 'Marie', 'marie@mail.com', 'hash_mdp_123');
-- Note : l'id n'est PAS specifie (AUTO_INCREMENT le genere)

2. Insertion multiple (plusieurs lignes en une fois)

-- Ajouter plusieurs produits en une seule requete
INSERT INTO produit (nom, prix, stock, id_categorie)
VALUES 
    ('Ordinateur', 899.99, 10, 1),  -- Ligne 1
    ('Souris', 25.50, 50, 1),       -- Ligne 2
    ('Clavier', 45.00, 30, 1);      -- Ligne 3
-- Plus rapide que 3 INSERT separés
💡 Avantage : Une seule requête = plus rapide que 3 requêtes séparées

INSERT - Variantes 🔧

3. Insertion avec TOUTES les colonnes (dans l'ordre)

-- Si vous donnez TOUTES les colonnes dans l'ordre de la table
INSERT INTO categorie 
VALUES (NULL, 'Informatique', 'Produits informatiques');
--      ^
--      NULL = MySQL genere l'id automatiquement
⚠️ Attention : Cette syntaxe est dangereuse !
Si la structure de la table change (nouvelle colonne), la requête plante.

4. Insertion depuis une autre table (copie)

-- Copier des produits d'une table vers une autre
INSERT INTO produit_archive (nom, prix, stock)
SELECT nom, prix, stock 
FROM produit 
WHERE stock = 0;
-- Copie tous les produits en rupture de stock

INSERT - Pièges à éviter ⚠️

PIÈGE #1 : Oublier une colonne NOT NULL
-- ❌ ERREUR : 'nom' est obligatoire (NOT NULL)
INSERT INTO client (prenom, email)
VALUES ('Marie', 'marie@mail.com');
-- Erreur : Column 'nom' cannot be null

-- ✅ CORRECT
INSERT INTO client (nom, prenom, email)
VALUES ('Dupont', 'Marie', 'marie@mail.com');
PIÈGE #2 : Mauvais ordre des valeurs
-- ❌ ERREUR : valeurs dans le mauvais ordre
INSERT INTO client (nom, prenom, email)
VALUES ('marie@mail.com', 'Dupont', 'Marie');
--      ^                 ^         ^
--      email dans "nom"  nom dans "prenom"...

-- ✅ CORRECT : respecter l'ordre
INSERT INTO client (nom, prenom, email)
VALUES ('Dupont', 'Marie', 'marie@mail.com');

INSERT - En pratique avec PHP 🐘

Comment insérer depuis PHP :

<?php
// ❌ DANGEREUX - Injection SQL possible
$nom = $_POST['nom'];
$sql = "INSERT INTO client (nom) VALUES ('$nom')";
// Si $nom = "'); DROP TABLE client; --" => CATASTROPHE

// ✅ SÉCURISÉ - Prepared Statements
$nom = $_POST['nom'];
$email = $_POST['email'];

$stmt = $pdo->prepare("INSERT INTO client (nom, email) VALUES (?, ?)");
$stmt->execute([$nom, $email]);
//               ^    ^
//               |    Valeur pour email
//               Valeur pour nom

// Récupérer l'ID de la ligne insérée
$newId = $pdo->lastInsertId();
echo "Client ajouté avec l'ID : $newId";
?>
🔐 Règle de sécurité : TOUJOURS utiliser les Prepared Statements en PHP

SELECT - Lire des données 📖

SELECT = Récupérer (lire) des données depuis une table
🤔 Pourquoi SELECT ?
Pour afficher, rechercher, filtrer les données : liste de produits, recherche clients...
Syntaxe de base :
SELECT colonnes FROM table WHERE condition;

SELECT est la requête la PLUS utilisée (90% du temps) !

SELECT * - Tout sélectionner 🌟

REQUETE : SELECT * FROM client; ^ * = toutes les colonnes RESULTAT : +----+---------+---------+-------------------+-----+ | id | nom | prenom | email | age | +----+---------+---------+-------------------+-----+ | 1 | Dupont | Marie | marie@mail.com | 25 | | 2 | Martin | Jean | jean@mail.com | 30 | | 3 | Durand | Sophie | sophie@mail.com | 28 | +----+---------+---------+-------------------+-----+ Toutes les lignes, toutes les colonnes
-- Selectionner TOUT
SELECT * FROM client;
-- Retourne TOUTES les colonnes de TOUTES les lignes
⚠️ Attention : SELECT * peut être lent sur de grandes tables !
Mieux vaut spécifier les colonnes nécessaires.

SELECT colonnes - Sélection précise 🎯

REQUETE : SELECT nom, email FROM client; ^ ^ Seulement ces 2 colonnes RESULTAT : +---------+-------------------+ | nom | email | +---------+-------------------+ | Dupont | marie@mail.com | | Martin | jean@mail.com | | Durand | sophie@mail.com | +---------+-------------------+ Toutes les lignes, mais seulement 2 colonnes
-- Selectionner certaines colonnes
SELECT nom, prenom, email FROM client;
-- Retourne seulement nom, prenom et email (pas l'age, ni l'id)

-- Avec alias (renommer les colonnes dans le resultat)
SELECT 
    nom AS nom_famille,
    prenom AS prenom_utilisateur,
    email
FROM client;

-- Resultat : colonnes renommees
-- nom_famille | prenom_utilisateur | email
💡 Bonne pratique : Ne sélectionnez que les colonnes dont vous avez besoin

WHERE - Filtrer les lignes 🔍

WHERE = Condition pour filtrer les résultats
REQUETE : SELECT * FROM produit WHERE prix < 100; ^ Condition : prix inferieur a 100 Table complete : Resultat filtre : +----+--------+-------+ +----+--------+-------+ | id | nom | prix | | id | nom | prix | +----+--------+-------+ +----+--------+-------+ | 1 | PC | 899 | | 2 | Souris | 25 | | 2 | Souris | 25 | --> | 3 | Cable | 15 | | 3 | Cable | 15 | +----+--------+-------+ +----+--------+-------+ Seulement les lignes ou prix < 100
-- Produits a moins de 100 euros
SELECT * FROM produit WHERE prix < 100;

-- Client specifique par ID
SELECT * FROM client WHERE id = 5;

-- Recherche par email
SELECT * FROM client WHERE email = 'marie@mail.com';

WHERE - Opérateurs de comparaison 🔢

Opérateur Signification Exemple
= Égal WHERE id = 5
!= ou <> Différent WHERE statut != 'annule'
< Inférieur WHERE prix < 100
> Supérieur WHERE age > 18
<= Inférieur ou égal WHERE stock <= 10
>= Supérieur ou égal WHERE note >= 10
-- Produits chers (plus de 500 euros)
SELECT * FROM produit WHERE prix > 500;

-- Produits en rupture de stock
SELECT * FROM produit WHERE stock = 0;

-- Produits disponibles
SELECT * FROM produit WHERE stock > 0;

WHERE - Opérateurs spéciaux 🎯

BETWEEN - Entre deux valeurs

-- Produits entre 50 et 200 euros
SELECT * FROM produit WHERE prix BETWEEN 50 AND 200;
-- Equivalent a : WHERE prix >= 50 AND prix <= 200

-- Commandes de decembre 2024
SELECT * FROM commande 
WHERE date BETWEEN '2024-12-01' AND '2024-12-31';

IN - Dans une liste

-- Clients avec ID 1, 5 ou 10
SELECT * FROM client WHERE id IN (1, 5, 10);
-- Equivalent a : WHERE id = 1 OR id = 5 OR id = 10

-- Produits de certaines categories
SELECT * FROM produit WHERE id_categorie IN (1, 3, 5);

IS NULL - Valeur nulle

-- Clients sans telephone
SELECT * FROM client WHERE telephone IS NULL;

-- Clients avec telephone
SELECT * FROM client WHERE telephone IS NOT NULL;

WHERE - LIKE recherche de motif 🔎

LIKE = Recherche avec motif
% = n'importe quels caractères (0 ou plus)
_ = exactement 1 caractère
Exemples de motifs : '%phone%' -> contient "phone" n'importe ou 'phone%' -> commence par "phone" '%phone' -> finit par "phone" '_phone' -> 1 caractere puis "phone" 'p_one' -> p + 1 caractere + one (phone, p1one...)
-- Produits contenant "phone" dans le nom
SELECT * FROM produit WHERE nom LIKE '%phone%';
-- Trouve : "iPhone", "Smartphone", "Telephone"

-- Clients dont le nom commence par "D"
SELECT * FROM client WHERE nom LIKE 'D%';
-- Trouve : "Dupont", "Durand", "Dufour"

-- Emails Gmail
SELECT * FROM client WHERE email LIKE '%@gmail.com';

-- Codes promo commencant par "PROMO"
SELECT * FROM commande WHERE code_promo LIKE 'PROMO%';
💡 Attention : LIKE est sensible à la casse selon la config MySQL
Utilisez LOWER() pour ignorer la casse

WHERE - AND / OR combinaisons 🔗

AND - Toutes les conditions doivent être vraies

-- Produits pas chers ET en stock
SELECT * FROM produit 
WHERE prix < 100 AND stock > 0;
--    ^            ^
--    Condition 1  Condition 2
--    Les DEUX doivent etre vraies

-- Adultes vivant a Paris
SELECT * FROM client 
WHERE age >= 18 AND ville = 'Paris';

OR - Au moins une condition doit être vraie

-- Produits de Paris OU Lyon
SELECT * FROM client 
WHERE ville = 'Paris' OR ville = 'Lyon';
--    ^                ^
--    Condition 1       Condition 2
--    UNE SEULE suffit

-- Produits en rupture OU stock faible
SELECT * FROM produit 
WHERE stock = 0 OR stock < 5;

Combinaison AND + OR (avec parenthèses)

-- Produits pas chers de categorie 1 OU 2
SELECT * FROM produit 
WHERE prix < 100 AND (id_categorie = 1 OR id_categorie = 2);
--                   ^                                      ^
--                   Parentheses obligatoires pour l'ordre

ORDER BY - Trier les résultats 📊

ORDER BY = Trier les résultats par une ou plusieurs colonnes
Sans ORDER BY : Avec ORDER BY prix ASC : +----+--------+-------+ +----+--------+-------+ | id | nom | prix | | id | nom | prix | +----+--------+-------+ +----+--------+-------+ | 1 | PC | 899 | | 3 | Cable | 15 | | 2 | Souris | 25 | --> | 2 | Souris | 25 | | 3 | Cable | 15 | | 1 | PC | 899 | +----+--------+-------+ +----+--------+-------+ Ordre aleatoire Trie par prix croissant
-- Trier par prix croissant (du moins cher au plus cher)
SELECT * FROM produit ORDER BY prix ASC;
--                                  ^
--                                  ASC = Ascendant (croissant)

-- Trier par prix decroissant (du plus cher au moins cher)
SELECT * FROM produit ORDER BY prix DESC;
--                                  ^
--                                  DESC = Descendant (decroissant)

-- Trier par plusieurs colonnes
SELECT * FROM produit 
ORDER BY id_categorie ASC, prix DESC;
--       ^                 ^
--       D'abord par       Puis par prix
--       categorie         (dans chaque categorie)

LIMIT - Limiter le nombre de résultats 🔢

LIMIT = Limiter le nombre de lignes retournées
Table complete (100 lignes) : SELECT * FROM produit; -> Retourne les 100 lignes Avec LIMIT : SELECT * FROM produit LIMIT 10; -> Retourne seulement les 10 premieres lignes
-- Les 10 premiers produits
SELECT * FROM produit LIMIT 10;

-- Les 5 produits les plus chers
SELECT * FROM produit 
ORDER BY prix DESC 
LIMIT 5;
--    ^
--    Les 5 premiers apres tri

-- Pagination : 10 produits a partir du 20e
SELECT * FROM produit 
LIMIT 10 OFFSET 20;
--    ^         ^
--    Nombre    Sauter les 20 premiers
-- Utilise pour page 3 (si 10 par page)
Pagination :
-- Page 1 : LIMIT 10 OFFSET 0
-- Page 2 : LIMIT 10 OFFSET 10
-- Page 3 : LIMIT 10 OFFSET 20
-- Formule : OFFSET = (page - 1) * parPage

SELECT - Exemple complet 🎯

Requête avec toutes les clauses :

SELECT nom, prix, stock               -- 1. Colonnes a selectionner
FROM produit                          -- 2. Table source
WHERE prix < 200 AND stock > 0        -- 3. Filtrer les lignes
ORDER BY prix ASC                     -- 4. Trier les resultats
LIMIT 10;                             -- 5. Limiter a 10 resultats

-- Ordre d'execution (important) :
-- 1. FROM    : Prendre la table "produit"
-- 2. WHERE   : Filtrer (prix < 200 ET stock > 0)
-- 3. ORDER BY: Trier par prix croissant
-- 4. LIMIT   : Garder les 10 premiers
-- 5. SELECT  : Retourner nom, prix, stock
Resultat : +------------+--------+-------+ | nom | prix | stock | +------------+--------+-------+ | Cable USB | 15.00 | 25 | | Souris | 25.50 | 50 | | Clavier | 45.00 | 30 | | Webcam | 79.99 | 15 | | Casque | 89.00 | 20 | +------------+--------+-------+ (10 lignes maximum)

UPDATE - Modifier des données ✏️

UPDATE = Modifier les données existantes dans une table
🤔 Pourquoi UPDATE ?
Pour corriger, mettre à jour : changer email, prix, statut...
Syntaxe :
UPDATE table SET colonne = nouvelle_valeur WHERE condition;
⚠️ DANGER : Sans WHERE, TOUTES les lignes sont modifiées !

UPDATE - Comment ça marche ⚙️

AVANT UPDATE : +----+---------+-------------------+ | id | nom | email | +----+---------+-------------------+ | 1 | Dupont | marie@mail.com | | 2 | Martin | jean@mail.com | +----+---------+-------------------+ REQUETE : UPDATE client SET email = 'nouveau@mail.com' WHERE id = 1; ^ ^ ^ | | Ligne a modifier Table Nouvelle valeur APRES UPDATE : +----+---------+-------------------+ | id | nom | email | +----+---------+-------------------+ | 1 | Dupont | nouveau@mail.com | <- MODIFIE | 2 | Martin | jean@mail.com | +----+---------+-------------------+ Seulement la ligne avec id=1 est modifiee

Explication :

UPDATE client                    -- 1. Table a modifier
SET email = 'nouveau@mail.com'   -- 2. Colonne et nouvelle valeur
WHERE id = 1;                    -- 3. Quelle(s) ligne(s) modifier

UPDATE - Modifier plusieurs colonnes 🔧

-- Modifier plusieurs colonnes en meme temps
UPDATE client 
SET 
    email = 'nouveau@mail.com',
    telephone = '0123456789',
    ville = 'Paris'
WHERE id = 1;
-- Les 3 colonnes sont modifiees pour id=1
AVANT : +----+---------+---------------+-----------+--------+ | id | nom | email | telephone | ville | +----+---------+---------------+-----------+--------+ | 1 | Dupont | old@mail.com | NULL | Lyon | +----+---------+---------------+-----------+--------+ APRES : +----+---------+-------------------+------------+--------+ | id | nom | email | telephone | ville | +----+---------+-------------------+------------+--------+ | 1 | Dupont | nouveau@mail.com | 0123456789 | Paris | +----+---------+-------------------+------------+--------+

UPDATE - Avec calculs 🧮

On peut utiliser la valeur actuelle dans le calcul :

1. Augmenter un prix de 10%

UPDATE produit 
SET prix = prix * 1.10
WHERE id_categorie = 1;
--    ^
--    Utilise la valeur actuelle
AVANT : APRES : +----+----------+-------+ +----+----------+--------+ | id | nom | prix | | id | nom | prix | +----+----------+-------+ +----+----------+--------+ | 1 | Produit1 | 100 | -> | 1 | Produit1 | 110.00 | | 2 | Produit2 | 50 | -> | 2 | Produit2 | 55.00 | +----+----------+-------+ +----+----------+--------+

2. Incrémenter un compteur

-- Augmenter le stock de 10
UPDATE produit 
SET stock = stock + 10
WHERE id = 5;

3. Appliquer une réduction

-- Reduire les prix de 20 euros
UPDATE produit 
SET prix = prix - 20
WHERE prix > 100;

UPDATE - Modifier plusieurs lignes 📊

-- Changer le statut de TOUTES les commandes validees
UPDATE commande 
SET statut = 'expediee'
WHERE statut = 'validee' AND date < '2024-12-01';
-- Toutes les lignes qui correspondent sont modifiees
AVANT : +----+------------+----------+ | id | date | statut | +----+------------+----------+ | 1 | 2024-11-15 | validee | <- Va etre modifie | 2 | 2024-11-20 | validee | <- Va etre modifie | 3 | 2024-12-05 | validee | <- Pas modifie (date >= 12-01) +----+------------+----------+ APRES : +----+------------+----------+ | id | date | statut | +----+------------+----------+ | 1 | 2024-11-15 | expediee | <- MODIFIE | 2 | 2024-11-20 | expediee | <- MODIFIE | 3 | 2024-12-05 | validee | +----+------------+----------+

UPDATE - DANGER sans WHERE ⚠️

💀 CATASTROPHE : Oublier le WHERE
-- ❌ ERREUR FATALE
UPDATE produit SET prix = 0;
-- TOUS les prix passent a 0 !

-- ✅ TOUJOURS mettre un WHERE
UPDATE produit SET prix = 0 WHERE id = 5;
-- Seulement le produit 5
Sans WHERE - CATASTROPHE : AVANT : APRES : +----+----------+-------+ +----+----------+-------+ | id | nom | prix | | id | nom | prix | +----+----------+-------+ +----+----------+-------+ | 1 | Produit1 | 100 | -> | 1 | Produit1 | 0 | <- TOUT | 2 | Produit2 | 50 | -> | 2 | Produit2 | 0 | <- A | 3 | Produit3 | 200 | -> | 3 | Produit3 | 0 | <- ZERO ! +----+----------+-------+ +----+----------+-------+
💡 Bonne pratique :
  1. Faire un SELECT avec le WHERE d'abord
  2. Vérifier que les bonnes lignes sont sélectionnées
  3. Remplacer SELECT * par UPDATE

UPDATE - En pratique avec PHP 🐘

<?php
// Modifier l'email d'un client

// ❌ DANGEREUX - Injection SQL
$email = $_POST['email'];
$id = $_GET['id'];
$sql = "UPDATE client SET email = '$email' WHERE id = $id";

// ✅ SECURISE - Prepared Statement
$email = $_POST['email'];
$id = $_GET['id'];

$stmt = $pdo->prepare("UPDATE client SET email = ? WHERE id = ?");
$stmt->execute([$email, $id]);

// Verifier le nombre de lignes modifiees
$nbModifies = $stmt->rowCount();
if ($nbModifies > 0) {
    echo "Client modifie avec succes";
} else {
    echo "Aucun client trouve avec cet ID";
}
?>

DELETE - Supprimer des données 🗑️

DELETE = Supprimer des lignes d'une table
🤔 Pourquoi DELETE ?
Pour supprimer définitivement : comptes obsolètes, commandes annulées...
Syntaxe :
DELETE FROM table WHERE condition;
💀 DANGER CRITIQUE :
  • Sans WHERE = TOUT est supprimé
  • Suppression IRRÉVERSIBLE (pas de CTRL+Z !)
  • Toujours faire un SELECT avant

DELETE - Comment ça marche ⚙️

AVANT DELETE : +----+---------+-------------------+ | id | nom | email | +----+---------+-------------------+ | 1 | Dupont | marie@mail.com | | 2 | Martin | jean@mail.com | | 3 | Durand | sophie@mail.com | +----+---------+-------------------+ REQUETE : DELETE FROM client WHERE id = 2; ^ ^ Table Ligne a supprimer APRES DELETE : +----+---------+-------------------+ | id | nom | email | +----+---------+-------------------+ | 1 | Dupont | marie@mail.com | | 3 | Durand | sophie@mail.com | +----+---------+-------------------+ La ligne avec id=2 a disparu DEFINITIVEMENT

Explication :

DELETE FROM client    -- 1. Table concernee
WHERE id = 2;         -- 2. Quelle(s) ligne(s) supprimer

-- ⚠️ Pas de "SET" comme UPDATE
-- ⚠️ Pas de colonnes a specifier
-- On supprime la LIGNE ENTIERE

DELETE - Cas pratiques 🎯

1. Supprimer un élément par ID

-- Supprimer un client specifique
DELETE FROM client WHERE id = 5;

2. Supprimer selon une condition

-- Supprimer les commandes annulees de 2023
DELETE FROM commande 
WHERE statut = 'annulee' 
AND date < '2024-01-01';

3. Supprimer les produits en rupture

-- Supprimer les produits sans stock
DELETE FROM produit WHERE stock = 0;
AVANT : +----+----------+-------+-------+ | id | nom | prix | stock | +----+----------+-------+-------+ | 1 | Produit1 | 100 | 10 | | 2 | Produit2 | 50 | 0 | <- Va etre supprime | 3 | Produit3 | 200 | 0 | <- Va etre supprime | 4 | Produit4 | 75 | 5 | +----+----------+-------+-------+ APRES : +----+----------+-------+-------+ | id | nom | prix | stock | +----+----------+-------+-------+ | 1 | Produit1 | 100 | 10 | | 4 | Produit4 | 75 | 5 | +----+----------+-------+-------+

DELETE - LA CATASTROPHE sans WHERE 💀

💀 ERREUR FATALE
-- ❌ CATASTROPHE : Oubli du WHERE
DELETE FROM client;
-- TOUS LES CLIENTS SONT SUPPRIMES !
-- IRRÉVERSIBLE !

-- ✅ TOUJOURS mettre un WHERE
DELETE FROM client WHERE id = 5;
Sans WHERE - APOCALYPSE : AVANT : APRES : +----+---------+-------+ +----+---------+-------+ | id | nom | email | | id | nom | email | +----+---------+-------+ +----+---------+-------+ | 1 | Dupont | ... | | 2 | Martin | ... | TABLE VIDE ! | 3 | Durand | ... | TOUT A DISPARU ! +----+---------+-------+ +----+---------+-------+ Pas de sauvegarde = PERTE DEFINITIVE
📖 Histoire vraie :
En 2019, une développeuse chez Pixar a accidentellement lancé :
rm -rf * (équivalent de DELETE sans WHERE)
→ 1 an de travail sur Toy Story 2 supprimé !
Heureusement sauvegardé par une employée en congé maternité.

DELETE - Bonne pratique 🛡️

💡 Méthode SÉCURISÉE :
  1. SELECT d'abord avec le même WHERE
  2. Vérifier les lignes qui seront supprimées
  3. Si OK, remplacer SELECT par DELETE
-- Etape 1 : SELECT pour verifier
SELECT * FROM commande 
WHERE statut = 'annulee' AND date < '2024-01-01';
-- Resultat : 3 lignes trouvees
-- -> Verifier que ce sont bien ces 3 lignes

-- Etape 2 : Remplacer SELECT par DELETE
DELETE FROM commande 
WHERE statut = 'annulee' AND date < '2024-01-01';
-- Supprime exactement les 3 lignes verifiees
⚠️ Checklist avant DELETE :
  • ✅ J'ai fait un SELECT d'abord
  • ✅ J'ai vérifié les lignes concernées
  • ✅ J'ai une sauvegarde récente
  • ✅ Mon WHERE est correct

DELETE vs TRUNCATE ⚡

Aspect DELETE TRUNCATE
Suppression Ligne par ligne Toute la table d'un coup
WHERE possible ✅ Oui ❌ Non
Vitesse Lent Très rapide
AUTO_INCREMENT Conservé Réinitialisé à 1
Rollback Possible (transaction) Difficile
-- DELETE : Supprime ligne par ligne
DELETE FROM produit WHERE stock = 0;

-- TRUNCATE : Vide TOUTE la table instantanement
TRUNCATE TABLE produit;
-- Equivalent a DELETE FROM produit (mais plus rapide)
-- ⚠️ ATTENTION : Supprime TOUT, pas de WHERE possible
Quand utiliser TRUNCATE ?
Seulement pour vider complètement une table de test/temporaire

DELETE - En pratique avec PHP 🐘

<?php
// Supprimer un client

// ❌ DANGEREUX
$id = $_GET['id'];
$sql = "DELETE FROM client WHERE id = $id";

// ✅ SECURISE - Prepared Statement
$id = $_GET['id'];

// Etape 1 : Verifier d'abord
$stmt = $pdo->prepare("SELECT * FROM client WHERE id = ?");
$stmt->execute([$id]);
$client = $stmt->fetch();

if ($client) {
    // Etape 2 : Confirmer avec l'utilisateur (JavaScript)
    echo "Supprimer {$client['nom']} ?";
    
    // Etape 3 : Supprimer si confirmation
    $stmt = $pdo->prepare("DELETE FROM client WHERE id = ?");
    $stmt->execute([$id]);
    
    $nbSupprimes = $stmt->rowCount();
    echo "$nbSupprimes client(s) supprime(s)";
} else {
    echo "Client introuvable";
}
?>
💡 Interface utilisateur :
// Toujours demander confirmation
if (confirm('Supprimer ce client ?')) {
    // Envoyer la requete de suppression
    window.location = 'delete.php?id=5';
}

WHERE : Conditions et opérateurs 🔍

Opérateur Description Exemple
= Égal WHERE id = 5
!= ou <> Différent WHERE statut != 'annule'
< > <= >= Comparaison WHERE prix >= 100
BETWEEN Entre deux valeurs WHERE prix BETWEEN 10 AND 100
IN Dans une liste WHERE id IN (1, 5, 10)
LIKE Motif (% = n'importe quoi) WHERE nom LIKE '%phone%'
IS NULL Valeur nulle WHERE telephone IS NULL
AND ET logique WHERE prix < 100 AND stock > 0
OR OU logique WHERE ville = 'Paris' OR ville = 'Lyon'

🔗 Partie 7

Les Jointures SQL

Relier les tables entre elles

Pourquoi les jointures ? 🤔

JOINTURE (JOIN) = Combiner les données de plusieurs tables
🤔 Le problème :
Dans une BDD bien conçue, les données sont réparties dans plusieurs tables.
Comment récupérer les infos de plusieurs tables en même temps ?
Exemple : Afficher les commandes avec les noms des clients Table : commande (pas de nom client) +----+------------+-------+-----------+ | id | id_client | total | date | +----+------------+-------+-----------+ | 1 | 1 | 99.99 | 2024-12-20| | 2 | 1 | 49.50 | 2024-12-25| | 3 | 2 | 29.99 | 2024-12-28| +----+------------+-------+-----------+ ^ | Comment avoir le nom du client ? v Table : client +----+---------+---------+ | id | nom | prenom | +----+---------+---------+ | 1 | Dupont | Marie | | 2 | Martin | Jean | +----+---------+---------+ Solution = JOINTURE !

Jointures - Le principe 🔗

Une jointure relie deux tables via une relation :

Relation : commande.id_client = client.id ^ ^ Cle etrangere Cle primaire C'est comme dire : "Pour chaque commande, trouve le client dont l'id correspond a id_client"

Résultat après jointure :

SELECT commande.*, client.nom, client.prenom FROM commande INNER JOIN client ON commande.id_client = client.id; Resultat : +----+-----------+-------+------------+---------+---------+ | id | id_client | total | date | nom | prenom | +----+-----------+-------+------------+---------+---------+ | 1 | 1 | 99.99 | 2024-12-20 | Dupont | Marie | | 2 | 1 | 49.50 | 2024-12-25 | Dupont | Marie | | 3 | 2 | 29.99 | 2024-12-28 | Martin | Jean | +----+-----------+-------+------------+---------+---------+ Donnees combinees des 2 tables !

INNER JOIN - Jointure interne 🔗

INNER JOIN = Retourne SEULEMENT les lignes qui ont une correspondance dans les DEUX tables
Syntaxe :
SELECT colonnes FROM table1 INNER JOIN table2 ON table1.cle = table2.cle;

Analogie : Comme une intersection de deux ensembles

INNER JOIN - Comment ça marche ⚙️

Table : commande +----+------------+-------+ | id | id_client | total | +----+------------+-------+ | 1 | 1 | 99.99 | | 2 | 1 | 49.50 | | 3 | 2 | 29.99 | | 4 | 5 | 19.99 | <- id_client=5 n'existe pas ! +----+------------+-------+ Table : client +----+---------+ | id | nom | +----+---------+ | 1 | Dupont | | 2 | Martin | | 3 | Durand | <- Pas de commande +----+---------+ INNER JOIN : Garde seulement les lignes avec correspondance Resultat : +----+------------+-------+---------+ | id | id_client | total | nom | +----+------------+-------+---------+ | 1 | 1 | 99.99 | Dupont | <- Match ! | 2 | 1 | 49.50 | Dupont | <- Match ! | 3 | 2 | 29.99 | Martin | <- Match ! +----+------------+-------+---------+ ❌ Commande 4 (client 5) : pas de match -> EXCLUE ❌ Client 3 (Durand) : pas de commande -> EXCLU

INNER JOIN - Exemple pratique 🎯

-- Requete : Commandes avec noms des clients
SELECT 
    commande.id,
    commande.total,
    commande.date,
    client.nom,
    client.prenom
FROM commande
INNER JOIN client ON commande.id_client = client.id;
--                   ^
--                   Condition de jointure

Explication ligne par ligne :

SELECT                              -- 1. Colonnes a afficher
    commande.id,                    -- De la table commande
    client.nom                      -- De la table client
FROM commande                       -- 2. Table principale
INNER JOIN client                   -- 3. Table a joindre
ON commande.id_client = client.id;  -- 4. Comment les relier

INNER JOIN - Avec alias (recommandé) 💡

Les alias rendent le code plus court et lisible :

-- Sans alias (long)
SELECT 
    commande.id,
    commande.total,
    client.nom,
    client.prenom
FROM commande
INNER JOIN client ON commande.id_client = client.id;

-- Avec alias (court)
SELECT 
    c.id,
    c.total,
    cl.nom,
    cl.prenom
FROM commande c                      -- c = alias pour commande
INNER JOIN client cl ON c.id_client = cl.id;
--                 ^                 ^
--                 Alias             Utilise l'alias
💡 Convention : Utilisez des alias courts et clairs
c pour commande, cl pour client, p pour produit...

INNER JOIN - Avec WHERE et ORDER BY 🔧

On peut ajouter des conditions et trier :

-- Commandes de plus de 50 euros avec nom du client
SELECT 
    c.id,
    c.total,
    c.date,
    cl.nom,
    cl.prenom
FROM commande c
INNER JOIN client cl ON c.id_client = cl.id
WHERE c.total > 50                   -- Filtre APRES jointure
ORDER BY c.total DESC;               -- Trie par montant

Ordre d'exécution :

  1. FROM : Prendre la table commande
  2. INNER JOIN : Joindre avec client
  3. WHERE : Filtrer (total > 50)
  4. ORDER BY : Trier
  5. SELECT : Retourner les colonnes

LEFT JOIN - Jointure gauche 👈

LEFT JOIN = Retourne TOUTES les lignes de la table de GAUCHE, même sans correspondance à droite
🤔 Pourquoi LEFT JOIN ?
Pour garder toutes les lignes de la table principale, même si pas de correspondance

Différence avec INNER JOIN :

  • INNER JOIN : Seulement les correspondances
  • LEFT JOIN : Tout à gauche + correspondances à droite

LEFT JOIN - Comment ça marche ⚙️

Table : client (GAUCHE) +----+---------+ | id | nom | +----+---------+ | 1 | Dupont | <- A des commandes | 2 | Martin | <- A des commandes | 3 | Durand | <- PAS de commande ! +----+---------+ Table : commande (DROITE) +----+------------+-------+ | id | id_client | total | +----+------------+-------+ | 1 | 1 | 99.99 | | 2 | 1 | 49.50 | | 3 | 2 | 29.99 | +----+------------+-------+ Pas de commande pour client 3 ! LEFT JOIN : Garde TOUS les clients + leurs commandes (si existent) Resultat : +----+---------+-----+-------+ | id | nom | c_id| total | +----+---------+-----+-------+ | 1 | Dupont | 1 | 99.99 | <- Match | 1 | Dupont | 2 | 49.50 | <- Match | 2 | Martin | 3 | 29.99 | <- Match | 3 | Durand |NULL | NULL | <- Pas de commande = NULL +----+---------+-----+-------+ ✅ TOUS les clients sont presents ❌ Pas de commande = NULL

LEFT JOIN - Exemple pratique 🎯

-- Tous les clients, avec ou sans commandes
SELECT 
    client.id,
    client.nom,
    client.prenom,
    commande.id AS commande_id,
    commande.total
FROM client                          -- Table de GAUCHE
LEFT JOIN commande ON client.id = commande.id_client;
-- Tous les clients, meme sans commande

Résultat :

+----+---------+---------+--------------+--------+ | id | nom | prenom | commande_id | total | +----+---------+---------+--------------+--------+ | 1 | Dupont | Marie | 1 | 99.99 | | 1 | Dupont | Marie | 2 | 49.50 | | 2 | Martin | Jean | 3 | 29.99 | | 3 | Durand | Sophie | NULL | NULL | <- Pas de commande +----+---------+---------+--------------+--------+

Durand apparaît avec NULL car pas de commande

LEFT JOIN - Trouver les lignes sans correspondance 🔍

Cas d'usage TRÈS utile : trouver ce qui manque

Clients SANS commande

SELECT client.*
FROM client
LEFT JOIN commande ON client.id = commande.id_client
WHERE commande.id IS NULL;
--    ^
--    Si NULL = pas de commande

-- Resultat : Seulement les clients sans commande
+----+---------+---------+
| id | nom     | prenom  |
+----+---------+---------+
| 3  | Durand  | Sophie  |
+----+---------+---------+

Produits jamais commandés

SELECT produit.*
FROM produit
LEFT JOIN ligne_commande lc ON produit.id = lc.id_produit
WHERE lc.id_produit IS NULL;
-- Produits qui n'ont jamais ete commandes

INNER JOIN vs LEFT JOIN 🆚

Donnees : client : [1-Dupont, 2-Martin, 3-Durand] commande : [cmd1->client1, cmd2->client1, cmd3->client2] (pas de commande pour client 3) INNER JOIN client + commande : +----+---------+--------------+ | id | nom | commande_id | +----+---------+--------------+ | 1 | Dupont | 1 | | 1 | Dupont | 2 | | 2 | Martin | 3 | +----+---------+--------------+ -> 3 lignes (Durand EXCLU) LEFT JOIN client + commande : +----+---------+--------------+ | id | nom | commande_id | +----+---------+--------------+ | 1 | Dupont | 1 | | 1 | Dupont | 2 | | 2 | Martin | 3 | | 3 | Durand | NULL | <- INCLUS avec NULL +----+---------+--------------+ -> 4 lignes (Durand INCLUS)
💡 Règle simple :
  • INNER JOIN : "Seulement les correspondances"
  • LEFT JOIN : "Tout à gauche + correspondances"

LEFT JOIN - Cas pratiques 🎯

1. Statistiques par client

-- Nombre de commandes par client (meme 0)
SELECT 
    client.nom,
    COUNT(commande.id) AS nb_commandes,
    COALESCE(SUM(commande.total), 0) AS total_depense
FROM client
LEFT JOIN commande ON client.id = commande.id_client
GROUP BY client.id;

-- Resultat :
-- Dupont  | 2 | 149.49
-- Martin  | 1 | 29.99
-- Durand  | 0 | 0.00     <- INCLUS avec 0

2. Liste complète produits + catégorie

-- Tous les produits, meme sans categorie
SELECT 
    produit.nom,
    produit.prix,
    categorie.nom AS categorie
FROM produit
LEFT JOIN categorie ON produit.id_categorie = categorie.id;

Jointures multiples 🔗🔗🔗

-- Commandes avec client ET produits
SELECT 
    cmd.id AS commande_id,
    cmd.date,
    cl.nom AS client_nom,
    p.nom AS produit_nom,
    lc.quantite,
    lc.prix_unitaire
FROM commande cmd
INNER JOIN client cl ON cmd.id_client = cl.id
INNER JOIN ligne_commande lc ON cmd.id = lc.id_commande
INNER JOIN produit p ON lc.id_produit = p.id
WHERE cmd.id = 1;

-- Produits avec leur catégorie
SELECT 
    p.nom AS produit,
    p.prix,
    c.nom AS categorie
FROM produit p
INNER JOIN categorie c ON p.id_categorie = c.id
ORDER BY c.nom, p.nom;

Fonctions d'agrégation 📊

Fonction Description Exemple
COUNT() Compter COUNT(*)
SUM() Somme SUM(total)
AVG() Moyenne AVG(prix)
MIN() Minimum MIN(prix)
MAX() Maximum MAX(prix)
-- Nombre de commandes par client
SELECT 
    client.nom,
    COUNT(commande.id) AS nb_commandes,
    SUM(commande.total) AS total_depense
FROM client
LEFT JOIN commande ON client.id = commande.id_client
GROUP BY client.id;

-- Prix moyen par catégorie
SELECT 
    categorie.nom,
    COUNT(produit.id) AS nb_produits,
    AVG(produit.prix) AS prix_moyen
FROM categorie
LEFT JOIN produit ON categorie.id = produit.id_categorie
GROUP BY categorie.id;

🎯 Récapitulatif

Les 3 modèles :

  1. MCD : Conception abstraite (entités, relations, cardinalités)
  2. MLD : Tables avec clés (transformation des relations)
  3. MPD : Code SQL réel (types, contraintes)

Les commandes SQL essentielles :

  • INSERT INTO : Ajouter
  • SELECT : Lire
  • UPDATE : Modifier
  • DELETE : Supprimer
  • INNER JOIN : Relier les tables
  • GROUP BY : Regrouper et compter

Méthodologie complète 🛠️

Étapes pour créer une BDD :
  1. 📝 Analyse : Comprendre le besoin
  2. 🎨 MCD : Dessiner entités + relations
  3. 📊 MLD : Transformer en tables
  4. 🔧 MPD : Écrire le CREATE TABLE
  5. 🗄️ Créer : Exécuter le SQL
  6. ➕ Insérer : Ajouter les données
  7. 🔍 Requêter : SELECT avec JOIN

Ressources utiles 📚

  • 📖 MySQL Documentation : dev.mysql.com/doc
  • 🎓 W3Schools SQL : Tutoriels interactifs
  • 🛠️ phpMyAdmin : Interface graphique pour MySQL
  • 🔧 MySQL Workbench : Outil de modélisation
  • 📊 draw.io : Dessiner des MCD en ligne
  • 💡 SQLZoo : Exercices SQL interactifs

Merci ! 👏

Des questions ?

🗄️ MCD → MLD → MPD → SQL = Maîtrise des BDD !