Está en la página 1de 10

SQL de Procedimientos

 
BASE DE DATOS 
SEMANA 6
 

[ BASE DE DATOS ]
 

CONTENIDO 
 
 
 
Presentación …………………………………..   3 
 
1. DESARROLLO TEMÁTICO ……………………  3 
• Funciones ………………………………….  4 
• Cursores ……………………………………  4 
• Procedimientos Almacenados …………….  5 
• Disparadores ……………………………….  7 
 
Conclusiones …………………………………….  10 
 
1.1. BIBLIOGRAFÍA ……………………………….  10 
 
 

 
 
 
 

 
2 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
 

PRESENTACIÓN 
Como podemos observar el SQL no es un lenguaje de programación propiamente dicho, sino 
simplemente  un  lenguaje  de  acceso  a  bases  de  datos  puesto  que  no  incorpora 
construcciones de control que permitan representar el flujo de control y de la información a 
través de un procedimiento software. 

En  esta  lectura  realizaremos  una  breve  descripción  del  lenguaje  y  de  los  componentes  del 
mismo,  describiendo  la  estructura  clásica  de  los  programas  PL/pgsql.  Se  trata  de  unas 
nociones  básicas  que  permitirán  a  todos  los  participantes  comprender  los  ejemplos 
propuestos a los largo del curso e iniciarse en la programación de aplicaciones con PL/pgsql. 

1. DESARROLLO TEMÁTICO 
Los programas PL/pgsql se estructuran agrupando las declaraciones o cláusulas del lenguaje 
en distintos bloques o secciones encargadas de tareas específicas, como son: 

• Declaración de las variables de la interfaz del programa y de las variables internas 
de ejecución. Se pueden utilizar los tipos de datos definidos por el SGBD y tipos de 
datos  definidos  por  el  usuario  para  definir  las  variables  y  asignar  valores  a  las 
mismas. 

• Flujo de control y operación de las tareas para las cuales se construye el programa. 
Se hace uso de los verbos de control de flujo y de sentencias SQL. 

Cada una de estas secciones viene identificada por una cláusula de cabecera de forma que la 
estructura general de un procedimiento es la siguiente: 

DECLARE 
  Declaración de las variables utilizadas 
BEGIN 
  Cuerpo del procedimiento 
END; 
 
No se debe confundir el uso de las sentencias de agrupamiento BEGIN/END de PL/pgSQL con 
los  comandos  de  la  base  de  datos  que  sirven  para  el  control  de  las  transacciones.  Las 
funciones  y  procedimientos  disparadores  no  pueden  iniciar  o  realizar  transacciones  y 
Postgres no soporta transacciones anidadas. 

 
[ BASE DE DATOS ] 3
 

Funciones 
Como  en  cualquier  lenguaje  de  programación  PL/pgsql  permite  la  declaración  de 
subprogramas  (subrutinas)  denominados  funciones.  Las  funciones  pueden  ser  invocadas 
desde un programa PL/pgsql u otra función. 

Una  función  PL/pgsql  tiene  como  objetivo  realizar  un  proceso  y  devolver  un  valor  al 
programa  o  subprograma  que  la  invocó.  Las  funciones  permiten  la  declaración  de  una 
interfaz  mediante  la  cual  se  les  puede  transferir  una  lista  de  valores.  Un  ejemplo  de  la 
implementación de funciones es: 

