Crie um segundo procedimento que use dois cursores aninhados.
Os cursores nos procedimentos armazenados permitem que você faça algo não muito semelhante ao SQL: itere através de um conjunto de resultados uma linha por vez, colocando os valores da coluna selecionada em variáveis e fazendo coisas com eles.
Eles são facilmente mal utilizados, já que o SQL, sendo declarativo e não processual, geralmente não deve precisar "para cada" operações do tipo, mas nesse caso, parece um aplicativo válido.
Quando você pega o jeito, os cursores são fáceis, mas exigem uma abordagem estruturada no código de suporte que nem sempre é intuitiva.
Recentemente, forneci algum código "padrão padrão" para trabalhar com um cursor para chamar um procedimento armazenado em uma resposta no Stack Overflow , e emprestarei muito fortemente dessa resposta, abaixo.
O uso de um cursor requer algum código padrão para cercá-lo.
Você tem SELECT
os valores que deseja transmitir, de onde quer que os esteja adquirindo (que pode ser uma tabela temporária, tabela base ou exibição e pode incluir chamadas para funções armazenadas) e, em seguida, chame seu procedimento existente com esses valores.
Aqui está um exemplo sintaticamente válido do código necessário, com comentários para explicar o que cada componente está fazendo.
Este exemplo usa 2 colunas para passar 2 valores para o procedimento chamado.
Observe que existem eventos que acontecem aqui em uma ordem específica por um motivo. As variáveis precisam ser declaradas primeiro, os cursores devem ser declarados antes dos manipuladores de continuar e os loops precisam seguir todas essas coisas.
Você não pode fazer coisas fora de ordem; portanto, quando aninha um cursor dentro de outro, é necessário redefinir o escopo do procedimento, aninhando código adicional dentro de BEGIN
... END
blocos dentro do corpo do procedimento; por exemplo, se você precisasse de um segundo cursor dentro do loop, basta declará-lo dentro do loop, dentro de outro bloco BEGIN
...END
DELIMITER $$
DROP PROCEDURE IF EXISTS `my_proc` $$
CREATE PROCEDURE `my_proc`(arg1 INT) -- 1 input argument; you might need more or fewer
BEGIN
-- 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
-- the cursor is implicitly closed when it goes out of scope, or can be explicitly closed if desired
CLOSE cursor1;
END $$
DELIMITER ;