#mysql #triggers
#mysql #триггеры
Вопрос:
Я получаю «ОШИБКА 1415 (0A000): не разрешено возвращать результирующий набор из триггера» при обновлении таблицы, содержащей следующий триггер, но не понимаю почему.
CREATE TRIGGER my_trigger AFTER UPDATE ON my_triggering_table
FOR EACH ROW CALL my_procedure();
Я уверен, что триггеры не могут использовать SELECT, который возвращает результирующий набор, но вызываемая процедура (и ее дочерние элементы) используют только КУРСОР ДЛЯ ВЫБОРА и ВЫБОРКИ, в которые, как я понимаю, разрешено. Они считывают, но не изменяют таблицу запуска.
Кто-нибудь может объяснить ошибку? (MySQL 5.5) Вызываемые процедуры ниже.
CREATE PROCEDURE my_procedure()
BEGIN
DECLARE v_mark VARCHAR(4);
DECLARE v_lat, v_lon DOUBLE;
DECLARE eof INT DEFAULT FALSE;
DECLARE my_cursor CURSOR FOR SELECT `mark`, `lat`, `lon` FROM my_triggering_table ORDER BY `order`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;
DELETE FROM my_output_table;
OPEN my_cursor;
loop1: LOOP
FETCH my_cursor INTO v_mark, v_lat, v_lon;
IF eof THEN
LEAVE loop1;
END IF;
CALL my_procedure_2(v_mark, v_lat, v_lon);
END LOOP;
CLOSE my_cursor;
END//
CREATE PROCEDURE my_procedure_2(IN from_mark VARCHAR(4), IN from_lat DOUBLE, IN from_lon DOUBLE)
BEGIN
DECLARE v_mark VARCHAR(4);
DECLARE v_lat, v_lon DOUBLE;
DECLARE eof INT DEFAULT FALSE;
DECLARE my_cursor CURSOR FOR SELECT `mark`, `lat`, `lon` FROM my_triggering_table ORDER BY `order`;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET eof = TRUE;
OPEN my_cursor;
loop1: LOOP
FETCH my_cursor INTO v_mark, v_lat, v_lon;
IF eof THEN
LEAVE loop1;
END IF;
INSERT INTO my_output_table(`from`, `to`, `dist`, `brg`, `lat`, `lon`)
VALUES(from_mark
, v_mark
, IF(from_mark = v_mark, NULL, getDist(from_lat, from_lon, v_lat, v_lon))
, IF(from_mark = v_mark, NULL, getBearing(from_lat, from_lon, v_lat, v_lon))
, coord_dec2ms(from_lat, true)
, coord_dec2ms(from_lon, false)
);
END LOOP;
CLOSE my_cursor;
END//
Вызываемые UDF не ссылаются ни на какие таблицы.
Комментарии:
1. Интересно. (Я не могу объяснить поведение, я не вижу проблемы.) Для отладки этого я бы сначала попробовал (временно) прокомментировать оператор INSERT
my_procedure_2
в. Это гарантировало бы, что любой триггер вставки ДО / ПОСЛЕ в my_output_table не будет запущен, а также отключит определяемые пользователем функции (getDist, getBearing, coord_dec2ms). Я бы отказался от функциональности, пока не получил что-то для выполнения, а затем начал добавлять материал обратно, чтобы найти, что вызывает ошибку.2. Любопытно, что похоже, что вы перебираете все строки
my_triggering_table
в my_procedure , и для каждой строки my_procedure_2 снова перебирает все строкиmy_triggering_table
. Итак, если в my_output_table 1000 строк, вmy_triggering_table
my_output_table будет 1000 * 1000 = 1000000 строк. И весь этот процесс выполняется для каждой строки, измененной оператором UPDATE (есть оператор DELETE, поэтому будет только 1 000 000 строк, а не N * 1 000 000 строк (N = количество обновленных строк.) Все это кажется мне немного странным.