Unidad 6. SQL
Unidad 6. SQL
Unidad 6. SQL
1
Escuela de Formación Profesional - UNaF
Unidad 6. SQL
Introducción
Lenguaje de Definición de datos
El modelo de datos relacional utiliza el concepto de relación, tupla y atributo, en tanto
en SQL los términos corresponden a tabla, fila y columna. En este libro tabla-relación,
tupla-fila y atributo-columna, se utilizan indistintamente.
Para administrar un modelo físico de datos, SQL presenta tres cláusulas básicas:
CREATE, DROP y ALTER. Los mismos se corresponden con crear, borrar o modificar
el esquema existente.
Obsevaciones: dominio texto (a diferencia del String que tiene longitud máxima,
el tipo de dato texto no está limitado)
La sintaxis utilizada, si bien es ANSI, tiene similitud con la utilizada por el DBMS
MySQL. Los valores posibles para los dominios de los atributos están ligados
directamente con los productos comerciales.
Asimismo ocurre con la definición de los atributos autoincrementales.
Por último, en el ejemplo anterior, se encuentran definidos dos índices para la tabla
Empresas. Estos índices se definen asociados a la clave primaria y clave candidata
respectivamente.
El siguiente ejemplo presenta la creación de otra tabla, donde se agrega la definición
de una clave foránea.
CREATE TABLE pacientesempresas (
idpacienteempresa INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
idpaciente_os INTEGER UNSIGNED NOT NULL,
idempresa INTEGER UNSIGNED NOT NULL,
fecha_desde DATE NOT NULL,
fecha_hasta DATE NULL,
PRIMARY KEY(idpacienteempresa),
INDEX empleadosempresas_FKIndex1(idempresa),
INDEX pacientesempresas_FKIndex2(idpaciente_os),
FOREIGN KEY(idempresa)
REFERENCES empresas(idempresa)
ON DELETE RESTRICT
ON UPDATE NO ACTION,
FOREIGN KEY(idpaciente_os)
REFERENCES pacientes_os(idpaciente_os)
ON DELETE RESTRICT
ON UPDATE NO ACTION);
Se agrega aquí la definición de dos índices secundarios: empleadosempresas
y pacientesempresas. Luego se definen las claves foráneas, con las referencias a las
tablas de donde se obtiene la CP. Se indica, además, el tipo de restricción de
integridad definido: el borrado está restringido y por la modificación no se toma acción.
Para eliminar una tabla del modelo la sentencia es:
DROP TABLE nombre_tabla;
Para modificar una tabla del modelo la sentencia es:
ALTER TABLE nombre_tabla ( … ) ;
Esta sentencia debe indicar, además, que tipo de modificación se desea realizar sobre
la tabla. Así entre paréntesis se pueden agregar, modificar o borrar atributos, índices o
restricciones de integridad.
A modo de ejemplo, la siguiente sentencia SQL agrega el atributo razón social a la
tabla empresa generada anteriormente, se quita el atributo cuit y se modifica el
dominio del atributo dirección por un string de longitud 50.
ALTER TABLE empresas (
Add column razon_social VARCHAR(100) NOT NULL,
Drop column cuit,
Alter column direccion VARCHAR(50) NULL);
Figura 1.
Estructura Básica
La estructura básica de una consulta SQL tiene el siguiente formato:
SELECT lista_de_atributos
FROM lista_de_tablas
WHERE predicado
Donde la lista_de_atributos indica los nombres de los atributos que serán presentados
en el resultado. Estos atributos deben estar contenidos en las tablas indicadas en la
consulta. Lista_de_tablas indica las tablas de la BD necesarias para resolver la
consulta; sobre las tablas indicadas en la lista se realiza un producto cartesiano. Por
último, predicado indica que condición deben cumplir las tuplas de las tablas para
estar en el resultado final de la consulta.
Ejemplo 1: presentar todos los alumnos que figuran en la tabla Alumnos
SELECT nombre FROM alumnos
Ejemplo 2: presentar todos los datos de los alumnos que figuran en la tabla alumnos.
SELECT idalumno, nombre, dni, idlocalidad, idcarrera FROM alumnos
SQL presenta un operador que permite reemplazar la escritura literal de todos los
atributos de la tabla. Este operador es el * , su aparición indica que todos los atributos
de las tablas definidas en el FROM, serán presentados en el resultado de la consulta.
El ejemplo anterior puede definirse como:
SELECT * FROM alumnos
Ambas soluciones del ejemplo 2 retornan la tabla Alumnos tal y como se presenta en
la figura 1.
Ejemplo 3: presentar todos los alumnos que cursen la carrera cuyo código es 2.
SELECT nombre FROM alumnos WHERE idcarrera = 2
En este caso es necesario utilizar la condición para filtrar en el resultado las tuplas
deseadas.
Ejemplo 4: presentar todos los alumnos que cursen la carrera cuyo código es 2 y vivan
en la localidad con código 1.
SELECT nombre
FROM alumnos
WHERE idcarrera = 2 AND idlocalidad = 1
En este caso es necesario utilizar la condición para filtrar en el resultado las tuplas
deseadas.
Ejemplo 6: mostrar todos los códigos de materias que estén en la tabla Inscripciones
que tengan al menos a un alumno aprobado.
SELECT idmateria FROM inscripciones WHERE resultado > 3
La Tabla temporal obtenida como resultado de la consulta es:
Se puede notar que el código 2 aparece varias veces en el resultado. Esto significa
que más de un alumno ha aprobado la materia cuyo código es 2. En determinadas
circunstancias puede no ser necesario que el mismo resultado aparezca varias veces.
Para eliminar tuplas repetidas se debe utilizar la cláusula DISTINCT.
SELECT DISTINCT idmateria
FROM inscripciones
WHERE resultado > 3
SQL define, además, el operador ALL. Este operador muestra todas las tuplas, aún las
repetidas. En caso de no poner explícitamente el operador DISTINCT, SQL asume el
operador ALL, por este motivo en general nunca se explicita.
Ejemplo 7: presentar todas las carreras que tiene entre 4 y 6 años de duración.
SELECT nombre
FROM carreras
WHERE duracion_años >= 4 AND duracion_años <= 6
Además, es posible realizar la misma consulta utilizando el operador BETWEEN. La
consulta anterior puede expresarse como:
SELECT nombre
FROM carreras
WHERE duracion_años BETWEEN 4 and 6
Los atributos utilizados en el SELECT de una consulta SQL pueden tener asociados
operaciones válidas para sus dominios.
Así, por ejemplo sería válida una consulta que devuelva el salario de un empleado
menos un 10% de retención.
SELECT nombre_empleado, salario * 0.9
FROM empleados
WHERE ocupacion = “Gerente”
Esta consulta devuelve el nombre de cada gerente y el valor correspondiente al 90 %
de su salario.
Sobre los atributos definidos en un SELECT se pueden realizar cualquiera de las
operaciones básicas definidas para su domino. Cada DBMS en particular define su
mapa de operaciones.
Hasta el momento, se presentaron consultas que solamente involucraron una tabla del
modelo de datos. Para realizar un producto cartesiano, basta con poner en la cláusula
FROM dos o más tablas.
Ejemplo 8: presentar el nombre de todos los alumnos y la carrera que cursa:
SELECT alumnos.nombre, carreras.nombre
FROM alumnos, carreras
WHERE alumnos.idcarrera = carreras.idcarrera
El resultado de la consulta se presenta en la siguiente tabla de resultados:
Operadores de string
Una de las características interesantes y que dotan a SQL de gran potencia en la
generación de consultas que relacionan Spring, resulta del uso del operador de
comparación LIKE.
Cuando una cadena se compara por igualdad (=) el resultado será verdadero si ambas
cadenas son iguales, falso en caso contrario.
Suponga que se desea saber el DNI y la localidad donde nació un alumno, cuando lo
único que se recuerda del alumno es que su nombre comienza con P. Si se definiera
al condición (nombre = “P”) no retornaría ninguna tupla, dado que no hay nombre
alguno de alumno que sea solamente P.
Dicha consulta puede resolverse de la siguiente forma:
SELECT nombre, idlocalidad, dni
FROM alumnos
WHERE nombre LIKE “P%”
El resultado obtenido se muestra en la siguiente tabla.
Ejemplo 12: presentar el nombre de los alumnos que tengan DNI que comience con 23
millones.
SELECT nombre
FROM alumnos
WHERE dni LIKE “23_ _ _ _ _ _“
Se puede notar que el atributo DNI se compara contra una cadena que comienza con
23. Luego se solicitan que aparezcan exactamente 6 caracteres más, sin importar
cuales sean.
En algunas situaciones es necesario presentar la tabla temporal que resuelve la
consulta ordenada por algún criterio. La cláusula ORDER BY permite ordenar las
tuplas resultantes por el atributo indicado.
Ejemplo 13: presentar los nombres de todas las materias y el año de curso, para la
carrera informática, ordenados por año de curso.
SELECT m.nombre, m.año_curso
FROM materias m, carreras c
WHERE c.nombre = “Informática” AND
m.idcarrera = c.idcarrera
ORDER BY año_curso
El resultado obtenido es el siguiente:
Por defecto la cláusula ORDER BY ordena las tuplas de menor a mayor, es decir en
orden creciente. Si se desea obtener el resultado ordenado de mayor a menor, hay
que utilizar el operador DESC.
Ejemplo 14: presentar los nombres de todas las materias y el año de curso, para la
carrera informática, ordenados por año de curso de mayor al menor.
SELECT m.nombre, m.año_curso
FROM materias m, carreras c
WHERE c.nombre="Informática" AND
m.idcarrera = c.idcarrera
ORDER BY año_curso DESC
• MIN: retorna como resultado el valor más pequeño dentro del conjunto de tuplas para
el atributo indicado
• SUM: retorna como resultado la suma del valor del atributo indicado para todas las
tuplas del conjunto.
Ejemplo 16: Retornar el nombre del alumno que aparece primero en una lista
alfabética.
SELECT MIN(nombre)
FROM alumnos
Este ejemplo toma como entrada todas las tuplas de alumnos. Para el atributo nombre
chequea el menor en orden alfabético y ese dato se presenta en el resultado.
Ejemplo 17: Retornar la máxima nota de alguna materia durante 2008.
SELECT MAX( resultado )
FROM inscripciones
WHERE año=2008
Aquí de la tabla inscripciones se filtran las tuplas correspondientes a 2008. Sobre ese
subconjunto se obtiene la mayor nota obtenida y se muestra como resultado. Si
hubiera varias tuplas con la misma nota esto no afecta la respuesta.
Ejemplo 18: Informar cuantos alumnos aprobaron el final de programación
SELECT COUNT(*)
FROM materias m, inscripciones i
WHERE i.idmateria=m.idmateria AND
m.nombre = “Programación” AND i.resultado > 3
En este ejemplo es necesario primero realizar un producto cartesiano entre las tablas
materias e inscripciones. En la primera se tiene definido el nombre de la materia, en la
segunda los resultados. Se filtran las tuplas con sentido del producto cartesiano,
aquellas que corresponden a Programación y que estén aprobadas. Luego la función
de agregación COUNT calcula cuantas tuplas hay en ese conjunto.
Ejemplo 19: informar cuantos alumnos aprobaron al menos un final durante 2008.
SELECT COUNT(*)
FROM inscripciones
WHERE resultado > 3 AND año = 2008
Esta consulta informa la cantidad de finales aprobados durante el 2008, sin embargo
no informa cuantos alumnos fueron los que aprobaron.
Suponga que un alumno aprobó 3 finales, entonces dicho alumno es contabilizado 3
veces, por lo tanto esta consulta no es una solución al ejercicio.
SELECT COUNT (DISTINCT *)
FROM inscripciones
GROUP BY c.nombre
HAVING count(*) > 20
Se puede observar que dentro de la cláusula HAVING es posible utilizar, nuevamente,
una función de agregación. En el HAVING se controla la validez de un grupo de tuplas,
por lo tanto es posible utilizar una función de agregación. En este ejemplo la función
de agregación retorna un valor entero, por lo que es posible mediante un operador
compararlo contra un valor literal (20), el resultado será un valor booleano Verdadero o
Falso. Si se da el primer caso el grupo se presenta en el resultado final.
Ejemplo 23: presentar para cada alumno el total de veces que rindió, siempre que el
promedio de sus notas supere siete.
SELECT a.nombre, COUNT(i.idmateria)
FROM alumnos a, inscripciones i
WHERE a.idalumno = i.idalumno
GROUP BY a.nombre
HAVING AVG(i.resultado) > 7
• >ALL, significa mayor que todos. El resultado será verdadero si el elemento simple
resulta mayor que todos los elementos del conjunto.
• <= SOME, significa menor o igual que alguno. El resultado será verdadero si el
elemento simple resulta menor o igual que alguno de los elementos del conjunto.
Para definir algunos ejemplos adicionales se agrega al modelo original las siguientes
tablas
DOCENTES = ( iddocente, nombre, sueldo, idcarrera)
DOCENTESMATERIAS=(iddocentemateria, iddocente, idmateria, añodictado )
Que representa a los docentes, los cuales solamente pueden ser docentes de una
carrera, y las materias que dictan año por año.
Ejemplo 26: mostrar aquellos docentes que cobren un sueldo superior a algún docente
de la carrera de Quimica.
SELECT nombre
FROM docentes
WHERE sueldo >SOME ( SELECT sueldo
FROM docentes d, carreras c
WHERE d.idcarrera = c.idcarrera AND
c.nombre= “Quimica”)
Ejemplo 27: Mostrar todos los docentes con sus salarios, excepto el docente que
cobre mayor sueldo.
SELECT nombre, sueldo
FROM docentes
WHERE sueldo < SOME ( SELECT sueldo
FROM docentes )
Otra forma de resolver
SELECT nombre, sueldo
FROM docentes
WHERE sueldo < > ( SELECT MAX( sueldo )
FROM docentes )
Cláusula Exists
La cláusula EXISTS se utiliza para comprobar si una subconsulta generó o no alguna
tupla como respuesta. El resultado de la cláusula EXISTS es verdadero si la
subconsulta tiene al menos una tupla, y falso en caso contrario. No es importante para
la subconsulta el o los atributos proyectados, debido a que solamente se chequea la
existencia o no de tuplas.
Ejemplo 28: Mostrar el nombre de los alumnos que hayan aprobado algún final durante
2007.
SELECT nombre
FROM alumnos
WHERE EXISTS ( SELECT *
FROM inscripciones
WHERE alumnos.idalumno = inscripciones.idalumno
AND resultado > 3 )
En el tabla temporal que resuelve esta consulta estará contenido el nombre de un
alumno siempre y cuando exista alguna tupla en la subconsulta. Para que la
subconsulta tenga una tupla es necesario encontrar al menos una inscripción para ese
alumno que resulte aprobada.
Ejemplo 29: mostrar aquellos alumnos que no se inscribieron en materia alguna
SELECT a.nombre
FROM alumnos a
WHERE NOT EXISTS ( SELECT *
FROM inscripciones i
WHERE a.idalumno = i.idalumno)
La subconsulta planteada devuelve para un alumno específico todas aquellas tuplas
de inscripciones que le correspondan. Sino devolviera alguna inscripción, la cláusula
NOT EXISTS en la consulta principal resulta verdadera, y por lo tanto el alumno se
presenta en la tabla resultado.
Suponga que las tablas ALUMNOS, MATERIAS, CARRERAS e INSCRIPCIONES
tiene los datos presentados en la figura 2.
Figura 2.
Operaciones con Valores Nulos
En SQL se debe tener especial cuidado cuando un atributo puede contener valores
nulos. En general, cuando se resuelve un algoritmo y el programador debe preguntar
si una variable tiene valor nulo genera una expresión del tipo:
Variable = ‘’
Al utilizar esta expresión, comillas sin ningún carácter en su interior se asume valor
nulo. Sin embargo este tipo de expresiones no tienen un comportamiento similar
cuando se trata de consultas SQL. Cuando un dominio de un atributo puede contener
valores nulos no puede tratarse de esta forma. Los dominios con posibles valores
nulos incorporan al conjunto de valores posibles el valor NULL. Este valor se almacena
por defecto si el usuario no define otro. Entonces, una consulta que pregunta por un
string nulo (‘’) no una respuesta satisfactoria. Para estas situaciones se define un
nuevo operador IS NULL o su negación IS NOT NULL.
Ejemplo 30: presentar todos los alumnos que no tengan definida una localidad de
procedencia.
SELECT a.nombre
FROM alumnos a
WHERE idlocalidad IS NULL
Productos naturales
En el capítulo anterior se presentó al producto natural como una operación adicional
del AR que permite resolver de una forma más eficiente el producto cartesiano. Hasta
el momento, en SQL se presentó al producto cartesiano como única opción para ligar
tablas.
Por las mismas cuestiones de performance planteadas en el capítulo 14 es necesario
que SQL presente una alternativa al producto cartesiano, el producto natural. Las
sentencias disponibles al efecto son: INNER JOIN, LEFT JOIN, RIGTH JOIN, FULL
JOIN. A continuación se detallan y muestran ejemplos de cada una de ellas.
Para realizar un producto natural como fue definido en el capítulo 14, debe utilizarse la
cláusula INNER JOIN.
Ejemplo 30.1: presentar todos los alumnos y su localidad de procedencia.
SELECT a.nombre, l.nombre
FROM alumnos a
INNER JOIN localidades l ON a.idlocalidad = l.idlocalidad
Nótese que en la definición del producto natural se realiza en la cláusula FROM
indicando las tablas involucradas en el producto, y luego de la sentencia ON la
condición que debe cumplirse.
El ejemplo 9 puede resolverse, ahora, de la siguiente forma
SELECT a.nombre, c.nombre, l.nombre
FROM alumnos a
INNER JOIN carreras c ON (a.idcarrera = c.idcarrera )
INNER JOIN localidades l ON (a.idlocalidad = l.idlocalidad)
Los otros productos tienen similar performance, pero su comportamiento es diferente.
Mientras que el INNER JOIN realiza un producto natural clásico, reuniendo las tuplas
de las relaciones que tienen sentido, tanto LEFT como RIGTH y FULL operan con
algunas diferencias.
Suponer:
Tabla1 LEFT JOIN Tabla2
En primera instancia se reúne cada tupla de la tabla 1 con su correspondiente tupla en
la tabla2, similar al INNER JOIN. Luego, si alguna tupla de la tabla 1 no se reúne con
una tupla de la tabla 2, igualmente aparece en el resultado, con los atributos de la
tabla 2 con valor nulo.
Ejemplo 31: presentar cada carrera con sus materias.
SELECT c.nombre, m.nombre
FROM carreras c
LEFT JOIN materias m ON (m.idcarrera = c.idcarrera)
Creación de Índice
La creación de un índice se hace a través de una sentencia CREATE INDEX, que
permite nombrar al índice. Supongamos que ya se tiene una tabla definida y las
consultas de búsqueda son muy lentas. Los índices pueden mejorar en gran medida el
rendimiento del sistema creando INDEX en la columna más utilizada en la cláusula
WHERE.
CREATE INDEX index_name
ON table_name (column_names)
Se puede agregar también un índice a una tabla existente con la siguiente sentencia:
ALTER TABLE name_tabla ADD INDEX(name);
Eliminación de Índice
La instrucción DROP INDEX seguida del nombre del índice permite eliminar el índice
en cuestión.
DROP INDEX index_id ON table_name
También:
ALTER TABLE table_name DROP INDEX index_name
Operadores de comparación
Los operadores de comparación que se pueden utilizar en la cláusula WHERE son:
Operador Significado
> Mayor que
< Menor que
>= Mayor igual que
<= Menor igual que
= Igual
<> Distinto
!= Distinto
Operadores lógicos
Operador Significado
Devuelve verdadero si las expresiones a su izquierda y
AND derecha son ambas verdaderas.
Devuelve verdadero si cualquiera de las dos expresiones
OR a izquierda y derecha del OR, son verdaderas.
Invierte la lógica de la expresión que esta a su derecha. Si
NOT era verdadera, mediante NOT pasa a ser falso.
Funciones para redondear el número de decimales
Función Descripción
ROUND(n,decimales) Redondea el número al siguiente
número con el número de decimales
indicado más cercano.
ROUND(8.239,2) devuelve 8.24
TRUNC(n,decimales) Los decimales del número se cortan
para que sólo aparezca en número de
decimales indicado.
Bibliografía:
Bertone, Rafael; Thomas, Pablo. Introducción a las bases de datos. Fundamentos y diseño. 1a.
Ed. Prentice Hall - Pearson Education, 2011.
IES Luis Vélez de Guevara. Departamento de Informática. Gestión de bases de datos v1.0, 2019