Sei sulla pagina 1di 15

Tema 4. Lenguajes relacionales comerciales.

Tema 4.Lenguajes relacionales comerciales.


Los lenguajes formales descritos en el capítulo 3 proporcionan una notación concisa para representar consultas.
Sin embargo los sistemas comerciales de BD requieren un lenguaje de consulta más amigable para el usuario.
Estudiaremos tres lenguajes comerciales: SQL, QBE y Quel, que representan una variedad de estilos. QBE está basado
en el cálculo relacional de dominios; Quel en el cálculo relacional de tuplas y SQL usa una combinación del álgebra
relacional y del cálculo relacional. Los tres han sido influyentes en sistemas de BD de investigación y en sistemas
distribuidos comercialmente.
Aunque nos referimos a estos lenguajes como lenguajes de consulta, contienen muchas otras capacidades
además de consultar la BD., como características para definir la estructura de la BD, para modificar los datos y para
especificar restricciones de seguridad.
No presentaremos una guía de usuario, sino sus construcciones y conceptos fundamentales.

4.1. SQL.
Existen numerosas versiones de SQL. La versión original fue desarrollada en el San José Research Laboratory
de IBM, y originalmente se llamó Sequel. Fue implementado como parte del Sistema R en los primeros setenta. Ha
evolucionado hasta cambiar su nombre a SQL (Structured Query Language, Lenguaje de consulta estructurado). Ahora
numerosos productos soportan el SQL.
En 1986, el American National Standards Institute (ANSI) publicó un SQL estándar. IBM ha publicado su
propio estándar de SQL inmerso, el Systems Application Architecture Database Interface (SAA-SQL).
SQL se ha establecido claramente como el lenguaje de BD relacional estándar.
El lenguaje SQL tiene varias partes:
n Lenguaje de definición de datos (DDL). El SQL-DDL proporciona órdenes para definir esquemas de
relación, eliminar relaciones, crear índices y modificar esquemas de relación.
n Lenguaje de manipulación de datos interactivo. El SQL-DML incluye un lenguaje de consultas basado en el
álgebra relacional y el cálculo relacional de tuplas. También incluye ordenes para insertar, eliminar y
modificar tuplas de la BD.
n Lenguaje de manipulación de datos inmerso (DML). La forma inmersa de SQL está diseñada para usar
dentro de los lenguajes de programación de propósito general, como Cobol, Pascal, o C.
n Definición de vista. El SQL-DDL incluye ordenes para definir vistas.
n Autorización. El SQL-DDL incluye órdenes para especificar derechos de acceso a relaciones y vistas.
n Integridad. El lenguaje Sequel original incluye órdenes para especificar restricciones de integridad complejas.
Versiones recientes de SQL proporcionan únicamente una forma limitada de comprobación de integridad.
n Control de transacciones. SQL incluye órdenes para especificar el comienzo y final de las transacciones.
Varias implementaciones permiten el bloqueo explícito de los datos de control de concurrencia.
En esta sección cubrimos solo el DDL básico, el DML interactivo y las vistas.

4.1.1. Estructura básica.

La estructura básica en una instrucción en SQL constra de tres cláusulas: select, from y where.
n La cláusula select corresponde a la operación proyección del álgebra relacional. Se usa para listar los atributos
que se desean en el resultado de una consulta.
n La cláusula from corresponde a la operación de producto cartesiano del álgebra relacional. Lista las relaciones
que se van a examinar en la evaluación de la expresión.
n La cláusula where corresponde al predicado de selección del álgebra relacional. Consta de un predicado que
incluye atributos de las relaciones que aparecen en la cláusula from.
Una consulta típica en SQL tiene la forma
select A1, A2, …, An
from r1, r2, …, rm
where P
es equivalente a la expresión del álgebra relacional:
∏A1, A2, …, An (σP (r1 x r2 x … x rm))
Si se omite la cláusula where, el predicado P es verdadero. La lista de atributos puede sustituirse por un
asterisco (*) para seleccionar todos los atributos de todas las relaciones que aparecen en la cláusula from.
SQL forma el producto cartesiano de las relaciones nombradas en from, realiza una selección del álgebra
relacional usando el predicado de la cláusula where y después proyecta el resultado a los atributos de la cláusula select.
El resultado de una consulta en SQL es una relación.
Ejemplo: select nombre_sucursal
from depósito

4.1.2. Operaciones de conjuntos y tuplas duplicadas.

Los lenguajes de consulta formales se basan en la noción matemática de relación como un conjunto. Por ello
nunca aparecen tuplas duplicadas en las relaciones. En la práctica, la eliminación de duplicados lleva bastante tiempo, por

27
Bases de Datos

lo que SQL permite duplicados en las relaciones. En aquellos casos en los que queremos forzar la eliminación de
duplicados, insertamos la palabra clave distinct después de select.
select distinct nombre_sucursal
from depósito
SQL permite el uso de la palabra all para especificar explícitamente que no se eliminen duplicados.
select all nombre_sucursal
from depósito

4.1.3. Operaciones de conjuntos.

SQL incluye las operaciones union, intersect y minus que operan sobre relaciones y corresponden a las
operaciones del álgebra relacional ∪, ∩, -.
Para encontrar a todos los clientes que tienen que tienen un préstamo, una cuenta, o los dos en la sucursal
Perryridge escribimos:
(select nombre_cliente
from depósito
where nombre_sucursal = “Perryridge”)
union
(select nombre_cliente
from préstamo
where nombre_sucursal = “ Perryridge”)
Por omisión la operación union elimina las tuplas duplicadas. Para retener duplicados se debe escribir union
all.
Aunque la operación union es parte del SQL estándar de ANSI, varios productos no la soportan. Las
operaciones intersect y minus eran parte del Sequel, pero no están incluidas en el estándar. Es posible expresar estas
operaciones utilizando otras características del SQL estándar de ANSI.

4.1.4. Predicados y conectores.

SQL no tiene una representación directa del producto natural, sin embargo, puesto que el producto natural se
define en función de un producto cartesiano, una selección y una proyección, es relativamente sencillo escribir una
expresión en SQL para el producto natural.
Por ejemplo, encontrar el nombre y la ciudad de todos los clientes que tienen un préstamo en alguna sucursal:
select distinct cliente.nombre_cliente, ciudad_cliente
from préstamo, cliente
where préstamo.nombre_cliente = cliente.nombre_cliente
Obsérvese que SQL usa la notación nombre_relación.nombre_atributo, como el álgebra relacional, para evitar
ambigüedad.
Ampliemos la consulta anterior, requiriendo también que todos los clientes tengan un préstamo en la sucursal
Perryridge. Para escribir esta consulta, necesitamos declarar los limites en la cláusula where, conectados por el conector
lógico and.
select distinct cliente.nombre_cliente, ciudad_cliente
from préstamo, cliente
where préstamo.nombre_cliente = cliente.nombre_cliente and nombre_sucu rsal = “ Perryridge”
SQL usa los conectores lógicos and or y not en vez de los símbolos matemáticos ∧, ∨, ¬. Muchas
implementaciones de SQL incluyen funciones aritméticas especiales para tipos de datos particulares, por ejemplo , IBM
SAA-SQL incluye numerosas funciones para el tipo de datos fecha.
SQL incluye un operador de comparación between para simplificar cláusulas where que especifican que un valor
sea menor o igual que un valor dado y mayor o igual que otro.
select número_cuenta select número_cuenta
from depósito è from depósito
where saldo >= 9000 and saldo <= 10000 where saldo between 9000 and 10000
Análogamente, podemos usar el operador de comparación not between.
SQL también incluye un operador dde selección para comparaciones de cadenas de caracteres. Los modelos se
describen usando dos caracteres especiales:
n tanto por ciento (%). El carácter % es igual a cualquier subcadena.
n subrayado (_). El carácter _ es igual a cualquier carácter.
Los modelos son sensibles al tipo de letra, es decir, los caracteres en mayúscula no son iguales a los caracteres en
minúscula. Para mostrar la igualdad, consideremos los ejemplos:
“Perry%” es igual a cualquier subcadena que empiece por “Perry”
“%idge%” es igual a cualquier cadena que contenga “idge”
“_ _ _” es igual a cualquier cadena de tres caracteres
“_ _ _ %” es igual a cualquier subcadena de al menos tres carácteres
Los modelos se expresan en SQL usando el operador de comparación like. Considérese la consulta “encontrar
los nombres de todos los clientes cuya calle incluya la cadena ‘Main’ ”:
select nombre_cliente

