LMD

Lenguaje interactivo de manipulación de datos (LMD)

El lenguaje de manipulación de datos (LMD) es el que se encarga de llevar a cabo las tareas de consulta o manipulación de los datos, organizados por el modelo de datos adecuado

Incluye órdenes para consultar, modificar, borrar o definir las tuplas (filas) que son almacenadas en las relaciones (tablas) de la base de datos

Existen cuatro operaciones básicas:

Definición básica de esquemas

Operación alias

SQL proporciona una operación para renombrar mediante un alias tanto las relaciones como los atributos

Tiene la siguiente sintaxis: nombre_original AS alias

La cláusula AS es opcional aunque si la escribimos resultará más claro porque nos informa que estamos definiendo un alias

Situaciones en las que es útil usar un alias:

  • Donde tenemos dos relaciones en la cláusula FROM que tienen el mismo nombre para sus atributos

    En estas situaciones se puede producir ambigüedad y podremos usar la operación alias para desambigüar los atributos y que quede claro a qué relación pertenecen

  • Cuando tenemos una operación calculada que genera un atributo en la cláusula SELECT

  • Cuando tenemos una operación calculada que genera un atributo despues de aplicar una operación de agregación

Para acceder a sus atributos se debe usar el alias seguido de un punto y el nombre del atributo

SELECT

Se puede utilizar el comando SELECT para consultar los datos almacenados en una relación de la base de datos

Devolverá un conjunto de tuplas de esa relación

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1, r_2, \cdots, r_m\\ \text{WHERE} P

Donde cada Ai representa a un atributo, cada ri una relación y P es un predicado

Por lo que una consulta SQL tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p(r_1 \Theta r_2 \Theta \cdots \Theta r_m) )

Si se omite la clausula WHERE, el predicado P es siempre cierto

Pero a diferencia de la expresión del álgebra relacional, el resultado de una consulta SQL puede contener varias tuplas repetidas

Cuando introducimos más de una relación en la claúsula FROM, SQL formará un producto cartesiano de todas las relaciones incluidas

Después se lleva a cabo la selección del álgebra relacional utilizando el predicado de la cláusula WHERE y despues proyecta el resultado sobre los atributos de la cláusula SELECT

Cláusula SELECT

En el ejemplo se ha resuelto la consulta obtener todas las cuentas de la relación cuenta con los atributos numero_cuenta, nombre_sucursal, saldo

En este caso, al usar DISTINCT estamos forzando a que se eliminen los repetidos

En el ejemplo se ha resuelto la consulta obtener todas las cuentas de la relación cuenta con los atributos numero_cuenta, nombre_sucursal, saldo

En este caso, al usar ALL estamos forzando a que NO se eliminen los repetidos

En el ejemplo se ha sustituido el comando ALL por el símbolo * y se ha prescindido de los atributos, ya que el resultado es equivalente

En el ejemplo se ha resuelto la consulta obtener todas las cuentas de la relación cuenta con los atributos numero_cuenta, nombre_sucursal, con un incremento de 1500 en el saldo

Como puede apreciarse, también podemos utilizar expresiones aritméticas que operen sobre los atributos

En el ejemplo se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama incremento

Cláusula FROM

La cláusula FROM define por sí misma un producto cartesiano de las relaciones que aparecen en la consulta

Dado que la reunión natural se define en términos de un producto cartesiano, una selección y una proyección, resulta relativamente sencillo escribir una expresión SQL para la reunión natural

Tenemos que en álgebra relacional podemos escribirla como:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (r_1 \Theta r_2 \Theta \cdots \Theta r_m)

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursal de ‘Navacerrada

Para ello se han introducido las relaciones cuenta (se le ha asignado el alias c) y cliente (se le ha asignado el alias cl)

Sólo con la cláusula FROM no podríamos resolver la consulta

Ya que el producto cartesiano se realiza sobre cada una de las posibles parejas que pueden formarse con la relación cuenta y cliente

Dándonos resultados repetidos y también todos aquellos que no fueran de la sucursal de ‘Navacerrada

Por eso se ha añadido la condición que relaciona ambas relaciones, el atributo numero_cuenta

