Buscar..


Parámetros

Parámetro Detalles
DEVOLUCIONES Especifica el tipo de datos que se pueden devolver desde una función.
REGRESO La variable real o el valor que sigue a la sintaxis de RETURN es lo que se devuelve a donde se llamó la función.

Observaciones

Una rutina almacenada es un procedimiento o una función.

Se invoca un procedimiento utilizando una instrucción CALL y solo puede devolver valores utilizando variables de salida.

Se puede llamar a una función desde dentro de una declaración como cualquier otra función y puede devolver un valor escalar.

Crear una función

La siguiente función de ejemplo (trivial) simplemente devuelve el valor constante de INT 12 .

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

La primera línea define a qué se DELIMITER || carácter delimitador ( DELIMITER || ), esto se debe configurar antes de que se cree una función, de lo contrario, si se deja en su valor predeterminado ; entonces el primero ; que se encuentra en el cuerpo de la función se tomará como el final de la CREATE , que generalmente no es lo que se desea.

Una vez que se haya ejecutado CREATE FUNCTION , debe configurar el delimitador a su valor predeterminado de ; como se ve después del código de función en el ejemplo anterior ( DELIMITER ; ).

La ejecución de esta función es la siguiente:

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

Un ejemplo ligeramente más complejo (pero aún trivial) toma un parámetro y le agrega una 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 |
+-----------+

Tenga en cuenta el uso de un argumento diferente a la directiva DELIMITER . En realidad, puede usar cualquier secuencia de caracteres que no aparezca en el cuerpo de la sentencia CREATE , pero la práctica habitual es usar un carácter no alfanumérico duplicado, como \\ , || o $$ .

Es una buena práctica cambiar siempre el parámetro antes y después de la creación, actualización o activación de una función, procedimiento o disparador, ya que algunas GUI no requieren que el delimitador cambie, mientras que las consultas en ejecución a través de la línea de comandos siempre requieren que se establezca el delimitador.

Crear procedimiento con una preparación construida

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 creación del procedimiento almacenado muestra el ajuste con un DELIMITER necesario en muchas herramientas del cliente.

Ejemplo de llamada:

call displayNext100WithName(1,"questions_mysql");

Salida de muestra con separador %3B (punto y coma): introduzca la descripción de la imagen aquí

Procedimiento almacenado con parámetros 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 ;

Invoca ( LLAMAR ) el procedimiento almacenado:

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

Resultado:

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

Un parámetro IN pasa un valor a un procedimiento. El procedimiento puede modificar el valor, pero la modificación no es visible para la persona que llama cuando el procedimiento vuelve.

Un parámetro OUT pasa un valor del procedimiento a la persona que llama. Su valor inicial es NULL dentro del procedimiento, y su valor es visible para la persona que llama cuando el procedimiento vuelve.

Un parámetro INOUT es inicializado por la persona que llama, puede ser modificado por el procedimiento, y cualquier cambio realizado por el procedimiento es visible para la persona que llama cuando el procedimiento regresa.

Ref: http://dev.mysql.com/doc/refman/5.7/en/create-procedure.html

Cursores

Los cursores le permiten iterar los resultados de la consulta uno por línea. DECLARE comando DECLARE se usa para iniciar el cursor y asociarlo con una consulta SQL específica:

DECLARE student CURSOR FOR SELECT name FROM studend;

Digamos que vendemos productos de algunos tipos. Queremos contar cuántos productos de cada tipo existen.

Nuestros datos:

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');

Podemos lograr el objetivo usando el procedimiento almacenado usando el cursor:

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 ;

Cuando puede llamar al procedimiento con:

CALL product_count();

El resultado estaría en la tabla product_type_count :

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

Si bien ese es un buen ejemplo de un CURSOR , observe cómo todo el cuerpo del procedimiento puede ser reemplazado por solo

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

Esto se ejecutará mucho más rápido.

Conjuntos de resultados múltiples

A diferencia de una instrucción SELECT , un Stored Procedure devuelve varios conjuntos de resultados. El código requiere que se use un código diferente para recopilar los resultados de una CALL en Perl, PHP, etc.

(¡Necesitas un código específico aquí o en otra parte!)

Crear una función

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 ;

El RETURNS data_type es cualquier tipo de datos MySQL.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow