Vous êtes sur la page 1sur 12

SQL embebido en C

Objetivos

Presentar los fundamentos de la manipulacin de bases de datos


relacionales desde programas.
Presentar las instrucciones bsicas del lenguaje SQL embebido.
Presentar la estructura de un programa en C con SQL embebido.
Realizar programas sencillos de manipulacin sobre la base de
datos Docencia cuyo esquema relacional se puede encontrar en el
anexo.

Contenidos

1. Manipulacin de bases de datos relacionales desde programas

Los lenguajes definidos para el modelo relacional de datos son lenguajes


orientados a la manipulacin de conjuntos de tuplas. En ellos los operadores
seleccionan tuplas con la informacin requerida en una consulta, o bien
actualizan grupos de tuplas de la forma especificada en un requerimiento de
actualizacin.

Esta caracterstica, que representa una mejora respecto a los lenguajes de


modelos de datos anteriores (red y jerrquico), introduce sin embargo un
problema a la hora de integrar estos lenguajes con los lenguajes de
programacin clsicos, ya que estos ltimos no contemplan la manipulacin
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: manipulacin individualizada de las tuplas, estructuras de
programacin tradicionales (seleccin y repeticin), interaccin con el usuario
y gestin de errores.

Por ello, la propuesta estndar 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 estacin
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 estacin.
El SQL embebido est pensado para ser utilizado intercalando sus
instrucciones en el cdigo de un programa escrito en un lenguaje de
programacin al que se denomina lenguaje husped(FORTRAN, COBOL, C,
etc.). Estas instrucciones se ejecutan cuando se ejecuta el programa de
acuerdo a su lgica interna. En este contexto, el intercambio de informacin
con el SGBD se realiza a travs de variables del lenguaje, a las que se
denomina variables huspedes; 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 programacin. Para superar esta dificultad existen dos opciones:
restringir las consultas a aquellas que devuelvan una nica tupla o bien
introducir algn mecanismo que permita seleccionar y manipular las tuplas de
una relacin individualmente, este ltimo mecanismo viene representado por
los cursores. En esencia un cursor es un puntero destinado a apuntar a las
tuplas de una relacin. El cursor puede moverse a travs de las tuplas de la
relacin, pudindose en cualquier momento seleccionar o actualizar la tupla
apuntada.

La estructura tpica de un programa de manipulacin de base de datos es la


siguiente:

Programa

Declaracin de variables

Declaracin de variables huspedes para acceso a la base de
datos

Fin declaracin de variables huspedes para acceso a la base
de datos

Fin declaracin de variables

Comienzo del cdigo del programa



instrucciones propias del lenguaje

Conexin a la base de datos

instrucciones de SQL
...
Desconexin de la base de datos

instrucciones propias del lenguaje

Fin del cdigo de programa

2. Instrucciones bsicas del SQL embebido

En general, cualquier instruccin del SQL interactivo se puede utilizar en el


SQL embebido con pequeas variaciones sintcticas que se refieren
principalmente al intercambio de informacin con el SGBD a travs de
variables del programa. Existen, adems, instrucciones especficas del SQL
embebido que permiten seleccionar y manipular las tuplas de una relacin
individualmente: son todas las relacionadas con el manejo de cursores.

Algunas consideraciones generales de sintaxis son:

1. Todas las instrucciones del SQL embebido van precedidas de las


palabras reservadas EXEC SQL, de forma que son fcilmente
identificables por el precompilador, y finalizan con un smbolo
especial. En el lenguaje C este smbolo es el punto y coma (;).
2. Las variables del lenguaje que son utilizadas en instrucciones SQL
(variables huspedes) deben ser declaradas en una seccin especial
encabezada y terminada de la siguiente forma:

EXEC SQL BEGIN DECLARE SECTION;


...
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 programacin y el
SGBD depende de cada sistema particular); sintcticamente pueden
aparecer en una instruccin SQL en cualquier lugar en el que puede
aparecer un literal y deben ir precedidas del smbolo dos puntos (: ).

Todo programa con SQL embebido debe incluir la declaracin de una