Después de añadirlo, tendremos sólo los valores que pertenecen a la relación, aunque puede seguir habiendo repetidos

Y la igualdad para la atributo nombre_sucursal con el valor ‘Navacerrada

Cláusula JOIN

En el ejemplo se ha usado la cláusula JOIN que nos devolverá un resultado equivalente

La cláusula JOIN permite realizar operaciones de reunión, las cuales toman dos relaciones y devuelven como resultado otra relación

Normalmente puede utilizarse la cláusula FROM para realizar reuniones externas o para cualquier situación en la que se pueda utilizar una reunión

Para distinguir si la reunión es externa se usará la palabra clave OUTER y para la interna INNER

Ambas son opcionales, aunque deja más claro qué tipo de reunión estamos usando

Hay cuatro tipos de reunión:

  • INNER JOIN

    Devuelve todas las tuplas cuando hay al menos una coincidencia en ambas relaciones

    En el ejemplo se ha usado la cláusula INNER JOIN que nos devolverá un resultado equivalente

    Ya que como dijimos, la palabra clave INNER era opcional

    Sin embargo, ahora tenemos más claro que la reunión era interna

  • LEFT OUTER JOIN

    Devuelve todas las tuplas de la relación de la izquierda, y las tuplas coincidentes de la relación de la derecha

    En el ejemplo se ha usado la cláusula LEFT JOIN que nos devolverá un resultado que ya no es equivalente, ya que aparecerán valores nulos

    Hemos prescindido de la palabra clave OUTER porque el resultado es equivalente

    En este caso LEFT JOIN nos mantiene todas las tuplas de la relación izquierda (cuenta)

    Las tuplas de la relación derecha (cliente) se mostrarán si hay una coincidencia con las de la izquierda

    Si existen valores en la relación izquierda pero no en la relación derecha, ésta mostrará null

  • RIGHT OUTER JOIN

    Devuelve todas las tuplas de la relación de la derecha, y las tuplas coincidentes de la relación de la izquierda

    En el ejemplo se ha usado la cláusula RIGHT JOIN que nos devolverá un resultado que ya no es equivalente, ya que aparecerán valores nulos

    Hemos prescindido de la palabra clave OUTER porque el resultado es equivalente

    En este caso RIGHT JOIN nos mantiene todas las tuplas de la relación derecha (cliente)

    Las tuplas de la relación izquierda (cuenta) se mostrarán si hay una coincidencia con las de la derecha

    Si existen valores en la relación derecha pero no en la relación izquierda, ésta mostrará null

  • FULL OUTER JOIN

    Devuelve todas las tuplas de las dos relaciones, la izquierda y la derecha

    En el ejemplo se ha usado la cláusula FULL JOIN que nos devolverá un resultado que ya no es equivalente, ya que aparecerán valores nulos

    Hemos prescindido de la palabra clave OUTER porque el resultado es equivalente

    En este caso FULL JOIN devuelve todas las filas de la tabla izquierda (cuenta) y de la tabla derecha (cliente)

    Combina el resultado de los LEFT JOIN y RIGHT JOIN

    Aparecerá null en cada una de las tablas alternativamente cuando no haya una coincidencia

El tipo de reunión define la manera de tratar las tuplas de cada relación que no casan con la tupla de la otra relación

Hay tres tipos de condiciones que se aplicarán a las reuniones:

  • reunión NATURAL

    Se utiliza cuando los atributos por los cuales se reúnen las relaciones tienen el mismo nombre

    En el ejemplo se ha usado la cláusula NATURAL JOIN que nos devolverá un resultado equivalente sin utilizar la condición ON

    Ya que el atributo numero_cuenta se llama igual en las relaciones cuenta y cliente

  • condición ON

    Su uso es similar al de la cláusula WHERE, pero está especializado en comparar atributos de ambas relaciones

  • condición USING

    Su uso es similar al de la reunión NATURAL, ya que se utiliza cuando los atributos por los cuales se reúnen las relaciones tienen el mismo nombre

    Sin embargo, sólo devolverá un resultado de la reunión, no todos como hace la reunión NATURAL

    En el ejemplo se ha usado la condición USING con el el atributo numero_cuenta, que nos devolverá un resultado que ya no es equivalente

    Ya que sólo devolverá sólo la primera coincidencia de cada pareja de la relación, no todas

