Download sql embebido felipe garcía gómez - Escuela Superior de Informática

Document related concepts
Transcript
UNIVERSIDAD DE CASTILLA-LA MANCHA
ESCUELA SUPERIOR DE INFORMÁTICA
SQL EMBEBIDO
FELIPE GARCÍA GÓMEZ
Profesor:
D. Francisco Ruiz González
Asignatura:
Bases de Datos
Titulación:
Ing. Sup. Informática
Fecha:
14-Marzo-2001
SQL EMBEBIDO
1. INTRODUCCIÓN
2. ESTRUCTURA DE UN PROGRAMA
3. ELEMENTOS DE UN PROGRAMA CON SQL EMBEBIDO
3.1 DELIMITADORES
3.2 ÁREA DE COMUNICACIÓN
3.3 VARIABLES DEL PROGRAMA
4. INTRODUCCIÓN DE MANIPULACIÓN SIN CURSORES
5. INTRODUCCIÓN DE MANIPULACIÓN CON CURSORES
6. EJEMPLO
7. COMPILACIÓN
8. BIBLIOGRAFÍA
UCLM-ESI . Bases de Datos
1
SQL EMBEBIDO
1.INTRODUCCIÓN
El acceso a una base de datos relacional desde un programa se nos puede plantear necesario
cuando se piensa en el desarrollo de aplicaciones complejas que se necesitan: manipulación
individualizada de las tuplas, estructuras de programación tradicionales (selección y repetición),
interacción con el usuario y gestión de errores.
Por ello, la propuesta estándar del lenguaje SQL/92 proporciona distintas interfaces del
lenguaje, es decir una sintaxis para poder usar el SQL en distintos contextos. Estas interfaces son: el
SQL directo (o interactivo) y el SQL embebido.
El SQL embebido está pensado para ser utilizado intercalando sus instrucciones en el código de
un programa escrito en un lenguaje de programación al que se denomina lenguaje huésped (FORTRAN,
COBOL, C, etc.). Estas instrucciones se ejecutan cuando se ejecuta el programa de acuerdo a su lógica
interna. En este contexto, el intercambio de información con el SGBD se realiza a través de variables
del lenguaje, a las que se denomina variables huéspedes; por ejemplo, el resultado de las consultas es
asignado a variables del programa declaradas con ese fin.
Por tanto, la idea básica del trabajo con SQL embebido en lenguajes tradicionales es escribir un
programa que manipule la base de datos con SQL usando las estructuras de control y variables del
lenguaje tradicional.
La dificultad principal que se plantea en el acceso a una base de datos relacional desde un
programa reside en la incompatibilidad entre los tipos de estructuras del modelo de datos y del lenguaje
de programación. Para superar esta dificultad existen dos opciones:
- Restringir las consultas a aquellas que devuelvan una única tupla o
- Introducir algún mecanismo que permita seleccionar y manipular las tuplas de una relación
individualmente, este último mecanismo viene representado por los cursores.
En esencia un cursor es un puntero destinado a apuntar a las tuplas de una relación. El cursor
puede moverse a través de las tuplas de la relación, pudiéndose en cualquier momento seleccionar o
actualizar la tupla apuntada.
2.ESTRUCTURA DE UN PROGRAMA CON SQL EMBEBIDO
La estructura típica de un programa de manipulación de base de datos es la siguiente:
Programa …
Declaración de variables
…
Declaración de variables huéspedes para acceso a la base de datos
Programa……
Fin declaración
de variables huéspedes para acceso a la base de datos
Declaración
de variables
…
…
Fin
declaración
variables
Declaración
de de
variables
huéspedes para acceso a la base de datos
Comienzo
del
código
del programa
…
…
Fin declaración
de variables huéspedes para acceso a la base de datos
… instrucciones propias del lenguaje
…
Fin declaración
de variables
Conexión
a la base
de datos
Comienzo del código
del programa
…
…
instruccionespropias
de SQLdel lenguaje
instrucciones
...
…
Desconexión
de lade
base
de datos
Conexión
a la base
datos
…
…
instruccionesdepropias
instrucciones
SQL del lenguaje
…
...
Fin del código de programa
3.ELEMENTOS DE UN PROGRAMA CON SQL EMBEBIDO
UCLM-ESI . Bases de Datos
2
SQL EMBEBIDO
Ya hemos comentado que la inclusión de sentencias SQL dentro de un programa requiere que
se dote a éste de algunos nuevos elementos de programación.
Éstos permiten que existan dentro del programa sentencias escritas en un lenguaje (SQL) ajeno
al de programación y soportan la comunicación de peticiones y resultados entre el programa y el SGBD.
Son , entre otros, los siguientes:
- Delimitadores
Son partículas añadidas a la sintaxis de las sentencias SQL para distinguirlas dentro
del programa fuente.
- Área de Comunicación
Es un área de datos definida en el programa que es utilizada por el SGBD para
comunicarle a aquél si su última petición se ha ejecutado correctamente o no.
- Variables de Programa
Sirven principalmente para contener en ellas los valores de datos que el programa lee o
escribe en las columnas de las tablas.
3.1 DELIMITADORES
Los compiladores de un lenguaje no entienden las sentencias SQL como instrucciones propias
del mismo. Por ello, deben aquellas incluirse entre delimitadores que sirven para distinguirlas dentro del
texto del programa fuente y permiten que sean procesadas por el Precompilador.
Todas las instrucciones del SQL embebido van precedidas de las palabras reservadas EXEC
SQL, de forma que son fácilmente identificables por el precompilador, y finalizan con un símbolo
especial. En el lenguaje C este símbolo es el punto y coma (;).
3.2 ÁREA DE COMUNICACIÓN DE SQL
Cuando se ejecuta un programa que tiene sentencias SQL embebidas, éstas son ejecutadas por
el SGBD y luego éste devuelve al programa los datos pedidos, si existen. Además, debe devolver una
información que indique al programa si su petición se ha ejecutado correctamente o no. Para ello, se usa
un área definida dentro del programa que se llama Área de Comunicación de SQL (en inglés SQLCA:
SQL Communication Area).
La SQLCA consiste en un conjunto de variables que almacenan información sobre el estado (y
los errores, si se producen) de la última instrucción que el programa ejecutó sobre la base de datos.
Para poder hacer uso de estas variables hay que declararla de la siguiente manera:
EXEC SQL INCLUDE SQLCA;
En un programa, cualquier instrucción SQL debería estar seguida por código que controlase los
valores de las variables SQLCODE y SQLSTATE relativos a la ejecución de la instrucción; para
simplificar esta tarea el lenguaje proporciona una sentencia para el control general de errores, ésta es la
sentencia WHENEVER:
EXEC SQL WHENEVER condición acción
condición ::= {SQLERROR | NOT FOUND}
acción ::={CONTINUE | GO TO etiqueta}
-
NOT FOUND se evalúa a cierto si no se han encontrado datos que cumplan las condiciones
especificadas en la instrucción (SQLCODE =+100).
- SQLERROR se evalúa a cierto si ha ocurrido algún error en la ejecución de la instrucción
(SQLCODE < 0).
La sentencia WHENEVER no es una instrucción ejecutable, es más bien una directriz al
procesador del lenguaje SQL:
- WHENEVER condición GO TO etiqueta significa que el procesador de SQL incluirá detrás de
cualquier sentencia SQL del programa la sentencia IF condición THEN GO TO etiqueta
- WHENEVER condición CONTINUE significa que el procesador de SQL no tomará ninguna
acción siendo responsabilidad del programador controlar el flujo del programa.
UCLM-ESI . Bases de Datos
3
SQL EMBEBIDO
3.3 VARIABLES DEL PROGRAMA
Las variables del lenguaje que son utilizadas en instrucciones SQL (variables huéspedes) deben
ser declaradas en una sección especial encabezada y terminada de la siguiente forma:
EXEC SQL BEGIN DECLARE SECTION;
... declaración de tipos y variables en C
EXEC SQL END DECLARE SECTION;
Ejemplo:
EXEC SQL BEGIN SECTION;
char cd[6];
int aux;
char cpx[4];
char cpy[4];
EXEC SQL END DECLARE SECTION;
Las variables deben tener un tipo apropiado al uso que se va a hacer de ellas (la compatibilidad
de tipos entre el lenguaje de programación y el SGBD depende de cada sistema particular);
sintácticamente pueden aparecer en una instrucción SQL en cualquier lugar en el que puede aparecer un
literal y deben ir precedidas del símbolo dos puntos ( : ).
De las instrucciones SQL que se pueden utilizar, es interesante destacar dos de ellas: la
conexión a la base de datos y la desconexión. Estas instrucciones tienen la siguiente sintaxis:
EXEC SQL CONNECT 'base_datos';
EXEC SQL DISCONNECT;
Es necesario matizar que antes de efectuar cualquier operación sobre la base de datos es
necesario conectarse a la misma usando la primera instrucción. Asimismo, para un correcto
funcionamiento de las sesiones de base de datos en el servidor, es obligatorio desconectarse de la base
de datos antes de que el programa finalice.
4. INTRODUCCIÓN DE MANIPULACIÓN SIN CURSORES
Hay una necesidad de cursores debido a que:
- SQL interactivo maneja conjuntos en lugar de registros aislados.
- El lenguaje de programación maneja un registro a la vez.
- El cursor es el mecanismo que permite moverse en un conjunto de tuplas para ser manipuladas
de una en una.
Sin embargo, existen una serie de operaciones que no involucran cursores, éstos son:
- Select: Permite asignar a un conjunto de variables el contenido de una tupla resultante de una
operación
- Insert
- Update
- Delete
La estructura de SELECT es:
SELECT [ALL | DISTINCT] lista_elemento_ selección
INTO lista_variable
FROM lista_relación
[WHERE condición_búsqueda]
[GROUP BY lista_atributo]
[HAVING condición_búsqueda]
UCLM-ESI . Bases de Datos
4
SQL EMBEBIDO
Ejemplo: “Obtener el código del departamento al que pertenece el profesor de código ‘JRF’ ”.
EXEC SQL SELECT cod_departamento INTO :vector
FROM Profesor
WHERE cod_pro = ‘JRF’;
Aquí la variable vector recibirá el valor de la columna de la tabla Profesor que cumpla la
condición (como máximo una fila).
En este contexto, la sentencia SELECT debe devolver una única tupla, en caso contrario se
producirá un error.
Como se puede observar la única variante de la sentencia consiste en la cláusula INTO que
especifica la lista de variables del programa que serán utilizadas para recibir los datos seleccionados.
Las sentencias de actualización: UPDATE (Permite modificar una o más tuplas de una
tabla), INSERT (Permite agregar una tupla a una tabla) y DELETE (Permite eliminar una o más tuplas),
tienen la misma sintaxis que en el SQL interactivo con la única diferencia de que pueden incluir
variables huéspedes.
Ejemplo de actualización: “Transferir la docencia de un profesor cuyo código se lee en la variable cpx a
un profesor cuyo código se lee en la variable cpy (cpx y cpy declaradas en un ejemplo anterior)”.
EXEC SQL UPDATE Docencia
SET cod_pro = :cdy
WHERE cod_pro = :cdx
Ejemplo: Implementado en C con SQL embebido
#include <stdio.h>
EXEC SQL include sqlca;
main() {
EXEC SQL BEGIN DECLARE SECTION;
int cant;
EXEC SQL END DECLARE SECTION;
EXEC SQL connect to 'dbventas';
EXEC SQL
select count(*) into :cant
from cliente;
printf(``La cantidad de tuplas de la tabla Cliente es %d \n'', cant);
}
5. INTRODUCCIÓN DE MANIPULACIÓN CON CURSORES
Como se ha comentado anteriormente, un cursor es un objeto SQL que permite la manipulación
de las tuplas de una relación de forma individualizada; intuitivamente se puede ver como un puntero a
las tuplas de una relación.
Un cursor siempre va asociado a una relación que se especifica al ser declarado. Ya que el
objetivo de su uso es poder navegar a través de las tuplas que constituyen dicha relación para
posteriormente manipularlas, estas tuplas deben estar ordenadas, siendo este orden implícitamente
definido por el sistema o bien definido por el programador en la declaración del cursor.
Desde que el cursor es activado (apertura del cursor) siempre tiene una posición (posición
actual) dentro del conjunto ordenado de tuplas. Esta posición puede ser: delante de una tupla, en una
tupla, y detrás de una tupla. Esta posición actual va a ser relevante para las instrucciones de
manipulación de la base de datos basadas en el uso de cursores. A continuación se presentan cada una
de ellas.
UCLM-ESI . Bases de Datos
5
SQL EMBEBIDO
Definición del cursor
DECLARE cursor CURSOR
FOR cursor_especificación
cursor_especificación ::= expresión_de_relación
[ORDER BY lista_elemento_orden]
[FOR {READ ONLY | UPDATE [OF lista_nom_atributo]]
elemento_orden ::= {nom_atributo | entero_positivo} [ASC | DESC]
La expresión_de_relación define la relación asociada al cursor, que será una sentencia
SELECT; su sintaxis es la misma que la del SQL interactivo con la diferencia de que puede incluir
variables huéspedes.
La cláusula ORDER BY permite especificar un orden para las tuplas de la relación definida por
expresión_de_relación. Los nombres de atributo o los enteros positivos (ordinal de la posición de un
atributo) se refieren a atributos de la relación definida por expresión_de_relación; los enteros positivos
se utilizan cuando el correspondiente atributo de la relación no lleva un nombre, es decir es un dato
calculado. Si no se incluye la cláusula ORDER BY, el sistema establece un orden por defecto.
La cláusula FOR READ ONLY (o UPDATE [OF lista_nom_atributo] ) indica que la relación
asociada al cursor no puede (o puede) ser actualizada por medio de las instrucciones UPDATE y
DELETE.
Apertura del cursor
OPEN cursor
La apertura de un cursor en un programa significa la evaluación de la expresión_de_relación
asociada. Cuando un cursor se abre, su posición actual pasa a ser delante de la primera tupla.
Manejo del cursor y selección de tuplas
FETCH [[selector_de_tupla] FROM] cursor INTO lista_variables
La instrucción FETCH permite mover el cursor dentro del conjunto ordenado de tuplas y
seleccionar (leer) la tupla en la que queda colocado; su posición actual después de ejecutarse la
instrucción es en la tupla seleccionada .
El selector_de_tupla puede ser: next, prior, first, last, absolute n, relative n. Para los casos next,
prior y relative el movimiento es relativo a la posición actual del cursor antes de ejecutarse la
instrucción fetch. En las opciones absolute n y relative n, un número positivo (respectivamente,
negativo) indica movimiento hacia delante (respectivamente, detrás) según la secuencia de ordenación
de las tuplas.
La lista de variables debe contener una variable huésped por cada atributo de la relación
asociada al cursor, estas variables recibirán los valores de la tupla seleccionada.
Si la instrucción FETCH no selecciona ninguna tupla, es decir no existe la tupla siguiente (next)
o la tupla anterior (prior) a la tupla en la posición actual del cursor, o bien no existe la enésima tupla a
partir de la posición actual (absolute y relative) hacia delante (n positivo) o hacia detrás (n negativo),
entonces la posición actual del cursor después de ejecutarse la instrucción pasa a ser detrás de la última
tupla o delante de la primera tupla.
UCLM-ESI . Bases de Datos
6
SQL EMBEBIDO
Borrado de tuplas con cursor
DELETE FROM relación
WHERE CURRENT OF cursor
Esta instrucción permite borrar la tupla en la posición actual del cursor, relación es la relación
que va a ser actualizada (el cursor cursor debe estar asociado a ella). Después de ejecutarse la
instrucción, la posición actual del cursor pasa a ser delante de la tupla siguiente a la tupla que ha sido
borrada o detrás de la última tupla si es que la tupla borrada era la última de la relación.
Actualización de tuplas con cursor
UPDATE relación
SET lista_asignación
WHERE CURRENT OF cursor
Esta instrucción permite actualizar la tupla en la posición actual del cursor. En lista_asignación
se indican las actualizaciones que se van a aplicar a los atributos de la tupla apuntada. La sintaxis de
esta cláusula es similar a la del SQL interactivo con la excepción de que se pueden incluir referencias a
variables huéspedes.
La ejecución de esta instrucción no modifica la posición actual del cursor.
7. EJEMPLO
*/
- Este ejemplo de programa en C (usando SQL embebido) imprimirá un informe.
- Este programa deberá ser precompilado para las sentencias SQL, antes de la compilación normal.
*/
/* ******************************************************/
/* ESTE PROGRAMA NO ES COMPILABLE O EJECUTABLE */
/* SU PROPOSITO ES SÓLO DE SEVIR DE EJEMPLO
*/
/*******************************************************/
#include <stdio.h>
/* Esta sección declara las variables locales */
EXEC SQL BEGIN DECLARE SECTION;
int ID_comprador;
char Nombre[100], Apellidos[100], Producto[100];
EXEC SQL END DECLARE SECTION;
/* Esto incluye la variable SQLCA */
EXEC SQL INCLUDE SQLCA;
main() {
/* Este es un posible camino para conectarse con la base de datos */
EXEC SQL CONNECT UserID/Password;
UCLM-ESI . Bases de Datos
7
SQL EMBEBIDO
/* Este código informa si estás conectado a la base de datos o si ha habido algún error durante la
conexión*/
if(sqlca.sqlcode)
{
printf(Printer, "Error conectando al servidor de la base de datos.\n");
exit();
}
printf("Conectado al servidor de la base de datos.\n");
/* Esto declara un "Cursor". Éste es usado cuando una consulta devuelve más de una fila, y una
operación va a ser realizada en cada fila resultante de la consulta. Después "Fetch" será usado para sacar
cada fila, una a una, pero para la consulta que está actualmente ejecutada, se usará el estamento "Open".
El "Declare" simplemente establece la consulta.*/
EXEC SQL DECLARE ProductoCursor CURSOR FOR
SELECT PRODUCTO, ID_COMPRADOR
FROM ANTIGÜEDADES
ORDER BY PRODUCTO;
EXEC SQL OPEN ProductoCursor;
/* Fetch pone los valores de la "siguiente" fila de la consulta en las variables locales, respectivamente.*/
EXEC SQL FETCH ProductoCursor INTO :Producto, :ID_comprador;
while(!sqlca.sqlcode)
{
/* Con cada fila, además hacemos un par de cosas. Primero, aumentamos el precio $5 (honorarios por
tramitaciones) y extraemos el nombre del comprador. Para hacer esto, usaremos Update y Select, antes
de imprimir la línea en la pantalla. La actuaclización, sin embargo, asume que un comprador dado sólo
ha comprado uno de todos los productos dados, o sino, el precio será incrementado demasiadas veces.
Además observa los dos puntos antes de los nombres de las variables locales cuando son usada dentro
de sentencias de SQL.*/
EXEC SQL UPDATE ANTIGÜEDADES
SET PRECIO = PRECIO + 5
WHERE PRODUCTO = :Producto AND ID_COMPRADOR = :ID_comprador;
EXEC SQL SELECT NOMBREPROPIETARIO, APELLIDOPROPIETARIO
INTO :Nombre, :Apellidos
FROM PROPIETARIOS_ANTIGÜEDADES
WHERE ID_COMPRADOR = :ID_comprador;
printf("%25s %25s %25s", Nombre, Apellidos, Producto);
EXEC SQL FETCH ProductoCursor INTO :Producto, :ID_comprador;
}
/* Cierra el cursor */
EXEC SQL CLOSE ProductoCursor;
EXEC SQL DISCONNECT;
exit();
}
8. COMPILACIÓN
Para compilar un programa SQL embebido en C podemos utilizar un precompilador
denominado esql .
El archivo debe tener extensión .ec, así para compilar por ejemplo un archivo llamado
miprograma.ec creando un ejecutable con nombre miprograma escribimos el siguiente comando:
esql –o miprograma miprograma.ec
UCLM-ESI . Bases de Datos
8
SQL EMBEBIDO
9. BIBLIOGRAFÍA
-Benavides Abajo,J; Olaizola Bartolomé,J.M.;Rivero Cornelio,E.
SQL Para usuarios y programadores(Segunda Edición). Ed. Paraninfo 1992.
-http://www.infor.una.es/~chernan/sqlemb.html
-http://mural.uv.es/gerloal/cap5.htm
-http://www2.ing.puc.cl/~jnavon/11C2412/Clases.html
UCLM-ESI . Bases de Datos
9