Я пытаюсь создать функцию, которая проверяет, находится ли какая-либо дата между, скажем, диапазоном дат A и B, между диапазоном дат C и D. Всякий раз, когда я пытаюсь запустить функцию, MySQL Workbench всегда выдает код ошибки: 2013 Потеряно соединение с сервером MySQL во время запроса. Я предполагаю, что эта ошибка возникает из-за того, что цикл работает вечно (пожалуйста, поправьте меня, если я думаю об этом совершенно неправильно).
Код таблицы:
CREATE TABLE TESTING(
LeaveStart DATE,
LeaveEnd DATE,
ProjectStart DATE,
ProjectEnd DATE,
Det BOOL,
ID INT);
Код вставки значения:
INSERT INTO TESTING VALUES('2018-01-01','2018-01-31','2018-01-10','2018-01-30',FALSE,1);
INSERT INTO TESTING VALUES('2018-01-01','2018-01-31','2018-01-10','2018-01-30',FALSE,2);
Функция:
DELIMITER //
CREATE FUNCTION SALARY_DEDUCTION (LeaveStart Date, LeaveEnd Date, ProjectStart DATE, ProjectEnd Date)
RETURNS BOOL NO SQL
DETERMINISTIC
BEGIN
DECLARE DET BOOL DEFAULT FALSE;
DECLARE DT DATE DEFAULT LeaveStart;
WHILE LeaveStart < LeaveEnd DO
IF DT BETWEEN ProjectStart AND ProjectEnd THEN
SET DET = TRUE;
ELSE
SET DET = FALSE;
SET DT = DATE_ADD(DT, INTERVAL 1 DAY);
END IF;
END WHILE;
RETURN DET;
END ; //
DELIMITER ;
Код вызова/водителя:
UPDATE TESTING AS T
SET
T.Det = SALARY_DEDUCTION(T.LeaveStart,T.LeaveEnd,T.ProjectStart,T.ProjectEnd)
WHERE
T.ID=1;
Примечание. Код драйвера может выдать код ошибки 1175: безопасное обновление. Его можно отключить, указав SET SQL_SAFE_UPDATES=0 перед кодом драйвера. Если бы кто-то мог также объяснить, почему он выдает ошибку, это было бы здорово.
DB-Fiddle: https://www.db-fiddle.com/f/4Bof1gdHRnkSYJwVZekRJ9/1
Обновлено:
DELIMITER //
CREATE FUNCTION SALARY_DEDUCTION_3(LeaveStart Date, LeaveEnd Date, ProjectStart DATE, ProjectEnd Date)
RETURNS BOOL NO SQL
DETERMINISTIC
BEGIN
DECLARE DET BOOL DEFAULT FALSE;
DECLARE CD DATE DEFAULT LeaveStart;
myloop: WHILE CD < LeaveEnd DO
IF CD BETWEEN ProjectStart AND ProjectEnd THEN
SET DET = TRUE;
LEAVE myloop;
END IF;
SET CD = DATE_ADD(CD, INTERVAL 1 DAY);
END WHILE myloop;
RETURN DET;
END ; //
DELIMITER ;
Ваш код создает бесконечный цикл (LeaveStart < LeaveEnd всегда равно true).
Кроме того, взгляните на код, если вам вообще нужен цикл. В настоящее время он вам не нужен, так как значение DET будет определяться из последнего раунда цикла. Все остальные раунды ничего не значат.
Вы можете просто сделать:
UPDATE TESTING
SET Det = (LeaveStart<ProjectEnd AND LeaveEnd>=ProjectStart AND LeaveStart<LeaveEnd)
WHERE ID=1;
@ДжайсалСингхани. Добавлен образец без цикла
Спасибо за ответ, теперь я понимаю свою ошибку с всегда истинным LeaveStart<LeaveEnd, я обновил эту ошибку в Edit (1) выше, а также добавил перерыв в цикле для выхода кода после того, как DET установлено в TRUE. Казалось, это решило проблему! Не знаю, как я это пропустил. Цикл в коде предназначен для увеличения дат от LeaveStart до LeaveEnd при проверке каждой даты, находится ли она между диапазоном ProjectStart и ProjectEnd. Если есть лучший способ сделать это, я буду признателен за любые предложения.