El uso de las condiciones de reunión es obligatorio en las reuniones externas, pero es opcional en las internas (si se omiten, se obtiene un producto cartesiano)

Cláusula WHERE

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo saldo tienen un valor inferior a 100

Para conseguirlo hemos utilizado la cláusula WHERE, gracias a la cuál podemos filtrar la consulta al admitir una condición usando el operador lógico de comparación <

Operador Descripción
< Menor que
<= Menor o igual que
> Mayor que
>= Mayor o igual que
= Igual que
<> Distinto que

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo nombre_sucursal tienen un valor igual a ‘Navacerrada‘ y su atributo saldo tienen un valor inferior a 100

Para conseguirlo se ha utilizado el conector lógico AND

Operadores lógicos de conexión
Operador Descripción
AND Es verdadera si y sólo si los dos operandos son verdaderos
OR Es verdadera si y sólo si los uno o ambos operandos son verdaderos
NOT Invierte el valor del operando
Operador BETWEEN

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo nombre_sucursal tienen un valor igual a ‘Navacerrada‘ y su atributo saldo tienen un valor entre 100 y 1000

En el ejemplo se ha utilizado una consulta equivalente, utilizando el operador de comparación BETWEEN, el cuál nos simplifica un poco las cláusulas WHERE

En el ejemplo se ha utilizado una consulta negando el operador de comparación NOT BETWEEN, el cuál nos devolverá aquellos valores que estén fuera de ese rango

Operador LIKE

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo nombre_sucursal tienen un valor igual a ‘Navacerrada

En el ejemplo se ha utilizado una consulta equivalente, utilizando el operador de comparación LIKE, el cuál nos simplifica un poco las cláusulas WHERE al permitirnos el uso de patrones con las cadenas de caracteres

Para la descripción de patrones podemos utilizar dos caracteres especiales:

  • %

    El tanto por ciento coincide con cualquier subcadena de caracteres

  • _

    El subrayado coincide con cualquier carácter

Estos patrones pueden ser combinados para obtener distintos tipos de consultas:

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón % después del texto, el cuál nos devolverá aquellos valores que empiecen por la cadena ‘Nava

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón % delante y después del texto, el cuál nos devolverá aquellos valores que incluyan como subcadena ‘Nava

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón _ repetido tres veces, el cuál nos devolverá aquellos valores que tengan exactamente tres caracteres

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón _ repetido tres veces y el patrón %, el cuál nos devolverá aquellos valores que tengan al menos tres caracteres

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón % en conjunto con el carácter especial de escape ‘\‘, el cuál nos devolverá aquellos valores que contengan ‘Nava%rrete

El carácter de escape (que puede ser cualquiera que nosotros elijamos) se utiliza antes de los caracteres especiales de patrón para indicar que ese carácter se va a tratar como un carácter normal y no como un patrón

Se define utilizando la palabra clave escape

En el ejemplo se ha utilizado el operador de comparación NOT LIKE utilizando el patrón %, el cuál nos devolverá aquellos valores que NO contengan ‘Nava%rrete

De esta forma también podemos buscar discordancias, solamente negando el operador LIKE

Valores nulos

SQL permite el uso de valores nulos para indicar la ausencia de información sobre el valor de un atributo

Se puede utilizar la palabra clave especial NULL en un predicado para comprobar si un valor es nulo

En el ejemplo se ha resuelto la consulta obtener todas las cuentas cuyo nombre de sucursal NO haya sido rellenado

En el ejemplo se ha resuelto la consulta obtener todas las cuentas cuyo nombre de sucursal haya sido rellenado

Como puede verse, también puede comprobarse la ausencia de valores nulos usando el operador lógico NOT

Dado que el predicado de las cláusulas WHERE puede incluir operaciones booleanas como AND, OR y NOT sobre los resultados de la comparaciones, los valores NULL amplían las operaciones booleanas

