Debutant 15 min de lecture · 3 245 mots

SQL pour debutants : SELECT, INSERT, UPDATE, DELETE

Introduction

SQL (Structured Query Language) est le langage universel pour interagir avec les bases de donnees relationnelles. Que vous utilisiez MySQL, PostgreSQL, MariaDB ou SQLite, les fondamentaux restent identiques. Maitriser les quatre operations de base – SELECT, INSERT, UPDATE et DELETE – constitue le socle indispensable de tout developpeur.

Dans cet article pratique, vous apprendrez :

  • Comment interroger des donnees avec SELECT et ses clauses essentielles
  • Comment inserer des enregistrements avec INSERT
  • Comment modifier des donnees existantes avec UPDATE
  • Comment supprimer des enregistrements avec DELETE
  • Les bonnes pratiques pour eviter les erreurs courantes
  • Les implications sur les performances de chaque operation
  • Prerequis et environnement de test

    Creation de la base de donnees d’exemple

    Pour suivre ce tutoriel, creez cette structure de base de donnees :

-- Creation de la base de donnees
CREATE DATABASE IF NOT EXISTS boutique_demo
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

USE boutique_demo;

-- Table des categories
CREATE TABLE categories (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    nom VARCHAR(100) NOT NULL,
    description TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_nom (nom)
) ENGINE=InnoDB;

-- Table des produits
CREATE TABLE produits (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    categorie_id INT UNSIGNED,
    nom VARCHAR(255) NOT NULL,
    description TEXT,
    prix DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    stock INT UNSIGNED NOT NULL DEFAULT 0,
    actif BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (categorie_id) REFERENCES categories(id) ON DELETE SET NULL,
    INDEX idx_categorie (categorie_id),
    INDEX idx_prix (prix),
    INDEX idx_actif (actif)
) ENGINE=InnoDB;

-- Table des clients
CREATE TABLE clients (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    nom VARCHAR(100) NOT NULL,
    prenom VARCHAR(100) NOT NULL,
    telephone VARCHAR(20),
    adresse TEXT,
    ville VARCHAR(100),
    code_postal VARCHAR(10),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_email (email),
    INDEX idx_ville (ville)
) ENGINE=InnoDB;

-- Table des commandes
CREATE TABLE commandes (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    client_id INT UNSIGNED NOT NULL,
    numero_commande VARCHAR(50) NOT NULL UNIQUE,
    total DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    statut ENUM('en_attente', 'confirmee', 'expediee', 'livree', 'annulee') DEFAULT 'en_attente',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE RESTRICT,
    INDEX idx_client (client_id),
    INDEX idx_statut (statut),
    INDEX idx_date (created_at)
) ENGINE=InnoDB;

-- Table de liaison commandes-produits
CREATE TABLE commande_produits (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    commande_id INT UNSIGNED NOT NULL,
    produit_id INT UNSIGNED NOT NULL,
    quantite INT UNSIGNED NOT NULL DEFAULT 1,
    prix_unitaire DECIMAL(10, 2) NOT NULL,
    FOREIGN KEY (commande_id) REFERENCES commandes(id) ON DELETE CASCADE,
    FOREIGN KEY (produit_id) REFERENCES produits(id) ON DELETE RESTRICT,
    UNIQUE KEY unique_commande_produit (commande_id, produit_id)
) ENGINE=InnoDB;

Insertion des donnees de test

-- Categories
INSERT INTO categories (nom, description) VALUES
('Electronique', 'Appareils electroniques et accessoires'),
('Vetements', 'Mode homme et femme'),
('Livres', 'Livres papier et numeriques'),
('Maison', 'Decoration et equipement maison'),
('Sport', 'Equipement et accessoires sportifs');