28
Tema 4. Lenguajes relacionales comerciales.

from cliente
where calle like “%Main%”
Para que los modelos incluyan caracteres de modelos especiales (% y _), SQL permite la especificación de un
carácter de escape carácter. El carácter de escape se usa inmediatamente antes de un carácter de modelo especial para indicar
que el carácter de modelo especial se va a tratar como un carácter normal. Definimos el carácter de escape para una
comparación like usando la palabra clave escape. Considérense los ejemplos con el carácter “\” como carácter de escape:
like “ab\%cd%” escape “\” es igual a todas las cadenas que empiezan por “ab%cd”
like “ab\\cd%” escape “\” es igual a todas las cadenas que empiezan por “ab\cd”.
SQL permite buscar desigualdades en vez de igualdades usando el operador de comparación not like.

4.1.5. Pertenencia a un conjunto.

SQL se basa en el cálculo relacional para operaciones que permiten probar la pertenencia de tuplas a una relación.
El conector in prueba si se es miembro de un conjunto, donde el conjunto es una colección de valores producidos por
una cláusula select. El conector not in prueba la no pertenencia.
Considérese encontrar a todos los clientes que tienen un préstamo y una cuenta en la sucursal Perryridge”.
Empezamos encontrando a todos los clientes que tienen cuenta, con la subconsulta:
(select nombre_cliente
from depósito
where nombre_sucursal = “Perryridge”)
Después necesitamos encontrar los clientes con préstamos de Perryridge y que aparecen en la lista de clientes que
tienen cuenta que acabamos de conseguir. Hacemos esto incorporando la subconsulta en un select externo. La consulta
resultante es:
select nombre_cliente
from depósito
where nombre_sucursal = “Perryridge” and
nombre_cliente in (select nombre_cliente
from depósito
where nombre_sucursal = “Perryridge”)
Este ejemplo muestra que es posible escribir la misma consulta de varias formas en SQL.
Hemos probado la pertenencia a una relación de una atributo. Es posible probar la pertenencia a una relación
arbitraria. SQL usa la notación <v1, v2, …, vn> para representar una tupla con n atributos que contiene los valores v1, v2,
…, vn. Utilizando esta notación, podemos encontrar a todos los clientes que tienen una cuenta y un préstamo en la
sucursal Perryridge.
select distinct nombre_cliente
from depósito
where nombre_sucursal = “Perryridge” and
<nombre_sucursal, nombre_cliente> in (select nombre_sucursal, nombre_cliente
from depósito)

4.1.6. Variables de tupla.

SQL toma prestada la notación de variables de tupla del cálculo relacional de tuplas. Una variable de tupla en
SQL debe estar asociada con una relación determinada. Las variables de tuplas se definen en la cláusula from. Por
ejemplo, encontrar el nombre y la ciudad de todos los clientes que tienen un préstamo en alguna sucursal.
select distinct T.nombre_cliente, ciudad_cliente
from préstamo S, cliente T
where S.nombre_cliente = T.nombre_cliente
Nótese que una variable de tupla se define en la cláusula from colocándola después del nombre de la relación
con que esta asociada, separada por uno o más espacios.
En consultas que contienen subconsultas, se aplica una regla de ámbito a las variables de tupla. En una
subconsulta, está permitido usar sólo variables definidas en la misma subconsulta o en cualquier consulta que la
contenga. Si una variable de tupla está definida tanto localmente como globalmente en una consulta que la contiene, se
aplica la definición local. Cuando escribimos nombre_relación.nombre_atributo, el nombre de la relación es una variable
de tupla definida implícitamente.
Las variables de tupla son muy útiles para comparar dos tuplas de la misma relación. En tales casos el álgebra
relacional usa la operación renombrar.
select distinct T.nombre_cliente
from depósito S, depósito T.
where S.nombre_cliente = “Jones” and
S.nombre_sucursal = T.nombre_sucursal

4.1.7. Comparación de conjuntos.

Considérese la consulta “Encontrar los nombres de todas las sucursales que tienen un activo mayor que alguna
sucursal de Brooklyn”. SQL ofrece la frase “mayor que algún” y se representa por > some.

29
Bases de Datos

select nombre_sucursal
from sucursal
where activo > some
(select activo from sucursal
where ciudad_sucursal = “Brooklyn”)
La subconsulta interior genera el conjunto de todos los valores de los activos de las sucursales de Brooklyn. La
comparación > some en la cláusula where del select externo es verdadera si el valor activo de la tupla es mayor que al
menos un miembro del conjunto de los activos de las sucursales de Brooklyn.
SQL también permite las comparaciones >some, ≤ some, ≥ some, = some y ≠ some. La palabra clave any es
sinónimo de some en SQL.
Ahora modifiquemos la consulta. Encontremos los nombres de todas las sucursales que tienen un activo
mayor que todas las sucursales de Brooklyn. La construcción > all corresponde a la frase “mayor que todos”.
select nombre_sucursal
from sucursal
where activo > all
(select activo from sucursal
where ciudad_sucursal = “ Brooklyn”)
SQL permite las comparaciones < all, ≤ all, ≥ all, = all, ≠ all.
Puesto que un select genera un conjunto de tuplas, podemos querer comparar conjuntos para determinar si un
contiene todos los miembros de algún otro conjunto. Tales comparaciones se hacen en SQL usando las contrucciones
contains y not contains.
Considérese encontrar a todos los clientes que tienen una cuenta en todas las sucursales de Brooklyn. Para cada
cliente, necesitamos ver si el conjunto de todas las sucursales en las que el cliente tiene una cuenta contiene al conjunto de
todas las sucursales de Brooklyn.
select distinct S.nombre_cliente
from depósito S
where (select T.nombre_sucursal from depósito
where S.nombre_cliente = T.nombre_cliente)
contains
(select nombre_sucursal from sucursal
where ciudad_sucursal = “Brooklyn”)
La contrucción contains fue introducida en el Sequel original, pero fue omitida en versiones posteriores y no
aparece en el ANSI estándar, probablemente por que es extremadamente caro.

4.1.8. Pruebas para relaciones vacías.

SQL incluye una característica para probar si una subconsulta tiene alguna tupla en su resultado. La construcción
exists devuelve el valor true si la subconsulta del argumento no está vacía. Podemos encontrar a todos los clientes que
tienen una cuenta y un préstamo en la sucursal Perryridge escribiendo:

select nombre_cliente from cliente


where exists (select * from depósito
where depósito.nombre_cliente = cliente.nombre_cliente and
nombre_sucursal = “Perryridge”)
and exists (select * from préstamo
where préstamo.nombre_cliente = cliente.nombre_cliente and
nombre_sucursal = “Perryridge”)
La no existencia de tuplas en una subconsulta puede probarse usando la construcción no exists.
Considérese de nuevo encontrar a todos los clientes que tienen una cuenta en todas las sucursales de Brooklyn.
Usando la construcción minus, podemos escribir la consulta como:
select distinct Snombre_cliente from depósito S
where not exists ((select nombre_sucursal from sucursal
where ciudad_sucursal = “Brooklyn”)
minus
(select T.nombre_sucursal from depósito T
where S.nombre_cliente = T.nombre_cliente))
La segunda subconsulta encuentra todas las sucursales en las que el cliente S.nombre_cliente tiene una cuneta.
Así, el select externo toma a cada cliente y prueba si el conjunto de todas las sucursalessituadas en Brooklyn menos el
conjunto de todas las sucursales en las que el cliente tiene cuenta, está vacío.

4.1.9. Ordenación de la presentación de tuplas.

30
Tema 4. Lenguajes relacionales comerciales.

SQL ofrece al usuario cierto control sobre el orden en que se van a presentar las tuplas en una relación. La
cláusula order by hace que las tuplas del resultado salgan en un orden determinado. Para listar en orden alfabético todos
los clientes escribiremos:
order by nombre_cliente
después de la cláusula where.
Por omisión, SQL muestra los elementos en orden ascendente. Para especificar el tipo de ordenación, podemos
especificar desc para orden descendente y asc para el ascendente. Además el orden puede realizarse sobre múltiples
atributos, si queremos listar la relación préstamo completa en orden descendente de cantidad, y si varios préstamos
tienen la misma cantidad, los ordenamos en orden ascendente por número de préstamo con:
order by cantidad desc, número_préstamo asc
Puesto que ordenar tuplas es muy costoso, lo más conveniente es hacerlo sólo cuando sea necesario.

4.1.10. Funciones de agregación.

SQL ofrece la posibilidad de calcular funciones en grupos de tuplas usando la cláusula group by, el atributo o
atributos dados en ella se usan para formar grupos. Las tupas con el mismo valor en todos los atributos en la cláusula
group by se colocan en un grupo. SQL incluye funciones para calcular: promedio (avg), mínimo (min), máximo (max),
total (sum) y contar (count).
Las operaciones como avg se llaman funciones de agregación porque operan sobre grupos de tuplas. El
resultado de una función de agregación es un valor único. Considérese encontrar el saldo promedio de las cuentas de
todas las sucursales.
select nombre_sucursal, avg (saldo)
from depósito
group by nombre_sucursal
La retención de duplicados es importante al calcular un promedio.
Hay casos prácticos en los los duplicados deben eliminarse antes de calcular la función de agregación. Si
queremos eliminar duplicados, usamos la palabra clave distinct en la expresión de agregados:
select *, count (distinct nombre_cliente)
A veces es útil declarar una condición que se aplica a los grupos más que a las tuplas. Por ejemplo, podriamos
estar interesados en las sucursales en las que el saldo promedio de las cuentas es mayor que 1200$. Esta condición se
aplica a cada grupo construido por group by. Para expresar una consulta de este tipo, usamos la cláusula having, que se
aplica después de la formación de grupos, por lo que pueden utilizarse funciones de agregación. Expresamos esta
consulta como:
select nombre_sucursal, avg (saldo)
from depósito
group by nombre_sucursal
having avg (saldo) > 1200
Considérese encontrar las sucursales con el saldo promedio mayor. Las funciones de agregados no pueden
componerse en SQL, por lo que no se puede utilizar max(avg(…)). Por lo que tendremos que encontrar las sucursales
para las que el saldo promedio es mayor o igual que todos los saldos promedio.
select nombre_sucursal from depósito
group by nombre_sucursal
having avg (saldo) ≥ all (select avg (saldo) from depósito
group by nombre_sucursal)
A veces deseamos tratar la relación completa como un grupo único. En tales casos no usamos la cláusula group
by, por lo que la función de agregación count se usa frecuentemente para contar el número de tuplas en una relación. La
notación para esto en SQL es count (*).
select count (*)
from r
Si en la misma consulta aparecen una cláusula where y una cláusula having, primero se aplica el predicado de la
where, las tuplas que lo satisfacen son colocadas en grupos por la cláusula group by, y después se aplica la having a cada
grupo. Los grupos que satisfacen el predicado de having son utilizados por la cláusula select para generar las tuplas del
resultado. Si no hay cláusula having, el conjunto completo de tuplas que satisfacen la cláusula where se trata como un
grupo único.
Por ejemplo, queremos encontrar el saldo promedio de todos los clientes con depósitos que viven en Harrison
y tiene por lo menos tres cuentas:
select avg (saldo) from depósito, cliente
where depósito.nombre_cliente = cliente.nombre_cliente and
ciudad_cliente = “Harrison”
group by depósito_nombre_cliente
having count (distinct número_cuenta) > 3
La versión estándar ANSI de SQL exige que se use count solamente como count (*) o count (distict …). Está
permitido usar distinct con max y min aunque el resultado no cambie. La palabra clave all puede usarse en vez de distinct
para especificar retención de duplicados, pero puesto que all esta implícito no es necesario.

4.1.11. La potencialidad de SQL.

31
Bases de Datos

SQL es tan poderoso en expresividad como el álgebra relacional, incluye las operaciones fundamentales del
álgebra. En SQL el producto cartesiano se representa por from, la proyección con select, los predicados de selección en
where, y además incluye la unión y la diferencia. Así, pues, podemos codificar cualquier expresión del álgebra relacional en
SQL.
Observamos que minus e intersect no son parte del SQL estándar, pero es posible expresarlas por medio de in
y not in de SQL.
SQL ofrece una rica colección de características, que incluyen funciones de agregación, ordenación de tuplas y
otras capacidades no incluidas en los lenguajes formales de consulta. Así, pues, SQL es estrictamente más poderoso que
el álgebra relacional.
Muchas implementaciones de SQL permiten hacer consultas en SQL desde un programa escrito en un lenguaje
de programación de propósito general como Pascal o C. Esta forma incorporada de SQL amplía aún más la capacidad del
programador para manipular la BD.
SQL no es tan potente como un lenguaje de programación de propósito general.

4.1.12. Modificación de la Base de Datos.

Ahora mostraremos como añadir, eliminar o modificar información utilizando SQL.


n Eliminación.
Una solicitud de eliminación se expresa casi de la misma forma que una consulta. Podemos suprimir
solamente tuplas completas, y en SQL se expresan por medio de:
delete r where P
donde P representa un predicado y r representa una relación. Las tuplas t de r para las que P(t) es cierto son eliminadas de
r.
Una orden delete opera sobre una sola relación. El predicado de la cláusula where puede ser tan complicado
como en una consulta, e incluso puede estar vacío, eliminando todas las tuplas de la relación.
Algunos ejemplo de eliminación son:
- Suprimir todos los préstamos.
delete cliente
- Suprimir todas las cuentas en las sucursales de Perryridge.
delete depósito
where nombre_sucursal in (select nombre_sucursal from sucursal
where ciudad_sucursal = “Perryridge”)

Si la solicitud delete contiene un select incorporado que hace referencia a la relación de la que se van a suprimir
tuplas, nos enfrentamos a anomalías potenciales, por ejemplo, si que remos suprimir las cuentas con saldos inferiores a
la media, cada vez que suprimimos tuplas el promedio cambia. El SQL estándar trata esto simplemente no permitiendo
solicitudas de supresión de este tipo.

n Inserción.
Para insertar datos en una relación, especificamos una tupla que se va a insertar o escribimos una consulta cuyo
resultado es un conjunto de tuplas que se van a insertar. Las tuplas a insertar deben tener el número exacto de atributos,
y los valores de atributos para las tuplas insertadas deben ser miembros del dominio de los atributos.
La sentencia insert más sencilla es una solicitud para insertar una tupla.
insert into depósito
valuse (“Perryridge”, 9732, “Smith”, 1200)
Si no se recuerda el orden de los atributos, SQL permite especificar los atributos como parte de la sentencia
insert.
insert into depósito (nombre_sucursal, número_cuenta, nombre_cliente, saldo)
valuse (“Perryridge”, 9732, “Smith”, 1200)
Podríamos querer insertar tuplas basadas en el resultado de una consulta. Supóngase que queremos
proporcionar a todos los clientes con préstamos en Perryrige una cuenta de 200$. El número de préstamo sirve como
número de cuenta.
insert into depósito
select nombre_sucursal, número_préstamo, nombre_cliente, 200
from préstamo
where nombre_sucursal = “Perryridge”
Usamos un select para especificar un conjunto de tuplas. Cada tupla tiene el nombre_sucursal, un
número_préstamo, el nombre_cliente y el saldo inicial de 200$.
El SQL estándar prohibe el select inmerso que haga referencia a la relación en la que las tuplas van a ser
insertadas, ya que podrían insertarse infinitas tuplas, dependiendo de la consulta.

n Actualizaciones

32
Tema 4. Lenguajes relacionales comerciales.

En ciertas situaciones podemos desear cambiar un valor en una tupla sin cambiar todos los valores en la tupla.
Para éste propósito puede usarse la sentencia update, y también podemos elegir las tuplas que se van a actualizar por
medio de una consulta.
Supóngase que queremos pagar el 5% de interés a todas las cuentas:
update depósito
set saldo = saldo * 1,05
Supóngase ahora que queremos pagar el 6% de interés a las cuentas con más de 10000$:
update depósito
set saldo = saldo * 1,06
where saldo > 10000
La cláusula where de la sentencia update puede contener cualquier construcción legal, incluyendo selects
anidados. Además como en insert y delete, cualquier select incorporado en la cláusula where de un update no debe hacer
referencia a la relación que se está actualizando.

4.1.13. Valores nulos.

Es posible que para las tuplas insertadas se den valores únicamente en algunos atributos del esquema. El resto
de los atributos son asignados a valores nulos representados por null.
insert into depósito
values (“Perryridge”, null, “Smith”, 1200)
Sabemos que Smith tiene una cuenta en Perryridge de 1200$, pero se desconoce el número de cuenta. Si
quisiéramos encontrar los datos de una cierta cuenta, no se podría determinar si es esa o no, ya que todas las
comapraciones con null son falsas por definición. Sin embargo, la palabra clave especial null puede usarse en un
predicado para probar si hay un valor nulo. Así, para encontrar a todos los clientes que aparecen en préstamo con valores
nulos para cantidad, escribimos:
select distinct nombre_cliente
from depósito
where cantidad is null
El predicado is not null prueba la ausencia de un valor nulo.
La existencia de valores nulos complica el procesamiento de los operadores de agregación. Supóngase que
algunos valores de préstamo tienen un valor nulo en cantidad. Considérese:
select sum (cantidad)
from préstamo
Los valores que se van a sumar en la consulta anterior incluyen valores nulos, pero no es posible llevar a cabo la
adición usando null, por tanto, necesitamos una regla especial para manejar funciones de agregación cuando aparecen
valores nulos. Como resultado, todas las operaciones de agregación, excepto count, ignoran tuplas con valores nulos en
los atributos de los argumentos. Es posible prohibir la inserción de valores nulos usando el lenguaje de definición de
datos de SQL, que veremos en el 4.1.15.

4.1.14. Vistas.

Una vista se define en SQL usando la orden create view. Para definir una vista debemos darla un nombre y
declarar la consulta que calcula la vista. La forma de la orden create view es:
create view v as >expresión de consulta>
donde >expresión de consulta> es cualquier consulta permitida y v el nombre que le damos a la vista..
Como ejemplo, considérese la vista que consta de nombres de sucursales y de los nombres de los clientes,
llamada todos_clientes. Definimos esta vista por medio de:
create view todos_clientes as
(select nombre_sucursal, nombre_cliente from depósito)
union
(select nombre_sucursal, nombre_cliente from préstamo)
Los nombres de vistas pueden aparecer en cualquier sitio en que puede aparecer un nombre de relación.
Usando la vista todos_clientes podemos encontrar a todos los clientes de la sucursal Perryridge.
select nombre_cliente from todos_clientes
where nombre_sucursal = “Perryridge”
La anomalía en la actualización de vistas, que se estudio en el álgebra relacional, también existe en SQL.
Considérese la vista info_préstamo definida por
create view info_préstamo as
(select nombre_sucursal, número_préstamo, nombre_cliente from préstamo)
Puesto que SQL permite que un nombre de vista aparezca donde puede aparecer el de una relación, podemos
escribir:
insert into info_préstamo
values (“Perryridge”, 3, “Ruth”)
Esta inserción está representada por una inserción en la relación préstamo, ya que préstamo es la relación real de
la cual se deriva la vista info_préstamo. Por tanto, debemos tener algún valor para cantidad. Este valor es un valor vacío,
así, el insert anterior resulta en la inserción de la tupla:

33
Bases de Datos

(“Perryridge”, 3, “Ruth”, null)


en la relación préstamo.
Como resultado, muchos DBMS basados en SQL imponen la siguiente condición a las modificaciones que se
permiten hacer a las relaciones a través de vistas:
n Se permite una modificación a través de una vista solo si la vista en cuestión está definida en terminos de
una relación de la BD relacional real, es decir, la BD del nivel conceptual.

4.1.15. Definición de datos.