AND VERDAD FALSO NULL
VERDAD VERDAD FALSO NULL
FALSO FALSO FALSO FALSO
NULL NULL FALSO NULL
OR VERDAD FALSO NULL
VERDAD VERDAD VERDAD VERDAD
FALSO VERDAD FALSO NULL
NULL VERDAD NULL NULL
NOT VERDAD FALSO NULL
FALSO VERDAD NULL

Cláusula ORDER BY

En ocasiones necesitamos devolver la información de las tuplas en cierto order

SQL permite ordenar los atributos utilizando la cláusula ORDER BY

En el ejemplo se ha utilizado el operador de comparación ASC con la cláusula ORDER BY para el atributo nombre_sucursal, el cuál nos devolverá los valores ordenados de forma ascendente (en order alfabético porque era un atributo alfanumérico) por el atributo nombre_sucursal

En el ejemplo se ha utilizado el operador de comparación DESC con la cláusula ORDER BY para el atributo nombre_sucursal, el cuál nos devolverá los valores ordenados de forma descendente (en order alfabético porque era un atributo alfanumérico) por el atributo nombre_sucursal

El tipo de ordenación devuelto por los operadores de comparación ASC y DESC dependerán del tipo del atributo, ya que no se ordena de igual manera un número, una cadena o una fecha

Si necesitamos ordenar más de un atributo, lo haremos separandolos por comas y seguido el operador de comparación (ASC ó DESC )

El método de ordenación por defecto es ASC, es opcional y podríamos prescindir de escribirlo

Operaciones sobre conjuntos

SQL permite realizar las operaciones sobre conjuntos del álgebra relacional unión \cup, intersección \cap y diferencia \neg

Para utilizarlas tendremos la única restricción de que los nombres de los atributos de las relaciones implicadas deben ser iguales

Operación UNION

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{UNION}\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una unión tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \cup \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco o que tienen un cliente asociado a ellas

A diferencia de la cláusa SELECT la operación UNION elimina los valores repetidos

Por esta razón es buena idea utilizar la operación UNION para crear claves, ya que con SELECT no obtendríamos claves únicas (permite repetidos)

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco o que tienen un cliente asociado a ellas

Al utilizar el operador ALL en conjunto con la operación UNION, estamos permitiendo que se comporte como un SELECT, ya que admite repetidos

Operación INTERSECT

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{INTERSECT}\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una intersección tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \cap \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que tienen un cliente asociado a ellas

La operación INTERSECT elimina los valores repetidos y sólo devuelve aquellos valores que tienen coincidencia en la relación cuenta y en cliente a la vez, no sólo en uno de ellos

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que tienen un cliente asociado a ellas

Al utilizar el operador ALL en conjunto con la operación INTERSECT, estamos permitiendo que se comporte como un SELECT, ya que admite repetidos

Operación EXCEPT

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{EXCEPT}\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una diferencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \cap \neg (\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) ) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que NO tienen un cliente asociado a ellas

La operación EXCEPT elimina los valores repetidos y sólo devuelve aquellos valores que tienen coincidencia en la relación cuenta pero no coinciden con cliente

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que NO tienen un cliente asociado a ellas

Al utilizar el operador ALL en conjunto con la operación EXCEPT, estamos permitiendo que se comporte como un SELECT, ya que admite repetidos

Operación IN