-- Produits
INSERT INTO produits (categorie_id, nom, description, prix, stock, actif) VALUES
(1, 'Smartphone Galaxy S24', 'Smartphone Samsung derniere generation', 899.99, 50, TRUE),
(1, 'Casque Bluetooth Sony', 'Casque audio sans fil avec reduction de bruit', 249.99, 100, TRUE),
(1, 'Tablette iPad Air', 'Tablette Apple 10.9 pouces', 699.00, 30, TRUE),
(2, 'Jean slim homme', 'Jean coupe slim bleu fonce', 59.99, 200, TRUE),
(2, 'T-shirt coton bio', 'T-shirt 100% coton biologique', 24.99, 500, TRUE),
(2, 'Veste en cuir', 'Veste en cuir veritable noir', 299.00, 25, FALSE),
(3, 'Clean Code', 'Robert C. Martin - Developper proprement', 34.90, 80, TRUE),
(3, 'Design Patterns', 'Gang of Four - Patterns de conception', 45.00, 45, TRUE),
(4, 'Lampe de bureau LED', 'Lampe LED reglable avec port USB', 39.99, 150, TRUE),
(4, 'Chaise ergonomique', 'Chaise de bureau ergonomique', 349.00, 20, TRUE),
(5, 'Tapis de yoga', 'Tapis antiderapant 6mm', 29.99, 300, TRUE),
(5, 'Halteres 10kg', 'Paire d halteres ajustables', 89.99, 60, TRUE);

-- Clients
INSERT INTO clients (email, nom, prenom, telephone, adresse, ville, code_postal) VALUES
('jean.dupont@email.com', 'Dupont', 'Jean', '0612345678', '12 rue de la Paix', 'Paris', '75001'),
('marie.martin@email.com', 'Martin', 'Marie', '0698765432', '45 avenue Victor Hugo', 'Lyon', '69003'),
('pierre.bernard@email.com', 'Bernard', 'Pierre', NULL, '8 boulevard Gambetta', 'Marseille', '13001'),
('sophie.petit@email.com', 'Petit', 'Sophie', '0611223344', '23 rue du Commerce', 'Bordeaux', '33000'),
('lucas.moreau@email.com', 'Moreau', 'Lucas', '0655667788', '67 rue de la Republique', 'Toulouse', '31000');

-- Commandes
INSERT INTO commandes (client_id, numero_commande, total, statut) VALUES
(1, 'CMD-2024-0001', 959.98, 'livree'),
(1, 'CMD-2024-0002', 84.98, 'expediee'),
(2, 'CMD-2024-0003', 699.00, 'confirmee'),
(3, 'CMD-2024-0004', 324.99, 'en_attente'),
(4, 'CMD-2024-0005', 79.89, 'livree');

-- Produits des commandes
INSERT INTO commande_produits (commande_id, produit_id, quantite, prix_unitaire) VALUES
(1, 1, 1, 899.99),
(1, 5, 2, 24.99),
(2, 5, 1, 24.99),
(2, 11, 2, 29.99),
(3, 3, 1, 699.00),
(4, 2, 1, 249.99),
(4, 5, 3, 24.99),
(5, 7, 1, 34.90),
(5, 8, 1, 45.00);

SELECT : Lire les donnees

Syntaxe de base

La commande SELECT permet de recuperer des donnees. Voici sa structure fondamentale :

SELECT colonnes
FROM table
[WHERE conditions]
[ORDER BY colonnes]
[LIMIT nombre];

Selections simples

-- Selectionner toutes les colonnes de tous les produits
SELECT * FROM produits;

-- Selectionner des colonnes specifiques
SELECT nom, prix, stock FROM produits;

-- Selectionner avec un alias de colonne
SELECT
    nom AS nom_produit,
    prix AS prix_ttc,
    stock AS quantite_disponible
FROM produits;

-- Selectionner des valeurs uniques (sans doublons)
SELECT DISTINCT ville FROM clients;

-- Selectionner avec une expression calculee
SELECT
    nom,
    prix,
    prix * 1.20 AS prix_avec_tva,
    stock,
    prix * stock AS valeur_stock
FROM produits;

Filtrer avec WHERE

La clause WHERE permet de filtrer les resultats :

-- Filtrer par valeur exacte
SELECT * FROM produits WHERE categorie_id = 1;

-- Filtrer par prix superieur a une valeur
SELECT nom, prix FROM produits WHERE prix > 100;

