Está en la página 1de 6

Bases de Datos Avanzada Clase Práctica No.

3 Curso 2021

Asignatura: Bases de Datos Avanzada.


Carrera: Ingeniería Informática.
Tipo de Curso: C.R.D. Año: 3ro. Semestre: 2do.
Actividad No. 4
Clase Práctica No. 3
Título: Lenguaje PL/pgSQL. Cursores
Contenido:
 Cursores
 Condicionales
 Estructuras repetitivas

Bibliografía:
- Date, C.J., Introducción a los Sistemas de Bases de Datos, 5ta. Capítulos 4 y 17.
- SQL Server 2000. Book Online.

INTRODUCCIÓN
Para el manejo de grandes cantidades de datos tanto en PostgreSQL como en otras bases de
datos relacionales existe el concepto de cursores, los cuales representan un resultset (conjunto de
datos) que son asociados a una variable, una variable de tipo cursor. Esta variable representa un
apuntador hacia una tabla virtual representada por una consulta y su respectivo comando SELECT
asociado.
Declaración de Variables de Cursor

 Los cursores se acceden únicamente mediante variables de cursor.


 Existen dos formas de declaración:
 Declarando variables de tipo refcursor.
Ejemplo: DECLARE
curs1 refcursor;

 Utilizando la sintaxis de declaración de un cursor.


nombre CURSOR [ ( argumentos ) ] FOR select_query ;

Ejemplo: DECLARE

curs2 CURSOR FOR SELECT * from table1;


curs3 CURSOR (key int) IS SELECT * from table1 where unique1 = key;

Apertura de Cursores
 Un cursor debe ser abierto para poder utilizarse.

1
Bases de Datos Avanzada Clase Práctica No. 3 Curso 2021
 Existen cuatro formas de abrir un cursor.

 OPEN FOR SELECT: Especificando una consulta como tal.


(ej. OPEN curs1 FOR SELECT * FROM < -- >WHERE < -- >; )

 OPEN FOR EXECUTE: La consulta se especifica como una expresion de texto, al igual que
se usa con el comando EXECUTE.
(ej. OPEN curs1 FOR EXECUTE ''SELECT * FROM '' || quote_ident($1);)

 Abrir cursores asignados: OPEN cursor [ ( valores de parámetros) ];


(ej. OPEN curs2;
OPEN curs3(42);)

Uso de Cursores

 FETCH: Retorna la siguiente fila del cursor.


 El valor se puede almacenar en una variable tipo fila, registro o a una lista de
variables simples separadas por comas (idem a SELECT INTO).
 Puede usarse la variable especial FOUND para chequear la recuperación.
(ej. FETCH curs1 INTO rowvar;
FETCH curs2 INTO foo, bar, baz; )
 CLOSE: Cierra un cursor abierto y libera sus recursos.
(ej. CLOSE curs1;)
 Retorno de cursores.
 Las funciones pueden retornar cursores (Abrir el cursor y devolver su nombre).
 El cursor podrá ser cerrado por el programador o cuando termine la transacción.
 El nombre del cursor retornado por la función puede ser especificado por el
peticionario o generado automáticamente.

Desarrollo:

Sobre el modelo agrícola responda:


obrero (cod_obrero, nom_obrero, dir_obrero, tipo_obrero, fecha_nacimiento ,cod_empresa)
obrero_agrícola (cod_obrero, salario, cod_categoria)
obrero_cooperativista (cod_obrero,cod_nivel)
empresa (cod_empresa, nom_empresa, dir_empresa)
categoría_ocupacional (cod_categoria, nom_categoria, desc_categoria)
nivel_escolar (cod_nivel, nom_nivel, desc_nivel)
cultivo (cod_cultivo, nom_cultivo, nom_cient_cultivo)
variedad (cod_cultivo, cod_variedad, desc_variedad, origen_variedad)
fertilizante (cod_fertilizante, nom_fertilizante, precio, cod_pais)
pais (cod_pais, nom_pais)
suelo (cod_suelo, nom_suelo, desc_suelo)

2
Bases de Datos Avanzada Clase Práctica No. 3 Curso 2021
norma_producción (cod_norma, cod_suelo, cod_fertilizante, cod_cultivo, cod_variedad,
producción, tiempo_cumplimiento)
cumplimiento_norma (cod_obrero, cod_norma, porciento_cumplimiento, fecha_cumplimiento,
fecha_inicio)

1. Se desea estimular a aquellos obreros agrícolas que sobrecumplieron el plan de producción


en menor tiempo de lo establecido. Para ello se incrementará el salario en 20 pesos por
cada día de sobrecumplimiento. Elabore una función que permita actualizar el salario de los
obreros agrícolas. Suponga que se tiene una función obrerosDestacados () que devuelve
un cursor con el código del obrero, salario y dí3as de sobrecumplimiento del obrero.

CREATE FUNCTION estimularObreros()


RETURNS void AS $BODY$
DECLARE
obreros refcursor;
codObrero varchar;
sal double precision;
diasSobrecumplimiento integer;
salTemp double precision;
BEGIN
obreros := obrerosDestacados();
LOOP
FETCH obreros INTO codObrero, sal, diasSobrecumplimiento;
EXIT WHEN NOT FOUND;
salTemp=0;
salTemp = sal + diasSobrecumplimiento*20;
UPDATE obrero_agricola SET salario = salTemp WHERE
obrero_agricola.cod_obrero = codObrero;
END LOOP;
CLOSE obreros;
END;
$BODY$
LANGUAGE plpgsql;

