Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 1610 minAvancé

Aide-mémoire : syntaxe et erreurs fréquentes

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • retrouver vite la syntaxe de chaque programme stocké ;
  • comprendre les messages d'erreur fréquents ;
  • vérifier ta copie avec une liste de contrôle.

Cet aide-mémoire rassemble la syntaxe MySQL 8.4 des procédures stockées, fonctions, curseurs, gestionnaires d'erreurs, triggers et événements, les codes d'erreur que tu rencontreras le plus souvent, et une liste de contrôle à relire avant de rendre une copie ou de déployer une routine. Chaque bloc renvoie au chapitre qui l'explique.

Procédure

sql
DELIMITER //
CREATE PROCEDURE nom_procedure(IN p_entree INT, OUT p_sortie INT, INOUT p_les_deux INT)
[SQL SECURITY { DEFINER | INVOKER }] [COMMENT '…']
BEGIN
  DECLARE v_variable INT DEFAULT 0;      -- variables et conditions d'abord
  -- curseurs ensuite, gestionnaires enfin
  SELECT COUNT(*) INTO p_sortie FROM … WHERE … = p_entree;
END //
DELIMITER ;

CALL nom_procedure(1, @sortie, @les_deux);
SELECT @sortie;
DROP PROCEDURE IF EXISTS nom_procedure;

Chapitres 2 et 3.

Fonction

sql
DELIMITER //
CREATE FUNCTION nom_fonction(p_valeur INT) RETURNS INT
DETERMINISTIC NO SQL            -- ou NOT DETERMINISTIC READS SQL DATA
BEGIN
  RETURN p_valeur * 2;
END //
DELIMITER ;

SELECT nom_fonction(colonne) FROM ma_table;

Une fonction : une seule valeur, ni transaction, ni jeu de résultats, ni SQL dynamique (chapitre 4).

Conditions et boucles

sql
IF condition THEN … ELSEIF condition THEN … ELSE … END IF;

CASE variable WHEN valeur THEN … ELSE … END CASE;

WHILE condition DO … END WHILE;

REPEAT … UNTIL condition END REPEAT;          -- au moins un tour

etiquette: LOOP
  IF fin THEN LEAVE etiquette; END IF;        -- break
  IF sauter THEN ITERATE etiquette; END IF;   -- continue
END LOOP etiquette;

Curseur

sql
DECLARE v_id INT;
DECLARE v_fini BOOLEAN DEFAULT FALSE;
DECLARE c CURSOR FOR SELECT id_poste FROM poste;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_fini = TRUE;

OPEN c;
lecture: LOOP
  FETCH c INTO v_id;
  IF v_fini THEN LEAVE lecture; END IF;
  -- traitement
END LOOP lecture;
CLOSE c;

Ordre des DECLARE : variables, curseurs, gestionnaires (chapitre 5).

Gestion des erreurs

sql
DECLARE nom_condition CONDITION FOR 1062;
DECLARE CONTINUE HANDLER FOR 1062 SET v_doublon = TRUE;     -- reprend après l'instruction
DECLARE EXIT HANDLER FOR SQLEXCEPTION                       -- quitte le bloc
BEGIN
  GET DIAGNOSTICS CONDITION 1 v_num = MYSQL_ERRNO, v_msg = MESSAGE_TEXT;
  ROLLBACK;
  RESIGNAL;                                                 -- relance l'erreur d'origine
END;

SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Message de 128 caractères au plus';

Priorité : numéro MySQL, puis SQLSTATE, puis SQLEXCEPTION, SQLWARNING, NOT FOUND (chapitre 6).

Procédure transactionnelle

sql
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    ROLLBACK;
    RESIGNAL;
  END;

  START TRANSACTION;
  SELECT … FOR UPDATE;          -- verrouiller ce qu'on va décider
  -- contrôles avec SIGNAL
  -- modifications
  COMMIT;
END

Une procédure qui ouvre une transaction ne s'appelle pas au milieu d'une autre (chapitre 7).

Trigger

sql
DELIMITER //
CREATE TRIGGER trg_table_role
{ BEFORE | AFTER } { INSERT | UPDATE | DELETE } ON nom_table
FOR EACH ROW
[ { FOLLOWS | PRECEDES } autre_trigger ]
BEGIN
  -- INSERT : NEW ; UPDATE : OLD et NEW ; DELETE : OLD
  -- BEFORE : SET NEW.colonne = … ou SIGNAL ; AFTER : écrire dans une autre table
END //
DELIMITER ;

SHOW TRIGGERS FROM parc;
DROP TRIGGER IF EXISTS trg_table_role;