-- Filtrer par prix dans une plage
SELECT nom, prix FROM produits WHERE prix BETWEEN 50 AND 200;

-- Filtrer par valeur NULL
SELECT * FROM clients WHERE telephone IS NULL;

-- Filtrer par valeur non NULL
SELECT * FROM clients WHERE telephone IS NOT NULL;

-- Filtrer avec LIKE pour les recherches partielles
SELECT * FROM produits WHERE nom LIKE '%Samsung%';       -- Contient "Samsung"
SELECT * FROM produits WHERE nom LIKE 'Casque%';         -- Commence par "Casque"
SELECT * FROM produits WHERE nom LIKE '%LED';            -- Finit par "LED"

-- Filtrer avec IN pour une liste de valeurs
SELECT * FROM commandes WHERE statut IN ('en_attente', 'confirmee');

-- Filtrer avec NOT IN
SELECT * FROM commandes WHERE statut NOT IN ('annulee', 'livree');

Combiner les conditions avec AND et OR

-- AND : toutes les conditions doivent etre vraies
SELECT * FROM produits
WHERE prix > 50
AND stock > 20
AND actif = TRUE;

-- OR : au moins une condition doit etre vraie
SELECT * FROM produits
WHERE categorie_id = 1
OR categorie_id = 2;

-- Combiner AND et OR avec des parentheses
SELECT * FROM produits
WHERE (categorie_id = 1 OR categorie_id = 2)
AND prix < 500
AND actif = TRUE;

-- Exemple complexe : produits electroniques chers ou tous les livres
SELECT * FROM produits
WHERE (categorie_id = 1 AND prix > 500)
OR categorie_id = 3;

Trier avec ORDER BY

-- Tri ascendant (par defaut)
SELECT nom, prix FROM produits ORDER BY prix ASC;

-- Tri descendant
SELECT nom, prix FROM produits ORDER BY prix DESC;

-- Tri sur plusieurs colonnes
SELECT nom, categorie_id, prix FROM produits
ORDER BY categorie_id ASC, prix DESC;

-- Tri avec expression
SELECT nom, prix, prix * stock AS valeur
FROM produits
ORDER BY valeur DESC;

Limiter les resultats avec LIMIT

-- Les 5 premiers produits
SELECT * FROM produits LIMIT 5;

-- Les 5 produits les plus chers
SELECT nom, prix FROM produits ORDER BY prix DESC LIMIT 5;

-- Pagination : page 2 avec 5 elements par page (sauter les 5 premiers)
SELECT * FROM produits ORDER BY id LIMIT 5 OFFSET 5;
-- Syntaxe alternative MySQL
SELECT * FROM produits ORDER BY id LIMIT 5, 5;

Fonctions d’agregation

-- Compter le nombre total de produits
SELECT COUNT(*) AS nombre_produits FROM produits;

-- Compter uniquement les produits actifs
SELECT COUNT(*) AS produits_actifs FROM produits WHERE actif = TRUE;

-- Calculer le prix moyen
SELECT AVG(prix) AS prix_moyen FROM produits;

-- Prix minimum et maximum
SELECT
    MIN(prix) AS prix_min,
    MAX(prix) AS prix_max
FROM produits;

-- Somme du stock total
SELECT SUM(stock) AS stock_total FROM produits;

-- Valeur totale du stock
SELECT SUM(prix * stock) AS valeur_totale_stock FROM produits;

Grouper avec GROUP BY

-- Nombre de produits par categorie
SELECT
    categorie_id,
    COUNT(*) AS nombre_produits
FROM produits
GROUP BY categorie_id;

-- Prix moyen par categorie
SELECT
    categorie_id,
    COUNT(*) AS nombre_produits,
    AVG(prix) AS prix_moyen,
    MIN(prix) AS prix_min,
    MAX(prix) AS prix_max
FROM produits
GROUP BY categorie_id;

-- Filtrer les groupes avec HAVING
SELECT
    categorie_id,
    COUNT(*) AS nombre_produits,
    AVG(prix) AS prix_moyen