• Función Factorial 
• El nombre de la función a crear. 
CREATE FUNCTION fib(int4) 
/* El tipo de datos que será devuelto. El tipo de datos que será devuelto puede 
ser declarado como tipo básico, complejo, tipo setof  u opaque. Modificadores 
setof indican que la función devolverá un grupo de objetos, antes que un solo 
objeto. */ 
RETURNS int4 
/*  Una  cadena  de  letras  que  define  la  función  y  cuyo  sentido  depende  del 
lenguaje. Puede ser un nombre interno de función, el sendero a un fichero de 
objeto, una cuestión en SQL o texto en un lenguaje procedimental. */ 
AS $$ 
    DECLARE 
       a int4; 
       res int4:=0; 
  BEGIN 
       a := $1; 
       IF(a = 1 OR a = 2) THEN 
        res:= 1; 
        ELSE 
            res := fib(a‐2) + fib(a‐1); 
       END IF; 
     RETURN res; 
    END; 
    $$ 
 /* Puede ser 'C', 'sql', 'internal' o 'plname', donde 'plname' es el nombre de un 
lenguaje procedimental creado. */ 
Language 'plpgsql'; 

Cursores 
Un cursor es un área de memoria de trabajo en la que se almacena la información de salida 
de  la  sentencia  SQL  y  que  es  necesario  declarar  para  posteriormente  poder  acceder  a  las 

 
4 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
 

tuplas que componen la salida de la sentencia. En lugar de ejecutar una consulta completa a 
la vez, es posible crear un cursor que encapsula la consulta, y después lee el resultado de la 
consulta un par de filas a la vez. 

El siguiente ejemplo recorre la tabla PRODUCTO usando un CURSOR: 

‐ Crear y usar el cursor 

BEGIN WORK; 
  DECLARE micursor CURSOR 
   FOR SELECT * FROM producto; 
 

‐ FETCH selecciona filas usando un cursor 

‐ FORWARD selecciona la(s) siguiente(s) filas 

‐ Seleccionar las primeras 3 filas en el cursor micursor 

FETCH FORWARD 3 IN micursor; 

‐ BACKWARD selecciona la(s) fila(s) anteriores 

‐ Seleccionar la fila anterior 

FETCH BACKWARD 1 IN micursor; 

‐ Cerrar el cursor y commit WORK 

    CLOSE micursor; 

COMMIT WORK; 

Se  recomienda  usar  los  cursores  sólo  dentro  de  transacciones,  ya  que  los  datos  que 
almacenan  abarcan  múltiples  consultas  de  usuario.  Para  mayor  información: 
http://www.postgresql.org/docs/8.1/static/sql‐declare.html. 

 
Procedimientos almacenados 
Un  procedimiento  almacenado  es  un  conjunto  nombrado  de  sentencias  SQL  y  de 
procedimientos. Este conjunto nombrado se guarda en la base de datos. Los procedimientos 
almacenados son invocados por nombre. 

 
[ BASE DE DATOS ] 5
 

Los procedimientos almacenados se invocan como una unidad. Por consiguiente, cuando 
 
desea  representarse  una  transacción  de  actualización  múltiple,  puede  crearse  un 
  procedimiento  que  se  guarda  en  la  base  de  datos.  El  contenido  completo  del 
procedimiento  almacenado  se  transmite  y  ejecuta,  con  lo  que  se  evita  la  evita  la 
  transmisión  y  ejecución  de  sentencias  SQL  individuales  por  la  red.  Por  consiguiente,  el 
uso de procedimientos almacenados reduce sustancialmente el tráfico por la red, con lo 
  que se mejora el rendimiento. 

   

Ejemplo: 

Supongamos que tenemos una tabla ps_stock que almacena la información de los productos 
por comprar 

CREATE TABLE ps_stock ( 
ps_code int4 NOT NULL, 
    ps_descript varchar(35) NOT NULL 
); 
 
Queremos que haya una función comprar_producto() que haga lo siguiente: 

• Cree  una  tabla  nueva  llamada  ps_stock  que  almacene  los  datos  de  los 
productos que tengan p_onhand = 0 o sea los productos que hay que renovar 
para luego poner a la venta. 

• Busque en la tabla producto todos los productos que ya no estén en stock y 
los inserte en la tabla comprar_producto 

• Nos devuelva la cantidad de productos que ya no se encuentran en stock; 

