Оператор SELECT из таблицы внутри курсора заставляет курсор выходить - PullRequest
2 голосов
/ 27 февраля 2012

Впервые в хранимых процедурах MySQL.Если я раскомментирую любую из 4 строк SELECT (ниже), тогда процедура EXITS выходит из цикла FETCH.Не понимаю почему

-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `UpdateStatusAudit`()
BEGIN
   -- Create loop for all $Service records
  DECLARE svc_id INT;
  DECLARE test INT;
  DECLARE svc_name VARCHAR(100);
  DECLARE no_more_rows BOOLEAN;
  DECLARE up_duration DECIMAL(11,2);
  DECLARE down_duration DECIMAL(11,2);
  DECLARE maint_duration DECIMAL(11,2);
  DECLARE degr_duration DECIMAL(11,2);
  DECLARE services_cur CURSOR FOR SELECT service_id,service_name FROM services ORDER BY service_id;

  -- Declare 'handlers' for exceptions
  DECLARE CONTINUE HANDLER FOR NOT FOUND
  SET no_more_rows = TRUE;

  OPEN services_cur;
  the_loop: LOOP
    FETCH services_cur INTO svc_id,svc_name;
    IF no_more_rows THEN
        CLOSE services_cur;
        LEAVE the_loop;
    END IF;
    SET up_duration = 0;
    SET down_duration = 0;
    SET maint_duration = 0;
    SET degr_duration = 0;
    SELECT svc_id;
    BEGIN
      -- SELECT IFNULL(sum(duration),0) INTO up_duration FROM daily_audit_summary where service_id = svc_id AND status = 'UP' AND Date = current_date - 1 group by date,service_id,status;
      -- SELECT IFNULL(sum(duration),0) INTO down_duration FROM daily_audit_summary where service_id = svc_id AND status = 'DOWN' AND Date = current_date - 1 group by date,service_id,status;
      -- SELECT IFNULL(sum(duration),0) INTO maint_duration FROM daily_audit_summary where service_id = svc_id AND status = 'MAINT' AND Date = current_date - 1 group by date,service_id,status;
      -- SELECT IFNULL(sum(duration),0) INTO degr_duration FROM daily_audit_summary where service_id = svc_id AND status = 'DEGR' AND Date = current_date - 1 group by date,service_id,status;
    END;   
    -- insert into daily_status 
    INSERT INTO daily_status (date,service_id,time_up,time_down,time_maint,time_degraded) values (current_date-1,svc_id,up_duration,down_duration,maint_duration,degr_duration);

  END LOOP the_loop;

END

Ответы [ 2 ]

3 голосов
/ 27 февраля 2012

Вы пытались назначить переменные следующим образом:

SELECT
  up_duration := IFNULL(SUM(duration), 0)
FROM daily_audit_summary
WHERE service_id = svc_id
  AND status = 'UP'
  AND Date = current_date - 1
GROUP BY
  date,
  service_id,
  status;

?

Вы также можете объединить все назначения в один SELECT:

SELECT
  up_duration    := SUM(CASE status WHEN 'UP'    THEN duration ELSE 0 END)
  down_duration  := SUM(CASE status WHEN 'DOWN'  THEN duration ELSE 0 END)
  maint_duration := SUM(CASE status WHEN 'MAINT' THEN duration ELSE 0 END)
  degr_duration  := SUM(CASE status WHEN 'DEGR'  THEN duration ELSE 0 END)
FROM daily_audit_summary
WHERE service_id = svc_id
  AND status = 'UP'
  AND Date = current_date - 1
GROUP BY
  date,
  service_id,
  status;

Новозможно, вы могли бы избежать курсора (и, следовательно, цикла), используя один оператор для выполнения всей работы :

INSERT INTO daily_status (
  date,
  service_id,
  time_up,
  time_down,
  time_maint,
  time_degraded
)
SELECT
  d.Date,
  s.service_id,
  SUM(CASE das.status WHEN 'UP'    THEN das.duration ELSE 0 END),
  SUM(CASE das.status WHEN 'DOWN'  THEN das.duration ELSE 0 END),
  SUM(CASE das.status WHEN 'MAINT' THEN das.duration ELSE 0 END),
  SUM(CASE das.status WHEN 'DEGR'  THEN das.duration ELSE 0 END)
FROM services s
  CROSS JOIN (SELECT CURRENT_DATE - 1 AS Date) AS d
  LEFT JOIN daily_audit_summary AS das
    ON s.service_id = das.service_id
   AND das.Date = d.Date;
2 голосов
/ 27 февраля 2012

Я думаю, что мне нужно дать лучшее объяснение ... Код находится в стадии разработки, и из-за требований я не могу избавиться от курсора "Services_cur".

Я обнаружил, что когда запрос для «Services_Cur» возвращает, скажем, 10 записей и в «цикле», если я использую инструкцию SELECT INTO из TABLE, например «ВЫБЕРИТЕ F1 В MyVar из Atable, где Afld = somevalue» LOOP завершается, как если бы курсор «Services Cur» был вне данных ??? Если я выдаю «SELECT 1234 INTO MyVar», цикл работает, и я получаю 10 результатов (как и ожидалось).

Я новичок в хранимых процедурах для MySql и не смог найти пример того, как кто-то выполняет серию «SELECT value for table» в цикле FETCHES.

Надеюсь, это поможет лучше объяснить проблему

Спасибо за любую помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...