20
 
07/12/2019

Imprimir calendario anual con PLSQL de Oracle (Procedimiento)

Imprimir calendario anual con PLSQL de Oracle (Procedimiento)Crear un procedimiento para imprimir el calendario anual ordenado por días, meses y semanas, a través de la implementación de código PL/SQL de Oracle.

En esta oportunidad he creado un procedimiento sencillo que nos sirva para imprimir o mostrar los días del año ordenados por meses y semanas, de acuerdo a ciertos parámetros aplicados, tal y como lo haría cualquier calendario.

Sin embargo, el código no contempla información sobre algunos otros detalles como por ejemplo: los días festivos y religiosos, así como las fases lunares. Por lo que es posible agregar mejoras en el procedimiento para que sirva además con algunas otras especificaciones, como por ejemplo: guardar los datos en una tabla de la base de datos, para su posterior uso en algún sistema o proceso que requiera de esta información.

En otra publicación estaré agregando nuevas instrucciones para que el procedimiento permita generar sentencias INSERT de los días del año, ordenados por semana.

Recuerda que si esta publicación te ha servido de ayuda para solucionar un problema informático, puedes apoyar mi trabajo realizando una contribución a través de mi perfil de usuario de la página.

Creando el procedimiento P_CALENDAR

Este procedimiento requiere de dos parámetros de entrada, los cuales hacen referencia al año y el mes a imprimir en el calendario.
CREATE OR REPLACE PROCEDURE P_CALENDAR (p_year IN NUMBER, p_month IN NUMBER)
IS
/* ************************************************************************************
* Procedimiento: p_calendar
* Descripción: Imprimir el calendario de un año/mes especificado
* Parámetros: p_year el año a consultar
* Retorna: p_month el mes a consultar
* *********************************************************************************
*/
v_anyo VARCHAR2 (4) := to_char(to_date(p_year-1,'yyyy'),'yyyy');
v_first_day_anyo DATE := last_day(to_date(v_anyo,'yyyy')) + 1;
v_month NUMBER := p_month;
v_first_day_month DATE;
v_last_day_month DATE;
v_last_weekday_where_month_end NUMBER;
v_days DATE;
v_days_ DATE;
v_week NUMBER;
v_week_ NUMBER;
v_numbers_of_weeks NUMBER := 0;
v_im NUMBER := 0;
v_ids NUMBER := 0;
v_id NUMBER := 0;
v_id_ NUMBER := 0;
v_days_week_ins VARCHAR2 (1000) := '';
v_dom DATE;
v_sab DATE;
v_flag BOOLEAN := FALSE;
-- Función para imprimir el nombre del mes
FUNCTION F_MONTHS (p_mon IN DATE,
p_format IN VARCHAR DEFAULT 'MONTH')
RETURN VARCHAR2
IS
v_month VARCHAR2 (15) := TO_CHAR (p_mon,p_format);
BEGIN
IF p_format = 'MON' THEN
IF v_month = 'JAN' THEN
v_month := 'ENE';
ELSIF v_month = 'APR' THEN
v_month := 'ABR';
ELSIF v_month = 'AUG' THEN
v_month := 'AGO';
ELSIF v_month = 'DEC' THEN
v_month := 'DIC';
END IF;
END IF;
RETURN v_month;
EXCEPTION
WHEN OTHERS
THEN
RETURN 'INDEFINIDO';
END F_MONTHS;
BEGIN
-- Primer ciclo de consulta de los días del mes
LOOP
v_im := v_month - 1;
v_first_day_month := ADD_MONTHS (v_first_day_anyo,v_im);
v_last_day_month := LAST_DAY (v_first_day_month);
v_last_weekday_where_month_end := 7 - TO_NUMBER (TO_CHAR (v_last_day_month,'d'));
DBMS_OUTPUT.PUT_LINE ( '-------------------------------------------------------------------------------------' );
DBMS_OUTPUT.PUT_LINE ( F_MONTHS (v_last_day_month,'MON') || ' ' );
DBMS_OUTPUT.PUT_LINE ( '=====================================================================================' );
DBMS_OUTPUT.PUT_LINE ( ' Dom Lun Mar Mié Jue Vie Sáb ' );
DBMS_OUTPUT.PUT_LINE ( '=====================================================================================' );
DBMS_OUTPUT.PUT_LINE ( '-------------------------------------------------------------------------------------' );
-- Segundo y tercer ciclo de consulta para ubicar los días en su columna correspondiente (Dom a Sáb)
LOOP
v_days := v_first_day_month + v_id_;
v_week := TO_NUMBER (TO_CHAR (v_days,'d'));
-- Número de semanas por mes
IF TO_CHAR (v_days,'mm') = p_month AND v_week = 2 THEN
v_numbers_of_weeks := v_numbers_of_weeks + 1;
END IF;
-- Organizar los días por grupo de siete (7) valores (las siete columnas de la semana)
IF MOD (v_id_,7) = 0 THEN
v_days_week_ins := '';
v_ids := 0;
v_id := 0;
LOOP
v_ids := v_ids + 1;
IF NOT v_flag THEN
v_days_ := (v_days + v_id);
END IF;
v_week_ := TO_CHAR (v_days_,'d');
-- Si el día de la columna coincide con el día de la fecha...
IF v_ids = v_week_ THEN
v_days_week_ins := v_days_week_ins || TO_CHAR (v_days_) || ' | ';
v_id := v_id + 1;
v_flag := FALSE;
ELSE
-- En caso contrario rellenar los días previos de la semana
v_days_week_ins := v_days_week_ins || TO_CHAR ((v_days_ - v_week_) + v_ids) || ' | ';
v_flag := TRUE;
END IF;
EXIT WHEN v_ids >= 7;
END LOOP;
DBMS_OUTPUT.PUT_LINE ( v_days_week_ins ); -- Imprimiendo el calendario
END IF;
v_id_ := v_id_ + 1;
EXIT WHEN v_id_ > (TO_NUMBER (TO_CHAR (v_last_day_month,'dd')) - 1) + v_last_weekday_where_month_end;
END LOOP;
DBMS_OUTPUT.PUT_LINE ( '-------------------------------------------------------------------------------------' );
DBMS_OUTPUT.PUT_LINE ( ' SEMANAS: ' || v_numbers_of_weeks || ' ' );
EXIT WHEN v_month >= p_month;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE('ERROR: ALGO SALIÓ MAL.' || sqlcode || ' - ' ||sqlerrm );
END P_CALENDAR;
/
Procedure created.

Ejecutar nuestro procedimiento llamado P_CALENDAR

Este subproceso nos permite imprimir los días calendario de un año y mes en específico como se muestra a continuación:
BEGIN
P_CALENDAR (2019, 1);
P_CALENDAR (2019, 2);
P_CALENDAR (2019, 3);
P_CALENDAR (2019, 4);
P_CALENDAR (2019, 5);
P_CALENDAR (2019, 6);
P_CALENDAR (2019, 7);
P_CALENDAR (2019, 8);
P_CALENDAR (2019, 9);
P_CALENDAR (2019, 10);
P_CALENDAR (2019, 11);
P_CALENDAR (2019, 12);
END;
Statement processed.

Mostrando los resultados

Los resultados que se muestran en las siguientes imágenes corresponden a algunos de los meses del año 2019 consultados en esta prueba.

Consulta Lo+ Top de Base De Datos
Todos los titulares en un solo lugar...