SQL permite comprobar la pertenencia de las tuplas a una relación que es equivalente a comprobar la pertenencia a un conjunto del álgebra relacional

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{IN}\\ (\text{SELECT} _1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \in \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursal de ‘Navacerrada

Anteriormente la resolvimos utilizando la cláusula JOIN

Pero como puede comprobarse, también podemos resolverla utilizando la teoría de conjuntos

La pertenencia nos devolverá los valores y en caso de no haber ninguno, mostrará null

El ejemplo resuelve la consulta de obtener todos los clientes que NO tienen cuenta en la sucursal de ‘Navacerrada

Al negar la pertenencia nos devolverá el resto de valores y en caso de no haber ninguno, mostrará null

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursal de ‘Logroño‘ ó ‘Navacerrada

Como puede apreciarse, la pertenencia o la no pertenencia, aparte de una subconsulta como en los ejemplos anteriores, también admite conjuntos enumerados

Siempre que esos conjuntos enumerados sean del mismo dominio que el atributo del que se quiere comprobar la pertenencia

Operadores de comparación

SQL ofrece la posibilidad de comparar conjuntos utilizando subconsultas

Operador SOME

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{SOME}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \approx \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

El ejemplo resuelve la consulta de obtener algún cliente que tiene cuenta en la sucursal de ‘Navacerrada

Anteriormente la resolvimos utilizando la operación IN

Pero como puede comprobarse, también podemos resolverla utilizando una comparación de conjuntos

En este caso utilizando el símbolo = delante del operador SOME para denotar que son iguales

El ejemplo resuelve la consulta de obtener algún cliente que NO tiene cuenta en la sucursal de ‘Navacerrada

Aunque podría parecer que es equivalente al ejemplo anterior con NOT INT, el resultado puede no ser igual

También podemos utilizar el resto de operadores lógicos de comparación

Operador ANY

Puede utilizarse también el operador ANY ya que es equivalente a SOME

Las primeras versiones de SQL sólo admitían el operador ANY, pero se añadió SOME para que se asemejase más al lenguaje natural, ya que any creaba ambigüedad en la lengua inglesa

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{ANY}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \approx \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

También podemos utilizar el resto de operadores lógicos de comparación

El ejemplo resuelve la consulta de obtener algún cliente que tiene cuenta en la sucursal de ‘Navacerrada

Anteriormente la resolvimos utilizando la operación SOME

Como puede verse es totalmente equivalente y sólo lo usaríamos por compatibilidad con versiones antiguas de SQL

Operador ALL

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{ALL}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \forall \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

También podemos utilizar el resto de operadores lógicos de comparación

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursales después de ‘Navacerrada‘ (alfabéticamente)

En realidad al utilizar el símbolo > delante del operador ALL estamos denotando que buscamos todos los valores que tengan una ordenación alfabética superior a ‘Navacerrada

Control de repetidos

SQL permite controlar si una subconsulta tiene tuplas repetidas en su resultado

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE UNIQUE}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2, \cdots, r_n\\ \text{WHERE} P)

Donde cada Ai representa a un atributo, cada ri una relación y P es predicado

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma \exists \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_2, \cdots, r_n) ) (r_1) )

Si se omite la clausula WHERE, el predicado P, es siempre cierto

Formalmente la evaluación de UNIQUE sobre una relación se define como falsa si y sólo si la relación contiene dos tuplas ri y rk tales que ri = rk

Como la comprobación ri = rk es falsa si algún atributo de ri ó rk es nulo, es posible que el resultado de UNIQUE sea cierto aunque haya varios duplicados de una misma tupla

Siempre que al menos uno de los atributos de la tupla sea nulo

El ejemplo resuelve la consulta de obtener todos los clientes que tienen a lo sumo una cuenta en la sucursal de ‘Navacerrada

Para ello se han introducido las relaciones cuenta (se le ha asignado el alias c) y cliente (se le ha asignado el alias cl)

Sólo con la cláusula FROM no podríamos resolver la consulta

Podríamos haber usado la cláusula JOIN, aunque puede seguir habiendo repetidos

Por eso se ha añadido el operador UNIQUE que relaciona ambas relaciones con el atributo numero_cuenta y la igualdad para la atributo nombre_sucursal con el valor ‘Navacerrada

Después de añadirlos, tendremos sólo los valores que pertenecen a la relación

El ejemplo resuelve la consulta de obtener todos los clientes que tienen más de una cuenta en la sucursal de ‘Navacerrada

Como puede verse, la negación de UNIQUE nos permite comprobar si hay más de un repetido

Funciones de agregación

Las funciones de agregación son funciones que toman una colección (un conjunto o multiconjunto) de valores como entrada y devuelven un solo valor

