Debutant 15 min de lecture · 3 262 mots

SQL pour debutants : SELECT, INSERT, UPDATE, DELETE

Estimated reading time: 16 minutes

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 boutiquedemo
CHARACTER SET utf8mb4
COLLATE utf8mb4unicodeci;

USE boutiquedemo;

-- Table des categories
CREATE TABLE categories (
    id INT UNSIGNED AUTOINCREMENT PRIMARY KEY,
    nom VARCHAR(100) NOT NULL,
    description TEXT,
    createdat TIMESTAMP DEFAULT CURRENTTIMESTAMP,
    INDEX idxnom (nom)
) ENGINE=InnoDB;

-- Table des produits
CREATE TABLE produits (
    id INT UNSIGNED AUTOINCREMENT PRIMARY KEY,
    categorieid 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,
    createdat TIMESTAMP DEFAULT CURRENTTIMESTAMP,
    updatedat TIMESTAMP DEFAULT CURRENTTIMESTAMP ON UPDATE CURRENTTIMESTAMP,
    FOREIGN KEY (categorieid) REFERENCES categories(id) ON DELETE SET NULL,
    INDEX idxcategorie (categorieid),
    INDEX idxprix (prix),
    INDEX idxactif (actif)
) ENGINE=InnoDB;

-- Table des clients
CREATE TABLE clients (
    id INT UNSIGNED AUTOINCREMENT 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),
    codepostal VARCHAR(10),
    createdat TIMESTAMP DEFAULT CURRENTTIMESTAMP,
    INDEX idxemail (email),
    INDEX idxville (ville)
) ENGINE=InnoDB;

-- Table des commandes
CREATE TABLE commandes (
    id INT UNSIGNED AUTOINCREMENT PRIMARY KEY,
    clientid INT UNSIGNED NOT NULL,
    numerocommande VARCHAR(50) NOT NULL UNIQUE,
    total DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
    statut ENUM('enattente', 'confirmee', 'expediee', 'livree', 'annulee') DEFAULT 'enattente',
    createdat TIMESTAMP DEFAULT CURRENTTIMESTAMP,
    updatedat TIMESTAMP DEFAULT CURRENTTIMESTAMP ON UPDATE CURRENTTIMESTAMP,
    FOREIGN KEY (clientid) REFERENCES clients(id) ON DELETE RESTRICT,
    INDEX idxclient (clientid),
    INDEX idxstatut (statut),
    INDEX idxdate (createdat)
) ENGINE=InnoDB;

-- Table de liaison commandes-produits
CREATE TABLE commandeproduits (
    id INT UNSIGNED AUTOINCREMENT PRIMARY KEY,
    commandeid INT UNSIGNED NOT NULL,
    produitid INT UNSIGNED NOT NULL,
    quantite INT UNSIGNED NOT NULL DEFAULT 1,
    prixunitaire DECIMAL(10, 2) NOT NULL,
    FOREIGN KEY (commandeid) REFERENCES commandes(id) ON DELETE CASCADE,
    FOREIGN KEY (produitid) REFERENCES produits(id) ON DELETE RESTRICT,
    UNIQUE KEY uniquecommandeproduit (commandeid, produitid)
) 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 (categorieid, 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, codepostal) 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 (clientid, numerocommande, 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, 'enattente'),
(4, 'CMD-2024-0005', 79.89, 'livree');

-- Produits des commandes
INSERT INTO commandeproduits (commandeid, produitid, quantite, prixunitaire) 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 nomproduit,
    prix AS prixttc,
    stock AS quantitedisponible
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 prixavectva,
    stock,
    prix  stock AS valeurstock
FROM produits;

Filtrer avec WHERE

La clause WHERE permet de filtrer les resultats :