FROM produits
GROUP BY categorie_id
HAVING COUNT(*) >= 2;

-- Nombre de commandes par statut
SELECT
    statut,
    COUNT(*) AS nombre_commandes,
    SUM(total) AS montant_total
FROM commandes
GROUP BY statut
ORDER BY nombre_commandes DESC;

INSERT : Inserer des donnees

Syntaxe de base

-- Insertion simple avec toutes les colonnes specifiees
INSERT INTO table (colonne1, colonne2, colonne3)
VALUES (valeur1, valeur2, valeur3);

-- Insertion avec valeurs par defaut pour certaines colonnes
INSERT INTO table (colonne1)
VALUES (valeur1);

Insertions pratiques

-- Inserer un nouveau client
INSERT INTO clients (email, nom, prenom, telephone, adresse, ville, code_postal)
VALUES ('nouveau@email.com', 'Nouveau', 'Client', '0600000000', '1 rue Test', 'Paris', '75000');

-- Inserer sans specifier les colonnes optionnelles
INSERT INTO clients (email, nom, prenom)
VALUES ('minimal@email.com', 'Minimal', 'Test');

-- Inserer plusieurs lignes en une seule requete (plus performant)
INSERT INTO produits (categorie_id, nom, prix, stock) VALUES
(1, 'Ecouteurs sans fil', 79.99, 200),
(1, 'Chargeur rapide', 29.99, 500),
(1, 'Coque de protection', 19.99, 1000);

-- Inserer avec clause ON DUPLICATE KEY UPDATE (MySQL)
INSERT INTO clients (email, nom, prenom)
VALUES ('jean.dupont@email.com', 'Dupont', 'Jean')
ON DUPLICATE KEY UPDATE
    nom = VALUES(nom),
    prenom = VALUES(prenom);

Inserer depuis un SELECT

-- Creer une table d'archive
CREATE TABLE produits_archive LIKE produits;

-- Inserer les produits inactifs dans l'archive
INSERT INTO produits_archive
SELECT * FROM produits WHERE actif = FALSE;

-- Inserer avec transformation
INSERT INTO rapport_ventes (produit_id, total_vendu, date_rapport)
SELECT
    produit_id,
    SUM(quantite * prix_unitaire),
    CURRENT_DATE
FROM commande_produits
GROUP BY produit_id;

Recuperer l’ID insere

-- Apres une insertion, recuperer l'ID auto-increment
INSERT INTO clients (email, nom, prenom)
VALUES ('test@email.com', 'Test', 'User');

SELECT LAST_INSERT_ID() AS nouvel_id;

UPDATE : Modifier des donnees

Syntaxe de base

UPDATE table
SET colonne1 = valeur1, colonne2 = valeur2
WHERE condition;

ATTENTION : Toujours utiliser WHERE pour eviter de modifier toutes les lignes !

Modifications pratiques

-- Modifier le prix d'un produit specifique
UPDATE produits
SET prix = 849.99
WHERE id = 1;

-- Modifier plusieurs colonnes
UPDATE produits
SET
    prix = 229.99,
    stock = 150,
    updated_at = CURRENT_TIMESTAMP
WHERE id = 2;

-- Augmenter tous les prix de 10%
UPDATE produits
SET prix = prix * 1.10
WHERE categorie_id = 1;

-- Desactiver les produits sans stock
UPDATE produits
SET actif = FALSE
WHERE stock = 0;

-- Modifier avec une sous-requete
UPDATE produits
SET prix = prix * 0.90
WHERE id IN (
    SELECT produit_id FROM commande_produits
    GROUP BY produit_id
    HAVING SUM(quantite) < 5
);

-- Modifier le statut d'une commande
UPDATE commandes
SET
    statut = 'expediee',
    updated_at = CURRENT_TIMESTAMP
WHERE numero_commande = 'CMD-2024-0003';

UPDATE avec LIMIT (MySQL)

-- Modifier seulement les 10 premiers produits les moins chers
UPDATE produits
SET prix = prix * 1.05
ORDER BY prix ASC
LIMIT 10;