Hasta ahora hemos supuesto que se nos da un conjunto de relaciones. Pero el conjunto de relaciones en una
BD debe ser especificado al sistema por medio de un lenguaje de definición de datos DDL.
El SQL-DDL permite la especificación no solo de un conjunto de relaciones, sino también de información
sobre cada relación, incluyendo: el esquema de cada relación, el dominio de valores asociado a cada atributo, el conjunto
de indices que se va a mantener para cada relación, la información de seguridad y autorización para cada relación, los
limites de integridad y la estructura física de almacenamiento de cada relación del disco.
Trataremos aquí la definición del esquema, dejando el resto para más adelante.
Una relación en SQL se define usando la orden create table:
create table r (A1 D1, A2, D2, …, An Dn)
donde r es el nombre de la relación, cada Ai es el nombre de un atributo del esquema de relación r, y Di es el tipo de
datos de los valores en el dominio del atributo correspondiente. La orden create table también incluye opciones para
especificar ciertas restricciones de integridad.
Una relación recién creada está inicialmente vacía. La orden insert puede usarse para cargar datos en la relación.
Para eliminar una relación de una BD en SQL, usamos la orden drop table. La orden drop table elimina toda
la información sobre la relación sacada de la BD. Elimina no sólo todas las tuplas de la relación, como haría delete, sino
también el esquema de r. Después no se puede insertar ninguna tupla en r a menos que se vuelva a crear.
drop table r

La orden alter table se usa para añadir atributos a una relación existente. Atodas las tuplas en la relación se les
asigna null como valor del nuevo atributo. La forma de la orden alter table es
alter table r add A D
donde r es el nombre de una relación existente, A es el nombre del nuevo atributo y D su dominio.
La orden alter aparece en algunas versiones de SQL pero no en el ANSI SQL.

4.2. Query By Example (QBE).


Query-By-Example (QBE) es el nombre de un lenguaje de manipulación de datos DML y del DBMS que lo
incluye. El DBMS QBE fue desarrollado en T.J. Watson Research Center de IBM a principios de los setenta. Está fuera
de uso, pero su DML es parte de Query Management Facility (QMF) de IBM. Estudiaremos sólo el DML. Existen dos
características distintivas del QBE:
n A diferencia de la mayoria de los lenguajes de consulta, QBE tiene una sintaxis bidimensional (necesita dos
dimensiones para expresar una consulta), si bien existe una versión unidimensional.
n Las consultas en QBE se expresan “por ejemplo”. En vez de dar un procedimiento para obtener la
respuesta deseada, el usuario da un ejemplo de lo que desea. El sistema generaliza este ejemplo para calcular
la respuesta a la consulta.

4.2.1. Estructura básica.

Las consultas en QBE se expresan utilizando tablas de esqueletos. Estas tablas muestran el esquema de la
relación. En vez de llenar la pantalla con todos los esqueletos, el usuario selecciona los esqueletos que necesita para una
consulta y los rellena con “filas ejemplo” . Una fila ejemplo esta formada por constantes y “elementos ejemplo” que son
en realidad variables de dominio. Para evitar confusión, en QBE las variables de dominio van precedidas de un carácter
de subrayado (_), como _x, y las constantes aparecen solas.
Un ejemplo de tabla esqueleto para la relación préstamo es:
Préstamo Nombre_sucursa Número_prestam Nombre_cliente Cantidad
l o

4.2.2. Consultas sencillas.

Para encontrar a todos los clientes que tienen una cuenta en la sucursal Perryridge sacamos el esqueleto para la
relación depósito y lo rellenamos como sigue:
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
Perrydridge P._x

34
Tema 4. Lenguajes relacionales comerciales.

La consulta anterior hace que el sistema busque en depósito las tuplas que tengan el valor Perryridge en al
atributo nombre_sucursal. Para cada una de estas tuplas, el valor del atributo nombre_cliente se asigna a la variable x. El
valor de la variable x se presenta, ya que la orden P. aparece en la columna nombre_cliente al lado de la variable x.
QBE supone que una posición en blanco en una fila contiene una variable única. Como resultado, si una
variable no aparece más de una vez en una consulta, puede omitirse, por ejemplo, en la consulta anterior podiamos
haber escrito P. en la columna nombre_cliente.
QBE realiza la eliminación de duplicados automáticamente, para evitarla hay que insertar la orden ALL.
despues de la orden P. (P.ALL.)
Para representar una relación completa, podemos crear una sola fila que contenga P. en cada campo.
Alternativamente, podemos colocar una única P. en la columna encabezada por el nombre de la relación.
QBE permite consultas que implican comparaciones aritméticas:
Préstamo Nombre_sucursa Número_prestam Nombre_cliente Cantidad
l o
P. > 1200

Las comparaciones pueden implicar sólo una expresión aritmética en la parte derecha de la operación de
comparación (por ejemplo, >(_x + _y -20)). La expresión puede incluir variables y constantes. El espacio en la parte
izquierda de la operación de comparación debe estar en blanco. Las operaciones de comparación que soporta QBE son
=, <, ≤, >, ≥ y ¬.
Restringir la parte derecha a una sola operación aritmética implica que no podemos comparar dos variables con
nombres distintos.
El propósito general de las variables en QBE es forzar a que los valores de determinadas tuplas tengan el
mismo valor en determinados atributos. Considérese encontrar a todos los clientes que tienen una cuenta tanyto en la
sucursal Perrydridge como en la sucursal Redwood.
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
Perryridge P._x
Redwood _x
El sistema encuentra dos tuplas distintas en depósito que coinciden en el atributo nombre_cliente, donde el
valor para el atributo nombre_sucursal es “Perryridge”, para una tupla y “Renwood” para la otra. Entonces se presenta el
valor del atributo nombre_cliente.

4.2.3. Consulta sobre varias relaciones.

QBE permite consultas que se extienden sobre varias relaciones diferentes. Las conexiones entre las diversas
relaciones se logran a través de variables que fuerzan a determinadas tuplas a tener el mismo valor en determinados
atributos. Supóngase que queremos encontrar el nombre y la ciudad de todos los clientes que tienen un préstamo de la
sucursal Perryridge.
Préstamo Nombre_sucursa Número_prestam Nombre_cliente Cantidad
l o
Perryridge _x

Cliente Nombre_cliente Calle Ciudad_cliente


P._x P._y
Cosideremos encontrar el nombre de todos los clientes que tienen una cuenta en la sucursal Perryridge pero que
no tienen un préstamo de esa sucursal. Las consultas que implican negación en QBE se expresan colocando un signo
not (¬) debajo del nombre de la relación y al lado de una fila ejemplo.
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
Perryridge P._x

Préstamo Nombre_sucursa Número_prestam Nombre_cliente Cantidad


l o
¬ PErryridge _x
El ¬ puede leerse como “no existe”. El hecho de colocar el ¬ debajo del nombre de la relación en vez de
debajo del atributo es importante. El uso de un ¬ debajo de un nombre de atributo es equivalente a ≠.

4.2.4. El cuadro de condiciones.

A veces resulta inconveniente o imposible expresar todos los limites de las variables de dominio dentro de las
tablas de esqueletos, ya que las comparaciones no pueden implicar dos variables distintas. Para superar esta dificultad,
QBE incluye una característica de cuadro de condiciones que permite la expresión de dichos límites. Supóngase que
queremos encontrar a todos los clientes cuyo nombre no sea Jones que tengan cuentas en dos sucursales diferentes.
Queremos incluir una restricción x≠”jones” en la consulta. Esto se hace imponiendo el cuadro de condiciones e
introduciendo el límite x¬=Jones.
Condiciones
x¬=Jones

35
Bases de Datos

