Objetivos
1. Manipulación de bases de datos relacionales desde programas
Los lenguajes definidos para el modelo relacional de datos son lenguajes orientados a la manipulación de conjuntos de tuplas. En ellos los operadores seleccionan tuplas con la información requerida en una consulta, o bien actualizan grupos de tuplas de la forma especificada en un requerimiento de actualización.
Esta característica, que representa una mejora respecto a los lenguajes de modelos de datos anteriores (red y jerárquico), introduce sin embargo un problema a la hora de integrar estos lenguajes con los lenguajes de programación clásicos, ya que estos últimos no contemplan la manipulación de estructuras de datos complejas (conjuntos de registros, listas de registros, etc.).
El acceso a una base de datos relacional desde un programa se plantea necesario cuando se piensa en el desarrollo de aplicaciones complejas que 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 directo (o interactivo) está pensado para usarse desde una estación de trabajo. En él, las instrucciones se ejecutan directamente desde el terminal y el resultado de las consultas se visualiza en el monitor de la estación.
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.
Como ya se ha comentado anteriormente, 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 bien 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.
La estructura típica de un programa de manipulación de base de datos es la siguiente:
Programa …2. Instrucciones básicas del SQL embebidoDeclaración de variables
…
Declaración de variables huéspedes para acceso a la base de datos
…
Fin declaración de variables huéspedes para acceso a la base de datos
…
Fin declaración de variablesComienzo del código del programa
…
instrucciones propias del lenguaje
…
Conexión a la base de datos
…
instrucciones de SQL
...
Desconexión de la base de datos
…
instrucciones propias del lenguaje
…
Fin del código de programa
En general, cualquier instrucción del SQL interactivo se puede utilizar en el SQL embebido con pequeñas variaciones sintácticas que se refieren principalmente al intercambio de información con el SGBD a través de variables del programa. Existen, además, instrucciones específicas del SQL embebido que permiten seleccionar y manipular las tuplas de una relación individualmente: son todas las relacionadas con el manejo de cursores.
Algunas consideraciones generales de sintaxis son:
Todo programa con SQL embebido debe incluir la declaración de una variable SQLCODE o una variable SQLSTATE o ambas. Después de la ejecución de cada instrucción SQL, el SGBD devuelve al programa en estas variables información sobre la ejecución de la instrucción.
La operación de consulta se realiza con la siguiente variante de la sentencia SELECT del lenguaje SQL interactivo:
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.
Los elementos de las lista de selección y de la lista de variables se corresponden uno a uno en el orden en que aparecen, por ello ambas listas deben tener el mismo número de elementos y ser de tipos de datos compatibles (esto depende de la implementación del SQL que se esté utilizando).
Las sentencias de actualización: UPDATE, INSERT y DELETE, tienen la misma sintaxis que en el SQL interactivo con la única diferencia de que pueden incluir variables huéspedes.
A continuación se presentan algunos ejemplos de SQL embebido en C relativos a la base de datos Docencia del anexo.
Declaración de variables huéspedes:
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"
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.
Definición del cursor
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 (resp., UPDATE [OF lista_nom_atributo] ) indica que la relación asociada al cursor no puede (resp., puede) ser actualizada por medio de las instrucciones UPDATE y DELETE.
Apertura del cursor
Manejo del cursor y selección de tuplas
El selector_de_tupla puede ser: next, prior, first, last, absolute n, relative n. La semántica de cada una de estas opciones es obvia, si bien 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.
Borrado de tuplas con cursor
Actualización de tuplas con cursor
La ejecución de esta instrucción no modifica la posición actual del cursor. La única restricción a su uso es que no pueden actualizarse los atributos que aparecen en la cláusula ORDER BY de la definición del cursor; es decir, los atributos por los cuales se ordena el conjunto de tuplas.
Ejemplo de operaciones de manipulación con cursor.
El siguiente fragmento de programa obtiene un informe de todos los profesores de la base de datos; de cada uno de ellos se presenta la siguiente información: código, nombre, departamento y el número total de créditos que imparte; si el profesor no tiene docencia asignada se debe indicar con el mensaje "Sin Docencia".
Declaración de variables huéspedes y cursores:
En este apartado se va a presentar de forma breve la forma de construir un programa en C con SQL embebido. Estos programas tienen las siguientes particularidades:
La forma de definir el área de trabajo es la siguiente:
3.2. Utilización de las instrucciones SQL mediante llamadas EXEC SQL
Las variables huéspedes se usan de la forma habitual en las instrucciones de C y en las instrucciones SQL deben ir precedidas del símbolo ‘:’.
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:
3.3. Uso del área de comunicación SQL para el control de las operaciones sobre la base de datos
Un aspecto fundamental para el correcto funcionamiento de los programas es el control de las operaciones que se van realizando sobre la base de datos. Dependiendo de si la instrucción SQL ejecutada ha producido un error o no, o ha realizado la operación esperada o no, el programa ha de tomar las medidas correspondientes (informar al usuario, pedir nuevos datos, terminar la ejecución, etc.).
Para realizar este control se utiliza el área de comunicación del SQL (en inglés SQLCA). 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:
El siguiente programa obtiene la información de los profesores que pertenecen a un departamento que el usuario especifica dando su código.
Escribir los programas en C con SQL embebido que correspondan a las siguientes operaciones:
Esquema Relacional de la base de datos Docencia
Departamento (cod_dep, nombre, director, telefono)
Clave Primaria: {cod_dep}
Asignatura (cod_asg, nombre, semestre, teoria, prac, cod_dep )
Clave Primaria: {cod_asg}
Clave Foranea: {cod_dep}
® Departamento
Profesor (cod_pro, nombre, telefono, cod_dep )
Clave Primaria: {cod_pro}
Clave Foranea: {cod_dep}
® Departamento
Docencia (cod_asg, cod_pro, gteo, gpra)
Clave Primaria: {cod_asg,
cod_pro}
Clave Foranea: {cod_asg}
® Asignatura
Clave Foranea: {cod_pro}
® Profesor
Desarrollo de Aplicaciones en Bases de Datos. Dpto. de
Lenguajes y Sistemas Informáticos. Universidad Politécnica
de Valencia.