CREATE OR REPLACE FUNCTION comprar_producto() 
    RETURNS int4 
    AS $$ 
    DECLARE 
       cont_pro int4; 
       fila_pro producto%ROWTYPE; 
    BEGIN 
SELECT COUNT(*) INTO cont_pro FROM producto WHERE p_onhand = 0; 
FOR fila_pro IN SELECT * FROM producto WHERE p_onhand=0 
           LOOP 
INSERT INTO ps_stock VALUES (fila_pro.p_code, fila_pro.p_descript); 
             END LOOP; 
       RETURN cont_pro; 

 
6 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
 

    END; 
      Language 'plpgsql'; 
 

Como ayuda para interpretar las líneas del procedimiento almacenado se observa que: 

- DECLARE se utiliza para especificar las variables utilizadas en el procedimiento. Debe 
especificarse tanto el nombre de la variable como su tipo de datos. 

- IN / OUT indica si el parámetro es de entrada o de salida o de ambas. 

- Data Type es uno de los tipos de datos SQL de procedimientos utilizado en el SGBD. 
Los  tipos  de  datos  normalmente  concuerdan  con  los  tipos  de  datos  utilizados  en  la 
sentencia de creación de tabla del SGBD. 

 
Disparadores 
Un disparador es un código SQl de procedimientos que automáticamente es invocado por el 
SGBD cuando ocurre un evento de manipulación de datos. Es útil recordar que: 

• Un  disparador  siempre  se  invoca  antes  o  después  de  que  una  fila  de  datos  se 
selecciona, inserta o actualiza. 

• Un disparador siempre está asociado con una tabla de base de datos. 

• Cada base de datos puede o no tener uno o más disparadores. 

• Un disparador se ejecuta como parte de la transacción que lo activó. 

Los disparadores son fundamentales para la operación y manejo apropiados de una base de 
datos. Por ejemplo: 

• Pueden utilizarse disparadores para hacer que se cumplan restricciones que pueden 
ser aplicadas a niveles de diseño y ejecución de SGBD. 

• Los disparadores agregan funcionalidad con la automatización de acciones críticas y 
el  suministro  de  advertencias  y  sugerencias  apropiadas  para  la  reutilización  de 
acciones  de  recuperación.  De  hecho,  uno  de  los  usos  más  comunes  de  los 
disparadores es mejorar la aplicación de la integridad referencial. 

 
[ BASE DE DATOS ] 7
 

• Pueden utilizarse disparadores para actualizar valores de tabla, insertar registros en la 
tabla e invocar otros procedimientos almacenados. 

Para ver cómo se crea y utiliza un disparador, se examinará el siguiente ejemplo: 

Nuestra  tabla  PRODUCTO  tiene  la  capacidad  de  almacenar  la  información  más  actual  e 
importante para nuestro sistema de control de compras, pero hay otro tipo de información  
que no es capaz de almacenar (por lo menos ahora), la información del cambio de datos. 

Nuestra  tabla  PRODUCTO  no  tiene  memoria  de  los  cambios  que  han  sufrido  sus  tuplas,  si 
alguien  viene  y  cambia  el  precio  de  venta  (producto.p_price),  no  hay  forma  de  obtener  el 
precio anterior. 

Si alguien borra un PRODUCTO, tampoco sabremos que artículo ha sido borrado ni por quien. 
Esto nos lleva a la primera gran área de utilización de los disparadores (triggers), la auditoria 
de tablas. 

Las acciones que debe realizar nuestro trigger son: 

1.  Necesitamos  llevar  un  registro  de  todos  los  cambios  relevantes  en  nuestra  tabla 
PRODUCTO, para empezar queremos tener un seguimiento de los cambios en los precios 
de los PRODUCTOS. 

2.  También  queremos  almacenar  en  algún  lugar  todos  aquellos  PRODUCTOS  que  hayan 
sido eliminados, también queremos guardar sus respectivos historiales de cambios. 

