MySQL: не разрешено возвращать результирующий набор из триггера

#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 = количество обновленных строк.) Все это кажется мне немного странным.