Verification avant UPDATE

Bonne pratique : Toujours tester avec SELECT avant d'executer UPDATE :

-- Etape 1 : Verifier quelles lignes seront affectees
SELECT * FROM produits
WHERE categorie_id = 1 AND prix > 500;

-- Etape 2 : Si le resultat est correct, executer UPDATE
UPDATE produits
SET prix = prix * 0.95
WHERE categorie_id = 1 AND prix > 500;

DELETE : Supprimer des donnees

Syntaxe de base

DELETE FROM table
WHERE condition;

ATTENTION CRITIQUE : Sans WHERE, TOUTES les lignes seront supprimees !

Suppressions pratiques

-- Supprimer un client specifique par ID
DELETE FROM clients WHERE id = 10;

-- Supprimer les commandes annulees de plus de 30 jours
DELETE FROM commandes
WHERE statut = 'annulee'
AND created_at < DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY);

-- Supprimer avec sous-requete
DELETE FROM produits
WHERE categorie_id IN (
    SELECT id FROM categories WHERE nom = 'Temporaire'
);

DELETE avec LIMIT (MySQL)

-- Supprimer seulement les 100 premieres lignes
DELETE FROM logs_archive
WHERE created_at < '2023-01-01'
ORDER BY created_at ASC
LIMIT 100;

Verification avant DELETE

Bonne pratique : Toujours tester avec SELECT COUNT avant DELETE :

-- Etape 1 : Compter les lignes qui seront supprimees
SELECT COUNT(*) AS lignes_a_supprimer
FROM commandes
WHERE statut = 'annulee'
AND created_at < DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY);

-- Etape 2 : Voir les donnees concernees
SELECT * FROM commandes
WHERE statut = 'annulee'
AND created_at < DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY);

-- Etape 3 : Executer la suppression si correct
DELETE FROM commandes
WHERE statut = 'annulee'
AND created_at < DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY);

TRUNCATE vs DELETE

-- DELETE : Supprime ligne par ligne, peut utiliser WHERE, conserve auto-increment
DELETE FROM logs;

-- TRUNCATE : Vide la table instantanement, remet auto-increment a 1
TRUNCATE TABLE logs;
Caracteristique DELETE TRUNCATE
Clause WHERE Oui Non
Vitesse Lent sur grosses tables Tres rapide
Transaction Rollback possible Non (DDL)
Auto-increment Conserve Reinitialise
Triggers Declenches Non declenches

Implications sur les performances

SELECT : Optimisation

-- MAUVAIS : Selectionner toutes les colonnes quand on n'en a besoin que de quelques-unes
SELECT * FROM produits;

-- BON : Specifier uniquement les colonnes necessaires
SELECT id, nom, prix FROM produits;

-- MAUVAIS : Requete sans index
SELECT * FROM produits WHERE description LIKE '%recherche%';

-- BON : Utiliser des colonnes indexees
SELECT * FROM produits WHERE nom LIKE 'recherche%';

-- Analyser une requete avec EXPLAIN
EXPLAIN SELECT * FROM produits WHERE prix > 100;
EXPLAIN ANALYZE SELECT * FROM commandes WHERE client_id = 1;

INSERT : Optimisation

-- MAUVAIS : Insertions individuelles en boucle
INSERT INTO produits (nom, prix) VALUES ('Produit 1', 10);
INSERT INTO produits (nom, prix) VALUES ('Produit 2', 20);
INSERT INTO produits (nom, prix) VALUES ('Produit 3', 30);

-- BON : Insertion groupee (batch insert)
INSERT INTO produits (nom, prix) VALUES
('Produit 1', 10),
('Produit 2', 20),
('Produit 3', 30);

-- TRES BON : Pour de gros volumes, desactiver temporairement les index
ALTER TABLE produits DISABLE KEYS;
-- insertions en masse...
ALTER TABLE produits ENABLE KEYS;

UPDATE et DELETE : Optimisation

-- MAUVAIS : UPDATE sans index sur la colonne de condition
UPDATE produits SET prix = 100 WHERE description = 'Texte a chercher';