Para encontrar todos los números de préstamo con cantidades entre 1300$ y 1500$ escribimos:
Préstamo Nombre_sucursa Número_prestam Nombre_cliente Cantidad
l o
P. _x

Condiciones
_x≥1300
_x≤1500
QBE también permite que aparezcan expresiones aritméticas complejas en un cuadro de condiciones, como
_y>2*_z, y también permite que aparezcan expresiones lógicas utilizando los operadores lógicos and y or, o los
simbolos & y |, como _x=(≥1300 and ¬1500).
QBE incluye un uso no convencional de la construcción or para permitir la comparación con un conjunto de
valores constantes. Para encontrar todas las sucursales que están situadas en Brooklyn o en Queens, escribimos:
Sucursal Nombre_sucursal Activo Ciudad_sucursal
P. _x

Condiciones
_x=(Brooklyn or Queens)

4.2.5. La relación resultado.

Si el resultado de una consulta incluye atributos de más de una relación, necesitamos un mecanismo para
representar el resultado deseado en una sola tabla. Para realizar esto, declaramos una relación resultado temporal que
incluye todos los atributos del resultado de la consulta. La impresión del resultado deseado se hace incluyendo la orden
P. solamente en la tabla esqueleto de resultado.
Considérese lencontrar nombre_cliente, ciudad_cliente y número_cuenta para todos los clientes que tienen una
cuenta en la sucursal Perryridge. Para realizar esto en QBE hacemos:

n Creamos una tabla esqueleto, llamada resultado, con atributos nombre_cliente, ciudad_cliente y
número_cuenta. El nombre de la tabla esqueleto recién creada debe ser diferente de cualquiera de los
nombres de relación de la BD que existían anteriormente.
n Escribimos la consulta:
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
Perryridge _z _x

Cliente Nombre_cliente Calle Ciudad_cliente


_x _y
La consulta resultante es:
Resultado Nombre_cliente Ciudad_client Número_cuenta
e
P. _x _y _z

4.2.6. Ordenación de la presentación de las tuplas.

QBE ofrece al usuario un cierto control sobre el orden en el que se presentan las tuplas en una relación. Esto
puede realizarse la orden AO. (orden ascendente) o bien DO. (orden descendente) en la columna apropiada.
QBE proporciona un mecanismo para clasificar y presentar datos en múltiples columnas. El orden en el que
debe llevarse a cabo la clasificación s eespecifica incluyendo con cada operador de clasificación un entero entre paréntesis.
Cliente Nombre_cliente Calle Ciudad_cliente
P.AO(1). P.DO(2).

4.2.7. Operaciones de agregación.

QBE incluye los operadores de agragados AVG, MAX, MIN, SUM y CNT. Estos operadores deben ser
postfijos con ALL. Para asegurar que todos los valores apropiados son considerados, por ejemplo P.SUM.ALL.
Supóngase que queremos eliminar los duplicados cuando se usa un operador de agregación. Puesto que todos
los operadores de agregados deben ser postfijos con ALL, debe añadirse un nuevo operador, UNQ, para especificar que
queremos los duplicados eliminados, como en P.CNT.UNQ.ALL.
QBE también ofrece la posibilidad de calcular funciones en grupos de tuplas usando el operador G., que es
análogo a la construcción group by de SQL. Así, para encontrar el saldo promedio en todas las sucursales podemos
escribir:
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
P.AO.G. P.AVG.ALL._x

36
Tema 4. Lenguajes relacionales comerciales.

La cuenta se puede usar para comprobar información negativa. Para encontrar a todos los clientes que tienen
una cuenta en la sucursal Perryridge, pero para quienes no hay dirección en el fichero, escribimos:
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
Perryridge _x

Cliente Nombre_cliente Calle Ciudad_cliente


CNT.ALL._x

Condiciones
CNT.ALL._x=0
El enfoque es contar el número de tuplas de cliente pertenecientes a cada cliente con depósito en Perryridge. Si
para un cliente la cuenta es 0, sabemos que para ese cliente la dirección no está disponible.
Considérese encontrar a todos los clientes que tienen una cuenta en todas las sucursales situadas en Brooklyn.
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
CNT.UNQ.ALL_ P.G._x
y

Sucursal Nombre_sucursal Activo Ciudad_sucursal


_y Brooklyn
_z Brooklyn

Condiciones
CNT.UNQ.ALL._y=CNT.UNQ.ALL._z
La variable de dominio z puede contener el valor de nombres de sucursales situadas en Brooklyn. Así,
CNT.UNQ.ALL._z es el número de sucursales distintas en Brooklyn. La variable de dominio y puede contener el valor
de sucursales que cumplen: estar situadas en Brooklyn y que el cliente cuyo nombre es x tiene una cuenta en la sucursal.
Así, CNT.UNQ.ALL._y es el número de sucursales distintas en Brooklyn en las que el cliente x tiene una cuenta. Si
CNT.UNQ.ALL._y=CNT.UNQ.ALL._z, entonces el cliente x debe tener una cuenta en todas las sucursales de
Brooklyn.

4.2.8. Modificación de la Base de Datos.

En esta sección mostramos como añadir, suprimir o cambiar información usando QBE.
n Supresión.
La supresión de tuplas de una relación se expresa casi de la misma forma que una consulta. La principal
diferencia es el empleo de D. en lugar de P. En QBE podemos eliminar tuplas completas así como valores en columnas
seleccionadas. En el caso en que eliminamos información solamente en algunas de las columnas, se insertan valores
nulos representados por -.
Una orden D. opera únicamente sobre una relación. Si queremos eliminar tuplas de distintas relaciones,
debemos usar un operador D. para cada relación.
Algunos ejemplos son:
Eliminar el valor de ciudad_sucursal de la sucursal Perryridge:
Sucursal Nombre_sucursal Activo Ciudad_sucursal
Perryridge D.
Eliminar las cuentas con números de cuenta entre 1300 y 1500:
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
D. _x

Condiciones
_x=(≥1300 and ≤ 1500)

n Inserción.
Para insertar datos en una relación, podemos especificar una tupla que se va a insertar o escribir una consulta
cuyo resultado sea un conjunto de tuplas que se va a insertar. La inserción se hace colocando el operador I. en la
expresión de la consulta.
La inserción más sencilla es una solicitud de insertar una tupla:
Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo
l
I. Peryridge 9732 Smith 1200
También podemos insertar una tupla que contiene solamente información parcial.
De forma más general podríamos querer insertar tuplas basadas en el resultado de una consulta. Consideremos
de nuevo la situación en la queremos dar a todos los clientes de préstamos de Perryridge una cuenta de 200$, siendo el
número de préstamo el número de cuenta. Escribimos:

37
Bases de Datos

Depósito Nombre_sucursa Número_cuenta Nombre_cliente Saldo


l
I. Perryridge _x _y 200

Depósito Nombre_sucursa Número_préstam Nombre_cliente Cantidad


l o
Perryridge _x _y