variable SQLCODE o una variable SQLSTATE o ambas. Despus de
la ejecucin de cada instruccin SQL, el SGBD devuelve al programa
en estas variables informacin sobre la ejecucin de la instruccin.

1. En un programa, cualquier instruccin SQL debera estar seguida por


cdigo que controlase los valores de las variables SQLCODE y
SQLSTATE relativos a la ejecucin de la instruccin; para simplificar
esta tarea el lenguaje proporciona una sentencia para el control general
de errores, sta es la sentencia WHENEVER:
EXEC SQL WHENEVER condicin accin
condicin ::= {SQLERROR | NOT FOUND}
accin ::={CONTINUE | GO TO etiqueta}

o NOT FOUND se evala a cierto si no se han encontrado datos


que cumplan las condiciones especificadas en la instruccin
(SQLCODE =+100).
o SQLERROR se evala a cierto si ha ocurrido algn error en la
ejecucin de la instruccin (SQLCODE < 0).

La sentencia WHENEVER no es una instruccin ejecutable, es


ms bien una directriz al procesador del lenguaje SQL:

WHENEVER condicin GO TO etiqueta significa que el


procesador de SQL incluir detrs de cualquier sentencia
SQL del programa la sentencia IFcondicin THEN GO TO
etiqueta
WHENEVER condicin CONTINUE significa que el
procesador de SQL no tomar ninguna accin siendo
responsabilidad del programador controlar el flujo del
programa.

2.1. Instrucciones de manipulacin sin cursores

La operacin de consulta se realiza con la siguiente variante de la sentencia


SELECT del lenguaje SQL interactivo:
SELECT [ALL | DISTINCT] lista_elemento_
seleccin
INTO lista_variable
FROM lista_relacin
[WHERE condicin_bsqueda]
[GROUP BY lista_atributo]
[HAVING condicin_bsqueda]
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


clusula INTO que especifica la lista de variables del programa que sern
utilizadas para recibir los datos seleccionados.
Los elementos de las lista de seleccin 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 nmero de elementos y ser de tipos de datos
compatibles (esto depende de la implementacin del SQL que se est
utilizando).

Las sentencias de actualizacin: UPDATE, INSERT y DELETE, tienen la


misma sintaxis que en el SQL interactivo con la nica diferencia de que
pueden incluir variables huspedes.

A continuacin se presentan algunos ejemplos de SQL embebido en C


relativos a la base de datos Docencia del anexo.

Declaracin de variables huspedes:


EXEC SQL BEGIN DECLARE SECTION;
char cd[6];
int aux;
char cpx[4];
char cpy[4];
EXEC SQL END DECLARE SECTION;
Consulta: "Obtener el cdigo del departamento al que pertenece el profesor
de cdigo JCR ".
EXEC SQL SELECT cod_dep INTO :cd
FROM Profesor
WHERE cod_pro = JCR;
Como se puede ver, la variable cd recibir el valor (cadena de 3 caracteres)
de la columna de la tabla Profesor que cumpla la condicin (como mximo
una fila).
De forma anloga, en la siguiente
Consulta: "Nmero de profesores de un departamento", se puede ver el uso
de la variable husped cd para el paso de informacin al SGBD.
EXEC SQL SELECT count(*) INTO :aux
FROM Profesor
WHERE cod_dep= :cd;
Al ejecutar esta instruccin el valor de la variable husped cd se transfiere
al SGBD para que ejecute la consulta correspondiente y el resultado de la
misma, un entero, es almacenado en la variable husped aux.

Actualizacin: "Transferir la docencia de un profesor cuyo cdigo se lee en


la variable cpx a un profesor cuyo cdigo se lee en la variable cpy"
EXEC SQL UPDATE Docencia
SET cod_pro = :cdy
WHERE cod_pro = :cdx
2.2. Instrucciones de manipulacin con cursores
Como se ha comentado anteriormente, un cursor es un objeto SQL que
permite la manipulacin de las tuplas de una relacin de forma
individualizada; intuitivamente se puede ver como un puntero a las tuplas de
una relacin.

Un cursor siempre va asociado a una relacin que se especifica al ser


