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:
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:
- SQL aplicará primero el predicado de la cláusula WHERE
- 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