SQL permite cinco funciones de agregación:

  • AVG

    Permite realizar la media aritmética de la colección, la cuál debe ser numérica

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener la media aritmética del saldo de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama media

  • MIN

    Permite determinar cuál es valor mínimo de la colección, la cuál no es obligatorio que sea numérica

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener el saldo más bajo de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama menor

  • MAX

    Permite determinar cuál es valor máximo de la colección, la cuál no es obligatorio que sea numérica

    Hay que tener en cuenta que NO admite DISTINCT pero si ALL, pero como es el valor por defecto, puede omitirse

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener el saldo más alto de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama mayor

  • SUM

    Permite realizar la suma de la colección, la cuál debe ser numérica

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener el saldo total de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama liquido

  • COUNT

    Permite contar el número de elementos que compone la colección, la cuál no es obligatorio que sea numérica

    Si hay valores nulos en la entrada, se toman como 0

    En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Cláusula GROUP BY

Existen circunstancias en las cuales sería deseable aplicar las funciones de agregación no sólo a un único conjunto de tuplas sino también a un grupo de conjuntos de tuplas

En SQL podemos especificarlo mediante la cláusula GROUP BY

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r\\ \text{WHERE} P\\ \text{GROUP BY} A_1, \cdots, A_2, \cdots, A_n\\ \text{HAVING} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una agrupación tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r) ) )

Si se omiten las clausulas WHERE ó HAVING, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total de cada sucursal

Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Para que la operación de agrupación pueda realizarse sin errores debemos utilizar el mismo orden de los atributos tanto en la cláusula SELECT como en GROUP BY

En el caso de que no vayan a intervenir en la agrupación, podremos omitir esos atributos colocándolos a la derecha de los que sí serán usados

Cláusula HAVING

En ocasiones necesitamos que una condición se aplique a los grupos en vez de a las tuplas

Para expresar este tipo de consultas utilizamos la cláusula HAVING

En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total de la sucursal de ‘Navacerrada

Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Se ha aplicado la condición sobre el atributo nombre_sucursal con el valor ‘Navacerrada‘ utilizando la cláusula HAVING para aplicarla sobre la agrupación y no sobre la relación

En el caso de que tendríamos una cláusula WHERE y una HAVING:

  1. SQL aplicará primero el predicado de la cláusula WHERE
  2. El resultado se dividirá en los grupos que satisfagan el predicado de la cláusula HAVING

En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total de la sucursal de ‘Navacerrada‘ y que tengan un saldo mayor de 100

Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Se ha aplicado la condición sobre el atributo nombre_sucursal con el valor ‘Navacerrada

Adicionalmente se ha aplicado la condición sobre el atributo saldo aplicándole la operación de agrupación COUNT con la condición de que sean mayores que 100

Ambas han sido aplicacadas sobre la cláusula HAVING

Como puede verse, pueden aplicarse sin problemas las operaciones de agregación dentro de la cláusula HAVING aunque también aparezcan en la cláusula SELECT

INSERT

Las relaciones recién creadas están inicialmente vacías

Se puede utilizar el comando INSERT para añadir datos a la relación

La forma más habitual de consulta de inserción será:

\text{INSERT INTO r}\\ \text{VALUES} (A_1, A_2, \cdots, A_n)

Donde cada Ai representa a un atributo, r la relación y cada Pi es un predicado

En el ejemplo se ha resuelto la consulta para añadir la cuenta C-9732 en la sucursal de ‘Navacerrada‘ con un saldo de 1200€

Los valores se especifican en el orden en que se relacionan los atributos correspondientes en el esquema de la relación

En el ejemplo se ha modificado el orden en que se relacionan los atributos correspondientes en el esquema de la relación y por eso los datos se han introducido de forma obligatoria, en el nuevo orden que hemos especificado

De esta forma podemos elegir nosotros en qué orden introducimos los datos

En el caso de no introducir un atributo, SQL tratará de introducir un valor por defecto o el valor nulo y si es la clave primaria, notificará el error e impedirá la actualización

En el ejemplo se ha resuelto la consulta para añadir el cliente ‘Pedro Almodovar‘ para todos los números de cuenta que existen en la sucursal de ‘Navacerrada‘ y que NO tienen un cliente asociado a ellas

En lugar de especificar una tupla se ha usado una subconsulta ya que la cláusula SELECT nos permitirá especificar un conjunto de tuplas

La forma más habitual de subconsulta para la inserción será:

\text{INSERT INTO} r1\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} P

Donde cada Ai representa a un atributo, ri las relaciones y P es un predicado

Se evaluará en primer lugar la cláusula SELECT y se insertarán en la relación cliente las tuplas obtenidas de la subconsulta

Hemos de tener cuidado al utilizar subconsultas anidadas, ya que al abusar de ellas, podríamos crear un bucle infinito de subconsultas y la inserción se realizaría de forma infinita, quedando la base de datos bloqueada

Por suerte los sistemas gestores de bases de datos tienen mecanismos o herramientas para realizar inserciones masivas de forma controlada, evitando el bloqueo de la base de datos

UPDATE

Se puede utilizar el comando UPDATE para modificar los valores de un conjunto de tuplas existentes de una relación

La forma más habitual de consulta de actualización será:

\text{UPDATE r}\\ \text{SET} A_1 = P_1, A_2 = P_2, \cdots, A_n = P_n

Donde cada Ai representa a un atributo, r la relación y cada Pi es un predicado

En el ejemplo se ha actualizado la relación llamada cuenta, en concreto al atributo saldo le hemos cambiado su valor a 100

El comando actualizará todas las tuplas de la relación cuenta

En el ejemplo se han actualizado sólo las tuplas que cumplen la condición introducida, en este caso las que en su atributo numero_cuenta tienen un valor igual a ‘C-9732

En lugar de especificar una tupla se ha usado una subconsulta ya que la cláusula SELECT nos permitirá especificar un conjunto de tuplas

Hemos de tener cuidado al utilizar subconsultas anidadas, ya que al abusar de ellas, podríamos crear un bucle infinito de subconsultas y la inserción se realizaría de forma infinita, quedando la base de datos bloqueada

Por suerte los sistemas gestores de bases de datos tienen mecanismos o herramientas para realizar inserciones masivas de forma controlada, evitando el bloqueo de la base de datos

Operador Case

El orden de dos instrucciones UPDATE es importante ya que si se cambia el orden de las instrucciones de actualización podemos obtener datos incoherentes

Para solucionar este problema tenemos el operador CASE

La forma más habitual de consulta de actualización será:

\text{UPDATE r}\\ \text{SET} A_1 = P_1, A_2 = P_2, \cdots, A_n = P_n

Donde cada Ai representa a un atributo, r la relación y cada Pi es un predicado el cual podemos sustituir por el siguiente predicado Q:

\text{CASE}\\ \text{WHEN} P_1 \text{THEN} r_1\\ \text{WHEN} P_2 \text{THEN} r_2\\ \cdots\\ \text{WHEN} P_n \text{THEN} r_n\\ \text{ELSE} r_0\\ \text{END}

Donde cada Pi cada predicado que puede satisfacerse, cada ri el resultado que se usará en la actualización

En el caso de no cumplirse ninguno de los predicados, se aplicaría el resultado r0

En el ejemplo se ha resuelto la consulta de actualización para añadir un 0.05 al saldo cuando es menor o igual que 100 con una modificación del 0.05, cuando es igual que 500 con una modificación del 0.07, cuando es mayor que 1000 con una modificación del 0.25 y una modificación del 0.01 en cualquier otro caso

Se ha utilizado la cláusula CASE para resolverlo al igualarlo con el atributo saldo que era el valor a actualizar

DELETE

Se puede utilizar el comando DELETE para borrar tuplas de una relación

Y sólo de esa relación, ya que no es capaz de trabajar sobre varias

La forma más habitual de consulta de borrado será:

\text{DELETE FROM r}\\ \text{WHERE} P

Donde r representa la relación y cada P es un predicado

En el ejemplo se ha borrado la relación llamada cuenta

El comando borrará todas las tuplas de la relación cuenta

En el ejemplo se han borrado sólo las tuplas que cumplen la condición introducida, en este caso las que en su atributo saldo tienen un valor inferior a 100

Hay que tener en cuenta que el comando DELETE comprueba primero cada tupla de la relación cuenta y luego borrará todas las tuplas que cumplen la condición

Es importante realizar todas las comprobaciones antes del borrado ya que el orden en que se procesan las tuplas puede variar la operación de borrado