Recherche…


Paramètres

Paramètre Détails
RÉSULTATS Spécifie le type de données pouvant être renvoyé par une fonction.
REVENIR La variable ou la valeur réelle qui suit la syntaxe RETURN à la valeur renvoyée à partir de laquelle la fonction a été appelée.

Remarques

Une routine stockée est une procédure ou une fonction.

Une procédure est appelée à l'aide d'une instruction CALL et ne peut que renvoyer des valeurs à l'aide de variables de sortie.

Une fonction peut être appelée depuis une instruction comme toute autre fonction et peut renvoyer une valeur scalaire.

Créer une fonction

La fonction exemple (triviale) suivante renvoie simplement la valeur INT constante 12 .

DELIMITER ||
CREATE FUNCTION functionname()
RETURNS INT
BEGIN
    RETURN 12;
END;
||
DELIMITER ;

La première ligne définit ce que le caractère de délimiteur ( DELIMITER || ) doit être changé, il faut le définir avant de créer une fonction, sinon si elle est laissée à sa valeur par défaut ; puis le premier ; ce qui se trouve dans le corps de la fonction sera considéré comme la fin de l'instruction CREATE , ce qui n'est généralement pas ce que l'on souhaite.

Après l'exécution de CREATE FUNCTION , vous devez redéfinir le délimiteur sur sa valeur par défaut ; comme on le voit après le code de fonction dans l'exemple ci-dessus ( DELIMITER ; ).

Exécution cette fonction est la suivante:

SELECT functionname();
+----------------+
| functionname() |
+----------------+
|             12 |
+----------------+

Un exemple légèrement plus complexe (mais néanmoins trivial) prend un paramètre et lui ajoute une constante:

DELIMITER $$
CREATE FUNCTION add_2 ( my_arg INT )
  RETURNS INT
BEGIN
  RETURN (my_arg + 2);
END;
$$
DELIMITER ;

SELECT add_2(12);
+-----------+
| add_2(12) |
+-----------+
|        14 |
+-----------+

Notez l'utilisation d'un argument différent pour la directive DELIMITER . Vous pouvez réellement utiliser n'importe quelle séquence de caractères n'apparaissant pas dans le corps de l'instruction CREATE , mais la pratique habituelle consiste à utiliser un caractère non alphanumérique doublé tel que \\ , || ou $$ .

Il est recommandé de toujours modifier le paramètre avant et après une fonction, une procédure ou une création ou une mise à jour de déclencheur car certaines interfaces graphiques ne nécessitent pas de modification du délimiteur alors que l'exécution de requêtes via la ligne de commande nécessite toujours la définition du délimiteur.

Créer une procédure avec une préparation construite

DROP PROCEDURE if exists displayNext100WithName;
DELIMITER $$
CREATE PROCEDURE displayNext100WithName
(    nStart int,
    tblName varchar(100)
)
BEGIN
    DECLARE thesql varchar(500); -- holds the constructed sql string to execute

    -- expands the sizing of the output buffer to accomodate the output (Max value is at least 4GB)
    SET session group_concat_max_len = 4096; -- prevents group_concat from barfing with error 1160 or whatever it is

    SET @thesql=CONCAT("select group_concat(qid order by qid SEPARATOR '%3B') as nums ","from (    select qid from ");
    SET @thesql=CONCAT(@thesql,tblName," where qid>? order by qid limit 100 )xDerived");
    PREPARE stmt1 FROM @thesql; -- create a statement object from the construct sql string to execute
    SET @p1 = nStart; -- transfers parameter passed into a User Variable compatible with the below EXECUTE
    EXECUTE stmt1 USING @p1;
     
    DEALLOCATE PREPARE stmt1; -- deallocate the statement object when finished
END$$
DELIMITER ;

La création de la procédure stockée montre l'encapsulation avec un DELIMITER nécessaire dans de nombreux outils clients.

Exemple d'appel:

call displayNext100WithName(1,"questions_mysql");

Exemple de sortie avec le séparateur %3B (point-virgule): entrer la description de l'image ici

Procédure stockée avec les paramètres IN, OUT, INOUT

DELIMITER $$
 
