Sei sulla pagina 1di 19

Firebird: SQL Procedimental (PSQL)

Tema 6

FIREBIRD: SQL PROCEDIMENTAL (PSQL)

Vicente Tejero Trueba

Pag 1

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

FIREBIRD: SQL PROCEDIMENTAL (PSQL)


1.- INTRODUCCION.............................................................................................................................. 1 2.- EXTENSIONES DEL LENGUAJE................................................................................................... 2 2.1.- Terminadores. .............................................................................................................................. 2 2.2.- Variables...................................................................................................................................... 3 2.3.- Sentencias bsicas........................................................................................................................ 4 2.4.- Cursores. ...................................................................................................................................... 5 2.5.- Sentencias control de flujo. ......................................................................................................... 8 2.6.- Ejecucin de cdigo..................................................................................................................... 9 2.7.- Eventos. ....................................................................................................................................... 9 3.- PROCEDIMIENTOS ALMACENADOS........................................................................................ 11 4.- TRIGGERS....................................................................................................................................... 13 5.- EXCEPCIONES ............................................................................................................................... 16

Vicente Tejero Trueba

Pag i

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

1.- INTRODUCCION
Uno de los grandes beneficios de la implementacin de SQL en Firebird es la posibilidad de compilar y ejecutar modulos de cdigo interno (procedimientos almacenados y triggers) desarrollados por un programador. Para ello se tiene PSQL, una sintaxis que combina sentencias de DML con una extensin para programacin. Se habla en este caso de programacin en el lado del servidor, ya que el cdigo se ejecutar en la mquina del servidor por el propio servidor. Esto tiene sus ventajas: - Diseo modular: Todas las aplicaciones que acceden a la misma base de datos comparten los procedimientos almacenados y por tanto se centralizan las reglas de empresa, se reutiliza cdigo y se reduce el tamao de las aplicaciones. - Facilidad en mantenimiento: Cuando se realiza un cambio en un procedimiento, ste se traslada de forma automtica a todas las aplicaciones que lo usan. - Mejora de eficiencia: El procesado complejo se realiza en el servidor reduciendo el trafico de red y la carga en los clientes. - Economa en la arquitectura: Las aplicaciones clientes se pueden orientar hacia la captura de datos y tareas interactivas mientas el trabajo complejo con datos se realiza en el servidor. - Funcionalidad extra: Operaciones que no se pueden realizar fcilmente mediante sentencias SQL pueden implementarse mediante procedimientos almacenados. Cada mdulo creado podr ser: Procedimiento almacenado: Se pueden utilizar como procedimientos seleccionables (sustituyen a una tabla o vista en una sentencia SELECT) o como procedimientos ejecutables (ejecutar una operacin o conjunto de operaciones en el lado del servidor) que se pueden llamar mediante EXECUTE PROCEDURE o desde otro procedimiento o trigger. Trigger: Es una rutina asociada a una tabla o vista que se lanza de forma automtica cuando se realiza una operacin de insercin, borrado o actualizacin de una fila. Un trigger nunca se llama directamente. Se suelen usar los triggers para realizar actualizaciones de datos ante cambios en filas, validar datos de entrada, transformaciones de datos, actualizaciones de integridad referencial en cascada o para hacer vistas de solo lectura actualizables. Un aspecto importante a tener en cuenta con los mdulos de PSQL es que no aportan control de transacciones. Un mdulo se ejecuta siempre en el mbito de una transaccin abierta previamente. Desde el mdulo no puede ser confirmada ni cancelada, lo nico que se puede es lanzar una excepcin ante un problema detectado. La aplicacin que ha llamado al mdulo ser la encargada de realizar la finalizacin apropiada de la transaccin (confirmar o deshacer). En este tema veremos los ejemplos a partir de la base de datos de bancos:

Vicente Tejero Trueba

Pag 1

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

2.- EXTENSIONES DEL LENGUAJE.


Los mdulos PSQL no son ms que sentencias SQL que comienzan con una clusula CREATE y finalizan con un terminador. En la definicin del mdulo apareceran un nmero variable de elementos como clausulas, palabras clave, bloques de sentencias, bucles, etc. Un mdulo de PSQL se define estableciendo dos elementos fundamentales: - La cabecera: En ella se incluyen todos los elementos de definicin del procedimiento o trigger como nombre del mdulo, parmetros de entrada y/o salida para los procedimientos, tipo de trigger, etc. - El cuerpo: En el se definen todos los elementos que desarrollan el mdulo como la declaracin de variables, el bloque de sentencias (entre el BEGIN END) y los manejadores de excepcin. As tendramos que en un procedimiento:
-- se inicia la cabecera CREATE PROCEDURE procedimiento (entrada INTEGER) RETURNS (salida INTEGER) --se acaba la cabecera AS -- se inicia el cuerpo DECLARE VARIABLE variable INT; BEGIN variable = entrada /2; salida =variable; END -- fin del cuerpo

2.1.- Terminadores. Muchos de los elementos que nos encontramos en un mdulo se deben indicar con el terminador ;. Ya que un mdulo es una sla sentencia finalizada con un terminador es necesario diferenciar ste de los elementos del mdulo. Esto se consigue mediante la sentencia SET TERM. Por ejemplo una definicin tipica de un procedimiento sera:
SET TERM ^; -- establece como terminador el ^ a partir de esta sentencia. CREATE PROCEDURE MI_PROCEDIMIENTO . AS BEGIN

Vicente Tejero Trueba

Pag 2

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL) sentencia; --sentencia acabada en ; END ^ -- finaliza la definicin del procedimiento mediante el terminador indicado, el ^

Tema 6

SET TERM ;^ -- fija de nuevo el terminador como ; y acaba la sentencia con el terminador actual ^

2.2.- Variables. En PSQL se pueden usar 5 tipos de variables en el cuerpo de un mdulo, con algunas restricciones segn sea procedimiento o trigger: - Variables locales, usadas para mantener valores locales en un mdulo. - Las variables NEW.columna y OLD.columna usadas en los triggers para almacenar los valores modificados de la fila o los antiguos. - Variables de contexto. - Argumentos de entrada pasados como constantes en los procedimientos almacenados. - Argumentos de salida, usados para devolver valores en los procedimientos almacenados. Las variables pueden usarse en sentencias SQL dentro de los mdulos aunque en este caso se preceden por : para diferenciarlas de las columnas de las tablas.
FOR SELECT cod_accta FROM ACCIONISTAS INTO :variable DO -- Variable lleva : al estar dentro de un select. BEGIN otra = otra + variable variable no lleva los : al no aparecer en una sentencia select. END

Una variable se asigna mediante el = ( variable = expresin), en donde se puede asignar a una variable cualquier expresin en la que usemos variables, operadores, funciones SQL.
codigo = GEN_ID(generador,1); codigo = codigo + IIF(codigo<0,0,codigo);

Las variables locales se declaran, una por una, antes del primer BEGIN siendo su mbito nicamente el cuerpo del procedimiento o trigger. En la misma sentencia es posible darles un valor: DECLARE VARIABLE variable {<tipo> | <dominio> | TYPE OF <dominio> | TYPE OF COLUMN <tabla o vista>.<columna>} [{DEFAULT valor } | {= valor}];
DECLARE VARIABLE variable INTEGER DEFAULT 0; DECLARE VARIABLE cadena CHAR(20) = hola;

En PSQL se pueden usar todas las variables de contexto y literales comentados en temas anteriores como NOW, CURRENT_USER, etc. Adems se define la variable ROW_COUNT que contiene el nmero de filas afectadas por la ltima sentencia de DML ejecutada. Los argumentos de entrada se definen en los procedimientos almacenados para que la aplicacin pueda pasar valores al mismo. Son declarados en la cabecera pudindose usar en cualquier punto del cuerpo. Los argumentos de entrada son siempre pasados por valor, por lo que cualquier cambio que se produzca dentro del cuerpo no se enva al exterior.

Vicente Tejero Trueba

Pag 3

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

A los argumentos de entrada se les puede asignar un valor por defecto lo que hace que se pueda omitir en la llamada al procedimiento. En este caso, una ver definido uno, todos los siguientes deben tener tambin un valor por defecto y omitirse en la llamada. Los argumentos de salida se definen en los procedimientos almacenados para que puedan devolver valores a la aplicacin que los llama. Se declaran en la cabecera pudindose usar en cualquier punto del cuerpo. CREATE PROCEDURE procedimiento [({arg_entrada <tipo> [= valor_defecto]}[, ] )] argumentos de entrada. [RETURNS ({arg_salida <tipo>}[, ] )] argumentos de salida.
CREATE PROCEDURE procedimiento (entrada INTEGER=0) RETURNS (salida INTEGER) AS DECLARE VARIABLE variable INT; BEGIN variable = entrada /2; salida =variable; END

OLD y NEW son exclusivos de los triggers. OLD contiene los valores de la fila para la que se activa el trigger antes de la modificacin o borrado. NEW los valores de la fila modificados o insertados. Estas variables se vern con ms detenimiento con los triggers.

2.3.- Sentencias bsicas. En PSQL existe la sentencia bloque, es decir, aquella que permite definir en su interior otras sentencias. En PSQL es BEGIN . END. Se usa tanto para el bloque principal como para otros internos. En PSQL se trabaja con la sentencia condicional IF THEN . ELSE. sta tiene como sintaxis: IF (<condicion>) THEN <sentencia compuesta> [ELSE <sentencia compuesta>] <sentencia compuesta> = {<bloque> | <sentencia>;} La clusula <condicion> es un predicado que se evalua a true o false. Si vale true se ejecuta la sentencia del THEN. Si vale false se evalua, si existe, la sentencia del ELSE. Podemos utilizar cualquier predicado. Por ejemplo podramos tener:
IF (EXISTS (select * from accionistas where cod_accta=:cod)) THEN var=BUENA; IF (nombre in (PEDRO,JUAN)) THEN var= nombre; ELSE

Vicente Tejero Trueba

Pag 4

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL) var=desconocido;

Tema 6

En PSQL se define una sentencia de tipo bucle: WHILE DO. WHILE (<condicion>) DO <sentencia compuesta> <sentencia compuesta> = {<bloque> | <sentencia>;} Por ejemplo podramos tener, el siguiente procedimiento que suma todos los nmeros desde el 0 hasta el que se indica como parmetro de entrada:
CREATE PROCEDURE SUMA (i INTEGER) RETURNS (su INTEGER) AS BEGIN su=i; i=i-1; WHILE (i>0) DO BEGIN su=su+i; i=i-1; END END

2.4.- Cursores. Un cursor es un elemento que nos permite obtener los valores de una fila perteneciente a un conjunto de salida obtenido a partir de una sentencia SELECT. En Firebird se trabaja tanto con cursores explcitos, definidos explcitamente, como con cursores implcitos, aparecen por debajo de una sentencia sin que nos demos cuenta. En los cursores implcitos nos encontramos con: SELECT . INTO ..: Se usa para asignar los campos de la nica fila obtenida en una sentencia a unas variables. Es semejante a una asignacin en la que la expresin se obtiene de la sentencia SELECT.
SELECT first 1 cod_accta, nom_accta FROM accionistas slo puede devolver una fila INTO :var_codigo, :var_nombre -- se almacenan los campos en las variables indicadas

La sentencia SELECT debe devolver como mximo una sla lnea. Se deben indicar tantas variables como campos se devuelvan. FOR SELECT: Se utiliza para recorrer una sentencia SELECT que devuelve una o ms filas realizando operaciones sobre los datos devueltos. FOR SELECT <lista columnas> FROM . INTO <lista variables> DO BEGIN <sentencias> [SUSPEND;]
Vicente Tejero Trueba Pag 5 IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

END En este caso se deben indicar tantas variables y del mismo tipo como columnas devuelva la sentencia. Por ejemplo podemos tener un procedimiento que obtiene la mxima cotizacin para un banco dado y actualiza el valor en la tabla bancos.
CREATE PROCEDURE ACT_PRE_MAX (banco INTEGER) AS DECLARE VARIABLE MAXIMO NUMERIC(12,2); DECLARE VARIABLE VALOR NUMERIC(12,2); BEGIN MAXIMO =0; FOR SELECT pre_ac_fe FROM cotizaciones WHERE cod_banco=:banco INTO :VALOR DO BEGIN IF (VALOR>MAXIMO) THEN VALO=MAXIMO; END UPDATE BANCOS SET PRE_MA_AC=:MAXIMO WHERE COD_BANCO=:BANCO; END ^

EXECUTE STATEMENT . INTO: Es equivalente a SELECT INTO con la diferencia de que aqu lo que se indica es una cadena que contiene la sentencia a ejecutar. Esto nos permite definir sentencias dinmicas.
sentencia = select first 1 cod_banco from bancos; --crea la sentencia en tiempo de ejecucin EXECUTE STATEMENT sentencia INTO :codigo; -- se ejecuta la sentencia almacenando el resultado en una variable

Mediante esta sentencia se pueden ejecuta sentencias que no devuelven filas como INSERT, UPDATE, DELETE, EXECUTE PROCEDURE y cualquier sentencia DDL excepto las de CREATE/DROP DATABASE. Se tiene que tener en cuenta que dentro de un mdulo no es posible ejecutar sentencias DDL directamente. Por ejemplo para ejecutar un procedimiento que se pasa como parmetro podramos tener:
CREATE PROCEDURE EJECU_PROCE(PROCE VARCHAR(30)) AS DECLARE VARIABLE SENTENCIA VARCHAR(1000); BEGIN SENTENCIA = EXECUTE PROCEDURE || PROCE; EXECUTE STATEMENT SENTENCIA; END^

FOR EXECUTE STATEMENT: Al igual que FOR SELECT permite recorrer las filas devueltas al ejecutar una sentencia. FOR EXECUTE STATEMENT sentencia INTO <lista variables> DO BEGIN <sentencias> END

Vicente Tejero Trueba

Pag 6

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

Cuando usemos esta sentencia tenemos que tener en cuenta que debemos garantizar que la cadena que generemos sea correcta, puesto que, a diferencia de FOR SELECT, la sentencia no es validada en el momento de definir el procedimiento. Tambin tenemos que tener en cuenta que la sentencia se ejecutar de forma m lenta ya que tiene que ser compilada cada vez que se vaya a ejecutar. Por ejemplo si queremos crear un procedimiento que concatene un campo cadena de una tabla podramos tener:
CREATE PROCEDURE CONCATENAR (TABLA VARCHAR(30), CAMPO VARCHAR(30)) RETURNS (CADENA VARCHAR(2000)) AS DECLARE VARIABLE SENTENCIA VARCHAR(1000); DECLARE VARIABLE VALOR VARCHAR(1000); BEGIN CADENA=; SENTENCIA = SELECT || CAMPO || FROM || TABLA; FOR EXECUTE STATEMENT SENTENCIA INTO :VALOR DO BEGIN CADENA = CADENA || , +VALOR; END END ^

Mediante la sentencia FOR SELECT es posible definir los procedimientos almacenados seleccionables, es decir, aquellos que pueden actuar como tablas en sentencias SELECT, en contraposicin con los procedimientos almacenados ejecutables que son aquellos que ejecutan una operacin programada. Un procedimiento almacenado ejecutable se obtiene con la inclusin de una sentencia SUSPEND dentro del bucle DO. Esto causa que, una vez asignadas las variables correspondientes al cursor, el bucle se pare hasta que la fila sea recogida por el servidor. Por ejemplo si queremos un procedimiento que devuelva un nombre propio para cada banco podramos tener:
CREATE PROCEDURE MIS_BANCOS () RETURNS (COD_BANCO VARCHAR(100)) AS BEGIN FOR SELECT COD_BANCO,NOM_BANCO FROM BANCOS INTO :COD_BANCO, MI_NOMBRE DO BEGIN MI_NOMBRE=EL BANCO ES || MI_NOMBRE; SUSPEND; END END ^ INT, MI_NOMBRE

Se podra llamar
select * from MIS_BANCOS()

Los cursores explcitos son aquellos que se definen de forma explcita mediante una sentencia de declaracin. En Firebird nos encontramos con las siguientes sentencias de gestin de cursores:
Vicente Tejero Trueba Pag 7 IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

DECLARE [VARIABLE] <nombre cursor> CURSOR FOR ( <sentencia select> ); OPEN < nombre cursor >; FETCH < nombre cursor > INTO <variable> [, <variable> ...]; CLOSE < nombre cursor >; Con los cursores explcitos se tienen que tener una serie de consideraciones: - Dos cursores no pueden tener el mismo nombre aunque si un cursor y una variable. Los nombres de cursores deben ser nicos. - Intentar hacer un fetch (devolver los valores para la fila actual) en un cursor no abierto da un error. - Se usa ROW_COUNT para comprobar si fetch devuelve o no filas. Por ejemplo el procedimiento MIS_BANCOS mediante cursores podra ser:
CREATE PROCEDURE MIS_BANCOS () RETURNS (COD_BANCO VARCHAR(100)) AS DECLARE MI_CURSOR CURSOR FOR SELECT COD_BANCO,NOM_BANCO FROM BANCOS declaro el cursor para la sentencia BEGIN INT, MI_NOMBRE

OPEN MI_CURSOR; -- abro el cursor. FETCH MI_CURSOR INTO :COD_BANCO, MI_NOMBRE; --obtengo los valores para la fila WHILE (ROW_COUNT>0) DO BEGIN MI_NOMBRE=EL BANCO ES || MI_NOMBRE; SUSPEND; FETCH MI_CURSOR INTO :COD_BANCO, MI_NOMBRE; END CLOSE MI_CURSOR; -- cierro el cursor. END ^

2.5.- Sentencias de control de flujo. Firebird proporciona varias sentencias que afectan al control de flujo: - SUSPEND: ya se ha comentado anteriormente. - EXIT: Hace que se vaya al final de un procedimiento. - END: Finaliza la ejecucin. Segn se tenga un procedimiento ejecutable, seleccionable o un trigger estas sentencias pueden trabajar con ciertos matices: MODULO SUSPEND Procedimiento Se suspende la ejecucin seleccionable hasta que la aplicacin solicite un nuevo registro al procedimiento Procedimiento Salta al END final (no se ejecutable aconseja) trigger No se usa EXIT Devuelve los valores (si los hay) y salta al END final Salta al END final Salta al END final END Devuelve el control a la aplicacin y pone SQLCODE a 100

Devuelve los valores y pasa el control a la aplicacin. Hace que se ejecute el siguiente trigger en la misma fase (AFTER o BEFORE)si hay. En otro caso termina el trigger.
IES Pedro Espinosa

Vicente Tejero Trueba

Pag 8

Firebird: SQL Procedimental (PSQL)

Tema 6

Adems de los anteriores se tiene la sentencia LEAVE. Se usa en los bucles para salir de ellos. Hace que se pase a la siguiente sentencia fuera del bucle.
CONT=0; WHILE (1=1) DO -- esta codicin supone un bucle infinito. BEGIN CONT=CONT+1; IF (CONT>9) THEN LEAVE; -- solo se puede salir mediante LEAVE. END .. cuando se ejecuta LEAVE se va a la siguiente sentencia

2.6.- Ejecucin de cdigo. En PSQL es posible ejecutar directamente procedimientos almacenados, sentencias y ms recientemente bloques de cdigo. Un procedimiento almacenado se ejecuta mediante la sentencia EXECUTE PROCEDURE. EXECUTE PROCEDURE procedimiento [(] [argumento [, .]] [)] [RETURNING_VALUES variable[,]; Esta sentencia permite llamar a un procedimiento almacenado indicando valores para los argumentos de entrada. Si se definen argumentos de salida se pueden devolver los valores en las variables indicadas.
EXECUTE PROCEDURE suma 5 RETURNING_VALUES :resultado; -- se llama al procedimiento suma visto en ejemplos anteriores.

Recientemente Firebird ha incluido la sentencia EXECUTE BLOCK. Esta sentencia no es realmente una sentencia de PSQL aunque hace que un PSQL dinmico est disponible en una sentencia SELECT. Tiene el efecto de que un bloque de cdigo de PSQL se pueda ejecutar en una sentencia de DSQL como si fuera un procedimiento almacenado. Su sintaxis es: EXECUTE BLOCK [ (parmetro tipo = ?[, parametro tipo = ? ...) ] [ RETURNS (parametro tipo[, param datatype ...]) ] AS [DECLARE VARIABLE var datatype; ...] BEGIN ... END

2.7.- Eventos. Los eventos son un mecanismo por el que desde Firebird se pueden enviar seales a las aplicaciones para notificar cualquier suceso de forma asncrona, es decir, sin que la aplicacin tenga que estar a la espera. Se envan eventos mediante:
Vicente Tejero Trueba Pag 9 IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

POST_EVENT evento;

Vicente Tejero Trueba

Pag 10

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

3.- PROCEDIMIENTOS ALMACENADOS


Un procedimiento almacenado es un mdulo escrito en PSQL, compilado por el interprete de lenguaje binario de Firebird y almacenado como cdigo ejecutable en los metadatos de la base de datos. Una vez compilado, el procedimiento puede ser invocado directamente desde una aplicacin u otro mdulo PSQL usando EXECUTE PROCEDURE o una sentencia SELECT. Se distinguen dos tipos de procedimientos almacenados: - Ejecutables: Son los procedimientos que se llaman con la sentencia EXECUTE PROCEDURE y que pueden devolver, opcionalmente, una nica fila de uno o ms valores. Se usan a menudo para realizar operaciones de insercin, actualizacin o borrado, o para larzar un conjunto de operaciones. - Seleccionable: Los procedimientos seleccionables son escritos con extensiones del lenguaje para generar un conjunto de salida de mltiples filas que es devuelto usando una sentencia SELECT. En principio no se hace distincin entre procedimiento ejecutable o seleccionable. Cuando son llamados, y no se ajustan a la forma de llamada, el sistema genera una excepcin. Es por tanto funcin del programador garantizar que se usan de la forma apropiada. Un procedimiento se crea mediante la sentencia CREATE PROCEDURE: CREATE PROCEDURE procedimiento [(argumento tipo[{= | DEFAULT} valor] [, argumento tipo[{= | DEFAULT} valor])] [RETURNS (argumento tipo [, argumento tipo])] AS aqu empieza el cuerpo [DECLARE [VARIABLE] variable tipo[{= | DEFAULT} valor]; BEGIN <sentencias> END <terminador> Como se ve se pueden indicar una lista de argumentos de entrada a los que se les pueden asignar valores por defecto. En este caso todos los siguientes argumentos de entrada deben tener tambin definidos valores por defecto. Se puede indicar uno o mas argumentos de salida mediante la clusula RETURNS. Se pueden declarar variables antes del bloque principal. Por ejemplo podramos tener
CREATE PROCEDURE PRUEBA (entrada integer = 10) se define un argumento de entrada con valor por defecto 10 RETURNS (salida integer) -- se define un argumento de salida AS DECLARE VARIABLE NUEVA INTEGER=3; -- declaramos una variable local BEGIN /* Procedure body */ nueva=nueva+entrada+5; -- usamos las variables locales y los argumentos salida=nueva; -- se rellena un argumento de salida SUSPEND; -- se envia la fila a la aplicacin que lo llame. END

Vicente Tejero Trueba

Pag 11

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

El anterior procedimiento se podra llamar como:


select * from prueba se llama como procedimiento seleccionable sin rellenar los argumentos select * from prueba(5) se llama al procedimiento seleccionable indicando el argumento

o como procedimiento ejecutable dentro de otro


.. AS DECLARE VARIABLE varia integer; BEGIN . execute procedure prueba(3) RETURNING_VALUES (varia); . END

En este caso la llamada al procedimiento ha funcionado tanto como seleccionable como ejecutable ya que devolva como mximo una fila. Si el procedimiento se hubiera definido para que devolviera mas de una fila (Sentencia suspend dentro de un for select , ) nos habra dado una excepcin al llamarlo mediante EXECUTE PROCEDURE. Una ventanja de los procedimientos almacenados es que se pueden definir de forma recursiva, es decir, se pueden llamar a s mismos. En Firebird se establecen varios mecanismos para modificar un procedimiento almacenado: {CREATE | ALTER | RECREATE | CREATE OR ALTER} PROCEDURE procedimiento [(argumento tipo[{= | DEFAULT} valor] [, argumento tipo[{= | DEFAULT} valor])] [RETURNS (argumento tipo [, argumento tipo])] AS aqu empieza el cuerpo [DECLARE [VARIABLE] variable tipo[{= | DEFAULT} valor]; BEGIN <sentencias> END <terminador> ALTER es el mtodo de ms bajo imparto para cambiar un procedimiento ya que, si ho hay dependencias que se vean afectadas, se puede ejecutar sin problemas. Para que se pueda ejecutar debe existir previamente el procedimiento. RECREATE es idntico a CREATE con la adiccin de que previamente hace un DROP PROCEDURE. En este caso se producirn excepciones si existen dependencias (no se puede borrar el objeto si antes no se eliminan las dependencias). CREATE OR ALTER crea un procedimiento si no existe. Si ya existe ejecuta una operacin ALTER. Un procedimiento se borra mediante DROP PROCEDURE procedimiento. Un procedimiento slo lo puede borrar el usuario SYSDBA o el propietario del procedimiento. Adems, para que se pueda realizar, no puede estar siendo usado en ninguna transaccin ni tener dependencias en otros objetos de la base de datos. Si el procedimiento es recursivo se necesita borrar en primer lugar la llamada a s mismo.

Vicente Tejero Trueba

Pag 12

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

4.- TRIGGERS
Un trigger o disparador es un mdulo que se ejecuta de forma automtica cuando se cambia el estado de una fila como respuesta a una peticin. Los triggers no se pueden invocar por aplicaciones u otros procedimientos. Adems, no pueden tener argumentos de entrada o salida. Los triggers se ejecutan a nivel de fila, una por cada imagen de fila cambiada y se establece un alto grado de granularidad en cuanto a cuando, en que orden condiciones se dispara un trigger particular. Esto se establece mediante la fase, evento y secuencia. Un trigger se puede ejecutar en una de dos fases relativas a la ejecucin de la peticin de cambio realizada: antes (befote) de escribir o despus (alter). En un trigger es posible definir esta fase en relacin a un evento (insercin, actualizacin o borrado) o a varios de ellos. En resumen tenemos que: Tipo trigger BEFORE INSERT AFTER INSERT Descripcin Se lanza antes de que se cree una nueva fila. Permite que se puedan cambiar los valores de entrada Se dispara despus de que se cree una nueva versin del registro. No se permite cambiar los valores de entrada. Normalmente se usa para modificar otras tablas Se dispara antes de que se cree una nueva versin del registro. Se permiten cambios en los valores de entrada Se lanza despus de que se cree una nueva versin del registro. No se permiten cambios en los valores de entrada. Normalmente se usa para modificar otras tablas Se lanza antes de que una fila existente se borre. No acepta cambios a ninguna columna en la fila. Se dispara despus de que una fila es borrada. Nose aceptan cambios a ninguna columna en la fila . Normalmente se usa para modificar otras tablas. Se dispara antes de que se ejecute cualquier cambio en el estado del dato. Se codifican las acciones de forma condicional. Se pueden hacer cambios en las columnas de la fila afectada salvo que sea una accin de borrado Se dispara despus de que se ejecute cualquier cambio en el estado del dato. Se codifican las acciones de forma condicional. No se pueden hacer cambios de la fila afectada.

BEFORE UPDATE AFTER UPDATE

BEFORE DELETE AFTER DELETE

BEFORE <evento> OR <evento> [OR <evento>] AFTER <evento> OR <evento> [OR <evento>]

Firebird permite ejecutar mltiples triggers para cada combinacin fase/evento. Para establecer el orden en el que se ejecutan se define un nmero de secuencia. Por defecto vale 0. Si se indican nmeros de secuencia se ejecutan los triggers en orden ascendente. Cuando varios triggers tienen definidos el mismo nmero de secuencia, se establece un orden alfabtico por sus nombres. Un trigger puede estar activo o inactivo. Slo se disparan los triggers activos. El estado se puede modificar mediante la sentencia ALTER. Un trigger se crea mediante la sentencia CREATE TRIGGER: CREATE TRIGGER nombre FOR {tabla | vista} [ACTIVE | INACTIVE ]

Vicente Tejero Trueba

Pag 13

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

{BEFORE |AFTER } {{DELETE | INSERT | UPDATE } | { DELETE OR {[INSERT [OR UPDATE]} | {INSERT OR []} | {UPDATE OR []}}} [POSITION numero] AS aqu empieza el cuerpo del trigger [DECLARE [VARIABLE] variable tipo[{= | DEFAULT} valor]; BEGIN <sentencias> END <terminador> Si usamos la sintaxis BEFORE INSERT OR DELETE OR UPDATE, se puede usar, dentro del cuerpo, las variables de contexto INSERTING, UPDATING y DELETING que indican ante que tipo de evento se est respondiendo. Adems de las variables anteriores, PSQL aporta las variables OLD y NEW. Contienen respectivamente los valores de las columnas existentes y los nuevos. No siempre estn disponibles. Por ejemplo ante un evento DELETE, solo tenemos valores OLD mientras que ante un INSERT solo tenemos NEW. Los triggers se usan para proporcionar valores por defecto, validar y transformar entradas del usuario, actualizar otras tablas relacionadas o para garantizar reglas de integridad.
CREATE TRIGGER BI_BANCOS FOR BANCOS BEFORE INSERT AS BEGIN new.nom_banco=upper(new.nom_banco); -- pasamos a maysculas el nombre de banco END

Un uso muy comn de los triggers es implementar las columnas autonumricas haciendo uso de un generador. Por ejemplo si tubieramos un generador llamado gen_cod_banco para generar codigos de bancos para la tabla bancos podramos tener el trigger:
CREATE TRIGGER BI_BANCOS FOR BANCOS BEFORE INSERT AS BEGIN IF (new.cod_banco is null) then si no se ha indicado un cod_banco new.cod banco=gen_id(gen_cod_banco,1); --se recoge el cod_banco del generador END

Un trigger puede ser modificado mediante las sentencia ALTER TRIGGER y CREATE OR ALTER TRIGGER. Ambas tienen una sintaxis semejante a la de CREATE TRIGGER con la nica diferencia que en ALTER TRIGGER no se indica la tabla sobre la que se trabaja: {{CREATE TRIGGER nombre} | {CREATE OR ALTER TRIGGER nombre FOR {tabla | vista}}} [ACTIVE | INACTIVE ] {BEFORE |AFTER } {{DELETE | INSERT | UPDATE } ..

Vicente Tejero Trueba

Pag 14

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

Los triggers se borran mediante la sentencia DROP TRIGGER nombre;

Vicente Tejero Trueba

Pag 15

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL)

Tema 6

5.- EXCEPCIONES
PSQL aporta un mecanismo para la gestin de errores. De forma estndar los mdulos gestionan las excepciones parando la ejecucin, deshaciendo el trabajo hecho desde la sentencia BEGIN inicial y pasando uno o ms mensajes de error. Una excepcin puede ocurrir por: - Error SQL: Mensajes SQL con cdigo negativo de SQLCODE. Adems se tienen otros cdigos SQLCODE que no representan error como el 0 (ejecutado correctamente) o el 100 (detectado fin de fichero). - Errores internos de Firebird: Tienen que ver con concurrencia, datos, metadatos y condiciones del entorno. Tienen un cdigo de error de nueve dgitos, normalmente empezando por 3355, que identifica de forma nica el GDSCODE. Un mismo SQLCODE puede ser descompuesto en varios GDSCODE de forma que te ltimo nos da una informacin mas precisa sobre el error producido. Cuando ocurre una excepcin se pueden trabajar muchas veces con ambos: SQLCODE y GDSCODE. Por ejemplo podramos tener el GDSCODE 335544747 usrname_too_long, el 335544768 password_too_long, 335544749 usrname_required, etc , todos bajo el mismo SQLCODE, el -85. - Excepciones de usuario: Son objetos creados en la base de datos y que se invocan cuando se cumple una condicin determinada. Como se ve , una excepcin no es ms que un mensaje que se genera cuando se produce un error. Todas las excepciones predefinidas (SQLCODE y GDSCODE) tiene mensajes de texto asociados. Una excepcin definida por el usuario se crea mediante CREATE EXCEPTION. CREATE EXCEPTION <nombre> <mensaje>; En donde nombre es un identificador de cmo mximo 31 caracteres y mensaje una cadena con conjunto de caracteres NONE. Por ejemplo podramos tener:
CREATE EXCEPTION BANCO_ERRONEO El nombre del banco no vlido;

Se puede borrar una excepcin (DROP EXCEPTION <nombre>) o modificar una existente (ALTER EXCEPTION <nombre> <mensaje>).

Las excepciones definidas internamente son lanzadas por el sistema en respuesta a errores que requieren que se pare la ejecucin. stas cubren un gran rango de condiciones incluyendo violaciones de restricciones de integridad, desbordamientos aritmticos y de cadena, referencias a objetos no existentes, corrupcin de datos, etc. Las excepciones GDSCODE y SQLCODE son las mismas que nos encontramos cuando se produce un error al ejecutar una sentencia de DSQL. Las excepciones de usuario, slo disponibles en mdulos PSQL, son usadas para codificar nuestros propios errores en la lgica de los programas. De esta forma podramos encontrarnos con un trigger usado para validar el nombre de un banco insertado o modificado:
CREATE TRIGGER BI_BANCOS FOR BANCOS trigger para validar el nombre del banco BEFORE INSERT OR UPDATE

Vicente Tejero Trueba

Pag 16

IES Pedro Espinosa

Firebird: SQL Procedimental (PSQL) AS BEGIN

Tema 6

IF (NEW.NOM_BANCO NOT CONTAINING BANCO) THEN si el nombre no cumple la condicin EXCEPTION BANCO_ERRONEO; lanzo la excepcin de usuario. END ^

Como se ve en este ejemplo, se puede lanzar una excepcin mediante la sentencia EXCEPTION: EXCEPTION [<nombre excepcion> [<mensaje en tiempo ejecucin>]] Si usamos esta sentencia sin ningn parmetro se puede relanzar la excepcin para que la gestione otro bloque. Otro uso posible es la de asignarle el mensaje directamente en tiempo de ejecucin.

Adems de poder lanzar nuestras propias excepciones Firebird aporta un mecanismo para gestionar, dentro de un mdulo, las excepciones generadas y as poder continuar con la ejecucin de nuestro cdigo. Esto se consigue mediante la sentencia WHEN: WHEN {<nombre excepcion> | GDSCODE codigo | SQLCODE codigo | ANY } DO BEGIN <sentencias> END Mediante la sentencia WHEN se cambia el mecanismo estndar de gestin de errores. Asi cuando se produce una excepcin se para la ejecucin del bloque en el que se produce. En lugar de pasar la ejecucin a la sentencia END final, se inicia un procedimiento de bsqueda de una sentencia WHEN que gestione la excepcin, comenzando por el bloque donde se produjo el error y pasando a los bloques ms externos. Una vez manejada la excepcin se continua con la ejecucin en la primera sentencia posterior al bloque de manejo de excepcin ejecutado. Una sentencia WHEN siempre se tiene que ubicar inmediatamente antes de una sentencia END (no puede haber otras sentencias entre ellas).
CREATE TRIGGER BI_BANCOS FOR BANCOS trigger para validar el nombre del banco BEFORE INSERT OR UPDATE AS BEGIN IF (NEW.NOM_BANCO NOT CONTAINING BANCO) THEN si el nombre no cumple la condicin EXCEPTION BANCO_ERRONEO; lanzo la excepcin de usuario. WHEN BANCO_ERRONEO DO capturo la excepcion y la gestiono. BEGIN NEW.NOM_BANCO = BANCO || NEW.NOM_BANCO; END END ^

Firebird aporta dos variables de contexto para poder consultar el error producido: SQLCODE y GDSCODE. Estas variables se asignan de forma automtica con el cdigo de error permaneciendo en el bloque de gestin de error. Fuera de este bloque siempre valen 0.

Vicente Tejero Trueba

Pag 17

IES Pedro Espinosa

Potrebbero piacerti anche