2. Se conoce que los Fertilizantes provenientes de Brasil, Venezuela y Bolivia, han aumentado
su precio en un 10%, 5% y 15% respectivamente. Implemente una función que permita
actualizar las filas correspondientes.
CREATE OR REPLACE FUNCTION actualizarPrecioFertilizantes()
RETURNS void AS $BODY$
DECLARE
fertilizantes refcursor;
codFertilizante varchar;
preciofert double precision;
3
Bases de Datos Avanzada Clase Práctica No. 3 Curso 2021
nombrepais varchar;
precioTemp double precision;
BEGIN
OPEN fertilizantes FOR SELECT fertilizante.cod_fertilizante,
fertilizante.precio, pais.nom_pais
FROM fertilizante
INNER JOIN pais
ON fertilizante.cod_pais = pais.cod_pais
WHERE pais.nom_pais = 'Brasil' OR pais.nom_pais = 'Venezuela' OR
pais.nom_pais = 'Bolivia';
LOOP
FETCH fertilizantes INTO codFertilizante, preciofert, nombrepais;
EXIT WHEN NOT FOUND;
precioTemp =0;

IF(nombrepais='Brasil') THEN
precioTemp = preciofert + preciofert*0.1;

ELSIF(nombrepais='Venezuela') THEN
precioTemp = preciofert + preciofert*0.05;

ELSIF(nombrepais='Bolivia') THEN
precioTemp = preciofert + preciofert*0.15;
END IF;

UPDATE fertilizante SET precio = precioTemp WHERE


fertilizante.cod_fertilizante = codFertilizante;
END LOOP;
CLOSE fertilizantes;
END;
$BODY$
LANGUAGE plpgsql;

3. El Ministerio de Agricultura decidió aumentar el salario a los obreros agrícolas atendiendo a


su categoría ocupacional (Técnico o Servicios). La resolución establece que el cambio de
salario para los Técnicos se irá aplicando aumentando en montos de 25 pesos hasta
sobrepasar los 500. En el caso de los trabajadores de Servicios se incrementara el salario
en un 15% del valor actual. Elabore una función que permita actualizar el salario de los
obreros.

CREATE OR REPLACE FUNCTION actualizarSalarioObreroAgricola()


RETURNS void AS $BODY$
DECLARE
obreoAgr refcursor;
codObrero varchar;
sal double precision;
categ varchar;

4
Bases de Datos Avanzada Clase Práctica No. 3 Curso 2021
salTemp double precision;
BEGIN
OPEN obreoAgr FOR SELECT cod_obrero, salario, nom_categoria
FROM obrero_agricola
INNER JOIN categoria_ocupacional
ON obrero_agricola.cod_categoria = categoria_ocupacional.cod_categoria;
WHERE categoría_ocupacional.nom_categoria LIKE 'Tecnico'
OR categoría_ocupacional.nom_categoria LIKE 'Servicios'

LOOP
FETCH obreoAgr INTO codObrero, sal, categ;
EXIT WHEN NOT FOUND;
salTemp =0;
IF(categ = 'Tecnico') THEN
salTemp = sal;

WHILE(salTemp < 500) LOOP


salTemp = salTemp+25;
END LOOP;
ELSE
salTemp = sal + sal *0.15;
END IF;
UPDATE obrero_agricola SET salario = salTemp WHERE
obrero_agricola.cod_obrero = codObrero;
END LOOP;
CLOSE obreoAgr;
END;
$BODY$
LANGUAGE plpgsql;

Estudio Individual
 Realice las siguientes funciones:
1. Devolver el tiempo de cumplimiento total (tiempo_cumplimiento) y la cantidad de normas de
una variedad de un cultivo.
2. Utilizando la función anterior, resuelva:
Si el tiempo de cumplimiento total es superior a 60 días y la cantidad de normas es mayor
que 3, entonces en cada norma de esa variedad de cultivo, el tiempo de cumplimiento se
debe actualizar. El nuevo tiempo de cumplimiento para cada norma será igual al que tenía
menos la diferencia del tiempo de cumplimiento total y 60 entre la cantidad de normas de
esa variedad.
Por ejemplo si para la variedad con código 01 del cultivo con código 02 el tiempo de
cumplimiento total registrado en las normas es de 65 y la cantidad de normas es 5,
entonces hay que actualizar cada tiempo de cumplimiento de esa variedad y el nuevo valor
será: tiempo_cumplimiento-((65-60)/5)

 Ejercitar para la próxima clase el trabajo con disparadores(Triggers) en PostgreSQL.

RESPUESTA 1:

5
Bases de Datos Avanzada Clase Práctica No. 3 Curso 2021

CREATE FUNCTION tiempo_cumplimiento_por_variedad_cultivo()


RETURNS refcursor AS
DECLARE
variedades refcursor;
BEGIN
OPEN variedades for select sum(tiempo_cumplimiento),
count(distinct cod_norma), cod_cultivo, cod_variedad from
norma_produccion
group by cod_cultivo, cod_variedad;
return variedades;
END
LANGUAGE plpgsql;

RESPUESTA 2:
CREATE FUNCTION actualizar_tiempo_cumplimiento()
RETURNS void AS
DECLARE
variedades refcursor;
tiempo_total integer;
cant_normas integer;
cod_cult character varying(2);
cod_varie character varying(2);
BEGIN
variedades = tiempo_cumplimiento_por_variedad_cultivo();
LOOP
FETCH variedades INTO
tiempo_total,cant_normas,cod_cult,cod_varie;
EXIT WHEN NOT FOUND;
IF (tiempo_total > 60) and (cant_normas > 3) THEN
update norma_produccion set tiempo_cumplimiento =
tiempo_cumplimiento - ((tiempo_total-60)/cant_normas)
where cod_cultivo = cod_cult and cod_variedad = cod_varie;
END IF;
END LOOP;
CLOSE variedades;
END
LANGUAGE plpgsql;

También podría gustarte