DROP PROCEDURE IF EXISTS sp_nested_loop$$
CREATE PROCEDURE sp_nested_loop(IN i INT, IN j INT, OUT x INT, OUT y INT, INOUT z INT)
BEGIN
    DECLARE a INTEGER DEFAULT 0;
    DECLARE b INTEGER DEFAULT 0;
    DECLARE c INTEGER DEFAULT 0;
    WHILE a < i DO
        WHILE b < j DO
            SET c = c + 1;
            SET b = b + 1;
        END WHILE;    
        SET a = a + 1;
        SET b = 0;        
    END WHILE;
    SET x = a, y = c;
    SET z = x + y + z;
END $$
DELIMITER ;

Invoque ( CALL ) la procédure stockée:

SET @z = 30;
call sp_nested_loop(10, 20, @x, @y, @z);
SELECT @x, @y, @z;

Résultat:

+------+------+------+
|  @x  |  @y  |  @z  |
+------+------+------+
|  10  |  200 |  240 |
+------+------+------+

Un paramètre IN transmet une valeur à une procédure. La procédure peut modifier la valeur, mais la modification n'est pas visible pour l'appelant au retour de la procédure.

Un paramètre OUT renvoie une valeur de la procédure à l'appelant. Sa valeur initiale est NULL dans la procédure et sa valeur est visible pour l'appelant lors du retour de la procédure.

Un paramètre INOUT est initialisé par l'appelant, peut être modifié par la procédure et toute modification apportée par la procédure est visible par l'appelant au retour de la procédure.

Réf: http://dev.mysql.com/doc/refman/5.7/fr/create-procedure.html

Des curseurs

Les curseurs vous permettent d'itérer les résultats de la requête une par une. DECLARE commande DECLARE est utilisée pour initialiser le curseur et l'associer à une requête SQL spécifique:

DECLARE student CURSOR FOR SELECT name FROM studend;

Disons que nous vendons des produits de certains types. Nous voulons compter le nombre de produits de chaque type.

Nos données:

CREATE TABLE product
(
  id   INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  type VARCHAR(50)      NOT NULL,
  name VARCHAR(255)     NOT NULL

);
CREATE TABLE product_type
(
  name VARCHAR(50) NOT NULL PRIMARY KEY
);
CREATE TABLE product_type_count
(
  type  VARCHAR(50)      NOT NULL PRIMARY KEY,
  count INT(10) UNSIGNED NOT NULL DEFAULT 0
);

INSERT INTO product_type (name) VALUES
  ('dress'),
  ('food');

INSERT INTO product (type, name) VALUES
  ('dress', 'T-shirt'),
  ('dress', 'Trousers'),
  ('food', 'Apple'),
  ('food', 'Tomatoes'),
  ('food', 'Meat');

Nous pouvons atteindre l'objectif en utilisant la procédure stockée à l'aide du curseur:

DELIMITER //
DROP PROCEDURE IF EXISTS product_count;
CREATE PROCEDURE product_count()
  BEGIN
    DECLARE p_type VARCHAR(255);
    DECLARE p_count INT(10) UNSIGNED;
    DECLARE done INT DEFAULT 0;
    DECLARE product CURSOR FOR
      SELECT
        type,
        COUNT(*)
      FROM product
      GROUP BY type;
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

    TRUNCATE product_type;

    OPEN product;
    
    REPEAT
      FETCH product
      INTO p_type, p_count;
      IF NOT done
      THEN
        INSERT INTO product_type_count
        SET
          type  = p_type,
          count = p_count;
      END IF;
    UNTIL done
    END REPEAT;
    
    CLOSE product;
  END //
DELIMITER ;

Quand vous pouvez appeler la procédure avec:

CALL product_count();

Le résultat serait dans la table product_type_count :

type   | count
----------------
dress  |   2
food   |   3

Bien que ce soit un bon exemple de CURSOR , notez comment le corps entier de la procédure peut être remplacé par un simple

INSERT INTO product_type_count
        (type, count)
    SELECT type, COUNT(*)
        FROM product
        GROUP BY type;

Cela va courir beaucoup plus vite.

Plusieurs ResultSets

Contrairement à une SELECT , une Stored Procedure renvoie plusieurs jeux de résultats. Le code différent requis pour être utilisé pour rassembler les résultats d'un CALL en Perl, PHP, etc.

(Besoin d'un code spécifique ici ou ailleurs!)

Créer une fonction

DELIMITER $$
CREATE
    DEFINER=`db_username`@`hostname_or_IP`
    FUNCTION `function_name`(optional_param data_type(length_if_applicable))
    RETURNS data_type
BEGIN
    /*
    SQL Statements goes here
    */
END$$
DELIMITER ;

Le type de données RETURNS est tout type de données MySQL.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow