Muchos de los motores de bases de datos, están incursionando en nuevas tecnologías, aplicando las nuevas técnicas para el tratamiento de información.
Existe una marcada tendencia a responsabilizar la base de datos en los procesos de ejecución de procesos, para quitar carga a los clientes que como es de imaginar poseen menos recursos. En el paradigma Cliente/Servidor esta característica es fundamental, ya que el Cliente hace peticiones al Servidor, el cual resuelve la instrucción y retorna al Cliente los datos solicitados.
Interbase
posee una forma de almacenar código en la base de datos, que permite ejecutar una serie de instrucciones que corren en el motor; esta característica permite realizar operaciones que antes debían ser implementadas por el cliente, mediante el lenguaje utilizado.Estos procedimientos se denominan Stored Procedures (Procedimientos almacenados), y pueden ser escritos en el Lenguaje de Triggers y Procedimientos. Otra forma de código que puede ser almacenada, se realiza mediante procesos denominados Triggers.
En esta unidad, es objetivo que el lector conozca el funcionamiento de los Procedimientos almacenados, su utilidad, y como programarlos. Comprenda la sintaxis del Lenguaje de Procedimientos y pueda utilizarlos junto con los Triggers para realizar programas potentes y de gran rendimiento.
Primeramente se iniciará el estudio de los procedimientos almacenados; el concepto, como programarlos con el lenguaje de Procedimientos. Se comentarán algunas características particulares de ellos, así como su ejecución y manipulación.
Se presentarán ejemplos de como establecer parámetros de entrada y salida, como se debe programar un procedimiento SELECT, el cual devuelve conjuntos de datos; y cual es la forma o característica de una procedimiento de ejecución.
En la segunda parte, se tratará en concepto de disparadores (Triggers), su filosofía de ejecución y manipulación, las características propias de cada tipo de Trigger, y como manipularlos efectivamente.
Por último se indicará como programar las excepciones y manipulación de errores en Interbase, utilizando la instrucción WHEN.
¿QUE ES UN PROCEDIMIENTO ALMACENADO?
Un procedimiento embebido o almacenado, son procedimientos escritos en lenguaje de Trigger o procedimiento, que es almacenado en la base de datos como parte de los METADATOS.
Una vez creados, pueden ser llamados de cualquier aplicación, o ser sustituido en una cláusula SELECT como una tabla o vista.
Los procedimientos pueden recibir parámetros de entrada y retornar valores a las aplicaciones.
Muchos de los procesos que son implementados utilizando el mismo lenguaje en el que se ha desarrollado la aplicación cliente, puede ser sustituidos por procesos implementados a través de procedimientos almacenados; esto tienen un ingrediente muy importante, ya que el programador puede estructurar mejor el código, y le permitirá tener cierta agilidad y mejora en el tiempo que invierte, separando los procesos inherentes a la interfaz, con los procesos de manipulación de información.
Un comentario muy importante al respecto de los procedimientos almacenados, es la gran similitud o al menos lo que parece que se persigue, con las bases de datos orientadas a objetos; no quiero decir que el hecho de poder programar procedimientos almacenados implique tener una base de datos Orientada a Objetos, sino que la tendencia de los motores de bases de datos, es por ese rumbo.
VENTAJAS DE LOS PROCEDIMIENTOS ALMACENADOS
Podemos encontrar muchas ventajas al utilizar procedimientos almacenados, y dependiendo del proceso que el usuario decida que deba de ser implementado puede llegar a mejorar el rendimiento de una aplicación.
Aquí mencionamos a nivel general algunas de las ventajas que pueden ser acreditadas a los procedimientos almacenados (Stored Procedures).
CUANDO DEBEN USARSE PROCEDIMIENTOS ALMACENADOS
La utilización de los procedimientos almacenados esta en función de la aplicación que se este desarrollando; sin embargo, se pueden establecer una orientación que permita al programador intuir donde puede ser útil un procedimiento y donde resulta inoficioso.
Los siguientes casos generales pueden ayudar mucho a un programador en la definición de la estructura de la base de datos en cuanto a procedimientos almacenados se refiere :
CREACIÓN DE PROCEDIMIENTOS ALMACENADOS
Los procedimientos son creados en Interbase por medio de la instrucción CREATE PROCEDURE. Esta instrucción permite crear diferentes tipos de procedimientos que serán almacenados en la base de datos.
Se pueden crear dos tipos de procedimientos almacenados.
Procedimientos SELECT
Son procedimientos que pueden ser utilizados en una sentencia SELECT a cambio de una tabla o una vista. Un procedimiento de este tipo puede arrojar más de un valor como parámetro de salida, o un mensaje de error.
Procedimientos EJECUTABLES
Son procedimientos que un aplicación puede llamar directamente con la sentencia EXECUTE PROCEDURE . Puede opcionalmente retornar valores.
Ambos tipos de procedimientos son creados de la misma forma y tienen la misma sintaxis esencialmente, la diferencia esta en la forma como ha sido escrito y la forma como se utilizará.
ESTRUCTURA DE UN PROCEDIMIENTO ALMACENADO
Un procedimiento almacenado está compuesto de un encabezado y un cuerpo.
El encabezado contiene:
El cuerpo del procedimiento contiene:
SINTAXIS PARA LA CREACION DEL PROCEDIMIENTO
Para poder entender de una manera más práctica lo anteriormente mencionado, es importante observar la sintaxis para la creación de un procedimiento mediante la orden CREATE PROCEDURE:
CREATE PROCEDURE
nombre [ (parámetro Tipo_de_dato [, parámetro Tipo_de_dato …])][RETURNS ( parámetro Tipo_de_dato [, parámetro Tipo_de_dato …])]
AS
<Cuerpo del procedimiento>;
<Cuerpo del procedimiento =[ <Lista de declaración de variables> ]<bloque>
< Lista de declaración de variables > =
DECLARE VARIABLE
variable Tipo_de_dato;[DECLARE VARIABLE variable Tipo_de_dato; …]
<bloque> = BEGIN
<Sentencias>
[ <Sentencias> …]
END
<Sentencias> = { <bloque | Sentencia>;}
EJEMPLOS
Como puede observarse, la sintaxis es muy sencilla y es fácil de aprender por su simplicidad en las palabras reservadas. En el Cuadro 1 se resumen la aplicación de cada una de los elementos de la sintaxis. Los siguientes ejemplos aclaran mejor la sintaxis inicial.
1.
CREATE
PROCEDURE almacen_alta (ALMACEN CHAR(3))END
Cuadro 1.
Nombre |
Nombre del procedimiento |
Parámetro< Tipo_de_dato |
Parámetros de entrada que el programa que lo llama utiliza para pasar valores al procedimiento. |
RETURNS Parámetro < Tipo_de_dato |
Parámetros que el procedimiento utiliza para retornar valores a los programas que lo llaman. El procedimiento retorna los valores de salida cuando se utiliza SUSPEND en el cuerpo del procedimiento. |
AS |
Palabra que separa la cabecera del procedimiento del cuerpo. |
DECLARE VARIABLE Variable < Tipo_de_dato |
Declara las variables locales utilizadas solamente en el procedimiento. Cada declaración debe ser declarada con DECLARE VARIABLE y seguida por un punto y coma (;). Variable : Nombre de la variable local. Data type : tipo de dato de la variable local. |
Sentencia |
Una sentencia en lenguaje de Trigger y procedimiento. |
En este ejemplo se ilustra la creación de un procedimiento que acepta un parámetro entrada ALMACEN de tipo CHAR(3), y la declaración de dos variables Articulo y ArtTmp.
2.
CREATE
PROCEDURE con_dame_nivel (CUENTA VARCHAR(15))END
La anterior instrucción crear un procedimiento CON_DAME_NIVEL que acepta como parámetro de entrada CUENTA de tipo VARCHAR(15) y retorna una variable NIVEL de tipo SMALLINT.
3.
CREATE
PROCEDURE duplicadosBEGIN
....
END
Este ejemplo permite ilustrar que los parámetros de entrada son opcionales. La instrucción anterior crear un procedimiento DUPLICADOS que no tiene parámetros de entrada, pero que retorna una variable Z de tipo CHAR(4).
4.
CREATE
PROCEDURE log_entradas_entrada (MAQUINA VARCHAR(31), NOMBRE VARCHAR(31))(ENTRADA INTEGER, USUARIO INTEGER, FECHA DATE, EJERCICIO CHAR(4))
....
END
Este ejemplo permite ilustra la forma de colocar varios parámetros de salida. La instrucción crea un procedimiento LOG_ENTRADAS_ENTRADA que acepta dos parámetros de entrada MAQUINA y NOMBRE de tipo VARCHAR(31) cada una, y retorna cuatro variables de salida, ENTRADA y USUARIO de tipo INTEGER, FECHA de tipo DATE y ejercicio de tipo CHAR(4).
En las próximas secciones se estudiará mas a fondo cada una de las sentencias utilizadas dentro del cuerpo del procedimiento. Como se puede notar, los anteriores ejemplos únicamente ilustran la utilización de parámetros, tanto de entrada como de salida y la declaración de variables, que se utilizarán dentro del cuerpo del procedimiento.
Los anteriores ejemplo ilustran los posibles casos en la utilización de parámetros, eso es para dejar claro cualquier posibilidad y el lector tenga un ejemplo de cada uno. En el ejemplo de curso, se encuentran todos estos procedimientos, así como los que se utilizarán más adelante.
EJECUTANDO PROCEDIMIENTOS ALMACENADOS
Ya se ha estudiado la cabecera y la forma de declaración de parámetros de entrada y salida en la sección anterior. Ahora se estudiará las posibilidades para llamar procedimientos y la forma de ejecutarlos.
Para llamar un procedimiento se utiliza la instrucción SQL EXECUTE PROCEDURE, que tiene la siguiente sintaxis:
Desde SQL la sintaxis es :
EXECUTE PROCEDURE
[TRANSACTION Transacción] Nombre[: Parámetro [[INDICATOR]: Indicador]]
[, : Parámetro [[INDICATOR]: Indicador] …]
[RETURNING_VALUES
: Parámetro [[INDICATOR]: Indicador]
[, : Parámetro [[INDICATOR]: Indicador] …]];
En el cuadro 2 se describen cada una de las claúsulas anteriores.
Cuadro 2
ARGUMENTO |
DESCRIPCION |
TRANSACTION Transacción |
Específica la transacción bajo la cual, la ejecución ocurre |
Nombre |
Nombre de un procedimiento existente en la base de datos. |
Parámetro |
Parámetros de entrada y salida que pueden ser una variable del lenguaje host o constante |
RETURNING_VALUES : parámetro |
Variable Host que toma los valores de una parámetro de salida. |
[ INDICATOR] : Indicador |
Variable host para indicar NULL o valores desconocidos. |
Desde DSQL la sintaxis es :
EXECUTE PROCEDURE
Nombre [ parámetro [,parámetro …]][RETURNING_VALUES parámetro [,parámetro …]]
Desde ISQL
EXECUTE PROCEDURE
Nombre [parámetro [,parámetro …]]En ISQL no es necesario anotar parámetros de salida, ya que automáticamente retorna valores de salida.
EXECUTE PROCEDURE
llama a un procedimiento definido en la base de datos. Si el procedimiento requiere parámetros de entrada, deben de ser suministrados a través de variables del lenguaje host o como constantes. SI el procedimiento requiere parámetros de salida, deben de suministrarse en la claúsula RETURNING_VALUES por medio de variables host.EJEMPLOS
Los siguientes ejemplos ilustran las llamadas a procedimientos almacenados.
1.
EXECUTE
PROCEDURE escandallo_controla( :M, :HIJO);Se puede observar en este ejemplo el llamado al procedimiento escandallo_controla, el cual no retorna valores y utiliza dos parámetros de entrada.
Este procedimiento es llamado desde otro procedimiento, es por esa razón que las variables tienen los dos puntos (:), eso se explicará más adelante.
2.
EXECUTE
PROCEDURE escandallo_ajusta_articulo (:ARTICULO, :COSTO)En este caso el procedimiento escandallo_ajusta_artículo es ejecutado enviando dos parámetros :artículo y :costo y retorna en la variable :coste un parámetro de salida.
3.
En isql se puede ejecutar el procedimiento anterior, para ello no es necesario anotar valores de retorno, ya que automáticamente los desplegaría. La razón es muy obvia, no hay forma de declarar variables host en isql.
La instrucción se ejecutaría de la siguiente manera:
EXECUTE
PROCEDURE escandallo_ajusta_articulo (10, 1000)La instrucción EXECUTE PROCEDURE no se utiliza para ejecutar los procedimientos SELECT, es utilizada para llamar los procedimientos.
Para ejecutar un procedimiento SELECT, se utiliza en lugar de una tabla o vista, y se suplen los parámetros delimitados por comas (,). Observar el siguiente ejemplo :
1.
SELECT
producto FROM Obtener_Producto_costo(:Valor)ORDER BY
Producto;El resultado de la instrucción SELECT anterior en el resultado de la ejecución del procedimiento Obtener_producto_costo, y retorna el parámetro de salida en Producto.
Un procedimiento Select, puede ser utilizado en cualquier parte donde una tabla o vista se puede desplegar. La única diferencia, es que hay que suplir los valores de entrada al procedimiento.
MODIFICANDO Y ELIMINANDO PROCEDIMIENTOS ALMACENADOS
MODIFICACIÓN DE PROCEDIMIENTOS. ALTER PROCEDURE
Para modificar un procedimiento se utiliza ALTER PROCEDURE, esta sentencia cambia la definición de un procedimiento almacenado sin afectar sus dependencias.
La sintaxis de ALTER PROCEDURE es similar a la de CREATE PROCEDURE.
ALTER PROCEDURE
nombre[( variable Tipo_de_dato [, variable Tipo_de_dato …])]
[RETURNS ( variable Tipo_de_dato [, variable Tipo_de_dato …])]
AS
<Cuerpo del procedimiento;
EJEMPLO :
ALTER PROCEDURE
ESCANDALLO_CONTROLA (PADRE VARCHAR(10),HIJO VARCHAR(10))
AS
DECLARE VARIABLE
M VARCHAR(10) ;BEGIN
FOR SELECT MAESTRO FROM ART_ESCANDALLO WHERE (DETALLE = :PADRE ) INTO :M
DO BEGIN
IF ( M = HIJO ) THEN EXCEPTION ERROR_ESCANDALLO ;
EXECUTE PROCEDURE ESCANDALLO_CONTROLA :M,:HIJO;
END
END
La sintaxis del cuerpo del procedimiento se irá explicando en los próximos apartados, en el anterior ejemplo se ha utilizado para indicar las modificaciones.
Hay que tener mucho cuidado al modificar el orden y tipo de los parámetros de un procedimiento, tanto para el código escrito en el cuerpo, como para los otros procesos que lo estén utilizando.
Un procedimiento puede ser modificado en su totalidad, tanto parámetros como cuerpo del procedimiento.
ELIMINACIÓN DE PROCEDIMIENTOS. DROP PROCEDURE
La sentencia DROP PROCEDURE borra un procedimiento de la base de datos.
Hay que tener en cuenta que:
NOTA: Para tener una idea de los procedimientos y sus dependencias, utilice SHOW PROCEDURE.
La sintaxis es:
DROP PROCEDURE nombre;
Ejemplo:
DROP PROCEDURE ESCANDALLO_CONTROLA;
COMANDOS ADICIONALES DEL LENGUAJE DE LOS PROCEDIMIENTOS
Mas que comandos, se podrían definir como sentencias para procedimientos. Las sentencias disponible definen la sintaxis utilizada para crear el cuerpo del procedimiento. Esta sintaxis es resumida en el cuadro 3 de el siguiente ítem de tema.
RESUMEN DE SENTENCIAS PARA PROCEDIMIENTOS
Las sentencias aquí utilizadas corresponden al LENGUAJE DE PROCEDIMIENTOS Y TRIGGERS; la lista del cuadro 3, corresponden a las instrucciones que pueden utilizarse el los procedimientos almacenados.
Cuadro 3
BEGIN...END |
Define un bloque se sentencias que se ejecutan como uno. |
Variable = expresión |
Sentencia de asignación, la cual asigna el valor de una expresión a una variable local. |
/*Comentario */ |
Comentario del programador. |
EXCEPTION nombre |
Dispara una excepción. Una excepción es un error definido por el usuario, el cual retorna un mensaje de error a la aplicación, al menos que se utilice WHEN. |
EXECUTE PROCEDURE Nombre [variable[,variable..] [RETURNING_VALUES variable[,variable..]] |
Ejecuta procedimientos almacenados, con los argumentos de entrada listados, retornando valores en la lista de argumentos de salida. Todas las variables deben de ser locales. |
FOR <Sentencia Select DO <Sentencia |
Repite la sentencia de bloque seguida al DO , por cada fila retornada de la sentencia SELECT. |
<Sentencia Select |
Una sentencia SELECT simple, excepto que la cláusula INTO debe venir incluida. |
<Sentencia : |
Cualquier sentencia del lenguaje TRIGGER en una bloque BEGIN..END. |
IF <Condición THEN <Sentencia ELSE <Sentencia |
Se prueba la <Condición, si es verdadero, se ejecuta el bloque seguido a THEN, si es falso, se ejecuta la sentencia seguida al ELSE. |
<condición |
Una expresión booleana (TRUE, FALSE, UNKNOWN), generalmente son dos expresiones como operando de un operador de comparación. |
POST_EVENT nombre |
Graba el evento. |
WHILE <Condición DO <Sentencia |
Mientras que la condición es verdadera, ejecuta la sentencia. |
WHEN {<error [, <error…]|ANY} DO <Sentencia |
Sentencia de manejo de errores. Cuando uno de los errores especificados ocurre, se ejecuta la sentencia. Las sentencias WHEN deben de ir al final de un bloque, antes del END. |
<error |
Corresponde a EXCEPTION nombre, SQLCODE codigo_error o GDSCODE número. ANY , maneja cualquier error. |
SUSPEND |
En un procedimiento SELECT suspende la ejecución hasta el próximo FETCH. Retorna valores de salida. |
EXIT |
Salta el END del procedimiento. |
Define un bloque se sentencias que se ejecutan como uno. La forma como se define un bloque, es iniciando con la instrucción BEGIN y finalizando con END.
Las instrucciones que pueden manipular bloques son :
Ejemplo :
CREATE
PROCEDURE LOG_ENTRADAS_ENTRADA (MAQUINA VARCHAR(31), NOMBRE VARCHAR(31))....
END
Ejemplo:
BEGIN /* BEGIN del cuerpo del procedimiento*/
....
FOR
SELECT ARTICULO FROM ART_ARTICULOS INTO :ARTICULOBEGIN /* BEGIN del bloque de la sentencia FOR SELECT*/
END /*END del cuerpo del procedimiento*/
Ejemplo:
...
IF
( TITULO IS NULL ) THENEjemplo :
...
BEGIN /* BEGIN del cuerpo del procedimiento*/
CONTADOR = 1 ;
END /*END del cuerpo del procedimiento*/
Ejemplo :
BEGIN /* BEGIN del cuerpo del procedimiento*/
...
WHEN
SQLCODE -530 DOBEGIN /* BEGIN del bloque de la instrucción WHEN*/
VALOR = 1;
SUSPEND
;END /END del bloque de la instrucción WHEN*/
Los comentario se colocan entre /* y */. Los comentarios siempre serán útiles, tanto para el programador, como para los futuros programadores de la aplicación, ya que le permitirán tener una guía. Es aconsejable no solo colocar comentarios, sino buenos comentarios, que permitan de alguna forma leer el código fuente sin necesidad de realizar procesos complejos para entenderlo.
Ejemplo :
CREATE
PROCEDURE POTENCIA (BASE INTEGER, EXPONENTE INTEGER)/* Este procedimiento toma como parámetros la base y el exponente al que hay que */
/* Elevar la base para calcular la potencia. */
CONTADOR = 1 ; /* Lleva las interacciones desde el valor 1 hasta el valor del exponente */
/*
La lógica consiste en ir multiplicando la base por ella misma Exponente veces */
La asignación se ha definido como :
Variable = Expresión.
Hay que notar que el resultado de la expresión se almacena en una variable, así el lado derecho queda definido como una variable, donde VARIABLE puede ser un valor de un parámetro de salida o una variable declarada con DECLARE VARIABLE.
La expresión puede ser :
Ejemplo:
RESULTADO = ( RESULTADO * BASE ) ;
Ejemplo :
D_HASTA = D_DESDE - 1 ;
Ejemplo :
CODIGO = GEN_ID( CONTA_CLIENTES , 1 ) ;
Explicaremos más adelante la sintaxis para la creación de generadores y su significado en las base de datos Interbase.
Ejemplo :
VALOR := CONCAT(VALOR1,VALOR2);
Donde CONCAT es alguna función definida en una DLL, por ejemplo.
Ejemplo :
D_HASTA = CAST((
'12-31-' || EJERCICIO)AS DATE ) ;En este caso se asigna un valor fecha, a la variable D_HASTA a partir de la variable EJERCICIO de tipo CHAR.
BIFURACIONES USANDO IF THEN ELSE
Las instrucciones condicionales son muy importantes es todo lenguaje que se este utilizando, podría decirse que no tiene sentido un lenguaje sin instrucciones IF...THEN..
La sintaxis para escribir esta clase de instrucciones es muy similar a la de muchos lenguajes de programación, aquí incluimos la utilizada por los Procedimientos almacenados.
IF <Condición THEN
<Sentencia ELSE
<Sentencia
La forma de evaluarse cual de las dos sentencias se ejecuta, depende del valor resultante en la condición, si es verdadero, se ejecutara la primera sentencia, si en falso, se ejecutará la sentencia correspondiente al ELSE.
La sentencia corresponde a cualquier sentencia que pueda ejecutarse en un procedimientos almacenado, incluso puede ser otro IF...THEN.
Por medio de ejemplos se ilustrará como puede ser establecida la condición de la Condición.
EJEMPLOS:
1.
IF
( DESTINO = -1 ) THENEste ejemplo ilustra la forma más simple de una instrucción IF, la comparación de igualdad por medio del operador =. Se pueden utilizar otros operadores de comparación como son:
< Menor que
> Mayor que
= Igual
<= Menor o Igual
= Mayor o Igual
IS NOT NULL No es de valor nulo
IS NULL Es de valor nulo.
Como por ejemplo
....
IF
( USUARIO IS NULL ) THEN
2.
IF
( PERIODO IN ('00','13','17','19') ) THEN PER_CAL = '01' ;Se puede realizar la comparación de una variable en un rango de valores, estos son escritos como una lista separada por comas (,) y cada valor del mismo tipo de la variable.
3.
IF
((DEBE<0)OR(HABER<0)) THEN SEPUEDE = 0 ;Se pueden utilizar los operadores lógicos y los paréntesis para agrupar valores booleanos.
Los operadores lógicos AND y OR y NOT.
4.
IF
( PERIODO = '14' ) THEN PER_CAL = '04' ;Si se van a comparar valores de tipo CHAR con constantes, estas se encierran entre comillas simples.
La única forma de realizar bucles o secuencias repetitivas es a través del WHILE DO, me refiero a sentencias repetitivas sin utilizar conjuntos de datos, que se verá mas adelante, que pueden ser implementadas con sentencias FOR SELECT.
La sintaxis utilizada es muy común a la utilizada por pascal:
DO <Sentencia
La condición de la claúsula <Condición tiene las mismas características que la condición que se utiliza en la sentencia IF.. THEN. Por lo tanto sobra explicarla de nuevo en esta sección.
La sentencia corresponde a cualquier sentencia válida en el LENGUAJE DE PROCEDIMIENTOS Y TRIGGERS.
Utilizar bucles en los procedimientos almacenados es muy útil para realizar cálculos, pero no para hacer navegación con las tablas o vistas, para ello se utiliza la instrucción FOR SELECT.
EJEMPLO:
1.
CREATE
PROCEDURE POTENCIA (BASE INTEGER, EXPONENTE INTEGER)Esta es la forma práctica de realizar un proceso POTENCIA.
2.
FOR SELECT JOB_CODE, JOB_GRADE, JOB_COUNTRY
FROM JOB
WHERE LANGUAGE_REQ IS NOT NULL
INTO :CODE, :GRADE, :CTY
DO
BEGIN
I = 1;
WHILE (I <= 5) DO
BEGIN
SELECT LANGUAGE_REQ[:I] FROM JOB
WHERE ((JOB_CODE = :CODE) AND (JOB_GRADE = :GRADE)
AND (JOB_COUNTRY = :CTY)) INTO :LANG;
I = I + 1;
SUSPEND;
END
END
El anterior ejemplo es la forma de mostrar el contenido de un campo de tipo ARRAY, para ello, es necesario utilizar la sentencia WHILE DO.
USANDO DECLARACIONES DE TIPO DML DENTRO DE LOS PROCEDIMIENTOS
USANDO SELECT EN UN PROCEDIMIENTO
La sentencias SELECT se pueden utilizar dentro de un procedimiento almacenado, pero si devuelven un solo valor. Pueden ser utilizadas para recuperar valores de los campos de las tablas, que puedan ser manipulados para cualquier proceso referente al PROCEDIMENTO ALMACENADO que la utilice.
Debe de contener una claúsula INTO donde se almacene el valor de retorno de la consulta.
Ejemplo:
1.
CREATE
PROCEDURE DAME_NIVELES_CONTABLES (EMPRESA SMALLINT, EJERCICIO CHAR(4))En este ejemplo se ilustra como la instrucción SELECT retorna un solo valor, que almacena en la variable niveles que es el parámetro de salida del procedimiento.
2.
CREATE
PROCEDURE LOG_ENTRADAS_VALIDA_SA (NOMBRE VARCHAR(31), ENTRADA INTEGER)UPDATE
SYS_ENTRADAS SET USUARIO = :USUARIO ,En este ejemplo se ilustra un forma de realizar una sentencia UPDATE con los valores de retorno de la instrucción SELECT.
USANDO INSERT, UPDATE Y DELETE
En el último ejemplo se puede observar la forma de realizar una sentencia UPDATE. Una de las ventajas de los procedimientos almacenados, es que permiten realizar actualizaciones, inserciones y borrados de datos de cualquier tabla de la base de datos.
Esta característica permite realizar verdaderos procesos de transacción, accediendo a muchos recursos de la base de datos de una forma centralizada.
EJEMPLOS:
1.
CREATE
PROCEDURE LOG_ENTRADAS_SALIDA (ENTRADA INTEGER)El procedimiento LOG_ENTRADAS_SALIDA actualiza la tabla SYS_ENTRADAS con la fecha actual, dado un valor clave ENTRADA.
2.
CREATE
PROCEDURE LOG_ENTRADAS_ALTA (MAQUINA VARCHAR(31), LOGIN VARCHAR(31), OS VARCHAR(100))Cuando se ejecuta el procedimiento LOG_ENTRADAS_ALTA, se inserta en la tabla SYS_ENTRADAS el registro de la entrada del usuario.
3.
CREATE
PROCEDURE LOG_ENTRADAS_VACIA_2 (ENTRADA INTEGER)Este procedimiento se utiliza para borrar las entradas de la tabla SYS_ENTRADAS.
La orden FOR SELECT retorna múltiples registros en un procedimiento. La sintaxis utilizada es:
FOR <Sentencia Select
DO <Sentencia
La sentencia FOR SELECT es diferente de la sentencia SELECT, ya que es obligatorio incluir la claúsula INTO dentro de la sentencia SELECT para el FOR SELECT.
Otra diferencia fundamental es la forma como se ejecuta la sentencia FOR SELECT. Por cada registro que retorna la instrucción FOR SELECT, se ejecutan las sentencias de la instrucción DO.
La serie de ejemplo siguientes, ilustra la utilización de la instrucción FOR SELECT.
Ejemplos:
1.
CREATE
PROCEDURE CONTACTOS_AJUSTABEGIN
SELECT
MAX(CONTACTO)FROM SYS_CONTACTOS
WHERE
(TERCERO=:TERCERO) INTO :CONTACTO ;IF
(CONTACTO IS NULL) THEN CONTACTO = 0 ;UPDATE
SYS_TERCEROS SET CONTACTOS=:CONTACTOWHERE (TERCERO=:TERCERO) ;
END
END
Cuando se ejecuta el procedimiento CONTACTOS AJUSTA, primero realiza una selección de todos los terceros de la tabla contactos, por cada tercero selecciona el valor del contacto más alto, y lo actualiza en el campo de la tabla SYS_TERCEROS, ajustando el número de contactos del tercero.
2.
Este ejemplo muestra la creación de un procedimiento que contiene dos FOR SELECT anidados. Tiene el mismo comportamiento de dos ciclos anidados en programación. Las dos instrucciones están completamente relacionadas, para realizar un borrado en propagación.
CREATE
PROCEDURE CON_CUENTAS_BAJA_PROPAGA (EMPRESA SMALLINT, EJERCICIO CHAR(4))AND
(EJERCICIO=:EJERCICIO)AND(NIVEL=:NIVEL)) ;END
PROCEDIMIENTOS QUE ACEPTAN PARÁMETROS
Los parámetros de entrada son utilizados para pasar valores de una aplicación a un procedimiento; son declarados como una lista separada por comas y entre paréntesis. Una vez declarados pueden ser utilizados en cualquier lugar donde una expresión pueda aparecer.
Todos los parámetros son pasados por valor, es decir que si se modifican dentro del procedimiento no afecta su valor externo.
Ejemplo:
La siguiente sentencia declara un procedimiento con dos valores de entrada.
CREATE PROCEDURE
NUEVA_TERCEROCUENTA (TERCERO INTEGER, CUENTACOMP CHAR(23))
AS
PROCEDIMIENTOS QUE RETORNAN VALORES
Los parámetros de salida son utilizados para retornar valores a las llamadas desde aplicaciones. Son declarados como una lista separada por comas y entre paréntesis, después de la palabra RETURNS.
Una vez declarado puede ser utilizado en cualquier parte del código donde una expresión pueda aparecer
Ejemplo:
CREATE
PROCEDURE DAME_PRODUCTORETURNS
(CODIGO INTEGER)AS
BEGIN
CODIGO = GEN_ID( CONTA_PRODUCTOS , 1 ) ;
END
Un procedimiento que retorna valores lo hace por medio de SUSPEND.
En una instrucción SELECT que utiliza valores de un procedimiento los nombres de las columnas deben empatar con los nombres de los parámetros de salida y sus tipos de datos.
Si es un procedimiento ejecutable no es necesario que empaten los valores de salida.
PROCEDIMIENTOS QUE DEVUELVEN MÚLTIPLES REGISTROS. LA ORDEN SUSPEND
La sentencia SUSPEND suspende la ejecución de un procedimiento almacenado. SUSPEND también retorna valores en los parámetros de salida de un procedimiento.
SUSPEND no debería ser utilizado en procedimiento ejecutables, ya que la próxima sentencia nunca es ejecutada. Debería de ser utilizada EXIT para indicar explícitamente que la sentencia termina el procedimiento.
Para observar mejor ese comportamiento se utiliza la siguiente tabla:
Tipo de procedimiento |
Comando |
Procedimiento Select |
SUSPEND Suspende la ejecución del procedimiento hasta que el próximo FETCH retorne valores. EXIT Salta al final END END Retorna control a la aplicación Establece SQLCODE a 100 |
Procedimiento ejecutable |
SUSPEND : Salta al final END No recomendado EXIT Salta al final END END Retorna valores Retorna control a la aplicación |
Ejemplo:
CREATE PROCEDURE
P RETURNS (r INTEGER)AS
BEGIN
r = 0;
WHILE
(r < 5) DOBEGIN
r = r + 1;
SUSPEND
;IF (r = 3) THEN
EXIT
;END
END;
Si se utiliza el procedimiento en un SELECT entonces:
SELECT
* FROM P;Retorna valores de 1,2 y 3 a la aplicación que lo llama, ya que el SUSPEND retorna el corriente valore de "r" a la aplicación. El procedimiento termina cuando él encuentra EXIT.
Si el procedimiento es utilizado como un procedimiento ejecutable, por ejemplo:
EXECUTE PROCEDURE
P;Entonces retorna 1, ya que SUSPEND termina el procedimiento y retorna el valor corriente de "r" a la aplicación. Esto no es recomendado, pero es incluido a modo de ejemplo.
CONCEPTO Y USO DE LOS DISPARADORES EN INTERBASE. TRIGGERS
Un TRIGGER es una rutina asociada con una tabla o vista que automáticamente ejecuta una acción cuando un registro o fila en una tabla o vista es insertada, actualizada o borrada.
Un TRIGGER nunca es utilizado directamente, el automáticamente se ejecuta cuando un usuario intenta hacer un INSERT, UPDATE o DELETE en el registro de una tabla.
La utilización de TRIGGERS tiene una serie de ventajas:
Un TRIGGER es definido con CREATE TRIGGER, el cual esta compuesto de CABECERA(header) y CUERPO(body).
La cabecera contiene:
El cuerpo (body) contiene:
Todas las sentencias de código terminan con punto y coma(;), por lo tanto hay que utilizar SET TERM para modificarlo antes de la definición del TRIGGRES y luego colocarlo con SET TERM de nuevo.
La sintaxis es:
CREATE TRIGGER
nombre FOR { tabla | vista}[ACTIVE | INACTIVE]
{BEFORE | AFTER} {DELETE | INSERT | UPDATE}
[POSITION numero]
AS
< Cuerpo del TRIGGER< Cuerpo del TRIGGER =[< Lista de declaración de variables>]< bloque>
< Lista de declaración de variables > =
DECLARE VARIABLE
variable Tipo_de_dato;[DECLARE VARIABLE variable Tipo_de_dato; …]
< bloque > =
BEGIN
< Sentencia
>[< Sentencia … >]
END
< Sentencia >= {< bloque > | Sentencia;}
Donde se tiene que:
Nombre |
Nombre del TRIGGER, debe de ser único en la base de datos. |
Tabla |
Nombre de la tabla o vista causante de que se dispare en TRIGGER. |
ACTIVE O INCATIVE . |
Especifica la acción del TRIGGER en la transacción. |
BEFORE o AFTER |
Especifica si el TRIGGER se dispara : BEFORE : Antes de la operación asociada.AFTER : Después de la operación asociada.Las operaciones asociadas son : INSERT, DELETE y UPDATE. |
DELETE, UPDATE INSERT. |
Especifica la operación que causa que el TRIGGER se dispare. |
POSITION número |
Especifica el orden en que se disparan los TRIGGERS asociados a una acción. Los TRIGGERS para una tabla no tienen que ser consecutivos, se disparan también en orden alfabético. |
DECLARE VARIABLE Variable < Tipo_de_dato |
Declara las variables locales utilizadas solamente en el TRIGGER. Cada declaración debe ser declarada con DECLARE VARIABLE y seguida por un punto y coma (;). Variable : Nombre de la variable local. Tipo_de_dato : tipo de dato de la variable local. |
Terminador |
Terminador definido por SET TERM, el cual significa el final del cuerpo del TRIGGER. |
Sentencia |
Una sentencia en lenguaje de TRIGGER y procedimiento. |
Por medio de los siguientes ejemplos se puede entender mejor el cuadro anterior.
1.
CREATE TRIGGER
APUNTES_ACT_ASIENTO FOR CON_APUNTESACTIVE
AFTER INSERT POSITION 0AS
BEGIN
UPDATE CON_ASIENTOS SET TOTAL = ( TOTAL + NEW.TOTAL )
WHERE ( (EJERCICIO=NEW.EJERCICIO) AND
(NASIENTO =NEW.NASIENTO )) ;
END
Este es un TRIGGER de respuesta definido para la tabla CON_APUNTES, que se dispara después de cualquier inserción de un registro.
2.
CREATE TRIGGER
SYS_CONSTANTES_BI0 FOR SYS_CONSTANTESACTIVE BEFORE INSERT POSITION
0AS
BEGIN
EXCEPTION ERROR_REGISTRO_UNICO ;
END
Este TRIGGER se dispara antes que se inserte un registro en la tabla SYS_CONSTANTES.
La utilización de NEW y OLD se explicará más adelante.
El lenguaje de Procedimiento y TRIGGERS en un completo lenguaje para almacenar procedimientos y TRIGGERS.
Este lenguaje incluye:
Tanto los Procedimientos como los TRIGGERS utilizan el mismo lenguaje, con algunas diferencias
RESUMEN DE SENTENCIAS PARA TRIGGERS
BEGIN...END |
Define un bloque se sentencias que se ejecutan como uno. |
Variable = expresión |
Sentencia de asignación, la cual asigna el valor de una expresión a una variable local. |
/*Comentario */ |
Comentario del programador. |
EXCEPTION nombre |
Dispara una excepción. Una excepción es un error definido por el usuario, el cual retorna un mensaje de error a la aplicación, al menos que se utilice WHEN. |
EXECUTE PROCEDURE Nombre [variable[,variable..] [RETURNING_VALUES variable[,variable..]] |
Ejecuta procedimientos almacenados, con los argumentos de entrada listados, retornando valores en la lista de argumentos de salida. Todas las variables deben de ser locales. |
FOR <Sentencia Select DO <Sentencia |
Repite la sentencia de bloque seguida al DO , por cada fila retornada de la sentencia SELECT. <Sentencia SELECT : Una sentencia SELECT simple, excepto que la cláusula INTO debe venir incluida. <Sentencia : Cualquier sentencia del lenguaje TRIGGER en una bloque BEGIN..END. |
IF <Condición THEN <Sentencia ELSE <Sentencia |
Se prueba la <Condición, si es verdadero, se ejecuta el bloque seguido a THEN, si es falso, se ejecuta la sentencia seguida al ELSE. <condición : Una expresión booleana (TRUE, FALSE, UNKNOWN), generalmente son dos expresiones como operandos de un operador de comparación. |
NEW.columna |
Nueva variable de contexto que indica un nuevo valor de la columna en una operación INSERT o UPDATE. |
OLD.columna |
Variable de contexto que indica un valor anterior antes de una operación UPDATE o DELETE. |
POST_EVENT nombre |
Graba el evento. |
WHEN {<error [, <error…]|ANY} DO <Sentencia |
Sentencia de manejo de errores. Cuando uno de los errores especificados ocurre, se ejecuta la sentencia. Las sentencias WHEN deben de ir al final de un bloque, antes del END. <error : Corresponde a EXCEPTION nombre, SQLCODE codigo_error o GDSCODE número. ANY , maneja cualquier error. |
WHILE <Condición DO <Sentencia |
Mientras que la condición es verdadera, ejecuta la sentencia. |
La utilización de estas sentencias es similar a las sentencias utilizadas en procedimientos, la única diferencia es la utilización de las variables de contexto NEW y OLD que se verán más adelante.
Otro concepto importante para no dejarlo de lado, consiste en la utilización de la palabra reservada POSITION, para ello se puede observar el siguiente ejemplo.
Ejemplo de Cabeceras:
CREATE TRIGGER
A FOR CONSTANTES BEFORE UPDATE POSITION 5 AS …CREATE TRIGGER
B FOR CONSTANTES BEFORE UPDATE POSITION 0 AS …CREATE TRIGGER
C FOR CONSTANTES AFTER UPDATE POSITION 5 AS …CREATE TRIGGER
D FOR CONSTANTES AFTER UPDATE POSITION 3 AS …Cuando la siguiente actualización se ejecuta:
UPDATE
CONSTANTES SET MODO_DE_CONTADORES = ‘1’WHERE
MODO_DE_CONTADORES = ‘0’;
La siguiente secuencia se dispara:
TRIGGER
B , A , la actualización ocurre,TRIGGER
D , entonces C finaliza.Los TRIGGERS pueden utilizar dos variables de contexto: OLD y NEW.
La variable de contexto OLD se refiere al valor corriente o previo en un registro que esta siendo actualizado o borrado. OLD no es utilizado para INSERT ( No es lógico , no hay anterior valor). NEW no es utilizado para DELETE ( no es lógico porque no hay nuevo valor). Las variables de contexto son utilizadas para comparar valores de una columna antes y después de ser modificadas.
El siguiente ejemplo muestra la utilización de estas sentencias.
SET TERM !! ;
CREATE TRIGGER
EDITA_VENTAS_AU0 FOR VENTASAFTER UPDATE
BEGIN
SET TERM ; !!
Este TRIGGER se dispara después que se actualiza la tabla Ventas, Actualizando la tabla clientes con los nuevos acumulados de ventas
Un generador es un objeto que es automáticamente incrementado cada vez que la función GEN_ID() es llamada.
Los generadores son utilizados para asegurar que un número insertado en una columna sea único.
Un Generador es creado con CREATE GENERATOR e inicializado con SET GENERATOR, si no son inicializados comienzan con un valor de 1.
Los generadores deben de ser creados antes de utilizar GEN_ID()
La sintaxis de GEN_ID() es :
GEN_ID
( nombre , paso)Donde nombre es un generador creado anteriormente y paso se refiere a la cantidad que se incrementara el generador, Paso puede ser un valor entero o el resultado de una expresión.
Lo siguientes ejemplos ilustran la utilización del OLD y el NEW, junto con los generadors:
1.
CREATE TRIGGER
Alta_Movimientos_bi0 FOR MOVIMIENTOSBEFORE INSERT AS
BEGIN
NEW.MOVIMIENTO = GEN_ID( CONTA_MOVIMIENTOS , 1 ) ;
END
!!2.
CREATE TRIGGER
ART_FAMILIAS_BI0 FOR ART_FAMILIASACTIVE BEFORE INSERT POSITION
0AS
BEGIN
NEW
.IVA = 1 ;NEW
.CUENTA_COMPRAS = '60000000' ;NEW
.CUENTA_VENTAS = '70000000' ;NEW
.TITULO = 'FARMACIA' ;END
MODIFICANDO LOS TRIGGERS. ALTER TRIGGER
ALTER TRIGGER
puede modificar :La sintaxis es:
ALTER TRIGGER
nombre[ACTIVE | INACTIVE]
[{BEFORE |
AFTER} {
DELETE |
INSERT |
UPDATE}]
[POSITION numero]
AS < Cuerpo del TRIGGER ;
La sintaxis de ALTER TRIGGER es idéntica que la de CREATE TRIGGER. Excepto que FOR tabla, es omitida, ya que no se puede modificar la tabla donde el TRIGGER esta asociado.
Ejemplos:
1.
ALTER TRIGGER
ALTA_MOVIMIENTOS_BI0ACTIVE
BEFORE
INSERT;2.
ALTER TRIGGER
ALTA_MOVIMIENTOS_BI0 FOR MOVIMIENTOSBEFORE INSERT AS
BEGIN
NEW.MOVIMIENTO = GEN_ID( CONTA_MOVIMIENTOS , 2 ) ;
END
BORRANDO TRIGGERS . DROP TRIGGER
Un TRIGGER puede ser removido temporalmente o permanentemente. Para removerlo temporalmente se hace con ALTER TRIGGER y se especifica INACTIVE
Para borrarlo permanentemente se hace con DROP, cuya sintaxis es:
DROP TRIGGER
nombre;Ejemplo:
DROP TRIGGER
ALTA_MOVIMIENTOS_BI0;Los TRIGGERS pueden utilizarse de muchas formas, he aquí algunos ejemplos:
Los triggers son almacenados en la base de datos, como también los procedimientos y excepciones.
Una excepción es un mensaje de error con nombre que puede ser disparado desde un procedimientos almacenado. Las excepciones son creadas con CREATE EXCEPTION, modificadas con ALTER EXCEPTION y eliminadas con DROP EXCEPTION.
Para disparar una excepción desde un procedimiento almacenado, se utiliza la instrucción EXCEPTION de la siguiente manera:
EXCEPTION
Nombre_excepción;Para poderse utilizar una excepción es necesario crearla y almacenarla en la base de datos mediante COMMIT.
CREANDO, MODIFICANDO Y BORRANDO EXCEPCIONES
Para crear una excepción se utiliza la siguiente sintaxis.
CREATE EXCEPTION
nombre "<Mensaje";Ejemplo:
CREATE EXCEPTION
ERROR_ESTRUCTURA_BLOQUEADA "Estructura de contabilidad bloqueada".Para modificar una excepción se utiliza la siguiente sintaxis:
ALTER EXCEPTION
nombre "<Mensaje";Ejemplo:
ALTER EXCEPTION
ERROR_ESTRUCTURA_BLOQUEADA "Estructura bloqueada".Para borrar una excepción se utiliza la siguiente sintaxis:
DROP EXCEPTION
name;Para poderla borrar es necesario que no este siendo utilizada.
DESENCADENANDO (RAISE) UNA EXCEPCIÓN
Para disparar una excepción desde un procedimiento almacenado, utilizar la siguiente sintaxis:
EXCEPTION
nombre;El "nombre" es el nombre de una excepción que existe en la base de datos.
Cuando una excepción es llamada o desencadenada sucede lo siguiente:
Si la excepción es manipulada con una instrucción WHEN, el comportamiento es diferente:
Ejemplo:
IF
(any_sales 0) THENEXCEPTION
REASSIGN_SALES;Los procedimientos almacenados pueden manipular tres tipos de errores con una instrucción WHEN DO.
La instrucción WHEN ANY manipula cualquier tipo de errror.
La sintaxis para la instrucción WHEN DO es la siguiente:
WHEN
{< error [, < error …] | ANY}DO
<Sentencias< error ={EXCEPTION nombre de excepción | SQLCODE numero | GDSCODE código de error}
La instrucción WHEN permite manipular cualquier clase de error, sea una excepción creada por un usuario, un error del SQL o un error reportado por interbase. La instrucción WHEN debe de ir antes del END del bloque y es la última instrucción del bloque.
RESPUESTAS A LAS PREGUNTAS DE LA UNIDAD 8
En primer lugar se dará de alta en el servidor por medio del Server manager, de la utilidad gsec (comando add) o incluso se podría utilizar una herramienta propia que utilizase el API de interbase (en concreto la función isc_add_user).
Posteriormente se le concederían los derechos de lectura (Select) para cada una de las tablas de la base de datos con el comando GRANT.
La cláusula ALL concede de una vez los derechos select,insert,update,delete y references.
La clausula PUBLIC concede los derechos especificados a cualquier usuario.
La ventaja es que se manejan varios derechos/usuarios con una sola cláusula, y el inconveniente es que se manejan en bloque, por lo que se conceden y revokan de la misma forma.
1. QUE ES UN PROCEDIMIENTO ALMACENADO.
2. Puede un TRIGGER ser utilizado directamente desde una aplicación
3. ¿QUÉ ES UNA EXCEPCIÓN?
INDICE
¿Qué es un procedimiento almacenado?
Ventajas de los procedimientos almacenados
¿Cuándo deben de usarse procedimientos almacenados?
Creación de procedimientos almacenados
Estructura de un procedimiento almacenado
Sintaxis para la creación del procecedimiento
Ejecutando procedimientos almacenados
Modificando y eliminando procedimientos almacenados
Comando adicionales del lenguaje de los procedimientos
Bifuraciones usando IF THEN ELSE
Usando declaraciones del tipo DML dentro de los procedimientos
Usando INSERT, UPDATE Y DELETE
Procedimientos que aceptan parámetros
Procedimientos que retornan valores
Procedimientos que devuelven multiples registros. La orden SUSPEND
Concepto y uso de los disparadores en InterBase. TRIGGERS
Resumen de sentencias para TRIGGERS
Creando, modificando y borrando excepciones