-- BON : Utiliser la cle primaire ou une colonne indexee
UPDATE produits SET prix = 100 WHERE id = 5;

-- MAUVAIS : DELETE massif en une requete
DELETE FROM logs WHERE created_at < '2020-01-01';

-- BON : DELETE par lots pour eviter les locks prolonges
DELETE FROM logs
WHERE created_at < '2020-01-01'
LIMIT 10000;
-- Repeter jusqu'a ce que 0 lignes soient affectees

Transactions : Garantir l'integrite

Les transactions permettent de regrouper plusieurs operations en une unite atomique :

-- Demarrer une transaction
START TRANSACTION;

-- Creer une commande
INSERT INTO commandes (client_id, numero_commande, total, statut)
VALUES (1, 'CMD-2024-0006', 149.98, 'en_attente');

-- Recuperer l'ID de la commande
SET @commande_id = LAST_INSERT_ID();

-- Ajouter les produits a la commande
INSERT INTO commande_produits (commande_id, produit_id, quantite, prix_unitaire)
VALUES
(@commande_id, 2, 1, 249.99);

-- Diminuer le stock
UPDATE produits
SET stock = stock - 1
WHERE id = 2;

-- Si tout est OK, valider la transaction
COMMIT;

-- En cas d'erreur, annuler toutes les modifications
-- ROLLBACK;

Niveaux d'isolation

-- Voir le niveau d'isolation actuel
SELECT @@transaction_isolation;

-- Modifier le niveau d'isolation pour la session
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- Niveaux disponibles :
-- READ UNCOMMITTED : Lecture des donnees non validees (dirty reads)
-- READ COMMITTED : Lecture des donnees validees uniquement
-- REPEATABLE READ : Lectures repetables coherentes (defaut MySQL)
-- SERIALIZABLE : Isolation maximale (plus lent)

Sauvegarde et restauration

Export avec mysqldump

# Sauvegarder une base complete
mysqldump -u root -p boutique_demo > boutique_backup.sql

# Sauvegarder avec structure seulement
mysqldump -u root -p --no-data boutique_demo > boutique_structure.sql

# Sauvegarder certaines tables
mysqldump -u root -p boutique_demo produits clients > tables_backup.sql

# Sauvegarder avec options recommandees
mysqldump -u root -p 
  --single-transaction 
  --routines 
  --triggers 
  --events 
  boutique_demo > boutique_full_backup.sql

Restauration

# Restaurer une base
mysql -u root -p boutique_demo < boutique_backup.sql

# Restaurer dans une nouvelle base
mysql -u root -p -e "CREATE DATABASE boutique_restore"
mysql -u root -p boutique_restore < boutique_backup.sql

Export SELECT vers fichier

-- Exporter le resultat d'une requete en CSV
SELECT nom, prix, stock
INTO OUTFILE '/tmp/produits_export.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY 'n'
FROM produits;

Erreurs courantes et solutions

Erreur 1 : Oublier WHERE dans UPDATE/DELETE

-- CATASTROPHE : Met a jour TOUS les produits !
UPDATE produits SET prix = 0;

-- Solution : Toujours utiliser WHERE
UPDATE produits SET prix = 0 WHERE id = 1;

-- Prevention : Activer le mode safe updates
SET SQL_SAFE_UPDATES = 1;

Erreur 2 : Violation de contrainte de cle etrangere

-- Erreur : Supprimer une categorie utilisee
DELETE FROM categories WHERE id = 1;
-- ERROR 1451: Cannot delete or update a parent row

-- Solution 1 : Supprimer d'abord les produits lies
DELETE FROM produits WHERE categorie_id = 1;
DELETE FROM categories WHERE id = 1;

-- Solution 2 : Mettre a jour les produits
UPDATE produits SET categorie_id = NULL WHERE categorie_id = 1;
DELETE FROM categories WHERE id = 1;

Erreur 3 : Duplicat de cle unique