Lo primero que vamos a hacer es crear una tabla que vaya a almacenar los cambios de precio 
de nuestra tabla PRODUCTO, la llamaremos: producto_actualizado 

CREATE TABLE producto_actualizado 

  pa_code int4 NOT NULL, 
  pa_descript varchar(35) NOT NULL, 
  pa_lastprice numeric(9,2) NOT NULL, 
  pa_newprice numeric(9,2) NOT NULL, 
  pa_user varchar(100) NOT NULL, 
  pa_date date NOT NULL, 
CONSTRAINT pa_producto_fk FOREIGN KEY (pa_code) REFERENCES  producto(p_code) 
); 
 

CREATE FUNCTION pa_producto_tri() 
RETURNS trigger 
AS $$ 
  BEGIN 

 
8 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]
 

    IF(TG_OP = 'UPDATE') THEN 
      IF(OLD.p_price != NEW.p_price) THEN 
      INSERT INTO producto_actualizado VALUES (  
OLD.p_code, OLD.p_descript, OLD.p_price, NEW.p_price, current_user, current_date 
      ); 
      END IF; 
    END IF; 
    RETURN NULL; 
  END; 
$$ 
Language 'plpgsql'; 
 
CREATE TRIGGER actualizar_producto 
AFTER UPDATE ON producto 
FOR EACH ROW 
EXECUTE PROCEDURE pa_producto_tri(); 
 

Como ayuda para interpretar las líneas del anterior código se observa que: 

• Pueden existir varios bloques o sub‐bloques en la sección de sentencias de un bloque. 
Los  sub‐bloques  pueden  ser  usados  para  ocultar  las  variables  a  los  bloques  más 
externos. 

• TG_OP: variable de tipo string que indica que tipo de evento está ocurriendo. 

• current_user: es el nombre del usuario que está actualmente conectado a la base de 
datos y que ejecuta las sentencias. 

• current_date: es la fecha actual del servidor, no del cliente. 

• NEW:  variable  compuesta  que  almacena  los  nuevos  valores  de  la  tupla  que  se  está 
modificando. 

• OLD:  variante  compuesta  que  almacena  los  valores  antiguos  de  la  tupla  que  se  está 
modificando 

• Normalmente una de las sentencias es el valor del retorno, usando la palabra RETURN. 

• Un trigger se ejecuta: 

1. antes o después de una inserción (INSERT) 

 
[ BASE DE DATOS ] 9
 

2. antes o después de una actualización (UPDATE) 

3. antes o después de un borrado (DELETE) 

• Después de Actualizar (UPDATE) sobre la tabla PRODUCTO, para cada fila, ejecutar la 
función pa_producto_tri. 

 
CONCLUSIONES 
• El código de SQL de procedimientos es ejecutado por el SGBD cuando es invocado 
–directa o indirectamente‐ por el usuario final. 

• Puede  usarse  el  PL/pgsql  de  procedimientos  para  crear  disparadores, 


procedimientos almacenados, cursores y funciones. 

1.1. BIBLIOGRAFÍA 
• C.J. Date, Introducción a los Sistemas de Bases de Datos, 5. ª edición, Adison Wesley 
Iberoamericana, 1993. 

• Korth y A. Siulberschatz, Fundamentos de Bases de Datos, 4. ª edición, McGraw‐Hill, 
Madrid, 2002. 

• Elmasri,  R.  &  Navathe,  S.B.  “Fundamentals  Of  Database  Systems”  Third  Edition. 
Addison‐ Wesley Pubs. 2000. 

• Rob, Peter.; Coronel, Carlos. “Sistemas de Bases de Datos: diseño, implementación y 
administración”, Quinta Edición, THOMSON, 2002. 

 
10 [ POLITÉCNICO GANCOLOMBIANO EN ALIANZA CON WHITNEY INTERNATIONAL SYSTEM ]

También podría gustarte