Escolar Documentos
Profissional Documentos
Cultura Documentos
3. El modelo relacional
Historia y panorámica de las bases de datos relacionales.
Publication: Una publicación genérica. Normalmente, esta relación se usa sólo para asignarles
un identificativo unívoco a todas las publicaciones presentes en la base de datos, dejando la
especificación de las demás características en relaciones específicas para cada tipo de
publicación. Además, se usa para implementar uniones complejas entre las publicaciones y
otras relaciones. Por ejemplo, la que existe entre una publicación y su autor. Gracias a la
estructura adoptada, se puede contar con publicaciones escritas de muchos autores y con
autores que escriben diferentes tipos de publicaciones.
Author: Representa al autor de una publicación. La llave primaria está compuesta por el
identificativo de la publicación y por el de la persona, lo que grantiza la unidad de la asociación
entre las dos entidades.
Person: Representa a una persona (por ejemplo, un autor) en la base de datos. Actualmente,
las informaciones consideradas interesantes son sólo el apellido y el nombre.
Institution: La institución (por ejemplo una universidad o una software house) responsable de
una publicación.
InBook: Una parte de un libro. La parte puede caracterizarse por un título, por el número del
capítulo o por el de la página. Las informaciones a propósito del libro y, por tanto, comunes a
sus diferentes partes, se memorizan en la relación Book.
Misc: Una publicación que no puede englobarse en ninguna de las categorías anteriores.
No voy a explicar el significado de los atributos que componen las diferentes relaciones, puesto
que sus nombres se explican por sí mismos. Sólo una anotación sobre el atributo "pub_month":
se ha definido como de tipo CHAR(3), es decir una cadena con una longitud fija de tres
caracteres que incluirá las abreviaturas de los nombres de los meses (las primeras tres letras
de los nombres ingleses).
Los lazos entre las relaciones deberían ser bastante fáciles de entender. Como ejemplo para
todos, usaremos el que conecta la relación Book con la relación Publisher. Este lazo sirve para
describir la la editorial de un libro. En la relación Book no están presentes todos los datos de la
editorial, sino sólo un identificativo numérico para ella. El número será la llave primaria de la
relación Publisher y como tal permitirá identificar una editorial precisa. En la relación Book el
atributo publisher es una llave externa hacia la relación Publisher.
Una situación más compleja es la que afecta a las relaciones Publication, Author y Person;
efectivamente, en Author están presentes dos llaves externas: una que identifica la publicación
a la que la instancia de relación se refiere, y otra que permite remontarse a los datos de la
persona que desempeña el papel de autor. Se podría preguntar cuál es la utilidad de la relación
Publication y por qué no se ha establecido directamente un nexo entre la relación Author y las
relaciones que representan los tipos de publicación concretos. La respuesta es que el modelo
relacional no permite hacerlo. En efecto, desde el momento en que un autor puede escribir
diferentes tipos de publicación, el atributo pubblicationID debería ser una llave externa hacia
todas las relaciones de las publicaciones, pero esto no está permitido desde el momento en
que contradice la definición misma de llave externa.
• llamada interactiva
• llamada a través de un programa de aplicación
En el primer caso, se usa un programa cuya finalidad consiste en recibir en input las
instrucciones SQL, transmitirlas a la DBMS y mostrar los resultados al usuario. Normalmente,
todas las DBMS ponen a disposición un programa de tipo textual con dichas funciones.
En el caso de PostgreSQL, la DBMS que usaré para implementar la base de datos que sirve de
ejemplo, el programa se llama "psql". La sintaxis que hay que utilizar para convocarlo en la
modalidad interactiva es la siguiente:
"dbname" es el nombre de la base de datos a la que se quiere acceder, mientras que "user" es
el nombre dek usuario con con el que se quiere acceder a la base de datos. Por ejemplo, la
orden:
activa el programa psql, accediendo a la base de datos mydb como usuario benfante. Si todo
ha ido bien, en concreto si la base de datos existe y el usuario cuenta con los permisos
necesarios para entrar, psql muestra un prompt parecido al siguiente:
mydb=>
Llegados a este punto, se pueden digitar las órdenes SQL (terminándolas con un ";" o con la
meta-orden "\g" (go) para hacer que se ejecuten) y leer en la pantalla los resultados que
producen.
Normalmente, los programas como psql se pueden utilizar también de modo no interactivo. Por
ejemplo, invocando psql con la siguiente orden:
el programa ejecuta las instrucciones SQL que están en el archivo instrucciones.sql y acaba
inmediatamente después. De este modo es posible automatizar operaciones que se tienen que
repetir frecuentemente o, en todo caso, que están compuestas por largas secuencias de
órdenes SQL, sin tener que escribirlas manualmente cada vez.
En el caso en que se invoquen las instrucciones SQL a través de un programa aplicativo, éstas
se ejecutan durante la ejecución de dicho programa, que usará los resultados para producir su
output. En esta situación, el usuario no usa directamente las órdenes SQL y podría incluso no
saber que el programa que está utilizando accede a una base de datos relacional: lo único que
ve es el interfaz que la aplicación le ofrece. Sustancialmente, tenemos dos sistemas para
escribir aplicaciones de este tipo:
• usar una biblioteca que gestiones la comunicación con la DBMS, transmita las
instrucciones SQL y nos permita manipular los resultados producidos. Bibliotecas de
este tipo son, por ejemplo, JDBC y ODBC. A menudo, los productores de las DBMS
ofrecen bibliotecas propietarias, que son específicas para su producto. Por ejemplo, en
el caso de PostgreSQL la biblioteca para el lenguaje C se llama "libpq". Con frecuencia
se intentan usar bibliotecas propietarias porque las aplicaciones resultan
absolutamente específicas (funcionan sólo con la base de datos para la que la
biblioteca se ha construido). Sin embargo, usando bibliotecas "standard", como JDBC o
ODBC, las aplicaciones funcionarán con cualquier DBMS que exponga la interfaz
solicitada por la biblioteca (a no ser que se empleen funciones específicas del DBMS).
• usar Embedded SQL (ESQL). En este caso, el código SQL está englobado en el código
de un lenguaje huésped y se usan los mecanismos normales del lenguaje para el paso
de los parámetros y el uso de los resultados. Normalmente, el código resultante es
convertido antes por un pre-procesador y después compilado por el compilador del
lenguaje huésped. Una ventaja ulterior si se usa ESQL reside en el hecho de que
existe un estándar ANSI que describe cómo tendría que funcionar. De este modo, es
posible que un programa escrito para una determinada DBMS pueda recompilarse y
funcionar también para otro. PostgreSQL pone a disposición un pre-procesador ESQL
para el lenguaje C (ecpg).
En las siguientes lecciones usaremos psql para enviar las instrucciones SQL que
implementarán, poblarán e interrogarán a la base de datos ejemplificada. En la última lección,
se presentará, sin embargo, un applet Java que empleará la biblioteca JDBC para consultar la
base de datos bibliográfica.
Con PostgreSQL está a disposición una orden invocable por shell Unix (o por shell del sistema
usado), que ejecuta la misma operación:
createdb biblio
Una vez creada la base de datos, se pueden crear las tablas que la componen. La instrucción
SQL propuesta para este fin es:
tipo_columna: es la indicación del tipo de dato que la columna podrá contener. Los principales
tipos previstos por el estándar SQL son:
• CHARACTER(n)
Una cadena de longitud fija con exactamente n caracteres. CHARACTER se puede
abreviar con CHAR
• CHARACTER VARYING(n)
Una cadena de longitud variable con un máximo de n caracteres. CHARACTER
VARYING se puede abreviar con VARCHAR o CHAR VARYING.
• INTEGER
Un número estero con signo. Se puede abreviar con INT. La precisión, es decir el
tamaño del número entero que se puede memorizar en una columna de este tipo,
depende de la implementación de la DBMS en cuestión.
• SMALLINT
Un número entero con signo y una precisión que no sea superior a INTEGER.
• FLOAT(p)
Un número con coma móvil y una precisión p. El valor máximo de p depende de la
implementación de la DBMS. Se puede usar FLOAT sin indicar la precisión,
empleando, por tanto, la precisión por defecto, también ésta dependiente de la
implementación. REAL y DOUBLE PRECISION son sinónimo para un FLOAT con
precisión concreta. También en este caso, las precisiones dependen de la
implementación, siempre que la precisión del primero no sea superior a la del segundo.
• DECIMAL(p,q)
Un número con coma fija de por lo menos p cifras y signo, con q cifras después de la
coma. DEC es la abreviatura de DECIMAL. DECIMAL(p) es una abreviatura de
DECIMAL(p,0). El valor máximo de p depende de la implementación.
• INTERVAL
Un periodo de tiempo (años, meses, días, horas, minutos, segundos y fracciones de
segundo).
donde valor es un valor válido para el tipo con el que la columna se ha definido.
• NOT NULL, que indica que la columna no puede tomar el valor NULL.
• PRIMARY KEY, que indica que la columna es la llave primaria de la tabla.
• una definición de referencia con la que se indica que la columna es una llave externa
hacia la tabla y los campos indicados en la definición. La sintaxis es la siguiente:
Las cláusulas ON DELETE y ON UPDATE indican qué acción hay que ejecutar en el
caso en que una tupla en la tabla referenciada sea eliminada o actualizada. De hecho,
en dichos casos en la columna referenciante (que es la que se está definiendo) podría
haber valores inconsistentes. Las acciones pueden ser:
CHECK (expresión_condicional)
PRIMARY KEY ( columna1 [ , columna2 ... ] ) Véase que en este caso, a diferencia de
la definición de la llave primaria como vínculo de columna, ésta se puede formar con
mas de un atributo.
• un control de valor, con la misma sintaxis y significado que el que se puede usar como
vínculo de columna.
Para aclarar mejor el uso de la instrucción CREATE TABLE, veamos algunas órdenes que
implementan la base de datos bibliográfica ejemplificada.
La instrucción anterior crea la tabla Publication, formada por las dos columna ID de tipo
INTEGER, y type de tipo CHAR(18). ID es la llave primaria de la relación. En el atributo type
hay un vínculo de no nulidad.
Crea la relación Book, formada por nueve atributos. La llave primaria es el atributo ID, que es
también una llave externa hacia la relación Publication. Sobre los atributos title, publisher y
pub_year hay vínculos de no nulidad. Además, el atributo publisher es una llave externa hacia
la tabla Publisher.
Crea la relación Author, compuesta por dos atributos: publicationID y personID. La llave
primaria en este caso está formada por la combinación de los dos atributos, como está indicado
por el vínculo de tabla PRIMARY KEY. PublicationID es una llave externa hacia la relación
Publication, mientras que personID lo es hacia la relación Person.
El archivo create_biblio.sql contiene todas las órdenes necesarias para crear la estructura de la
base de datos bibliográfica ejemplificada.
Suponiendo que en la base de datos no esté ya presente ninguna de las informaciones que le
afectan (como por ejemplo alguno de los autores o las actas del congreso al que se refiere), su
inclusión en nuestra base de datos de ejemplo corresponde a la inclusión de las siguientes
líneas:
cinco líneas en la tabla Person, que corresponden a cada uno de los autores y de los
coordinadores;
dos líneas en la tabla Publication: una para las actas del congreso y una para el artículo
contenido en esas actas;
La instrucción SQL que lleva a cabo la inclusión de una nueva línea en una tabla es INSERT.
La sintaxis con la que ésta se usa comunmente es:
lista_campos es la lista de los nombres de los campos a los que hay que asignar un valor,
separados entre sí por una coma. Los campos no incluidos en la lista tomarán su valor por
defecto o NULL si no lo tienen por defecto. Es un error no incluir en la lista un campo que no
tenga un valor por defecto y que no pueda tomar el valor NULL. En el caso en que no se
especifique la lista, habrá que especificar los valores de todos los campos de la tabla.
lista_valores es la lista de los valores que se les darán a los campos de la tabla en el orden y
número especificados por la lista_campos o en la de la definición de la tabla (si no se especifica
lista_campos). Los valores pueden ser una expresión escalar del tipo apropiado para el campo
o las keyword DEFAULT o NULL, si el campo prevé un valor por defecto o admite el valor
NULL.
La única diferencia con la sintaxis anterior consiste en la sustitución de la cláusula VALUES por
la instrucción SELECT.
La instrucción SELECT se examinará con detalle en la siguiente lección (Interrogar a la base de
datos). Por el momento, es suficiente saber que SELECT permite extraer de las tablas de la
base de datos datos que se organizan en una nueva relación.
La anterior instrucción INSERT permite incluir en la tabla y en los campos especificados datos
provenientes de otras tablas. Obviamente, para que la instrucción se ejecute con éxito, los
datos producidos por la instrucción SELECT tendrán que ser compatibles con los vínculos y los
dominios de los campos de la tabla en la que se esta efectuando la inserción.
En el archivo poblad_biblio.sql están presentes las instrucciones SQL que pueblan la base de
datos bibliográfica con los datos que se usarán en los ejemplos de las siguientes lecciones.
La instrucción SELECT produce una tabla que se obtiene aplicando el siguiente procedimiento
(por lo menos desde el punto de vista lógico, cada DBMS optimiza la ejecución de las
interrogaciones según las propias estrategias):
1. produce una tabla que se obtiene como producto cartesiano de las tablas especificadas
en la cláusula FROM. Cada elemento de la lista_referencias_tabla sigue la siguiente
sintaxis:
referencia_tabla [ [ AS ] alias_tabla ]
La referencia puede ser el nombre de una tabla o una expresión (puesta entre
paréntesis) cuyo resultado es una tabla, y por lo tanto incluso otra SELECT. El alias es
un nombre que sirve para indicar brevemente una referencia de tabla. En el caso en
que la referencia de tabla sea una expresión, es obligatorio especificar un alias.
2. de la tabla anterior elimina todas las líneas que no satisfacen la expresión condicional
(es decir las líneas por las cuales la expresión condicional devuelve falso como
resultado) de la cláusula WHERE.
3. (si está presente la cláusula GROUP BY) las líneas de la tabla resultante del paso 2 se
reagrupan según los valores presentes en las columnas especificadas en la cláusula
GROUP BY. Líneas con valores iguales se unen en una única línea. Las columnas no
comprendidas en la cláusula tienen que comprender expresiones con funciones de
agregación (como por ejemplo AVG, que calcula la media) que, por tanto, se calculan
produciendo un único valor para cada grupo.
4. (si está presente la cláusula HAVING) del resultado del punto 3 se eliminan las líneas
que no satisfacen la expresión condicional de la cláusula HAVING.
expresión_escalar [ [ AS ] alias_columna ]
Una expresión escalar es una expresión que produce como resultado un valor escalar.
Los tipos de datos escalares del lenguaje SQL son principalmente los descritos en la
lección 6 (Crear la base de datos), excepto INTERVAL, DATE, TIME y TIMESTAMP.
Las expresiones escalares de los elementos de SELECT normalmente afectan a las
columnas de la tabla resultante del punto 4. En el caso en que se den ambigüedades,
por la presencia de columnas con los mismos nombres en dos o más tablas incluidas
en la cláusula FOR, se pueden resolver prefijando el nombre o el alias de la columna
con el nombre o el alias de la tabla, separados por un punto. Por ejemplo, T.C indica la
columna C de la tabla T. El alias de columna es el nombre que se le da a la columna.
Toda la lista de las columnas de una tabla puede especificarse usando el carácter '*'.
6. (si está presente la opción DISTINCT) se eliminan las líneas que resultan duplicadas.
En el caso en que no estén presentes ni ALL ni DISTINCT, se asume ALL.
7. (si está presente la cláusula ORDER BY) las líneas de la tabla se ordenan según los
valores presentes en las columnas especificadas en la cláusula. La sintaxis que hay
que usar es la siguiente:
El orden por defecto es ascendente. En el caso en que se quiera efectuar el decreciente hay
que especificar la opción DESC. Si no se especifica la cláusula ORDER BY, hay que considerar
la tabla sin ningún orden; de hecho, para la definición de relación del modelo relacional, las
líneas de la tabla forman un conjunto: en el sentido matemático y para los elementos de un
conjunto no se ha definido ninguna propiedad de orden. En la práctica, sin embargo, el orden
que se obtiene no especificando la cláusula de orden es casi siempre el que refleja su
memorización física y por tanto, a menudo, al que se debe que las líneas hayan sido incluidas
en la tabla.
La secuencia de operaciones que acabamos de presentar hay que considerarla válida sólo
desde el punto de vista conceptual. Efectivamente, no está escrito que se ejecuten
exactamente de este modo y en este orden, sobre todo desde el momento en que cada DBMS
optimizará las interrogaciones según las estrategias más oportunas.
Examinaremos ahora algunos ejemplos de la instrucción SELECT. Se supone que los datos
presentes en la base de datos de ejemplo son sólo los que se han incluido gracias al archivo
[poblad_biblio.sql] presentado en la lección 7 (Poblar la base de datos). En caso contrario, las
interrogaciones ofrecerán resultados diferentes.
EJEMPLO 1
Extrae de la tabla Person los apellidos y los ordena alfabéticamente. En nuestro caso, el
resultado es el siguiente:
surname
--------------------------------
Agosti
Batini
Bayer
Benfante
Carey
Cochowsky
DeWitt
Kim
Knuth
Lenzerini
Maryansky
McCreight
McGill
Melucci
Richardson
Salton
Santucci
Shekita
Spaccapietra
de Petra
Véase el orden errado de la última línea, debido a que se ha usado el carácter ASCII
minúsculo.
La query anterior devolvería líneas duplicadas en el caso en que en la tabla estuviesen
presentes personas con el mismo apellido. Para evitarlo hay que especificar la opción
DISTINCT:
ESEMPIO 2
Produce una tabla que tiene todas las columnas de la tabla Person. Las líneas se filtran para
que estén presentes sólo las que tienen el apellido que empieza con el carácter 'B'. El operador
LIKE permite una comparación entre cadenas de caracteres usando pattern construidos con los
caracteres '%' e '_'. El primero sustituye un número no precisado de caracteres (también 0),
mientras que el segundo sustituye uno solo.
ESEMPIO 3
SELECT PUB.*, PER.surname AS S, PER.given_names
FROM Publication PUB, Author AUT, Person PER
WHERE PUB.ID = AUT.publicationID
AND AUT.personID = PER.ID
AND PUB.type = 'Book'
ORDER BY S
En este caso, la tabla resultante contiene todas las columnas de la tabla Publication (indicada
con el alias PUB definido en la cláusula FROM) y las columnas surname y given_names de la
tabla Person. La cláusula FROM genera el producto cartesiano de las tablas Publication, Author
y Person, de las que se seleccionan sólo las líneas en que el identificativo de la publicación y el
del autor se corresponden. Además, se limita a considerar sólo las publicaciones del tipo
'Book'. Para acabar, la tabla se ordena según los apellidos del autor, indicado mediante el alias
S, definido en la cláusula SELECT.
ESEMPIO 4
En este ejemplo, se ve el uso de una expresión condicional que contiene el operador IN, que
devuelve el valor verdadero si el valor del operando a su izquierda está incluido en la tabla
resultado de la expresión a su derecha. La query entre paréntesis produce una tabla de una
única columna, que contiene los identificativos de las publicaciones del tipo 'Book' de las que
Knuth es autor. La query más externa extrae, por tanto, de la tabla Book las informaciones de
los libros con esos identificativos.
EJEMPLO 5
count
-----
12
ESEMPIO 6
UPDATE nombre_tabla
SET lista_asignaciones
[ WHERE expresión_condicional ]
nombre_columna = expresión_escalar
Veamos un ejemplo:
UPDATE Person
SET given_names = 'Stefano'
WHERE surname = 'Spaccapietra'
La instrucción delete elimina de una tabla todas las líneas que satisfacen la expresión
condicional de la cláusula WHERE. Si WHERE no se especifica, se cancelan todas las líneas
de la tabla.
fracasará desde el momento en que existe un vínculo de integridad que liga una llave externa
de la tabla Prueba2 con la tabla Prueba1.
Sin embargo, la instrucción:
se ejecutará con éxito y producirá también la eliminación del vínculo de integridad referencial
presente en la tabla Prueba2.
En el caso en que se quiera modificar una tabla existente en la base de datos, la instrucción
que se tiene que usar es ALTER TABLE. Desde el momento en que la sintaxis de esta
instrucción resulta más bien complicada, se explicará descomponiéndola de acuerdo a las
funciones que se quieren obtener:
La sintaxis y el significado de la cláusula que define el nuevo valor de defecto son idénticos a
los de la cláusula_defecto que se usa en la orden CREATE TABLE.
La sintaxis que hay que usar para la definición del vínculo es la misma que se usa en la orden
CREATE TABLE para los vínculos de tabla.
1. Seguridad
La ejecución de una operación en los datos de la base de datos por parte de un usuario está
supeditada a la posesión por parte del usuario de los privilegios necesarios para la operación
concreta ejecutada en el conjunto de datos específico.
En general, los privilegios se asignan del siguiente modo:
Un usuario que crea una tabla o cualquier otro objeto de la base de datos es el propietario y
se le garantizan automáticamente todos los privilegios aplicables a dicho objeto, con la
posibilidad de darles también a otros usuarios dichos privilegios (privilegio de concesión).
Un usario que tenga un privilegio y posea además sobre él el privilegio de concesión puede
asignarle tal pricilegio a otro usuario y pasarle también el privilegio de concesión.
Los privilegios los concede quien tiene el permiso (es decir el propietario del objeto y quien
tiene el privilegio de concesión) mediante la orden GRANT, y los revoca mediante la orden
REVOKE.
USAGE
Privilegio para usar un dominio específico u otro objeto de la base de datos.
SELECT
Privilegio para acceder a todas las columnas de una tabla o de una vista.
INSERT [ (nombre_columna) ]
Si se especifica la opción nombre_columna, es el privilegio para incluir valores en la columna
indicada de una tabla o de una vista. Sin el nombre_columna es el privilegio para añadir valores
a todas las columnas, incluidas las que se añadirán a continuación.
UPDATE [ (nombre_columna) ]
Si se especifica la opción nombre_columna, se trata del privilegio para actualizar el valor en la
columna indicada de una tabla o de una vista. Si no, permite actualizar el valor de todas las
columnas, incluidas las que se añadirán a continuación.
DELETE
Privilegio para eliminar líneas de una tabla o de una vista.
REFERENCES [ (nombre_columna) ]
Si se especifica la opción nombre_columna, es el privilegio de referirse a la columna indicada
de una tabla o de una vista en la definición de un vínculo de integridad. Sin la opción, concede
dicho privilegio para todas las columnas, incluidas las que se añaden a continuación.
El objeto al que se refiere el privilegio es generalmente una tabla o una vista. La sintaxis para
su especificación es en ese caso:
[TABLE] nombre_tabla
tipo_objeto nombre_objeto
Por ejemplo:
le asigna al usuario benfante los privilegios de SELECT e INSERT sobre todas las columnas de
la tabla persona y el de UPDATE sobre la columna nombre de dicha tabla. Se les garantiza,
además, el privilegio de asignar estos permisos a otros usuarios.
Las transacciones SQL son conjuntos de instrucciones que hay que tratar como unidades
atómicas, es decir no descomponibles en las instrucciones individuales de las que están
formadas. Gracias a esta atomicidad, las transacciones permiten que se ejecuten operaciones
complejas en la base de datos, manteniendo la integridad. Efectivamente, una transacción se
ejecuta con éxito si y sólo si todas las operaciones que la componen terminan con éxito. Si no,
es decir si una de las operaciones falla, o si la transacción se anula explícitamente, todas las
operaciones anteriores son también anuladas. Las operaciones de una transacción no tienen
ningún efecto sobre la base de datos hasta que la transacción no se completa con éxito.
Desde el momento en que a una base de datos pueden acceder diferentes usuarios al mismo
tiempo, en cada instante podremos tener distintas transacciones que manipulen la base de
datos a la vez. El estándar SQL prevé que normalmente las transacciones se ejecuten en el
"nivel de aislamiento serializable" (isolation level SERIALIZABLE), o sea en una modalidad de
ejecución que garantice la "serializabilidad" de las transacciones. El hecho de que las
transacciones se puedan serializar significa que su efecto global sobre la base de datos es el
que se obtendría si aquéllas se ejecutasen no al mismo tiempo, sino una después de otra.
En el lenguaje SQL estándar, no existe una instrucción que haga iniciar explícitamente una
transacción. Las instrucciones se dividen en dos clases: las que pueden empezar una
transacción y las que no la hacen empezar. En el momento en que se intenta ejecutar una
instrucción del primer tipo, si no está ya en marcha una transacción, empieza una. La
transacción continúa hasta que una de las instrucciones falla, provocando la anulación de toda
la transacción, o hasta que se ejecuten las instrucciones COMMIT WORK o ROLLBACK
WORK. La instrucción COMMIT WORK termina la transacción confirmándola, convirtiendo en
definitivos los efectos de sus instrucciones sobre la base de datos. Sin embargo, la instrucción
ROLLBACK WORK acaba anulándola.
A menudo, las DBMS que se encuentran en el mercado implementan la gestión de las
transacciones de modo distinto a como está previsto en el estándar (al menos en sus
colocaciones por defecto). En este caso, normalmente está prevista una orden que empieza
explícitamente una transacción (BEGIN TRANSACTION, START WORK u otro). Si una
transacción no se ha empezado explícitamente, las instrucciones concretas componen una
cada una.
Para entender mejor cuáles podrían ser las consecuencias de la manipulación concurrente de
los datos de una base de datos sin usar transacciones, veamos un ejemplo. Supongamos que
tenemos una base de datos con la que gestionamos los pedidos de los productos que
vendemos. En concreto, cuando un cliente nos solicita un producto, comprobamos la
disponibilidad y, en el caso en que podamos satisfacer el pedido, restamos a la cantidad que
tenemos la cantidad que se nos ha pedido. Traduciendo todo esto a SQL, obtenemos la
cantidad almacenada con la instrucción (instrucción A):
UPDATE productos
SET almacenamiento=almacenamiento-1
WHERE productoID=1453
Si dos usuarios intentan ejecutar esta operación, sin que las dos instrucciones que la
componen se hayan reagrupado en una transacción, podría suceder que las instrucciones se
ejecuten en el orden y con los resultados siguientes:
1. Instrucción A, ejecutada por el usuario 1: se devuelve un almacenamiento del producto
equivalente a 1, por lo que el pedido será aprobado.
2. Instrucción A, ejecutada por el usuario 2: como antes, el almacenamiento es 1 y
también en este caso el pedido se aprobará.
3. Instrucción B, ejecutada por el usuario 1: en este punto, en la base de datos el
almacenamiento para el producto vale 0.
4. Instrucción B, ejecutada por el usuario 2: ahora el almacenamiento vale -1, que,
obviamente, es un valor equivocado.
Como se ve, el resultado final es que uno de los dos clientes no podrá recibir (al menos no
inmediatamente) la mercancía, dado que no teníamos en almacén una cantidad suficiente para
ambos clientes. Si las dos instrucciones se hubieran incluido en una transacción, el problema
no se habría producido, dado que la transacción del segundo usuario no habría podido leer el
valor del almacenamiento hasta que no se hubiese completado la transacción del primer
usuario. En ese momento, el almacenamiento habría tenido valor 0 y el pedido no habría
estado erróneamente aprobado.
3. Vistas
Hasta ahora las únicas tablas de las que nos hemos ocupado han sido las definidas con la
orden CREATE TABLE. El lenguaje SQL también pone a disposición la posibilidad de definir
tablas "virtuales", las vistas, calculadas a partir de otras tablas. Son virtuales en el sentido que
no ocupan espacio en el disco, pero son el resultado de interrogaciones sobre otras tablas y,
por lo tanto, siempre están alineadas con los valores contenidos en dichas tablas.
La instrucción SQL para definir una vista es la siguiente:
Ésta nos permite ejecutar la query que la define simplemente utilizando la instrucción:
Podemos también introducir ulteriores condiciones (o hacer que el resultado se ordene según
una columna concreta de la vista, etc...):
SELECT title FROM book_publisher89
WHERE name = "ACM Press"
Esta última interrogación nos ofrece la lista de los títulos de los libros publicados por ACM
Press en 1989.
Como se ve, por lo que respecta a las operaciones de interrogación, una vista se comporta
como una tabla normal. Las diferencias aparecen cuando se intentan aplicar a una vista
operaciones de actualización. Por ejemplo, si intentamos ejecutar la siguiente instrucción:
La DBMS no conseguirá ejecutarla, devolviendo un error del tipo "No INSERT permission". El
motivo es que no es capaz de crear las líneas correspondientes a nuestro nuevo récord en las
dos tablas "reales" en las que se ha originado la vista (los problemas son varios: tiene que
crear sólo una línea en la tabla Book y conectarla a una línea concreta de la tabla Publisher, o
crear una línea en ambas tablas; cómo decidir qué valores darles a las llaves primarias de los
eventuales nuevos récords; qué valores darles a los otros campos de las dos tablas, etc...)
Gracias a las vistas (y a la asignación prudente de los permisos a los usuarios) es posible
conseguir que diferentes usuarios tengan una percepción de la estructura de la base de datos,
si bien muy diferentes de la que tiene realmente, e impedir que algunas categorías de usuarios
puedan acceder a informaciones que no les competen.
Por ejemplo, supongamos que contamos con una tabla en la que se han memorizado los datos
personales de los empleados de una empresa, así como las cantidades que conforman sus
respectivos sueldos. Obviamente, habría que evitar la consulta de los datos relativos a los
sueldos por parte de los usuarios, excepto quienes se tienen que ocupar de su
erogación/administración. Un sistema para hacerlo consiste en definir una vista que contenga
sólo las columnas de los datos personales. Así, todos los usuarios autorizados a acceder a
dichos datos, pero no a los de los sueldos, podrán entrar sólo a través de dicha vista. Ulteriores
particiones podrían hacerse en sentido horizontal, creando por ejemplo una vista que sólo
contenga las informaciones sobre los directivos y otra con los datos del resto de los
dependientes. Además, las vistas a menudo contribuyen a facilitar la independencia entre
aplicaciones y estructura de los datos, lo que hace que las bases de datos de los instrumentos
sean tan útiles. Efectivamente, si en un momento determinado fuese necesario cambiar la
estructura de la base de datos (descomponiendo, por ejemplo, una tabla en dos por motivos de
eficacia), no habría que modificar todas las aplicaciones adaptándolas a la nueva estructura,
sino que sería suficiente crear las vistas pertinentes, de modo que, desde el punto de vista de
las aplicaciones, nada haya cambiado.
American National Standards Institute - "Database Language Embedded SQL", Document ANSI
X3.168-1989
R. Elmasri and S.B. Navathe - "Fundamentals of Database Systems", Second Edition, The
Benjamin/Cummings publishing company, 1994
F.D. Rolland - "The essence of databases", Prentice Hall, 1998
E.F. Codd - "A Relational Model of Data for Large Shared Data Banks", Communications of the
ACM 13, No. 6, June 1970
C.J. Date with Hugh Darwen - "A Guide To The SQL Standard", Fourth Edition, Addison-
Wesley, 1997
Helmut Kopka and Patrick W. Daly - "A Guide to LaTeX 2e", Second Edition, Addison-Wesley,
1995
Jason Hunter with William Crawford - "Java Servlet Programming", O'Reilly, 1998
ftp://gatekeeper.dec.com/pub/standards/sql
Raccolta di Working Draft del linguaggio SQL3 in formato ps e txt
http://www.jcc.com/SQLPages/jccs_sql.html
La pagina riguardante lo standard SQL della JCC Consulting, Inc.
http://www.postgresql.org
Il sito dedicato a PostgreSQL. Vi si puo' inoltre trovare una versione elettronica del libro di
Bruce Momjian - "PostgreSQL: Introduction and Concepts"