Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Chame um procedimento armazenado da instrução DECLARE ao usar cursores no MySQL


Usar um cursor requer algum código clichê padrão para cercá-lo.

Usar um cursor para chamar um procedimento armazenado para cada conjunto de valores da tabela requer essencialmente o mesmo clichê. Você SELECT os valores que você deseja passar, de onde quer que você os obtenha (que pode ser uma tabela temporária, tabela base ou exibição, e pode incluir chamadas para funções armazenadas) e, em seguida, chame o procedimento com esses valores.

Eu escrevi um exemplo sintaticamente válido desse código clichê, abaixo, com comentários para explicar o que cada componente está fazendo. Há poucas coisas que eu não gosto mais do que ser solicitado a fazer algo "só porque" - então tudo é (espero) explicado.

Você mencionou chamar o procedimento com vários valores, então este exemplo usa 2.

Observe que os eventos que acontecem com ela estão em uma ordem específica por um motivo. As variáveis ​​devem ser declaradas primeiro, os cursores devem ser declarados antes de seus manipuladores continue e os loops devem seguir todas essas coisas. Isso dá a impressão de que há uma inflexibilidade bastante extrema aqui, mas esse não é realmente o caso. Você pode redefinir a ordenação aninhando código adicional dentro de BEGIN ... END bloqueios dentro do corpo do procedimento; por exemplo, se você precisasse de um segundo cursor dentro do loop, bastaria declará-lo dentro do loop, dentro de outro BEGIN ... END .
DELIMITER $$

DROP PROCEDURE IF EXISTS `my_proc` $$
CREATE PROCEDURE `my_proc`(arg1 INT) -- 1 input argument; you might not need one
BEGIN

-- from http://stackoverflow.com/questions/35858541/call-a-stored-procedure-from-the-declare-statement-when-using-cursors-in-mysql

-- declare the program variables where we'll hold the values we're sending into the procedure;
-- declare as many of them as there are input arguments to the second procedure,
-- with appropriate data types.

DECLARE val1 INT DEFAULT NULL;
DECLARE val2 INT DEFAULT NULL;

-- we need a boolean variable to tell us when the cursor is out of data

DECLARE done TINYINT DEFAULT FALSE;

-- declare a cursor to select the desired columns from the desired source table1
-- the input argument (which you might or might not need) is used in this example for row selection

DECLARE cursor1 -- cursor1 is an arbitrary label, an identifier for the cursor
 CURSOR FOR
 SELECT t1.c1, 
        t1.c2
   FROM table1 t1
  WHERE c3 = arg1; 

-- this fancy spacing is of course not required; all of this could go on the same line.

-- a cursor that runs out of data throws an exception; we need to catch this.
-- when the NOT FOUND condition fires, "done" -- which defaults to FALSE -- will be set to true,
-- and since this is a CONTINUE handler, execution continues with the next statement.   

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

-- open the cursor

OPEN cursor1;

my_loop: -- loops have to have an arbitrary label; it's used to leave the loop
LOOP

  -- read the values from the next row that is available in the cursor

  FETCH NEXT FROM cursor1 INTO val1, val2;

  IF done THEN -- this will be true when we are out of rows to read, so we go to the statement after END LOOP.
    LEAVE my_loop; 
  ELSE -- val1 and val2 will be the next values from c1 and c2 in table t1, 
       -- so now we call the procedure with them for this "row"
    CALL the_other_procedure(val1,val2);
    -- maybe do more stuff here
  END IF;
END LOOP;

-- execution continues here when LEAVE my_loop is encountered;
-- you might have more things you want to do here

END $$

DELIMITER ;