-- Erreur : Email deja existant
INSERT INTO clients (email, nom, prenom)
VALUES ('jean.dupont@email.com', 'Autre', 'Personne');
-- ERROR 1062: Duplicate entry 'jean.dupont@email.com' for key 'email'

-- Solution 1 : Utiliser INSERT IGNORE
INSERT IGNORE INTO clients (email, nom, prenom)
VALUES ('jean.dupont@email.com', 'Autre', 'Personne');

-- Solution 2 : Utiliser ON DUPLICATE KEY UPDATE
INSERT INTO clients (email, nom, prenom)
VALUES ('jean.dupont@email.com', 'Autre', 'Personne')
ON DUPLICATE KEY UPDATE
    nom = VALUES(nom),
    prenom = VALUES(prenom);

-- Solution 3 : Utiliser REPLACE (supprime puis insere)
REPLACE INTO clients (email, nom, prenom)
VALUES ('jean.dupont@email.com', 'Autre', 'Personne');

Exercices pratiques

Exercice 1 : Requetes SELECT

-- 1. Lister tous les produits de la categorie Electronique tries par prix decroissant

-- 2. Trouver les clients qui n'ont pas de numero de telephone

-- 3. Calculer le chiffre d'affaires total par mois

-- 4. Lister les 3 produits les plus vendus

Solutions

-- Solution 1
SELECT p.* FROM produits p
JOIN categories c ON p.categorie_id = c.id
WHERE c.nom = 'Electronique'
ORDER BY p.prix DESC;

-- Solution 2
SELECT * FROM clients WHERE telephone IS NULL;

-- Solution 3
SELECT
    DATE_FORMAT(created_at, '%Y-%m') AS mois,
    SUM(total) AS chiffre_affaires
FROM commandes
WHERE statut != 'annulee'
GROUP BY DATE_FORMAT(created_at, '%Y-%m')
ORDER BY mois;

-- Solution 4
SELECT
    p.nom,
    SUM(cp.quantite) AS total_vendu
FROM produits p
JOIN commande_produits cp ON p.id = cp.produit_id
GROUP BY p.id, p.nom
ORDER BY total_vendu DESC
LIMIT 3;

Exercice 2 : Operations de modification

-- 1. Inserer 3 nouveaux produits dans la categorie Sport

-- 2. Augmenter de 5% le prix des produits avec stock < 50

-- 3. Supprimer les clients sans commande

Solutions

-- Solution 1
INSERT INTO produits (categorie_id, nom, prix, stock) VALUES
(5, 'Ballon de football', 29.99, 100),
(5, 'Raquette de tennis', 89.99, 50),
(5, 'Gants de boxe', 49.99, 75);

-- Solution 2
UPDATE produits
SET prix = prix * 1.05
WHERE stock < 50;

-- Solution 3
DELETE FROM clients
WHERE id NOT IN (
    SELECT DISTINCT client_id FROM commandes
);

Conclusion

Vous maitrisez maintenant les quatre operations fondamentales de SQL :

  • SELECT : Interroger et analyser vos donnees avec filtres, tris et agregations
  • INSERT : Ajouter de nouvelles donnees de maniere efficace
  • UPDATE : Modifier des enregistrements existants en toute securite
  • DELETE : Supprimer des donnees avec precision
  • Points cles a retenir

  • Toujours utiliser WHERE avec UPDATE et DELETE
  • Tester avec SELECT avant de modifier ou supprimer
  • Utiliser les transactions pour les operations multiples
  • Optimiser les requetes en utilisant les index
  • Sauvegarder regulierement vos donnees
  • Prochaines etapes

    Dans les articles suivants, vous apprendrez :

  • Les jointures pour lier plusieurs tables
  • Les sous-requetes avancees
  • L'optimisation des performances avec les index
  • Les fonctions de fenetre et CTEs
  • La maitrise de ces fondamentaux vous permettra de construire des applications robustes et performantes. Pratiquez regulierement avec des donnees de test avant de travailler sur des bases de production.

    Une remarque, un retour ?

    Cet article est vivant - corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisissez celui qui vous convient.

    Laisser un commentaire