-- Filtrer par valeur exacte
SELECT  FROM produits WHERE categorieid = 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 ('enattente', '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 categorieid = 1
OR categorieid = 2;

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

-- Exemple complexe : produits electroniques chers ou tous les livres
SELECT  FROM produits
WHERE (categorieid = 1 AND prix > 500)
OR categorieid = 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, categorieid, prix FROM produits
ORDER BY categorieid 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 nombreproduits FROM produits;

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

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

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

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

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

Grouper avec GROUP BY

-- Nombre de produits par categorie
SELECT
    categorieid,
    COUNT() AS nombreproduits
FROM produits
GROUP BY categorieid;

-- Prix moyen par categorie
SELECT
    categorieid,
    COUNT() AS nombreproduits,
    AVG(prix) AS prixmoyen,
    MIN(prix) AS prixmin,
    MAX(prix) AS prixmax
FROM produits
GROUP BY categorieid;

-- Filtrer les groupes avec HAVING
SELECT
    categorieid,
    COUNT() AS nombreproduits,
    AVG(prix) AS prixmoyen
FROM produits
GROUP BY categorieid
HAVING COUNT() >= 2;

-- Nombre de commandes par statut
SELECT
    statut,
    COUNT() AS nombrecommandes,
    SUM(total) AS montanttotal
FROM commandes
GROUP BY statut
ORDER BY nombrecommandes 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, codepostal)
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 (categorieid, 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 produitsarchive LIKE produits;

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

-- Inserer avec transformation
INSERT INTO rapportventes (produitid, totalvendu, daterapport)
SELECT
    produitid,
    SUM(quantite  prixunitaire),
    CURRENTDATE
FROM commandeproduits
GROUP BY produitid;

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 LASTINSERTID() AS nouvelid;

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,
    updatedat = CURRENTTIMESTAMP
WHERE id = 2;

-- Augmenter tous les prix de 10%
UPDATE produits
SET prix = prix  1.10
WHERE categorieid = 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 produitid FROM commandeproduits
    GROUP BY produitid
    HAVING SUM(quantite) < 5
);

-- Modifier le statut d'une commande
UPDATE commandes
SET
    statut = 'expediee',
    updatedat = CURRENTTIMESTAMP
WHERE numerocommande = '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 categorieid = 1 AND prix > 500;

-- Etape 2 : Si le resultat est correct, executer UPDATE
UPDATE produits
SET prix = prix  0.95
WHERE categorieid = 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 createdat < DATESUB(CURRENTDATE, INTERVAL 30 DAY);

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

DELETE avec LIMIT (MySQL)

-- Supprimer seulement les 100 premieres lignes
DELETE FROM logsarchive
WHERE createdat < '2023-01-01'
ORDER BY createdat 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 lignesasupprimer
FROM commandes
WHERE statut = 'annulee'
AND createdat < DATESUB(CURRENTDATE, INTERVAL 30 DAY);

-- Etape 2 : Voir les donnees concernees
SELECT  FROM commandes
WHERE statut = 'annulee'
AND createdat < DATESUB(CURRENTDATE, INTERVAL 30 DAY);

-- Etape 3 : Executer la suppression si correct
DELETE FROM commandes
WHERE statut = 'annulee'
AND createdat < DATESUB(CURRENTDATE, 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 clientid = 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 createdat < '2020-01-01';

-- BON : DELETE par lots pour eviter les locks prolonges
DELETE FROM logs
WHERE createdat < '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 (clientid, numerocommande, total, statut)
VALUES (1, 'CMD-2024-0006', 149.98, 'enattente');

-- Recuperer l'ID de la commande
SET @commandeid = LASTINSERTID();

-- Ajouter les produits a la commande
INSERT INTO commandeproduits (commandeid, produitid, quantite, prixunitaire)
VALUES
(@commandeid, 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 @@transactionisolation;

-- 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 boutiquedemo > boutiquebackup.sql

# Sauvegarder avec structure seulement
mysqldump -u root -p --no-data boutiquedemo > boutiquestructure.sql

# Sauvegarder certaines tables
mysqldump -u root -p boutiquedemo produits clients > tablesbackup.sql

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

Restauration

# Restaurer une base
mysql -u root -p boutiquedemo < boutiquebackup.sql

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

Export SELECT vers fichier

-- Exporter le resultat d'une requete en CSV
SELECT nom, prix, stock
INTO OUTFILE '/tmp/produitsexport.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 SQLSAFEUPDATES = 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 categorieid = 1;
DELETE FROM categories WHERE id = 1;

-- Solution 2 : Mettre a jour les produits
UPDATE produits SET categorieid = NULL WHERE categorieid = 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.categorieid = c.id
WHERE c.nom = 'Electronique'
ORDER BY p.prix DESC;

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

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

-- Solution 4
SELECT
    p.nom,
    SUM(cp.quantite) AS totalvendu
FROM produits p
JOIN commandeproduits cp ON p.id = cp.produitid
GROUP BY p.id, p.nom
ORDER BY totalvendu 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 (categorieid, 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 clientid 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.