Atelier MySQL - déclencheurs (triggers)
et procédures stockées.
.


Précisions sur... Prise en charge des déclencheurs (triggers) sous MySQL.

Mysql prend gère les procédures stockées depuis la version 5.0 et les déclencheurs depuis la version 5.0.2. La documentation officielle est ici :


Rappels sur... Accéder à MySQL en commandes en ligne.

Pour faire les tests de cet atelier, vous utiliserez (au choix) PHPMyAdmin ou la ligne de commande MySQL. Pour accéder à la ligne de commande MySQL :

  • Ouvrez l'invite de commande (Démarrer Exécuter cmd)
  • Placez-vous sur le lecteur où MySQL est installé (par exemple : C:)
  • Placez-vous dans le répertoire bin de MySQL (par exemple : CD \mysql\bin)
  • Connectez-vous avec :
       mysql -uroot
       mysql -uroot -p (s'il faut saisir un mot de passe)
       mysql -uroot -p -hadresse-du-serveur-mySQL (si vous vous connectez depuis une autre machine que le serveur MySQL)

1
Les déclencheurs (en anglais : triggers).

Exemples d'utilisations des déclencheurs.
Création d'un déclencheur.
Notes d'après la doc officielle.

Note : actuellement, les déclencheurs ont les mêmes limitations que les procédures stockées : ils ne peuvent pas contenir de références directes aux tables via leur nom. Cette limitation sera levée dès que possible.

Cependant, dans la commande d'activation d'un déclencheur, vous pouvez faire référence aux colonnes dan la table associée au déclencheur en utilisant les mots OLD et NEW. OLD.col_name faire référence à une colonne d'une ligne existante avant sa modification ou son effacement. NEW.col_name faire référence à une colonne d'une ligne après insertion ou modification.

L'utilisation de SET NEW.col_name = value requiert le droit de UPDATE sur la colonne. L'utilisation de SET value = NEW.col_name requiert le droit de SELECT sur la colonne.

La commande CREATE TRIGGER requiert le droit de SUPER. Elle a été ajoutée en MySQL 5.0.2.

Exemple de trigger d'après la doc officielle.
Détruire un déclencheur.
D'autres précisions sur les déclencheurs.

2
Procédures stockée et fonctions.

Les procédures stockées sont des traitements pris en charge (développement et exécution) au niveau du serveur de données (par exemple MySQL), alors qu'ils sont traditionnellement au niveau du serveur de traitements (par exemple PHP).

Cas où les procédures stockées sont utiles.
Syntaxe des procédures stockées.
Exemple de fonction stockée : la recherche approximative.

3
Quelques trucs utiles.

4
Démonstrations.

Ceci a été testé en MySQL 5.1.30 et risque de ne pas marcher en 5.0 (interdit de faire un SELECT dans un trigger, interdit d'appeler une fonction à partir d'un trigger).

Cette démonstration utilise une table user avec un champ login, où la valeur NULL est interdite :

CREATE TABLE IF NOT EXISTS `user` (`login` varchar(255) NOT NULL);

___________________________________________________
Une simple fonction qui retourne une constante, elle reçoit un paramètre inutile

DROP FUNCTION IF EXISTS test;
CREATE FUNCTION test (i VARCHAR(255)) RETURNS VARCHAR(255) RETURN 'coucou';
SELECT test('abcd');

___________________________________________________
La même fonction mais dans un bloc BEGIN...END, nécessite DELIMITER

DROP FUNCTION IF EXISTS test;

DELIMITER //
CREATE FUNCTION test (i VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
RETURN 'coucou';
END//
DELIMITER ;

SELECT test('abcd');
_______________________________________________________
La même fonction renvoie le nombre de logins dans la table user

DELIMITER //

DROP FUNCTION IF EXISTS test //

CREATE FUNCTION test (i VARCHAR(255)) RETURNS INT
BEGIN
    SELECT count(*) FROM user INTO @result;
    RETURN @result;

END//
DELIMITER ;

SELECT test('abcd');
_______________________________________________________
La fonction login_existe renvoie 0 ou 1 si le login reçu en paramètre est déjà dans la table

DELIMITER //

DROP FUNCTION IF EXISTS login_existe //

CREATE FUNCTION login_existe (newlogin VARCHAR(255)) RETURNS INT
BEGIN
    SELECT count(*) FROM user WHERE login = newlogin INTO @result;
    RETURN @result;
END//
DELIMITER ;

SELECT login_existe('spastore');
_______________________________________________________
Le trigger qui annule l'insertion si le login est déjà dans la table user :

DELIMITER //

DROP TRIGGER IF EXISTS valide_insertion //

CREATE TRIGGER valide_insertion BEFORE INSERT ON user FOR EACH ROW
BEGIN
    IF login_existe(NEW.login) THEN
        SET NEW.login=NULL;
    END IF;

END //

DELIMITER ;

Remarque : qu'est-ce que c'est ce SET NEW.login=NULL qui fait salement planter la requête ? Sous MySQL, à l'heure actuelle (5.1.30), c'est la seule solution pour que le trigger annule l'insertion dans la table. Contrairement aux autres SGBD, il n'esiste pas de solution propre genre "ROLLBACK". Ceci est en préparation, un RETURN FALSE; devrait bientôt résoudre le problème.
_______________________________________________________
La même chose, en un seul trigger (sans passer par la fonction login_existe)

DELIMITER //

DROP TRIGGER IF EXISTS valide_insertion//

CREATE TRIGGER valide_insertion BEFORE INSERT ON user FOR EACH ROW
BEGIN
    SELECT count(*) FROM user WHERE login = NEW.login INTO @result;
    IF @result THEN
        SET NEW.login=NULL;
    END IF;
END //

DELIMITER ;


Sébastien PASTORE.