Есть матрица расписания запусков:
Первая строка – 15-и минутные интервалы, вторая строка часовые интервалы, третья строка
дни недели, четвертая дни месяца, пятая месяцы года. С помощью данной матрицы задается периодичность запусков.
Требуется написать функцию на Oracle PL/SQL, которая бы возвращала дату следующего запуска (тип Date) от двух входных параметров:
Первый параметр (тип Date): дата, от которой ведется отчет;
Второй параметр (тип Varchar2): это текстовая переменная, в которой перечислены все выбранные ячейки. Ячейки разделены «,» (запятой), а строки разделены «;» (точкой с запятой), например, для данного рисунка расписание будет выглядеть следующим образом: 0,45;0,4,8,12,17,22;2,6;1,2,3,4,5,11,18,24;1,2,3,9,11;
Контрольный пример:
Дата отсчета: 09.07.2010 23:36
Строка: 0,45;12;1,2,6;3,6,14,18,21,24,28;1,2,3,4,5,6,7,8,9,10,11,12;
Результат: 18.07.2010 12:00
Примечание. В данном примере, используется американский календарь, в котором 1 – это воскресенье, 2 – понедельник и т.д.
Решение:
DECLARE
p_interval VARCHAR2(250);
d1 TIMESTAMP := SYSDATE;
d2 TIMESTAMP := d1;
p_result_day TIMESTAMP;
v_byminute VARCHAR2(50);
v_byhour VARCHAR2(50);
v_byweekday VARCHAR2(50);
v_bymontday VARCHAR2(50);
v_bymonth VARCHAR2(50);
v_slr_name VARCHAR2(30) := 'slr' || to_char(systimestamp, 'yyymmddhh24missff');
BEGIN
p_interval := '0,15,45;0,4,8,12,17,22;2,4,5,6;1,2,3,4,5,11,18,24;1,2,3,9,11;'; -- в конце можно не ставить ;
v_byminute := regexp_substr(p_interval, '[^;]+', 1, 1);
v_byhour := regexp_substr(p_interval, '[^;]+', 1, 2);
v_byweekday := regexp_substr(p_interval, '[^;]+', 1, 3);
v_bymontday := regexp_substr(p_interval, '[^;]+', 1, 4);
v_bymonth := regexp_substr(p_interval, '[^;]+', 1, 5);
-- преобразуем дни в наименования
SELECT listagg(regexp_substr('SUN|MON|TUE|WED|THU|FRI|SAT', '[^|]+', 1, dy),',') within GROUP(ORDER BY dy)
INTO v_byweekday
FROM (SELECT regexp_substr(v_byweekday, '[^,]+', 1, LEVEL) dy
FROM dual
CONNECT BY LEVEL <= regexp_count(v_byweekday, ',') + 1);
-- создаем уникальный календарь
dbms_scheduler.create_schedule(schedule_name => v_slr_name,
repeat_interval => 'FREQ=YEARLY;BYMONTHDAY='||v_bymontday||';BYDAY=' || v_byweekday||';BYHOUR='||v_byhour||';BYMINUTE='||v_byminute);
dbms_scheduler.evaluate_calendar_string(calendar_string => v_slr_name,
start_date => d1,
return_date_after => d2,
next_run_date => p_result_day);
dbms_output.put_line('Next date is ' || to_char(p_result_day, 'dd.mm.yyyy hh24:mi:ss'));
-- удаляем созданный календарь
dbms_scheduler.drop_schedule(schedule_name => v_slr_name);
END;
/
Комментариев нет:
Отправить комментарий