declarado. Ya que el objetivo de su uso es poder navegar a travs de las tuplas
que constituyen dicha relacin para posteriormente manipularlas, estas tuplas
deben estar ordenadas, siendo este orden implcitamente definido por el
sistema o bien definido por el programador en la declaracin del cursor.

Desde que el cursor es activado (apertura del cursor) siempre tiene una
posicin (posicin actual) dentro del conjunto ordenado de tuplas. Esta
posicin puede ser: delante de una tupla, en una tupla, y detrs de una tupla.
Esta posicin actual va a ser relevante para las instrucciones de manipulacin
de la base de datos basadas en el uso de cursores. A continuacin se presentan
cada una de ellas.

Definicin del cursor

DECLARE cursor CURSOR


FOR cursor_especificacin
cursor_especificacin ::= expresin_de_relacin
[ORDER
BY lista_elemento_orden]
[FOR {READ ONLY | UPDATE [OF
lista_nom_atributo]]
elemento_orden ::= {nom_atributo | entero_positivo}
[ASC | DESC]
La expresin_de_relacin define la relacin 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 huspedes.

La clusula ORDER BY permite especificar un orden para las tuplas de la


relacin definida por expresin_de_relacin. Los nombres de atributo o los
enteros positivos (ordinal de la posicin de un atributo) se refieren a atributos
de la relacin definida por expresin_de_relacin; los enteros positivos se
utilizan cuando el correspondiente atributo de la relacin no lleva un nombre,
es decir es un dato calculado. Si no se incluye la clusula ORDER BY, el
sistema establece un orden por defecto.

La clusula FOR READ ONLY (resp., UPDATE [OF lista_nom_atributo] )


indica que la relacin asociada al cursor no puede (resp., 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 evaluacin de
la expresin_de_relacin asociada. Cuando un cursor se abre, su posicin
actual pasa a ser delante de la primera tupla.

Manejo del cursor y seleccin de tuplas


FETCH [[selector_de_tupla]
FROM] cursor INTO lista_variables
La instruccin FETCH permite mover el cursor dentro del conjunto
ordenado de tuplas y seleccionar (leer) la tupla en la que queda colocado; su
posicin actual despus de ejecutarse la instruccin es en la tupla
seleccionada .

El selector_de_tupla puede ser: next, prior, first, last, absolute n, relative n.


La semntica de cada una de estas opciones es obvia, si bien para los
casos next, prior y relative el movimiento es relativo a la posicin actual del
cursor antes de ejecutarse la instruccin fetch. En las opciones absolute
n y relative n, un nmero positivo (respectivamente, negativo) indica
movimiento hacia delante (respectivamente, detrs) segn la secuencia de
ordenacin de las tuplas.

La lista de variables debe contener una variable husped por cada atributo
de la relacin asociada al cursor, estas variables recibirn los valores de la
tupla seleccionada.

Si la instruccin FETCH no selecciona ninguna tupla, es decir no existe la


tupla siguiente (next) o la tupla anterior (prior) a la tupla en la posicin actual
del cursor, o bien no existe la ensima tupla a partir de la posicin actual
(absolute y relative) hacia delante (n positivo) o hacia detrs (n negativo),
entonces la posicin actual del cursor despus de ejecutarse la instruccin
pasa a serdetrs de la ltima tupla o delante de la primera tupla.

Borrado de tuplas con cursor

DELETE FROM relacin


WHERE CURRENT OF cursor
Esta instruccin permite borrar la tupla en la posicin actual del
cursor, relacin es la relacin que va a ser actualizada (el cursor cursor debe
estar asociado a ella). Despus de ejecutarse la instruccin, la posicin actual
del cursor pasa a ser delante de la tupla siguiente a la tupla que ha sido
borrada o detrs de la ltima tupla si es que la tupla borrada era la ltima de
la relacin.

Actualizacin de tuplas con cursor


UPDATE relacin
SET lista_asignacin
WHERE CURRENT OF cursor
Esta instruccin permite actualizar la tupla en la posicin actual del cursor.
En lista_asignacin se indican las actualizaciones que se van a aplicar a los
atributos de la tupla apuntada. La sintaxis de esta clusula es similar a la del
SQL interactivo con la excepcin de que se pueden incluir referencias a
variables huspedes.

La ejecucin de esta instruccin no modifica la posicin actual del cursor.


La nica restriccin a su uso es que no pueden actualizarse los atributos que
aparecen en la clusula ORDER BY de la definicin del cursor; es decir, los
atributos por los cuales se ordena el conjunto de tuplas.

Ejemplo de operaciones de manipulacin 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
informacin: cdigo, nombre, departamento y el nmero total de crditos que
imparte; si el profesor no tiene docencia asignada se debe indicar con el
mensaje "Sin Docencia".

Declaracin de variables huspedes y cursores:

EXEC SQL BEGIN DECLARE SECTION;


STRUCT PRO_ {
char cod_pro[4];
char nombre[41];
char cod_dep[6]; } pro;
int aux1;
int aux2;
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE c_pro CURSOR FOR
SELECT cod_pro, nombre, cod_dep
FROM Profesor ;
Fragmento de cdigo de programa:
EXEC SQL OPEN c_pro;
EXEC SQL FETCH c_pro INTO :pro;
mientras sqlca.sqlcode = 0
EXEC SQL SELECT count(*), sum(D.gteo * A.teoria
)+ sum(D.gpra * A.prac)
INTO :aux1, :aux2
FROM Docencia D, Asignatura A
WHERE D.cod_pro = :pro.cod_pro
AND
D.cod_asg = A.cod_asg
si aux1 = 0
entonces escribir (pro.cod_pro,
pro.nombre, "Sin Docencia")
sinoescribir (pro.cod_pro, pro.nombre,
aux2);
escribir("\n");
EXEC SQL FETCH c_pro INTO :pro; }
3. Estructura de un programa en C con SQL embebido

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:

Definicin de un rea de trabajo del programa mediante la declaracin


de un conjunto de variables huspedes.
Utilizacin de instrucciones SQL mediante llamadas EXEC SQL.
Utilizacin del rea de comunicacin SQL para controlar la ejecucin
de las operaciones sobre la base de datos.

3.1. Definicin del rea de trabajo

La forma de definir el rea de trabajo es la siguiente:

EXEC SQL BEGIN DECLARE SECTION;


declaracin de tipos y variables en C
EXEC SQL END DECLARE SECTION;
Las variables declaradas dentro de esta seccin son variables huspedes y
sirven para recibir informacin de la base de datos o para enviar informacin a
la base de datos.

3.2. Utilizacin de las instrucciones SQL mediante llamadas EXEC SQL

Las variables huspedes se usan de la forma habitual en las instrucciones de


C y en las instrucciones SQL deben ir precedidas del smbolo :.

De las instrucciones SQL que se pueden utilizar, es interesante destacar dos


de ellas: la conexin a la base de datos y la desconexin. Estas instrucciones
tienen la siguiente sintaxis:

EXEC SQL CONNECT 'base_datos';


EXEC SQL DISCONNECT;
Es necesario destacar que antes de efectuar cualquier operacin sobre la
base de datos es necesario conectarse a la misma usando la primera
instruccin. 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.
3.3. Uso del rea de comunicacin 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 instruccin SQL ejecutada ha producido un error o no, o
ha realizado la operacin esperada o no, el programa ha de tomar las medidas
correspondientes (informar al usuario, pedir nuevos datos, terminar la
ejecucin, etc.).

Para realizar este control se utiliza el rea de comunicacin del SQL (en
ingls SQLCA). La SQLCA consiste en un conjunto de variables que
almacenan informacin sobre el estado (y los errores, si se producen) de la
ltima instruccin 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;
La inclusin de esta declaracin implica la aparicin de una nueva variable
estructurada denominada sqlca.La declaracin de esta variable es la siguiente:
typedef struct {
char sqlcaid[8];
long sqlcabc;
long sqlcode;
struct {
short sqlerrml;
char sqlerrmc[70]; } sqlerrm;
char sqlerrp[8];
long sqlerrd[6];
struct {
char sqlwarn0;
char sqlwarn1;
char sqlwarn2;
char sqlwarn3;
char sqlwarn4;
char sqlwarn5;
char sqlwarn6;
char sqlwarn7; } sqlwarn;
char sqlext[8]; } IISQLCA;
extern IISQLCA sqlca;
El uso de cada uno de los campos de la variable sqlca es el siguiente:

sqlcaid: de tipo cadena de 8 caracteres e inicializada a "SQLCA". El


valor no cambia.
sqlcabc: de tipo entero de 4 bytes e inicializada a la longitud en bytes
de SQLCA, esto es 136. Este valor permanece inalterado.
sqlcode: de tipo entero de 4 bytes que almacena el cdigo de retorno de
la instruccin SQL ejecutada en ltimo lugar. Sus valores se puede
agrupar de la siguiente forma:
o = 0, la instruccin se ejecuto con xito, aunque es posible que
existan mensajes de atencin (ver sqlwarn0)
o < 0, sucedi algn error en la ejecucin de la instruccin. El
valor negativo contenido coincide en valor absoluto con el
nmero de error (positivo) devuelto por la variable errorno.
o > 0, la instruccin se ejecuto con xito pero alguna condicin
excepcional se ha dado. Por ejemplo, el valor +100 indica que la
instruccin no ha afectado a ninguna tupla de ninguna relacin
de la base de datos.
sqlerrm: de tipo cadena de longitud variable con un contador de
2 bytes y un buffer de 70 caracteres. Esta variable se usa para los
mensajes de error.
sqlerrp: actualmente no se usa.
sqlerrd: un vector de 6 enteros de 4 bytes. Slo se usan sqlerrd(1) para
almacenar los nmeros de error devueltos por el servidor
y sqlerrd(3) para guardar el nmero de filas procesadas por la
instruccin.
sqlwarn0-sqlwarn7: se actualizan a "W" para indicar que ha sucedido
algn hecho especial que no puede ser considerado un error.

4. Programa ejemplo

El siguiente programa obtiene la informacin de los profesores que


pertenecen a un departamento que el usuario especifica dando su cdigo.

# include <stdio.h>
# include <string.h>
exec sql include sqlca;
exec sql begin declare section;
struct pro_ {
char cod_pro[4];
char nombre[41];
int telefono;
char cod_dep[6];
} pro;
char cd[6];
exec sql end declare section;
main(){
exec sql declare c_pro cursor for
select cod_pro, nombre, telefono,
cod_dep
from Profesor
where cod_dep = :cd;
printf("Dame el cdigo del departamento ");
scanf("%5s", cd);
printf("%-4s %-40s %-10s", "Cdigo", "Nombre",
"Telfono");
printf("\n");
printf("--------------------------------------
---------------\n");
exec sql connect apb_emb;
exec sql open c_pro;
exec sql fetch c_pro into :pro;
while ( sqlca.sqlcode == 0 )
{
printf("%-4s %-40.40s %-5d",
pro.cod_pro, pro.nombre, pro.telefono);
printf("\n");
exec sql fetch c_pro into :pro;
}
exec sql close c_pro;
exec sql disconnect;
}
6. Ejercicios propuestos

Escribir los programas en C con SQL embebido que correspondan a las


siguientes operaciones:

1. Generacin de un listado de la informacin completa de los


departamentos.
2. Peticin del cdigo de un departamento y obtencin de toda su
informacin. Es necesario que se controle la existencia del
departamento. Adems se ha de permitir que se pueda realizar la
consulta de varios departamentos sin necesidad de ejecutar varias veces
el programa.
3. Peticin del cdigo de un departamento y presentacin del
departamento as como el nmero de profesores que pertenecen a l.
Tambin hay que presentar un listado con la informacin de los
profesores que pertenecen a l. Hay que controlar la existencia del
departamento.
4. Presentacin en pantalla de la informacin que corresponde al plan de
ordenacin docente de los departamentos. Se ha de extraer la
informacin de cada departamento junto con los profesores que
pertenecen a l indicado para cada uno de ellos: si imparte docencia,
que asignaturas imparte y cuantos grupos de teora y prcticas tiene a su
carga para cada asignatura; si no imparte docencia, este mismo hecho.

Vous aimerez peut-être aussi