Download 1. Una simple gramática sintáctica La gramática sintáctica utilizada

Document related concepts

Normalización de bases de datos wikipedia , lookup

Clave primaria wikipedia , lookup

SQL wikipedia , lookup

Modelo de base de datos wikipedia , lookup

Base de datos relacional wikipedia , lookup

Transcript
1. Una simple gramática sintáctica
La gramática sintáctica utilizada en las diferentes lecciones para explicar la sintaxis de las instrucciones SQL.
2. Web, Base de datos y DBMS
Las características y funciones principales según las cuales se clasifican normalmente los DBMS.
3. El modelo relacional
Historia y panorámica de las bases de datos relacionales.
4. Breve historia de SQL
Historia y desarrollo de SQL desde 1974 hasta hoy
5. Una base de datos de ejemplo
Presentación de la estructura de la base de datos que será utilizada para los ejemplos de las siguientes lecciones.
6. Instrumentos para interactuar con un DBMS
Las dos modalidades de interacción con DBMS: invocación interactiva e invocación a través de un programa aplicativo
7. Crear la base de datos
La creación de la base de datos consiste en la creación de las tablas que lo componen
8. Poblar la base de datos
Con la expresión "población de la base de datos" se entiende la actividad de inclusión de los datos en ella.
9. Interrogar a la base de datos
Las instrucciones necesarias para extraer de una base de datos relacional los datos que interesan.
10. Actualizar la base de datos
Cómo modificar los datos ya incluidos en las tablas de la base de datos.
11. Modificar la estructura de la base de datos
A veces no es suficiente modificar los datos, sino que hay que actualizar la estructura misma de la base de datos para hacer que
puedan representarse nuevas informaciones
12. Uso multiusuario de una base de datos
Normalmente, el acceso a los datos se da de manera colectiva por parte de varios usuarios la mismo tiempo
11. Referencias bibliográficas y web
Sitios Web y libros de profundización sobre SQL.
Gramática Simple
La gramática sintáctica utilizada en las diferentes lecciones para explicar la sintaxis de las instrucciones
SQL es muy simple:

El texto en mayúscula tiene que aparecer como es. El lenguaje SQL no es case-sensitive, por lo
que después, en los ejemplos, aparecerán tanto letras mayúsculas como minúsculas, de manera
que aumenta la legibilidad.

El texto en minúscula indica elementos que tienen que ser especificados después. Por ejemplo,
si aparece vínculos_de_columna no significa que en esa posición haya que escribir
correctamente la secuencia de caracteres, sino que encontrarán sitio los vínculos de la columna,
especificados con su sintaxis concreta, que se explica en otro lugar.

Los corchetes ([]) indican elementos opcionales y que por tanto no tienen por qué aparecer.

Los puntos suspensivos (...) indican elementos que se pueden repetir. Por ejemplo:
[ , [ vínculo_de_tabla ] ... ]
indica que el elemento ", [vínculo_de_tabla]" se puede repetir tantas veces como sea necesario.

Elementos separados por el carácter "|", y eventualmente agrupados entre llaves ({}), indican
elementos que alternativos. Por ejemplo:
{ elemento1 | elemento2 }
indica que en esa posición habrá que escribir o elemento1 o elemento2.

