Несколько курсоров в вложенных циклах в MySQL
Я хочу сделать что-то, что кажется немного сложным в MySQL.
На самом деле, я хочу открыть курсор, сделать цикл и в этом цикле открыть второй курсор, используя данные из предыдущей выборки, которые будут выполнены, и повторно зациклировать результаты.
DECLARE idind INT;
DECLARE idcrit INT;
DECLARE idindid INT;
DECLARE done INT DEFAULT 0;
DECLARE done2 INT DEFAULT 0;
DECLARE curIndicateur CURSOR FOR SELECT id_indicateur FROM indicateur;
DECLARE curCritereIndicateur CURSOR FOR SELECT C.id_critere FROM critere C where C.id_indicateur=idind;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
set idindid=54;
OPEN curIndicateur;
REPEAT
FETCH curIndicateur INTO idind;
open curCritereIndicateur;
REPEAT
FETCH curIndicateur INTO idcrit;
INSERT INTO SLA_DEMANDE_STATUS (iddemande,idindicateur,indicateur_status,progression) values('0009',idcrit,'OK',10.0);
UNTIL done END REPEAT;
close curCritereIndicateur;
UNTIL done END REPEAT;
CLOSE curIndicateur;
На самом деле, как сделать "Пока не сделано" по-разному для двух курсоров, потому что вы можете объявить только один обработчик для SQLSTATE?
Если первый конец, второй конец тоже.
Ответы
Ответ 1
Вам нужно определить новый BLOCK внутри вашего 1-го курсорного цикла и использовать в объявлении разные объявления.
Что-то вроде:
BLOCK1: begin
declare v_col1 int;
declare no_more_rows boolean1 := FALSE;
declare cursor1 cursor for
select col1
from MyTable;
declare continue handler for not found
set no_more_rows1 := TRUE;
open cursor1;
LOOP1: loop
fetch cursor1
into v_col1;
if no_more_rows1 then
close cursor1;
leave LOOP1;
end if;
BLOCK2: begin
declare v_col2 int;
declare no_more_rows2 boolean := FALSE;
declare cursor2 cursor for
select col2
from MyOtherTable
where ref_id = v_col1;
declare continue handler for not found
set no_more_rows2 := TRUE;
open cursor2;
LOOP2: loop
fetch cursor2
into v_col2;
if no_more_rows then
close cursor2;
leave LOOP2;
end if;
end loop LOOP2;
end BLOCK2;
end loop LOOP1;
end BLOCK1;
Ответ 2
Исправьте меня, если я ошибаюсь, но похоже, что вы пытаетесь сделать, это массовая вставка записей в таблицу "SLA_DEMANDE_STATUS". Включите каждый критерий для каждого найденного индикатора и по умолчанию используйте значения "0009", "ОК" и 10.0 для каждого индикатора "Критерии".
Все это можно сделать в одной SQL-Insert. INSERT INTO... из SQL-Select...
Теперь, если вы хотите включить только одну запись "id_indicateur", вы можете добавить это к предложению WHERE оператора select.
Обратите внимание, что мой SQL-Select имеет принудительные значения, соответствующие столбцам, которые вы хотите заполнить. Все они будут вставлены в таблицу назначения с тем же именем. Приятная вещь об этом, вы можете просто запустить часть SQL-SELECT, чтобы увидеть данные, которые вы должны были бы EXPECT, чтобы вставить... если это неверно, вы можете настроить его, чтобы он соответствовал любым ограничениям.
insert into SLA_DEMANDE_STATUS
( iddemande,
idindicateur,
indicateur_status,
progression )
SELECT
'0009' iddemande,
c.id_criterere idindicateur,
'OK' indicateur_status,
10.0 progression
FROM
indicateur i;
JOIN critere c
ON i.id_indicateur = c.id_indicateur
Ответ 3
вы можете использовать loop и reset значение дескриптора, например:
get_something:loop
open cur;
fetch cur into temp_key;
if no_more_record=1 then
set no_more_record=0;
close cur;
leave get_something;
else
//do your job;
end if;
end loop;
Ответ 4
Или переопределите CONTINUE HANDLE:
//...
LOOP1: LOOP
fetch cursor1
into v_col1;
if no_more_rows1 then
close cursor1;
leave LOOP1;
end if;
//...
SET no_more_rows1=false;//That new
END LOOP LOOP1;
Кажется, что все операторы select внутри цикла выполняют CONTINUE HANDLE
Ответ 5
DECLARE _idp INT;
DECLARE _cant INT;
DECLARE _rec INT;
DECLARE done INT DEFAULT 0;
-- Definición de la consulta
DECLARE primera CURSOR FOR SELECT dp.id_prod, SUM(dp.cantidad) AS cantidad, pp.receta FROM tm_detalle_pedido AS dp INNER JOIN tm_producto_pres AS pp
DECLARE segunda CURSOR FOR SELECT id_ins, cant FROM tm_producto_ingr WHERE id_pres = _idp;
-- Declaración de un manejador de error tipo NOT FOUND
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- Abrimos el primer cursor
OPEN primera;
REPEAT
FETCH primera INTO _idp, _cant, _rec;
IF NOT done THEN
OPEN segunda;
block2: BEGIN
DECLARE doneLangLat INT DEFAULT 0;
DECLARE _ii INT;
DECLARE i FLOAT;
DECLARE _canti FLOAT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET doneLangLat = 1;
REPEAT
FETCH segunda INTO _ii,_canti;
IF NOT doneLangLat THEN
IF _rec = 1 THEN
SET i = _canti * _cant;
-- Insertamos
INSERT INTO tm_inventario (id_ins,id_tipo_ope,id_cv,cant,fecha_r)
VALUES (_ii, 2, @id, i, _fecha);
END IF;
END IF;
UNTIL doneLangLat END REPEAT;
END block2;
CLOSE segunda;
END IF;
UNTIL done END REPEAT;
CLOSE primera;