Chapitres 8 et 9.

Événement

sql
CREATE EVENT ev_nom
  ON SCHEDULE EVERY 1 DAY STARTS '2026-11-09 03:00:00'    -- ou AT '2026-12-01 01:00:00'
  DO DELETE FROM audit_ticket WHERE modifie_le < NOW() - INTERVAL 1 YEAR;

SHOW VARIABLES LIKE 'event_scheduler';                    -- ON (MySQL), OFF par défaut (MariaDB)
ALTER EVENT ev_nom DISABLE;
DROP EVENT IF EXISTS ev_nom;

Chapitre 10.

Sécurité et SQL dynamique

sql
CREATE DEFINER = 'routines_parc'@'localhost' PROCEDURE … SQL SECURITY DEFINER …
GRANT EXECUTE ON PROCEDURE parc.cloturer_ticket TO 'helpdesk'@'192.168.21.20';

SET @valeur = p_valeur;                                        -- USING : variables de session
SET @sql = CONCAT('SELECT … WHERE colonne = ? ORDER BY ', v_colonne_liste_blanche);
PREPARE stmt FROM @sql;
EXECUTE stmt USING @valeur;
DEALLOCATE PREPARE stmt;

Chapitre 11.

Les erreurs fréquentes

CodeMessage (début)Cause habituelle
1064You have an error in your SQL syntaxDELIMITER oublié, DECLARE mal placé, mot réservé
1172Result consisted of more than one rowSELECT … INTO qui renvoie plusieurs lignes
1305PROCEDURE … does not existMauvaise base courante, ou routine perdue à la restauration
1321FUNCTION … ended without RETURNUn chemin de la fonction sans RETURN
1329No data - zero rows fetchedFETCH sans gestionnaire NOT FOUND, SELECT … INTO sans ligne (avertissement)
1337, 1338… declaration after cursor or handler declarationOrdre des DECLARE
1339Case not found for CASE statementInstruction CASE sans ELSE
1362Updating of NEW row is not allowed in after triggerSET NEW.… dans un trigger AFTER
1363There is no OLD row in on INSERT triggerOLD dans un INSERT, NEW dans un DELETE
1370execute command denied to user …Droit EXECUTE manquant, à l'appelant ou au propriétaire
1415Not allowed to return a result set from a functionSELECT sans INTO dans une fonction
1418This function has none of DETERMINISTIC, NO SQL, or READS SQL DATACaractéristique manquante, journal binaire actif
1422Explicit or implicit commit is not allowed in stored function or triggerCOMMIT ou LDD dans une fonction ou un trigger
1442Can't update table '…' in stored function/triggerLe trigger modifie sa propre table
1449The user specified as a definer ('…') does not existObjet orphelin
1568Transaction characteristics can't be changed while a transaction is in progressSET TRANSACTION dans une transaction ouverte
1644Ton messageSIGNAL SQLSTATE '45000' : une erreur métier
1648Data too long for condition item 'MESSAGE_TEXT'Message de plus de 128 caractères

La liste de contrôle

Avant de rendre une copie ou de déployer une routine, vérifie :

  1. DELIMITER // avant, END // à la fin, DELIMITER ; après (dans le client mysql).
  2. Les paramètres ont le bon mode (IN, OUT, INOUT) et un préfixe qui les distingue des colonnes (p_).
  3. Les DECLARE sont au début du bloc, dans l'ordre : variables, curseurs, gestionnaires.
  4. Chaque IF a son END IF;, chaque boucle son END …, chaque CASE son ELSE.
  5. Un trigger a FOR EACH ROW, utilise NEW et OLD selon l'événement, ne modifie NEW qu'en BEFORE et ne touche pas à sa propre table.
  6. Les comparaisons avec une valeur qui peut être NULL utilisent IS NULL ou <=>.
  7. Une procédure qui modifie plusieurs tables a sa transaction, un gestionnaire ROLLBACK + RESIGNAL, et un COMMIT.
  8. Une fonction déclare DETERMINISTIC, NO SQL ou READS SQL DATA, et renvoie une valeur sur chaque chemin.
  9. Les messages de SIGNAL sont compréhensibles par un utilisateur et font moins de 128 caractères.
  10. Aucun paramètre n'est collé dans une requête dynamique ; le propriétaire et les droits EXECUTE sont les bons ; le script de test et le script d'annulation existent.

Chapitre terminé !

Tu as lu ce chapitre jusqu'au bout. Passe au suivant tant que c'est frais.

chapitres
–
de série
–
du cours
–
Cours suivant : UMLRevoir le sommaire du cours