El texto escrito entre comillas simples (') o dobles (") se escribe exactamente como está indicado
(comillas, mayúsculas y minúsculas incluidas).

Los demás caracteres (por ejemplo las comas(,) o las comillas dobles(")) tienen que aparecer
como son.
Web, Bases de datos, DBMS
El World Wide Web quizá sea una de las mayores fuentes de información a la que hoy podemos
dirigirnos: teniendo a disposición una conexión a Internet y un navegador Web, un software común de
cualquier ordenador, tenemos la posibilidad de consultar un patrimonio de cientos de millones de páginas
a propósito de cualquier argumento que nos interese.
A menudo, estas páginas no son documentos estáticos, sino que se crean dinámicamente cuando las
invocamos, y las informaciones que contienen se extraen de una base de datos. Si se trata de una base
de datos relacional (veremos a continuación qué significa esto), es probable que el lenguaje usado para
recuperar las informaciones que se nos muestran sea SQL (Structured Query Language).
Antes de ocuparnos de qué es y cómo se usa SQL intentemos entender qué se entiende con la
expresión database, que a menudo en español se traduce como "base de datos".
Una base de datos es una colección de datos que es gestionada y organizada por un software
específico, el DBMS (DataBase Management System, Sistema de Gestión de DataBase). Un DBMS es
sustancialmente un software que se coloca entre el usuario y los datos como tales. Gracias a este
estrato intermedio el usuario y las aplicaciones no acceden a los datos tal y como se memorizan
efectivamente, es decir a su representación física, sino que se ve sólo una representación lógica. Esto
permite un grado elevado de independencia entre las aplicaciones y la memorización física de los datos.
El administrador de la base de datos, si lo necesita, puede decidir memorizar los datos de un modo
diferente o incluso cambiar el DBMS sin que las aplicaciones, es decir los usuarios, se resientan. Lo
importante es que no cambie la representación lógica de esos datos, que es la única cosa que los
usuarios conocen. Esta representación lógica se conoce como 'Esquema de la base de datos' y es la
forma de representación de los datos de más bajo nivel a la que un usuario de la base de datos puede
acceder. Por ejemplo, en la Figura 1 está representada una situación en la que el administrador de la
base de datos ha decidido que, por motivos de eficacia, era necesario cambiar el disco en el que se
habían memorizado algunos datos, repartiéndolos, además, en más discos para permitir accesos
paralelos a subconjuntos de datos independientes. Desde el punto de vista del usuario, no ha cambiado
absolutamente nada y probablemente ni siquiera conoce el cambio que se ha producido.
La característica principal según la cual los DBMS se clasifican es la representación lógica de los datos
que muestran a sus usuarios. Con el paso de los años, se han adoptado numerosos modelos para los
datos, al frente de los cuales existen diversos tipos de bases de datos. Los más comunes son:
Bases de datos jerárquicos: los datos se organizan en grupos unidos entre ellos por relaciones de
"posesión", en las que un conjunto de datos puede tener otros conjuntos de datos, pero un conjunto
puede pertenecer sólo a otro conjunto. La estructura resultante es un árbol de conjuntos de datos.
Bases de datos reticulares: el modelo reticular es muy parecido al jerárquico, y de hecho nace como
una extensión de este último. También en este modelo conjuntos de datos están unidos por relaciones
de posesión, pero cada conjunto de datos puede pertenecer a uno o más conjuntos. La estructura
resultante es una red de conjuntos de datos.
Bases de datos relacionales: las bases de datos que pertenecen a esta categoría se basan en el
modelo relaciones, cuya estructura principal es la relación, es decir una tabla bidimensional compuesta
por líneas y columnas. Cada línea, que en terminología relacional se llama tupla, representa una entidad
que nosotros queremos memorizar en la base de datos. las características de cada entidad están
definidas por las columnas de las relaciones, que se llaman atributos. Entidades con características
comunes, es decir descritas por el mismo conjunto de atributos, formarán parte de la misma relación.
Base de datos por objetos (object-oriented): el esquema de una base de datos por objetos está
representado por un conjunto de clases que definen las características y el comportamiento de los
objetos que poblarán la base de datos. La diferencia principal respecto a los modelos examinados hasta
ahora es la no positividad de los datos. En efecto, con una base de datos tradicional (entendiendo con
este término cualquier base de datos no por objetos), las operaciones que se tienen que efectuar en los
datos se les piden a las aplicaciones que los usan. Con una base de datos object-oriented, al contrario,
los objetos memorizados en la base de datos contienen tanto los datos como las operaciones posibles
con tales datos. En cierto sentido, se podrá pensar en los objetos como en datos a los que se les ha
puesto una inyección de inteligencia que les permite saber cómo comportarse, sin tener que apoyarse en
aplicaciones externas.
Los primeros dos tipos de bases de datos, los jerárquicos y reticulares, hoy ya casi pertenecen a la
historia de la informática.
La mayor parte de las bases de datos que hoy se usan pertenece a la categoría de las bases de datos
relacionales. Los motivos de este éxito (también comercial) hay que buscarlos en el rigor matemático y
en la potencialidad expresiva del modelo relacional en que se basan, en su facilidad de uso y, último
pero no menos importante, en la disponibilidad de un lenguaje de interrogación estándar, el SQL, que, al
menos potencialmente, permite que se desarrollen aplicaciones independientes del DBMS concreto
relacional que se use.
Las bases de datos por objetos son la nueva frontera en la investigación sobre las bases de datos;
efectivamente, sus características de extendibilidad, que se derivan de la posibilidad de definir nuevos
tipos de datos y comportamientos, las hacen particularmente apetecibles para todas las aplicaciones que
usan datos complejos, como por ejemplo imágenes, sonidos o ambos coordinados. Por desgracia, la
falta de un modelo universalmente aceptado para los objetos, así como que no exista un lenguaje de
interrogación estándar, hace que cada productor implemente la propia visión específica, a menudo
absolutamente incompatible con las otras. Recientemente, han aparecido en el mercado algunas bases
de datos definidas como object-relational, que intentan introducir en el modelo relacional las
características de extendibilidad propias de las bases de datos object-oriented.
Independientemente del tipo de base de datos, las funciones principales que se pueden esperar de un
DBMS son:
1. permitir el acceso a los datos a través de un esquema conceptual, en vez de hacerlo a través de
un esquema físico;
2. compartir e integrar los datos entre aplicaciones diferentes;
3. controlar el acceso compartido a los datos;
4. garantizar la seguridad e integridad de los datos;
Gracias a estas características, las aplicaciones que se desarrollan pueden contar con una fuente de
datos segura, fiable y generalmente escalabale. Estas propiedades son deseables para aplicaciones que
usan la red Internet como infraestructura y que por tanto tienen evidentes problemas de seguridad y de
escala.
El Modelo Relacional
Las bases de datos relacionales son el tipo de bases de datos actualmente más difundido. Los motivos
de este éxito son fundamentalmente dos:
1. ofrecen sistemas simples y eficaces para representar y manipular los datos
2. se basan en un modelo, el relacional, con sólidas bases teóricas
El modelo relacional fue propuesto originariamente por E.F. Codd en un ya famoso artículo de 1970.
Gracias a su coherencia y facilidad de uso, el modelo se ha convertido en los años 80 en el más
usado para la producción de DBMS.
La estructura fundamental del modelo relacional es precisamente esa, "relación", es decir una tabla
bidimensional constituida por líneas (tuple) y columnas (atributos). Las relaciones representan las
entidades que se consideran interesantes en la base de datos. Cada instancia de la entidad encontrará
sitio en una tupla de la relación, mientras que los atributos de la relación representarán las propiedades
de la entidad. Por ejemplo, si en la base de datos se tienen que representar personas, se podrá definir
una relación llamada "Personas", cuyos atributos describen las características de las personas(Figura 2).
Cada tupla de la relación "Personas" representará una persona concreta.
En realidad, siendo rigurosos, una relación es sólo la definición de la estructura de la tabla, es decir su
nombre y la lista de los atributos que la componen. Cuando se puebla con las tuplas, se habla de
"instancia de relación". Por eso, la anterior Figura 2 representa una instancia de la relación persona. Una
representación de la definiticón de esa relación podría ser la siguiente:
Personas (nombre, apellido, fecha_nacimiento, sexo, estado_civil)
A continuación, se indicarán ambas (relación e instancia de relación) con el término "relación", a no ser
que no quede claro por el contexto a qué acepción se refiere.
Las tuplas en una relación son un conjunto en el sentido matemático del término, es decir una colección
no ordenada de elementos diferentes. Para distinguir una tupla de otra, se recurre al concepto de "llave
primaria", o sea a un conjunto de atributos que permiten identificar unívocamente una tupla en una
relación. Naturalmente, en una relación puede haber más combinaciones de atributos que permitan
identificar unívocamente una tupla ("llaves candidatas"), pero entre éstas se elegirá una sola para utilizar
como llave primaria. Los atributos de la llave primaria no pueden asumir el valor nulo (que significa un
valor no determinado), en tanto que ya no permitirían identificar una tupla concreta en una relación. Esta
propiedad de las relaciones y de sus llaves primarias está bajo el nombre de integridad de las entidades
(entity integrity).
A menudo, para obtener una llave primaria "económica", es decir compuesta de pocos atributos
fácilmente manipulables, se introducen uno o más atributos ficticios, con códigos identificativos unívocos
para cada tupla de la relación.
Cada atributo de una relación se caracteriza por un nombre y por un dominio. El dominio indica qué
valores pueden ser asumidos por una columna de la relación. A menudo un dominio se define a través
de la declaración de un tipo para el atributo (por ejemplo diciendo que es una cadena de diez
caracteres), pero también es posible definir dominios más complejos y precisos. Por ejemplo, para el
atributo "sexo" de nuestra relacion "Personas" podemos definir un dominio por el cual los únicos valores
válidos son 'M' y 'F'; o bien por el atributo "fecha_nacimiento" podremos definir un dominio por el que se
consideren válidas sólo las fechas de nacimiento después del uno de enero de 1960, si en nuestra base
de datos no está previsto que haya personas con fecha de nacimiento anterior a esa. El DBMS se
ocupará de controlar que en los atributos de las relaciones se incluyan sólo los valores permitidos por
sus dominios. Característica fundamental de los dominios de una base de datos relacional es que sean
"atómicos", es decir que los valores contenidos en las columnas no se puedan separar en valores de
dominios más simples. Más formalmente se dice que no es posible tener atributos multivalor
(multivalued). Por ejemplo, si una característica de las personas en nuestra base de datos fuese la de
tener uno o más hijos, no sería posible escribir la relación Personas de la siguiente manera:
Personas (nombre, apellido, fecha_nacimiento, sexo, estado_civil, hijos)
En efecto, el atributo hijos es un atributo no-atómico, bien porque una persona puede tener más de un
hijo o porque cada hijo tendrá diferentes características que lo describen. Para representar estas
entidades en una base de datos relacional hay que definir dos relaciones:
Personas (*número_persona, nombre, apellido, fecha_nacimiento, sexo, estado_civil)
Hijos(*número_persona, *nombre_apellido, edad, sexo)
En las relaciones precedentes, los asteriscos (*) indican los atributos que componen sus llaves primarias.
Nótese la introducción en la relación Personas del atributo número_persona, a través del cual se asigna
a cada persona un identificativo numérico unívoco que se usa como llave primaria. Estas relaciones
contienen sólo atributos atómicos. Si una persona tiene más de un hijo, éstos se representarán en tuplas
diferentes de la relación Hijos. Las diferentes características de los hijos las representan los atributos de
la relación Hijos. La unión entre las dos relaciones está constituida por los atributos número_persona que
aparecen en ambas relaciones y que permiten que se asigne cada tupla de la relación hijos a una tupla
concreta de la relación Personas. Más formalmente se dice que el atributo número_persona de la
relación Hijos es una llave externa (foreign key) hacia la relación Personas. Una llave externa es una
combinación de atributos de una relación que son, a su vez, una llave primaria para otra relación. Una
característica fundamental de los valores presentes en una llave externa es que, a no ser que no sean
null, tienen que corresponder a valores existentes en la llave primaria de la relación a la que se refieren.
En nuestro ejemplo, esto significa que no puede existir en la relación Hijos una tupla con un valor del
atributo número_persona sin que también en la relación Personas exista una tupla con el mismo valor
para su llave primaria. Esta propiedad va bajo el nombre de integridad referencial (referential integrity)
Una de las grandes ventajas del modelo relacional es que define también un álgebra, llamada "álgebra
relacional". Todas las manipulaciones posibles sobre las relaciones se obtienen gracias a la combinación
de tan sólo cinco operadores: RESTRICT, PROJECT, TIMES, UNION y MINUS. Por comodidad, se han
definido también tres operadores adicionales que de todos modos se pueden obtener aplicando los cinco
fundamentales: JOIN, INTERSECT y DIVIDE. Los operadores relacionales reciben como argumento una
relación o un conjunto de relaciones y restituyen una única relación como resultado.
Veamos brevemente estos ocho operadores:
RESTRICT: restituye una relación que contiene un subconjunto de las tuplas de la relación a la que se
aplica. Los atributos se quedan como estaban.
PROJECT: restituye una relación con un subconjunto de los atributos de la relación a la que viene
aplicado. Las tuplas de la relación resultado se componen de las tuplas de la relacion original, de manera
que siguen siendo un conjunto en sentido matemático.
TIME: se aplica a dos relaciones y efectúa el producto cartesiano de las tuplas. Cada tupla de la primera
relación está concatenada con cada tupla de la segunda.
JOIN: se concatenan las tuplas de dos relaciones de acuerdo con el valor de un conjunto de sus
atributos.
UNION: aplicando este operador a dos relaciones compatibles, se obtiene una que contiene las tuplas de
ambas relaciones. Dos relaciones son compatibles si tienen el mismo número de atributos y los atributos
correspondientes en las dos relaciones tienen el mismo dominio.
MINUS: aplicado a dos relaciones compatibles restituye una tercera que contiene las tuplas que se
encuentran sólo en la primera relación.
INTERSECT: aplicado a dos relaciones compatibles restituye una relación que contiene las tuplas que
existen en ambas.
DIVIDE: aplicado a dos relaciones que tengan atributos comunes, restituye una tercera que contiene
todas las tuplas de la primera relación que se puede hacer que correspondan con todos los valores de la
segunda relación.
En las siguientes tablas, a título de ejemplo, se representan los resultados de la aplicación de algunos
operadores relacionales a las relaciones Personas e Hijos. Como nombres para las relaciones resultado
se han utilizado las expresiones que las producen.
Personas
número_persona
nombre
2
Mario
apellido fecha_nacimiento sexo stado_civil
Rossi
29/03/1965
M
Casado
1
3
Giuseppe
Russo
Alessandra Mondella
15/11/1972
M
Soltero
13/06/1970
F
Soltera
Hijos
número_persona nombre_apellido edad sexo
2
Maria Rossi
3
F
2
Gianni Rossi
5
M
RESTRICT (Personas)
sesso='M'
número_persona nombre apellido fecha_nacimiento sexo estado_civil
2
1
Mario
Rossi
29/03/1965
M
Casado
Giuseppe Russo
15/11/1972
M
Soltero
PROJECT sexo (Personas)
sexo
M
F
RESTRICT (Personas)
sexo='M'
n.
nombre apellido nacimiento sexo stado_civil
Mario Rossi
nombre
edad sexo
apellido 29/03/1965 M
Csado
Maria Rossi
3
F
Mario Rossi Apellido 29/03/1965 M
Casado
Gianni Rossi
5
M
Las bases de datos relacionales efectúan todas las operaciones en las tablas usando el álgebra
relacional, aunque normalmente no le permiten al usuario usarla. El usuario interacciona con la base de
datos a través de una interfaz diferente el lenguaje SQL, un lenguaje declarativo que permite escribir
conjuntos de datos. Las instrucciones SQL vienen descompuestas por el DBMS en una serie de
operaciones relacionales.
Historia del SQL
La historia de SQL (que se pronuncia deletreando en inglés las letras que lo componen, es decir "ese-cuele" y no "siquel" como se oye a menudo) empieza en 1974 con la definición, por parte de Donald
Chamberlin y de otras personas que trabajaban en los laboratorios de investigación de IBM, de un
lenguaje para la especificación de las características de las bases de datos que adoptaban el modelo
relacional. Este lenguaje se llamaba SEQUEL (Structured English Query Language) y se implementó en
un prototipo llamado SEQUEL-XRM entre 1974 y 1975. Las experimentaciones con ese prototipo
condujeron, entre 1976 y 1977, a una revisión del lenguaje (SEQUEL/2), que a partir de ese momento
cambió de nombre por motivos legales, convirtiéndose en SQL. El prototipo (System R), basado en este
lenguaje, se adoptó y utilizó internamente en IBM y lo adoptaron algunos de sus clientes elegidos.
Gracias al éxito de este sistema, que no estaba todavía comercializado, también otras compañías
empezaron a desarrollar sus productos relacionales basados en SQL. A partir de 1981, IBM comenzó a
entregar sus productos relacionales y en 1983 empezó a vender DB2. En el curso de los años ochenta,
numerosas compañías (por ejemplo Oracle y Sybase, sólo por citar algunos) comercializaron productos
basados en SQL, que se convierte en el estándar industrial de hecho por lo que respecta a las bases de
datos relacionales.
En 1986, el ANSI adoptó SQL (sustancialmente adoptó el dialecto SQL de IBM) como estándar para los
lenguajes relacionales y en 1987 se transfomó en estándar ISO. Esta versión del estándar va con el
nombre de SQL/86. En los años siguientes, éste ha sufrido diversas revisiones que han conducido
primero a la versión SQL/89 y, posteriormente, a la actual SQL/92.
El hecho de tener un estándar definido por un lenguaje para bases de datos relacionales abre
potencialmente el camino a la intercomunicabilidad entre todos los productos que se basan en él. Desde
el punto de vista práctico, por desgracia las cosas fueron de otro modo. Efectivamente, en general cada
productor adopta e implementa en la propia base de datos sólo el corazón del lenguaje SQL (el así
llamado Entry level o al máximo el Intermediate level), extendiéndolo de manera individual según la
propia visión que cada cual tenga del mundo de las bases de datos.
Actualmente, está en marcha un proceso de revisión del lenguaje por parte de los comités ANSI e ISO,
que debería terminar en la definición de lo que en este momento se conoce como SQL3. Las
características principales de esta nueva encarnación de SQL deberían ser su transformación en un
lenguaje stand-alone (mientras ahora se usa como lenguaje hospedado en otros lenguajes) y la
introducción de nuevos tipos de datos más complejos que permitan, por ejemplo, el tratamiento de datos
multimediales.
Una Base de Datos como Ejemplo
Presentaremos ahora la estructura de la base de datos que se utilizará para los ejemplos de las
siguientes lecciones. No se describirán las fases de análisis ni los modelos conceptuales y lógicoa que
han sido necesarios para alcanzar tal estructura, desde el momento en que esto se apartaría de los
objetivos de este curso. La estructura de la base de datos está representada en el diagrama relacional
de la Figura 3. Cada rectángulo representa una relación. El nombre de la relación está en la sección más
oscura de la parte alta del rectángulo. El resto del rectángulo está subdividido en tres columnas, en las
cuales están definidas las características de los atributos que componen la relación. La columna central
contiene los nombres de los atributos; la de la derecha, su tipo (han sido utilizados los tipos del SQL/92),
y la de la izquierda sus propiedades, Las propiedades de los atributos se indican con las siglas "PK" y
"FK", que significan respectivamente que los correspondientes atributos forman parte de la llave primaria
de la relación (Primary Key) o de una llave externa (Foreign Key). Las flechas hacen converger las llaves
externas con las primarias a las que se refieren. Los nombres de los atributos en negrita indican que
éstos no pueden tomar el valor NULL, o sea que no pueden ser indeterminados.
Clica en la foto para agrandarla
La finalidad de la base de datos consiste en contener las informaciones bibliográficas de un conjunto de
publicaciones, a fin de poderlas consultar fácilmente y utilizarlas para la construcción de otras
bibliografías. Ésta se ha modelado en la falsa línea del sistema bibliográfico del sistema LaTeX, para
contar con un ambiente consolidado al que referirse y facilitar la realización de programas de conversión
entre un sistema y otro.
El significado de las relaciones que componen la base de datos es el siguiente:
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.
Editor: Representa al coordinador de una publicación. La estructura es idéntica a la de la tabla Author.
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.
Publisher: La casa editorial de una publicación.
Institution: La institución (por ejemplo una universidad o una software house) responsable de una
publicación.
Book: Un libro con una casa editorial precisa.
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.
Proceedings: Las actas de un congreso o de una conferencia.
InProceedings: Una parte de las actas de un congreso. Las informaciones referidas a la publicación que
contiene esa parte están en la relación Proceedings.
Article: Un artículo publicado en un periódico o en una revista.
Manual: Una publicación de documentación técnica.
Techreport: Un informe técnico publicado por una escuela u otra institución.
Thesis: Una tesina o una tesis.
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.
En las siguientes lecciones se implementará la base de datos de ejemplo usando el lenguaje SQL
estándar. El DBMS específico usado será PostgresSQL, pero se podrá sustituir con cualquier DBMS que
soporte l'Entry level del SQL/92.
Interactuar con el DBMS
Como ya se ha dicho, la interacción con una base de datos relacional se da normalmente empleando
instrucciones SQL. El envío de las instrucciones a la DBMS se puede dar de dos maneras:


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:
psql [ dbname [ user ] ]
"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:
psql mydb benfante
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:
psql -f instrucciones.sql mydb benfante
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.
Crear una Base de Datos
Una base de datos en un sistema relacional está compuesta por un conjunto de tablas, que
corresponden a las relaciones del modelo relacional. En la terminología usada en SQL no se alude a las
relaciones, del mismo modo que no se usa el término atributo, pero sí la palabra columna, y no se habla
de tupla, sino de línea. A continuación se usarán indistintamente ambas terminologías, por lo que tabla
estará en lugar de relación, columna en el de atributo y línea en el de tupla, y viceversa.
Prácticamente, la creación de la base de datos consiste en la creación de las tablas que la componen.
En realidad, antes de poder proceder a la creación de las tablas, normalmente hay que crear la base de
datos, lo que a menudo significa definir un espacio de nombres separado para cada conjunto de tablas.
De esta manera, para una DBMS se pueden gestionar diferentes bases de datos independientes al
mismo tiempo sin que se den conflictos con los nombres que se usan en cada una de ellas. El sistema
previsto por el estándar para crear los espacios separados de nombres consiste en usar las
instrucciones SQL "CREATE SCHEMA". A menudo, dicho sistema no se usa (o por lo menos no con los
fines y el significado previstos por el estándar), pero cada DBMS prevé un procedimiento propietario para
crear una base de datos. Normalmente, se amplía el lenguaje SQL introduciendo una instrucción no
prevista en el estándar: "CREATE DATABASE".
La sintaxis empleada por PostgreSQL, pero también por las DBMS más difundidas, es la siguiente:
CREATE DATABASE nombre_base de datos
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 nombre_base de datos
Para crear nuestra base de datos bibliográfica, usaremos pues la orden:
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:
CREATE TABLE nombre_tabla (
nombre_columna tipo_columna [ cláusula_defecto ] [ vínculos_de_columna ]
[ , nombre_columna tipo_columna [ cláusula_defecto ] [ vínculos_de_columna ] ... ]
[ , [ vínculo_de tabla] ... ] )
nombre_columna: es el nombre de la columna que compone la tabla. Sería mejor no exagerar con la
longitud de los identificadores de columna, puesto que SQL Entry Level prevé nombres con no más de
18 caracteres. Consúltese, de todos modos, la documentación de la base de datos específica. Los
nombres tienen que comenzar con un carácter alfabético.
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).

DATE, TIME y TIMESTAMP
Un instante temporal preciso. DATE permite indicar el año, el mes y el día. Con TIME se pueden
especificar la hora, los minutos y los segundos. TIMESTAMP es la combinación de los dos
anteriores. Los segundos son un número con coma, lo que permite especificar también
fracciones de segundo.
cláusula_defecto: indica el valor de defecto que tomará la columna si no se le asigna uno
explícitamente en el momento en que se crea la línea. La sintaxis que hay que usar es la siguiente:
DEFAULT { valor | NULL }
donde valor es un valor válido para el tipo con el que la columna se ha definido.
vínculos_de_columna: son vínculos de integridad que se aplican a cada atributo concreto. Son:



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:
REFERENCES nombre_tabla [ ( columna1 [ , columna2 ... ] ) ]
[ ON DELETE { CASCADE | SET DEFAULT | SET NULL } ]
[ ON UPDATE { CASCADE | SET DEFAULT | SET NULL } ]
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:
o
o
o

CASCADE: eliminar la tupla que contiene la columna referenciante (en el caso de ON
DELETE) o también actualizar la columna referenciante (en el caso de ON UPDATE).
SET DEFAULT: asignar a la columna referenziante su valor de defecto.
SET NULL: asignar a la columna referenciante el valor NULL.
un control de valor, con el que se permite o no asignar un valor a la columna en función del
resultado de una expresión. La sintaxis que se usa es:
CHECK (expresión_condicional)
donde expresión_condicional es una expresión que ofrece verdadero o falso.
Por ejemplo, si estamos definiendo la columna COLUMNA1, con el siguiente control:
CHECK ( COLUMNA1 < 1000 )
en dicha columna se podrán incluir sólo valores inferiores a 1000.
vínculo_de_tabla: son vínculos de integridad que se pueden referir a más columnas de la tabla. Son:

la definición de la llave primaria:
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.

las definiciones de las llaves externas:
FOREIGN KEY ( columna1 [ , columna2 ... ] ) definiciones_de_referencia
La definición_de_referencia tiene la misma sintaxis y significado que la que puede aparecer
como vínculo de columna.

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.
CREATE TABLE Publication (
ID INTEGER PRIMARY KEY,
type CHAR(18) NOT NULL
);
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.
CREATE TABLE Book (
ID INTEGER PRIMARY KEY REFERENCES Publication(ID),
title VARCHAR(160) NOT NULL,
publisher INTEGER NOT NULL REFERENCES Publisher(ID),
volume VARCHAR(16),
series VARCHAR(160),
edition VARCHAR(16),
pub_month CHAR(3),
pub_year INTEGER NOT NULL,
note VARCHAR(255)
);
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.
CREATE TABLE Author (
publicationID INTEGER REFERENCES Publication(ID),
personID INTEGER REFERENCES Person(ID),
PRIMARY KEY (publicationID, personID)
);
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.
NOTA SOBRE POSTGRESQL
En PotgreSQL, por lo menos hasta la versión 6.5.1, no se han implementado todavía los vínculos sobre
las llaves externas. El parser acepta, de todos modos, las sintaxis SQL que le afectan, y por tanto los
constructos FOREIGN KEY y REFERENCES no producen un error, sino sólo un warning.
Poblar la Base de Datos
Con la expresión "población de la base de datos" se entiende la actividad de inclusión de los datos
dentro de ella. En una base de datos relacional esto corresponde a la creación de las líneas que
componen las tablas que constituyen la base de datos. Normalmente, la memorización de una
información concreta corresponde a la inclusión de una o más líneas en una o más tablas de la base de
datos. Tómese, por ejemplo, la siguiente información bibliográfica:
M. Agosti, L. Benfante, M. Melucci. OFAHIR: "On-the-Fly" Automatic Authoring of Hypertexts for
Information Retrieval. In S. Spaccapietra, F. Maryansky (Eds), Searching for Semantics: Data Mining,
Reverse Engineering. Proc. of the 7th IFIP 2.6 Working Conference on Database Semantics (DS-7),
Leysin, Switzerland, October 1997, 129-154.
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;
 una línea en la tabla Institution;
 dos líneas en la tabla Publication: una para las actas del congreso y una para el artículo contenido en
esas actas;
 una línea en la tabla Proceedings;
 una línea en la taba InProceedings;
 tres líneas en la tabla Author, una para cada autor de la publicación.
 dos líneas en la tabla Editor, una para cada coordinador de la publicación.
El orden de las operaciones anteriores no es puramente casual; de hecho, la inserción de las líneas tiene
que hacerse de modo que se respeten los vínculos impuestos en las tablas. Por ejemplo, dado que no
podrá existir una llave externa sin que antes se haya incluido la línea a la que se refiere, antes de poder
meter una línea en la tabla InProceedings se tendrá que haber puesto la línea correspondiente en la
tabla Proceedings. En el caso en que un vínculo sea violado, la DBMS impedirá la operación de inclusión
abortándola. Véase la lección anterior (Crear la base de datos) para la descripción de los vínculos que se
les pueden imponer a una tabla y a sus columnas.
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:
INSERT INTO nombre_tabla [ ( lista_campos ) ]
VALUES ( lista_valores )
nombre_tabla es el nombre de la tabla en la que se tiene que incluir la nueva línea.
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.
El ejemplo anterior de inclusión se ejecuta a través de las siguientes instrucciones SQL:
INSERT INTO Person VALUES ( 1, 'Agosti', 'Maristella' );
INSERT INTO Person VALUES ( 2, 'Benfante', 'Lucio' );
INSERT INTO Person VALUES ( 3, 'Melucci', 'Massimo' );
INSERT INTO Person VALUES ( 4, 'Spaccapietra', 'S.' );
INSERT INTO Person VALUES ( 5, 'Maryansky', 'F.' );
INSERT INTO Institution ( ID, name, city, country )
VALUES ( 1, '7th IFIP 2.6 Working Conference on Database Semantics (DS-7)',
'Leysin', 'Switzerland' );
INSERT INTO Publication VALUES ( 1, 'Proceedings' );
INSERT INTO Publication VALUES ( 2, 'InProceedings' );
INSERT INTO Proceedings ( ID, title, organization, pub_month, pub_year )
VALUES ( 1, 'Searching for Semantics: Data Mining, Reverse Engineering',
1, 'Oct', 1997 );
INSERT INTO InProceedings ( ID, proceedingsID, title, pages )
VALUES ( 2, 1,
'OFAHIR: "On-the-Fly" Automatic Authoring of Hypertexts for Information Retrieval', '129-154' );
INSERT INTO Author VALUES ( 2, 1 );
INSERT INTO Author VALUES ( 2, 2 );
INSERT INTO Author VALUES ( 2, 3 );
INSERT INTO Editor VALUES ( 1, 4 );
INSERT INTO Editor VALUES ( 1, 5 );
Otra forma bastante usada de la instrucción INSERT sigue la siguiente sintaxis:
INSERT INTO nombre_tabla [ ( lista_campos ) ]
instrucción_select
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.
Interrogar la Base de Datos
En la lección anterior se han examinado los constructos que el lenguaje SQL pone a disposición para
incluir los datos en una base de datos relacional. Vamos a ver ahora, sin embargo, las instrucciones
necesarias para extraer de ella los datos que nos interesen. La instrucción SQL que se propone para
dicho fin es SELECT. Desde el momento en que la interrogación es quizá la función más usada de una
base de datos, las opciones de la instrucción SELECT son numerosas y a veces bastante complicadas.
Por esta razón vamos a describirlas simplificadas, utilizando ejemplos para la presentación de las
características más complejas, en concreto las que se refieren a la especificación de las expresiones
condicionales.
La sintaxis con que la instrucción SELECT se tiene que usar es la siguiente:
SELECT [ ALL | DISTINCT ] lista_elementos_selección
FROM lista_referencias_tabla
[ WHERE expresión_condicional ]
[ GROUP BY lista_columnas ]
[ HAVING expresión_condicional ]
[ ORDER BY lista_columnas ]
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.
5. Se claculan las columnas presentes en la cláusula SELECT (las de la
lista_elementos_selección). En concreto, se calculan las columnas con las funciones de
agregación que derivan del reagrupamiento que se ha producido en el punto 3. Cada elemento
de la lista_elementos_selección sigue la siguiente sintaxis:
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:
ORDER BY nombre_columna [ ASC | DESC ] [ , nombre_columna [ ASC | DESC ] ... ]
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
SELECT surname FROM Person
ORDER BY surname
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:
SELECT DISTINCT surname FROM Person
ORDER BY surname
ESEMPIO 2
SELECT * FROM Person
WHERE surname LIKE 'B%'
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
SELECT title, volume, pub_year
FROM Book
WHERE ID IN
( SELECT PUB.ID
FROM Publication PUB, Author AUT, Person PER
WHERE PUB.ID = AUT.publicationID
AND AUT.personID = PER.ID
AND PUB.type = 'Book'
AND PER.surname = 'Knuth' )
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
SELECT COUNT(*) FROM Publication
count
----12
Cuenta el número de líneas presentes en la tabla Publication.
ESEMPIO 6
SELECT type, COUNT(ID) FROM Publication
GROUP BY type
Cuenta el número de publicaciones presentes en la base de datos subdividiéndolas por tipos.
Las funciones de agregación previstas por el estándar SQL son COUNT, SUM, AVG, MAX y MIN, las
cuales calculan respectivamente los números, la suma, la media aritmética, el máximo y el mínimo de los
valores escalares presentes en la columna a la que se aplican.
Actualizar la Base de Datos
Normalmente, las informaciones presentes en una base de datos no son estáticas, sino que evolucionan
en el tiempo. Existe, por tanto, la necesidad no sólo de añadir nuevos datos, sino de modificar los que
están ya incluidos en las tablas de la base de datos. Las instrucciones SQL que se usan para este fin
son UPDATE y DELETE. La primera modifica los valores presentes en una o más columnas de una o
más líneas de una tabla. La segunda elimina una o más líneas de una tabla.
La sintaxis de UPDATE es la siguiente:
UPDATE nombre_tabla
SET lista_asignaciones
[ WHERE expresión_condicional ]
Las asignaciones se especifican del modo:
nombre_columna = expresión_escalar
La instrucción UPDATE actualiza las columnas de la tabla que se han especificado en la cláusula SET,
utilizando los valores que son calculados por las correspondientes expresiones escalares. Si se expresa
también la cláusula WHERE, se actualizan sólo las líneas que satisfacen la expresión condicional. Véase
que la expresión escalar usada para actualizar una columna puede ser también el resultado de una
query escalar, es decir una query que devuelve una sola línea y una sola columna.
Veamos un ejemplo:
UPDATE Person
SET given_names = 'Stefano'
WHERE surname = 'Spaccapietra'
La instrucción anterior cambia el valor de la columna given_name de la tabla Person en las líneas (en
nuestro caso es una sola) en que la columna surname tiene valor 'Spaccapietra'.
La sintaxis de DELETE es:
DELETE FROM nombre_tabla
[ WHERE expresión_condicional ]
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.
Si en la definición de la tabla se han especificado las cláusulas ON UPDATE u ON DELETE, en el
momento en que se ejecutan estas operaciones también se ejecutan las que habían estado previstas en
las columnas referenciadas (CASCADE, SET DEFAULT o SET NULL).
Modificar la estructura de la Base de Datos
En el curso de la lección anterior, se ha visto cómo modificar los datos ya presentes en la base de datos.
A veces, sin embargo, no basta con modificar los datos, sino que es necesario actualizar la estructura
misma de la base de datos para conseguir que se puedan representar nuevas informaciones. Desde el
momento en que la estructura de la base de datos se da sustancialmente por la unión de las tablas que
la componen, su actualización corresponde a la eliminación de tablas o al cambio de sus características.
Para eliminar una tabla de una base de datos la orden SQL que hay que usar es DROP TABLE:
DROP TABLE nombre_tabla { RESTRICT | CASCADE }
nombre_tabla es el nombre de la tabla que tiene que se eliminada.
Si se especifica la cláusula CASCADE, se eliminan automáticamente los vínculos de integridad y las
vistas (view) en que la tabla está implicada. Y viceversa: si se especifica la cláusula RESTRICT y existen
vínculos de integridad o vistas que se refieran a la tabla, la operación fracasa.
Por ejemplo, se han definido las dos siguientes tablas:
CREATE TABLE Prueba1 (
Id INTEGER PRIMARY KEY,
Nombre VARCHAR(50))
CREATE TABLE Prueba2 (
Id INTEGER PRIMARY KEY,
Nombre VARCHAR(50),
toPrueba1 INTEGER REFERENCES Prueba1(Id))
Si se quiere eliminar la tabla Prueba1, la instrucción:
DROP TABLE Prueba1 RESTRICT
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:
DROP TABLE Prueba1 CASCADE
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:
Adición de una nueva columna a la tabla
ALTER TABLE nombre_tabla ADD [ COLUMN ] definición_columna
nombre_tabla es el nombre de la tabla que se quiere modificar.
La definición de la columna sigue la misma sintaxis que se ha visto en la lección "Crear la base de datos"
en la explicación de la instrucción CREATE TABLE. Por lo tanto, habrá que especificar el nombre de la
columna, su tipo y, eventualmente, su valor por defecto y los vínculos impuestos en la columna.
La la palabra clave COLUMN se puede omitir (aquí y en todos los casos sucesivos).
Eliminación de una columna de la tabla
ALTER TABLE nombre_tabla
DROP [ COLUMN ] nombre_columna { RESTRICT | CASCADE }
nombre_columna es el nombre de la columna que se quiere eliminar. Las cláusulas RESSTRIC y
CASCADE se comportan exactamente como en la instrucción DROP TABLE que se ha visto
anteriormente.
La instrucción fallará, además de en los casos ya vistos para RESTRICT, si se intenta eliminar una
columna que es la única de una tabla.
Cambio del valor por defecto de una columna
ALTER TABLE nombre_tabla
ALTER [ COLUMN ] nombre_columna { SET cláusula_defecto | DROP DEFAULT }
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.
Eliminación de un vínculo de la tabla
ALTER TABLE nombre_tabla
DROP CONSTRAINT nombre_vínculo { RESTRICT | CASCADE }
Elimina el vínculo identificado por el nombre especificado. La operación falla si se ha especificado la
cláusula RESTRICT y existen otros vínculos que dependen del que se intenta eliminar. Especificando la
cláusula CASCADE la operación se completará siempre con éxito, borrando además los vínculos que
dependen de que se ha eliminado.
A menudo se quiere eliminar un vínculo al que no se le ha dado un nombre explícitamente, poniendo
antes de la definición del vínculo la cláusula opcional [CONSTRAINT nombre_vínculo]. En ese caso,
desde el momento que la DBMS habrá asignado de todos modos un nombre al vínculo para poderlo
identificar, será necesario interrogar a las tablas de sistema de la DBMS y que nos dé su nombre. La
particular interrogación solicitada depende de la DBMS específica que se haya usado.
Adición de un vínculo a la tabla
ALTER TABLE nombre_columna
ADD vínculo_de_tabla
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.
Utilización Multiusuario de una Base de Datos
Home page
Hasta ahora hemos examinado las características del lenguaje SQL que se
refieren a la definición y a la manipulación de los datos presentes en una
base de datos, sin preocuparnos del hecho de que normalmente el acceso a
tales datos se produce al mismo tiempo por parte de muchos usuarios.
Los mecanismo que hay que tener en cuenta para este método de acceso
se refieren principalmente a la seguridad de los datos, la gestión de las
transacciones y la posibilidad de definir las vistas en las tablas de la base de
datos.
Test
F.a.q.
Copyright
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.
semana
CSS
500 Applet Java
Dynamic HTML
350 Javascript
un JS a la
Guía HTML
Guía a las
Macromedia Flash
Accessibilidad
Curso Javascript
Tutorial Javascript
 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.
PHP
Tutorial DHTML
La Guía Smil
La guía a
La sintaxis de la orden GRANT es la siguiente:
GRANT lista_privilegios ON objeto TO lista_usuarios [ WITH GRANT
OPTION ]
Esto asigna al usuario los privilegios presentes en la lista_privilegios sobre
el objeto especificado.
Los privilegios asignables son los siguientes (con sus respectivas sintaxis):
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
En el caso de otros objetos, sigue la sintaxis:
tipo_objeto nombre_objeto
donde tipo_objeto puede ser DOMAIN, CHARACTER SET, COLLATION o
TRANSLATION (véase C.J. Date - "A Guide to The SQL Standard" para una
explicación de tales objetos).
En el caso de objetos que no sean tablas o vistas, el único privilegio
aplicable es el de USAGE.
IIS
Introducción al Java
La Guía Perl
Curso CGI
Curso SQL
Seminario Apache
Seminario
La lista_usuarios es una lista de identificativos de usuarios o grupos de
usuarios. Puede usarse también la palabra clave PUBLIC, que indica todos
los usuarios y los grupos coocidos en el sistema.
Si está presente la opción [ WITH GRANT OPTION ], se asigna además el
privilegio de concesión, que permite a los usuarios transferir ulteriormente
los privilegios que se les han asignado.
Por ejemplo:
GRANT SELECT, INSERT, UPDATE(nombre) ON persona TO benfante
WITH GRANT OPTION
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.
Para quitarles los privilegios a los usuarios se usa REVOKE:
REVOKE [ GRANT OPTION FOR ] lista_privilegios ON objeto FROM
lista_usuarios { RESTRIC | CASCADE }
lista_privilegios, objeto y lista_usuarios tienen el mismo significado que las
correspondientes opciones de GRANT. La opción GRANT OPTION FOR
revoca el privilegio de concesión. Si se especifica la cláusula RESTRICT, la
orden REVOKE puede fallar si el usuario al que se le han revocado los
privilegios se los ha concedido posteriormente a otros. Si está presente la
cláusula CASCADE, la instrucción se completará siempre con éxito y se
revocarán también los privilegios de esos usuarios y de todos aquellos a
quienes a su vez se les han concedido (...y así hasta que no haya más
privilegios "abandonados", es decir concedidos sin que quien los ha
concedido los posea todavía). Se destruirán, además, los objetos de la base
de datos construidos gracias a dichos permisos.
2. Gestión de las transacciones
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):
SELECT almacenamiento FROM productos
WHERE productoID=1453
La actualización del almacenamiento, una vez comprobada la disponibilidad
se obtiene con la siguiente instrucción (instrucción B):
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:
CREATE VIEW nombre_vista [ ( lista_nombres_columnas ) ]
AS expresión_tabla
Crea una vista llamada nombre_vista definitda por la expresión_tabla.
Típicamente, expresión_tabla es una instrucción select que producirá la
tabla que interesa. La lista_nombres_columnas se puede usar para asignar
nombres a las columnas de la vista. Esto es útil en el caso en que las
columnas que derivan de la expresión_tabla sean resultado de un cálculo
(por ejemplo COUNT(nombre_columna)) y por ello no tengan un nombre
explícito. Una vez creada, una vista se puede utilizar como una tabla
normal. Las unicas limitaciones se refieren a las operaciones que cambian
los datos contenidos en ella. En efecto, no todas las vistas pueden
actualizarse. Las reglas que discriminan entre una vista actualizable y una
no actualizable son más bien complejas, y no es este el lugar para
describirlas (véanse los libros en la bibliografía, concretamente el de C.J.
Date). Aquí vamos a limitarnos a intentar entender, mediante un ejemplo,
por qué sucede esto.
Hagamos la prueba usando la siguiente vista en nuestra base de datos
bibliográfica:
CREATE VIEW book_publisher89
AS SELECT B.title, P.name
FROM Book B, Publisher P
WHERE B.publisher = P.ID
AND B.pub_year=1989
Ésta nos permite ejecutar la query que la define simplemente utilizando la
instrucción:
SELECT * FROM book_publisher89
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:
INSERT INTO book_publisher89
VALUES( "Nuevo libro", "publisher")
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.