n Actualizaciones
Existen situaciones en las que se desea cambiar un valor en una tupla sin cambiar todos los valores en la tupla.
Para este propósito utilizamos el operador U.. Podemos elegir las tuplas que se van a actualizar usando una consulta.
QBE, sin embargo, no permite que los usuarios actualicen los campos de claves primarias.
Supóngase que actualizamos el activo de Perryridge a 10.000.000$:
Sucursal Nombre_sucursal Activo Ciudad_sucursal
Perryridge U.10000000
El campo en blanco del atributo ciudad_sucursal implica que no se necesita actualización de ese valor.
La consulta anterior actualiza el activo sin tener en cuenta el valor anterior. Hay circunstancias en las que
necesitamos actualizar un valor de campo usando el valor anterior del campo. Esto puede expresarse usando dos filas:
una especificando las tuplas antiguas que necesitan ser actualizadas y otra indicando las nuevas tuplas actualizadas que se
van a insertar en la BD.
Supóngase que se están haciendo pagos de intereses, al 5%. Escribimos:
Depósito Nombre_sucursa Número_préstam Nombre_cliente Cantidad
l o
U. _x*1,05
_x
Esta consulta especifica que cada vez recuperamos una tupla de la relación depósito, determinamos el saldo _x,
y actualizamos el saldo a _x*1,05.

4.3. QUEL.
Quel se introdujo como lenguaje de consulta para el DBMS Ingres, desarrollado en la Universidad de
California, Berkeley. Una versión comercial de Ingres fue desarrollada por Relational Technology Inc.. El sistema Ingres
académico ofreció solo el lenguaje Quel, mientras que el comercial actual ofrece Quel y SQL.

4.3.1. Estructura básica.

La estructura básica de Quel sigue muy de cerca la del cálculo relacional de tuplas. Gran parte de las consultas en
Quel se expresan mediante el uso de tres tipos de cláusulas: range of, retrieve y where.
Cada una de las variables de tupla se declara en una cláusula range of. Decimos range of t is r para declarar que t
es una variable de tupla restringida a tomar valores de tuplas en la relación r.
La cláusula retrieve tiene una función similar a la cláusula select de SQL.
La cláusula where contiene el presicado de selección.
Una consulta típica en Quel es de la forma:
range of t1 is r1

range of tm is rm
retrieve (ti.Aj, …, tk.Al)
where P
Las tx son las variables de tupla, rx son relaciones y las Ax son atributos. Quel, como SQL, usa la notación t.A
para expresar el valor de la variable de tupla t en el atributo A Esto significa lo mismo que t[a] en el cálculo relacional de
tuplas.
Quel no incluye operaciones del álgebra relacional como intersect, union y minus. Además, Quel no permite
subconsultas anidadas. Estas limitaciones no reducen el poder expresivo de Quel, más bien eliminan algunas formas
alternativas de expresar una consulta cara al usuario.

4.3.2. Consultas sencillas.

Para encontrar el nombre de todos los clientes que tienen una cuneta en Perryridge escribimos:
range of t is depósito
retrieve (t.nombre_cliente)
where t.nombre_sucursal = “Perryridge”
Esta consulta no elimina duplicados. Para eliminarlos debemos añadir la palabra clave unique a la cláusula
retrieve de la forma:retrieve unique (t.nombre_cliente).
Para mostrar una consulta en Quel que implique más de una relación, consideremos encontrar el nombre y la
ciudad de todos los clientes que tienen un préstamo en Perryridge:
range of t is préstamo

38
Tema 4. Lenguajes relacionales comerciales.

range of s is cliente
retrieve (t.nombre_cliente, s.ciudad_cliente)
where t.nombre_sucursal = “Perryridge” and t.nombre_cliente= s.nombre_cliente
Obsérvese que Quel, como SQL, usa los conectores lógicos and, or y not, en vez de los matemáticos ∧, ∨, y ¬.
Como en SQL, necesitamos expresar el predicado del producto explícitamente. Quel no tiene una notación especial para
el producto natural.

4.3.3. Variables de tupla.

Para ciertas consultas necesitamos tener dos variables de tupla que tengan como rango la misma relación.
Considérese encontrar los nombres de todos los clientes que tienen una cuenta en la misma sucursal en la que Jones
tiene una cuenta.
range of t is depósito
range of s is depósito
retrieve (t.nombre_cliente)
where s.nombre_cliente = “Jones” and t.nombre_sucursal= s.nombre_sucursal
Puesto que la consulta anterior necesita que comparemos las tuplas pertenecientes a Jones con cada tupla de
depósito, necesitamos dos variables de tupla distintas cuyo rango sea depósito. Sin embargo, es frecuente el caso de que
una consulta requiera solo una variable de tupla cuyo rango sea una relación. En dichos casos, podemos omitir la
sentencia range of para esa relación y usar el nombre de relación como una variable de tupla declarada implícitamente.
Siguiendo este convenio, para encontrar el nombre de todos los clientes que tienen un préstamo y una cuenta en la
sucursal Perryridge:
retrieve unique (préstamo.nombre_cliente)
where depósito.nombre_sucursal = “ Perryridge” and
préstamo.nombre_sucursal = “Perryridge” and
depósito.nombre_cliente = préstamo.nombre_cliente
El Quel académico original no permite el uso de variables de tupla declaradas implícitamente.

4.3.4. Funciones de agregación.

Las funciones de agregación en Quel calculan funciones sobre grupos de tuplas. Toman una forma diferente de
la de SQL, en Quel, el agrupamiento se especifica como parte de cada expresión de agregación.
Las expresiones de agregación en Quel pueden tomar las formas siguientes:
función de agregación (t.A)
función de agregación (t.A where P)
función de agregación (t.A by S.B1, …, S.Bn where P)
donde función de agregación puede ser count, sum, avg, max, min, countu, sumu, avgu, o any; t es una variable de
tupla; A, B1 y Bn son atributos, y P es un predicado similar al de la cláusula where. Una expresión de agregación puede
aparecer en cualquier lugar donde puede aparecer una constante. El significado intuitivo de count, sum, avg, max y min
es intuitivo, any se explicará más adelante y countu, sumu y avgu son idénticas a count, sum y avg respectivamente,
excepto que eliminan duplicados de sus operandos.
Para encontrar el saldo promedio de cuenta para todas las cuentas de la sucursal Perryridge, escribimos:
range of t is depósito
retrieve avg (t.saldo where t.nombre_sucursal = “Perryridge”)
En la cláusula pueden aparecer valores de agregación. Supóngase que queremos encontrar todas las cuentas cuyo
saldo sea mayor que el promedio de todos los saldos del banco:
range of u is depósito
range of t is depósito
retrieve (t.número_cuenta)
where t.saldo > avg (u.saldo)
Consideremos ahora una modificación de esta consulta. En vez de usar el saldo promedio del banco,
consideremos solo la sucursal Perryridge
range of u is depósito
range of t is depósito
retrieve (t.número_cuenta)
where t.saldo > avg (u.saldo where u.nombre_sucursal = “Perryridge”)
Modifiquemos aún más la consulta. Ahora queremos encontrar a todos los clientes cuyo saldo sea mayor que el
saldo promedio de la sucursal donde se tiene la cuenta. En este caso necesitamos calcular para cada tupla t de depósito el
saldo promedio en la sucursal t.nombre_sucursal. Para formar estos grupos de tuplas necesitamos usar la construcción
by en la expresión de agregación:
range of u is depósito
range of t is depósito
retrieve (t.número_cuenta)
where t.saldo > avg (u.saldo by t.nombre_sucursal where u.nombre_sucursal = “Perryridge”)
El efecto de la construcción by en Quel es diferente al de group by en SQL. La fuente principal de esa diferencia
es el papel de las variables de tupla. La variable de tupla t usada en by es la misma que se utiliza en el resto de la consulta.

39
Bases de Datos

Sin embargo, todas las demás variables de tuplas son locales de la misma expresión de agregación, incluso si una variable
con el mismo nombre aparece en otra parte de la consulta.
Consideremos encontrar el nombre de todos los clientes que tienen una cuenta en Perryridge, epro no tienen
un préstamo en Perryridge. Podemos escribir esta consulta en Quel usando la operación de agregación count si
pensamos en la consulta de la forma “encontrar el nombre de todos los clientes que tienen una cuenta en Perryridge y
para quienes el número de préstamos en la sucursal Perryridge es cero”.
Range of t is depósito
range of u is préstamo
retrieve unique (t.nombre_cliente)
where t.nombre_sucursal = Perryridge and
count (u.número_préstamo by t.nombre_cliente
where u.nombre_sucursal = “Perryridge”
and u.nombre_cliente = t,nombre_cliente) = 0
Quel ofrece otra función de agregación que es aplicable a este ejemplo, llamada any. Si sustituimos count en la
consulta por any, obtenemos 1 si la cuenta es mayor que 0, de lo contrario obtenemos 0. La función any permite la
ejecución más rápida de la consulta, ya que el procesamiento puede detenerse tan pronto como se encuentre una tupla.
El uso de una comparación con any es análogo al cuantificador existe del cálculo relacional.
Como un ejemplo más complicado, considérese encontrar el nombre de todos los clientes que tienen una
cuenta en todas las sucursales de Brooklyn. Nuestra estrategia será averiguar cuantas sucursales hay en Brooklyn y
después comparar este número con el número de sucursales distintas en Brooklyn en las que cada cliente tiene una
cuenta:
range of t is depósito
range of s is sucursal
range of u is sucursal
retrieve unique (t.nombre_cliente)
where countu (s.nombre_sucursal by t.nombre_cliente
where s.ciudad_sucursal = “Brooklyn” and
s.nombre_sucursal = t,nombre_sucursal) =
countu (u.nombre_sucursal where u.ciudad_sucursal = “Brooklyn”)
Usamos by en la primera expresión countu, puesto que debemos restringir la consideración a un único cliente
cada vez. Sin embargo, no usamos by en la última expresión countu, puesto que estamos interesados en contar todas las
sucursales en Brooklyn independientes de las variables de tupla obligatorias a esta expresión countu.

4.3.5. Modificación de la Base de Datos.

La modificación de la BD en Quel es similar a la modificación en SQL, aunque la sintaxis es un poco distinta.


n Eliminación.
La forma de una eliminación en Quel es
range of t is r
delete t
where P
La variable de tupla t puede estar definida explícitamente. El predicado P puede ser cualquier predicado válido
en Quel. Si se omite la cláusula where, se eliminan todas las tuplas en la relación..
Por ejemplo, eliminar todas las cuentas de las sucursales de Needham será:
range of t is depósito
range of u is sucursal
delete t
where t.nombre_sucursal = u.nombre_sucursal and u.ciudad_sucursal = “Needham”

n Inserción.
La inserción en Quel toma dos formas generales: inserción de una sola tupla e inserción de un conjunto de
tuplas. Quel usa la palabra clave append para inserción.
Como ejemplos pondremos, insertar el hecho de que Smith tiene 1200$ en la cuenta 9732 en Perryridge:
append to depósito (nombre_sucursal = “Perryridge”, …, saldo = 1200)
Proporcionar a todos los clientes con préstamos en Perryridge una cuenta de 200$, siendo el número de
préstamo el número de cuenta:
range of t is préstamo
append to depósito (t.nombre_sucursal, número_cuenta = t.número_préstamo,
t.nombre_cliente, saldo = 200)
where t.nombre_sucursal = “Perryridge”

n Actualizaciones.
Las actualizaciones se expresan en Quel usando la orden replace. Por ejemplo, para pagar el 6% de interés a las
cuentes de más de 10000$ y el 5% al resto. Escribiremos:
range of t is depósito
replace t (saldo = 1,06 * saldo)

40
Tema 4. Lenguajes relacionales comerciales.

where t.saldo > 10000


replace t (saldo = 1,05 * saldo)
where t.saldo ≤ 10000

4.3.6. Operaciones de conjuntos.

Consideremos una consulta para la cual se usó la operación union en SQL, como es encontrar el nombre de
todos los clientes que tienen una cuenta, un préstamo o ambos en Perryridge. Puesto que no tenemos una operación
union en Quel, y sabemos que Quel está basado en el cálculo relacional de tuplas, podríamos guiarnos por la expresión
del cálculo relacional de tuplas para esta consulta:
{t|∃s∈préstamo (t[nombre_cliente] = s[nombre_cliente] ∧ s[nombre_sucursal] = “Perryridge”)
∨ ∃u∈depósito (t[nombre_sucursal] = u[nombre_sucursal] ∧ u[nombre_sucursal] = “Perryridge”)}
La expresión anterior no nos conduce a una consulta en Quel. El problema es que en la copnsulta del cálculo
relacional de tuplas, obtenemos los clientes tanto de variable de tupla s como de la u. En Quel, la cláusula retrieve debe
ser una de las siguientes:
retrieve s.nombre_cliente retrieve u.nombre_cliente
Si elegimos la primera, excluimos a los clientes que tienen depósitos pero no préstamos, si elegimos la segunda
sucede lo contrario.
Para escribir esta consulta en Quel, debemos hacer una nueva relación e insertar tuplas en ella, llamada temp.
Obtenemos los clientes con depósitos de la sucursal Perryridge escribiendo:
range of u is depósito
retrieve into temp unique (u.nombre_cliente)
where u.nombre_sucursal = “Perryridge”
La cláusula into temp hace que se cree una nueva relación, que contiene el resultado de esta consulta. Ahora
podemos encontrar a todos los clientes con préstamos de la sucursal Perryridge e insertarlos en la recién creada relación
temp. Hacemos esto por medio de la orden append:
range of s is préstamo
append to temp unique (s.nombre_cliente)
where s.nombre_sucursal = “Perryridge”
Ahora tenemos una relación temp que contiene a todos los clientes que tienen una cuenta, un préstamo, o
ambos, en Perryridge. El uso de la palabra clave unique asegura que se han eliminado todos los duplicados.
La estrategia de utilizar append nos permite realizar uniones en Quel. Para realizar una diferencia de conjuntos
r-s creamos una relación temporal representada por r y eliminamos las tuplas de esta relación temporal que también
están en s.
Por ejemplo, si queremos encontrar el nombre de todos los clientes que tienen una cuenta en Perryridge pero
que no tienen un préstamo de Perryridge:
range of u is depósito
retrieve into temp unique (u.nombre_cliente)
where u.nombre_sucursal = “Perryridge”

range of s is préstamo
range of t is temp
delete (t)
where s.nombre_sucursal = “Perryridge” and t.nombre_cliente = s.nombre_cliente
La relación temp contiene la lista de clientes deseada, por lo que escribimos el final de la consulta:
range of t is temp
retrieve unique (t.nombre_cliente)

41

Potrebbero piacerti anche