BD t08 SQL DML
BD t08 SQL DML
Relacionales
Tema 8. SQL: Manipulación de
Datos (DML)
Tema 8. SQL: DML
1
Objetivos
Aprender la sintaxis de la sentencia SELECT del SQL con el
fin de escribir sentencias de consulta y de modificación de
datos ya almacenados en una base de datos relacional
DML: Data Manipulation Language del SQL
Diferenciar entre el lenguaje ANSI SQL y los dialectos SQL
implementados por sistemas de bases de datos comerciales
Entender el modelo de ejecución de las sentencias SQL
Conocer buenas prácticas de programación de sentencias
SELECT
Tema 8. SQL: DML
2
Bibliografía
[CB 2015] Connolly, T.M.; Begg C.E.: Database
Systems: A Practical Approach to Design,
Implementation, and Management, 6th Edition.
Pearson. (Capítulos 6 y 7)
[EN 2016] Elmasri, R.; Navathe, S.B.: Fundamentals of
Contenidos
8.1 Consulta: recuperación o selección de datos
Running Example. Presentación del esquema y datos
utilizados en los ejemplos
Sentencia SELECT del lenguaje estándar ANSI SQL
◼ Con indicaciones acerca del lenguaje Oracle SQL
Ejemplos resueltos
8.2 Buenas prácticas de programación
8.3 Modificación de datos
Introducción, actualización y borrado de datos
Anexo: Estructura el lenguaje Oracle SQL
8.1 Consulta
4
EMPLEADO
nombre apellido nss dni fechanacim ciudad est_civil salario nssjefe dep
DEPARTAMENTO
nombre coddep nssdire
FAMILIAR
nssemp numero nombre fechanacim parentesco
* Código y nombre del departamento dirigido por el empleado con NSS 111
SELECT coddep, nombre
FROM departamento
WHERE nssdire = 111;
* Nombres y apellidos de los empleados cuyo estado civil no sea ‘soltero’
SELECT nombre, apellido
FROM empleado
WHERE est_civil <> 'S';
* Nombres de los familiares que tienen un parentesco distinto a ‘HIJO’
SELECT nombre
FROM familiar
WHERE NOT (parentesco = 'HIJO’ );
* NSS y nombre de empleados que cobran entre 900€ y 1200€
SELECT nombre, apellido
FROM empleado Buenas prácticas de redacción SQL
WHERE salario BETWEEN 900 AND 1200; Palabras reservadas en MAYÚSCULA
Atributos y tablas en minúscula
8. SQL: DML. 8.1 Consulta
SELECT. Aritmética
17
Operaciones aritméticas
Aplicación de operadores aritméticos ( +, -, *, / ) sobre valores
numéricos
Se muestra el resultado de la operación, pero no se modifica
ningún dato almacenado en la tabla
* ¿Cómo quedarían los salarios de los empleados del departamento D3 tras un
aumento del 10% ? apellido nombre 1.1*salario
SELECT apellido, nombre, 1.1*salario CALAVERA RIGOBERTA 990
FROM empleado
WHERE dep = 'D3'; FABERGÉ CASIANA 1012
SELECT. NULL
21
NULL
No es un valor, sino una marca que indica desconocimiento o
ausencia de información
Comparar NULL usando =, <>, >, >=, <, <=, con cualquier cosa
siempre da FALSE o UNKNOWN
◼ NULL es distinto a cualquier otra cosa, incluso a otro NULL
SELECT. NULL
22
EDITORIAL
nombre calle numero cod_post ciudad
Espasa Josefa Valcárcel 42 28027 Madrid
Santillana Avenida de los Artesanos 6 28760 Tres Cantos, Madrid
Edebé Paseo San Juan Bosco 62 08017 Barcelona
LIBRO
ISBN titulo año edicion num_copias editorial
9788408217251 Un científico en el supermercado 2019 1 14 Espasa
9788491223542 Malamandra 2019 5 5 Santillana
9788468315775 Mentira 2015 4 12 Edebé
9788467009101 Divina comedia 2010 50 25 Espasa
9788468319612 La nueva vida del señor Rutin 2014 23 16 Edebé
8. SQL: DML. 8.1 Consulta
* Todos los datos del empleado ‘SOLANO’ junto con los datos de
su departamento
Si lo hacemos “a mano”, buscamos en la tabla EMPLEADO la
fila que tiene el valor ‘SOLANO’ en la columna “apellido”
Esa fila contiene los datos de dicho empleado. Pero no
tenemos todos los datos del departamento, sino sólo su
código ‘D1’ (columna “dep”)
Los datos de los departamentos están en DEPARTAMENTO
GUMERSINDA MIMOS 543 45F 1980 C/QUINTO, 5 PINOSO 850 NULL NULL
FAMILIAR
DEPARTAMENTO
nssemp numero nombre añonacim parentesco
nombre coddep nssdire
123 1 JONÁS 1992 HIJO
321 2 RÓMULA 1923 ABUELA INVESTIGACION D2 222
222 1 ELEUTERIO 2002 HIJO ADMINISTRACION D1 111
321 1 RENATA 2002 HIJA
1936
PERSONAL D3 333
111 2 JULIANA MADRE
321 3 TORCUATA 1938 ABUELA TRAINING D4 NULL
111 3 SINFOROSA 1947 ABUELA
8. SQL: DML. 8.1 Consulta
* Para todo empleado, mostrar sus datos junto con los datos de su
departamento
Es necesario combinar cada fila de la tabla EMPLEADO con
aquella fila de DEPARTAMENTO cuyo valor en “coddep” sea
igual al valor de “dep”
Se consigue aplicando la operación REUNIÓN (JOIN) a las
dos tablas
SELECT *
FROM empleado JOIN departamento
ON dep = coddep;
8. SQL: DML. 8.1 Consulta
EMPLEADO DEPARTAMENTO
nombre apellido nss ... dep nombre coddep nssdire
JONÁS SOLANO 123 … D1 INVESTIGACION D2 222
RIGOBERTA CALAVERA 321 … D3 ADMINISTRACION D1 111
EUSEBIO MULETAS 222 … D2 PERSONAL D3 333
MACARENO SOSO 111 … D1 TRAINING D4 NULL
CASIANA FABERGÉ 333 … D3
FILOMENA RASCAS 234 … D1 SELECT *
GUMERSINDA MIMOS 543 … NULL FROM empleado JOIN departamento
ON dep=coddep;
nombre apellido nss ... dep nombre coddep nssdire
Importante: En el resultado del JOIN no está la empleada GUMERSINDA MIMOS , ¿Por qué?
Tampoco aparece el departamento TRAINING. ¿Por qué?
8. SQL: DML. 8.1 Consulta
dos tablas:
SELECT *
FROM empleado JOIN familiar
ON nss = nssemp;
8. SQL: DML. 8.1 Consulta
Importante: En el resultado del JOIN faltan varios empleados (CASIANA por ejemplo) ¿Por qué?
¿Y faltan familiares? ¿Por qué?
8. SQL: DML. 8.1 Consulta
SELECT lista_columnas_de_R_y_S
FROM R JOIN S
ON condición_de_reunión;
Sinónimo: INNER JOIN (reunión interna)
8. SQL: DML. 8.1 Consulta
EJEMPLAR
PRESTAMO
ISBN numero estante libro ejemplar socio fecha …
9788408217251 1 H4
9788408217251 1 S02 14/09/2019
9788408217251 2 H4
9788408217251 2 S03 14/09/2019
9788408217251 3 H5
9788408217251 3 S06 15/10/2019
9788467009101 1 M2
9788467009101 1 S04 09/09/2019
9788467009101 2 M2
9788467009101 1 S04 19/10/2019
9788468319612 1 S1
9788408217251 3 S02 20/10/2019
9788491223542 1 S2
9788491223542 2 S03 09/10/2019
9788491223542 2 A3
9788491223542 2 S01 18/11/2019
9788468315775 1 S7
SELECT libro, numero, estante, fecha
FROM prestamo JOIN ejemplar
ON libro = ISBN Resultado de la consulta
libro numero estante fecha
AND ejemplar = numero
WHERE socio = 'S03' ; 9788408217251 2 H4 14/09/2019
9788491223542 2 A3 09/10/2019
8. SQL: DML. 8.1 Consulta
SELECT. Calificación
39
SELECT. Calificación
40
SELECT. Calificación
41
SELECT. Calificación
42
SELECT. Calificación
43
EMPLEADO
nombre apellido nss dni añonacim direccion ciudad salario nssjefe dep
e→ JONÁS SOLANO 123 11A 1945 C/PEZ, 10 MURCIA 1100 111 D1
e.nombre j.nombre
SELECT e.nombre, j.nombre JONÁS MACARENO
RIGOBERTA CASIANA
FROM empleado e JOIN empleado j EUSEBIO JONÁS
ON e.nssjefe = j.nss; CASIANA JONÁS
FILOMENA MACARENO
8. SQL: DML. 8.1 Consulta
SELECT parentesco, apellido, nssdire El 1er JOIN obtiene una fila con los datos
FROM familiar JOIN empleado de cada familiar y los de su empleado
ON nssemp = nss El 2º JOIN obtiene una fila para cada
JOIN departamento familiar con todos sus datos, los de su
ON dep = coddep empleado y los del departamento al
que pertenece el empleado
WHERE parentesco IN ('ABUELA', 'MADRE');
El WHERE selecciona sólo aquellas
filas correspondientes a familiares
con parentesco ABUELA o MADRE
8. SQL: DML. 8.1 Consulta
SELECT lista_columnas_de_R_y_S
FROM R, S
WHERE condición_de_reunión;
Selección incondicional
No incluir WHERE equivale a una condición TRUE
para todas las filas
Si en la cláusula FROM aparece sólo una tabla, se obtienen
todas las filas de dicha tabla
* Seleccionar los nss de todxs lxs empleadxs
SELECT nss
FROM empleado;
Si el FROM incluye más de una tabla, se obtiene el producto
cartesiano entre dichas tablas
Se combina cada fila de una tabla con todas las filas de la otra
* Obtener todas las combinaciones de los datos de empleadxs con los de
departamentos
SELECT * ¿Qué era el
PRODUCTO
FROM empleado, departamento; CARTESIANO?
8. SQL: DML. 8.1 Consulta
JONÁS SOLANO 123 11A 10/10/1945 C/PEZ, 10 MURCIA 1100 111 D1 ADMINISTRACION D1 111
RIGOBERTA CALAVERA 321 21C 12/11/1974 C/BOJ, 2 YECLA 900 333 D3 ADMINISTRACION D1 111
EUSEBIO MULETAS 222 22B 01/01/1969 C/RIF, 6 TOTANA 2100 123 D2 ADMINISTRACION D1 111
MACARENO SOSO 111 23D 06/04/1944 C/MAR, 4 JUMILLA 1100 NULL D1 ADMINISTRACION D1 111
CASIANA FABERGÉ 333 33B 15/06/1943 C/SOL, 8 MURCIA 920 123 D3 ADMINISTRACION D1 111
FILOMENA RASCAS 234 34E 18/07/1970 C/NUEZ, 3 MURCIA 1100 111 D1 ADMINISTRACION D1 111
GUMERSINDA MIMOS 543 45F 10/02/1980 C/QUINTO, 5 PINOSO 850 NULL NULL ADMINISTRACION D1 111
JONÁS SOLANO 123 11A 10/10/1945 C/PEZ, 10 MURCIA 1100 111 D1 INVESTIGACION D2 222
RIGOBERTA CALAVERA 321 21C 12/11/1974 C/BOJ, 2 YECLA 900 333 D3 INVESTIGACION D2 222
EUSEBIO MULETAS 222 22B 01/01/1969 C/RIF, 6 TOTANA 2100 123 D2 INVESTIGACION D2 222
MACARENO SOSO 111 23D 06/04/1944 C/MAR, 4 JUMILLA 1100 NULL D1 INVESTIGACION D2 222
CASIANA FABERGÉ 333 33B 15/06/1943 C/SOL, 8 MURCIA 920 123 D3 INVESTIGACION D2 222
FILOMENA RASCAS 234 34E 18/07/1970 C/NUEZ, 3 MURCIA 1100 111 D1 INVESTIGACION D2 222
GUMERSINDA MIMOS 543 45F 10/02/1980 C/QUINTO, 5 PINOSO 850 NULL NULL INVESTIGACION D2 222
… sigue…
… sigue…
JONÁS SOLANO 123 11A 10/10/1945 C/PEZ, 10 MURCIA 1100 111 D1 PERSONAL D3 333
RIGOBERTA CALAVERA 321 21C 12/11/1974 C/BOJ, 2 YECLA 900 333 D3 PERSONAL D3 333
EUSEBIO MULETAS 222 22B 01/01/1969 C/RIF, 6 TOTANA 2100 123 D2 PERSONAL D3 333
MACARENO SOSO 111 23D 06/04/1944 C/MAR, 4 JUMILLA 1100 NULL D1 PERSONAL D3 333
CASIANA FABERGÉ 333 33B 15/06/1943 C/SOL, 8 MURCIA 920 123 D3 PERSONAL D3 333
FILOMENA RASCAS 234 34E 18/07/1970 C/NUEZ, 3 MURCIA 1100 111 D1 PERSONAL D3 333
GUMERSINDA MIMOS 543 45F 10/02/1980 C/QUINTO, 5 PINOSO 850 NULL NULL PERSONAL D3 333
JONÁS SOLANO 123 11A 10/10/1945 C/PEZ, 10 MURCIA 1100 111 D1 TRAINING D4 NULL
RIGOBERTA CALAVERA 321 21C 12/11/1974 C/BOJ, 2 YECLA 900 333 D3 TRAINING D4 NULL
EUSEBIO MULETAS 222 22B 01/01/1969 C/RIF, 6 TOTANA 2100 123 D2 TRAINING D4 NULL
MACARENO SOSO 111 23D 06/04/1944 C/MAR, 4 JUMILLA 1100 NULL D1 TRAINING D4 NULL
CASIANA FABERGÉ 333 33B 15/06/1943 C/SOL, 8 MURCIA 920 123 D3 TRAINING D4 NULL
FILOMENA RASCAS 234 34E 18/07/1970 C/NUEZ, 3 MURCIA 1100 111 D1 TRAINING D4 NULL
GUMERSINDA MIMOS 543 45F 10/02/1980 C/QUINTO, 5 PINOSO 850 NULL NULL TRAINING D4 NULL
Formato
SELECT ...
FROM R1 NATURAL JOIN R2
WHERE ...
NO necesita condición de reunión
No incluye la cláusula ON condición
El SGBD asume una condición de reunión para cada par
de columnas con igual nombre en una y otra tabla
Y sólo se incluye una de estas columnas en el resultado
Elimina una de las columnas idénticas
Veámoslo con un ejemplo...
8. SQL: DML. 8.1 Consulta
D1 O2 ALBACETE
oficina o JOIN departamento d
ON o.coddep = d.coddep
oficina NATURAL JOIN departamento o.coddep oficina ubicacion d.coddep nombre nssdire
coddep oficina ubicacion nombre nssdire D1 O1 MURCIA D1 ADMINISTRACION 111
D1 O1 MURCIA ADMINISTRACION 111 D3 O1 MADRID D3 PERSONAL 333
D3 O1 MADRID PERSONAL 333 D2 O1 ALICANTE D2 INVESTIGACION 222
D2 O1 ALICANTE INVESTIGACION 222 D1 O3 TOLEDO D1 ADMINISTRACION 111
D1 O3 TOLEDO ADMINISTRACION 111 D3 O2 ALICANTE D3 PERSONAL 333
D3 O2 ALICANTE PERSONAL 333 D1 O2 ALBACETE D1 ADMINISTRACION 111
D1 O2 ALBACETE ADMINISTRACION 111
Columnas idénticas
8. SQL: DML. 8.1 Consulta
Punto de partida:
* Datos de cada empleado y de su departamento
SELECT *
FROM (empleado e JOIN departamento d
ON dep = coddep);
Es una reunión “interna”
En el resultado no aparecen los empleados sin departamento, ni los
departamentos a los que no pertenece ningún empleado
◼ No están la empleada 543 ni el departamento D4
e.nombre apellido nss ... dep d.nombre coddep nssdire
JONÁS SOLANO 123 … D1 ADMINISTRACION D1 111
RIGOBERTA CALAVERA 321 … D3 PERSONAL D3 333
EUSEBIO MULETAS 222 … D2 INVESTIGACION D2 222
MACARENO SOSO 111 … D1 ADMINISTRACION D1 111
CASIANA FABERGÉ 333 … D3 PERSONAL D3 333
FILOMENA RASCAS 234 … D1 ADMINISTRACION D1 111
8. SQL: DML. 8.1 Consulta
Función COALESCE()
Permite mostrar el valor que se desee en cierta columna del
resultado de una consulta, en lugar de un NULL
Suele usarse con dos parámetros: COALESCE(columna, valor)
◼ “columna” corresponde a una columna de alguna de las tablas del FROM
◼ “valor” debe ser del mismo tipo de datos que la “columna” (1er parámetro)
SELECT nombre, apellido, COALESCE(dep, 'SIN DEPARTAMENTO')
FROM empleado;
Muestra para cada empleado, su nombre y apellido, y el código del
departamento al que pertenece, pero para aquel empleado con NULL en la
columna “dep” (que es CHAR), mostraría la cadena ‘SIN DEPARTAMENTO’
SELECT nss, nombre, COALESCE(nssjefe, 0)
FROM empleado;
Muestra para cada empleado, su nss, nombre y el nss de su jefe, pero para
cada empleado con NULL en la columna “nssjefe” (que es NUMBER), mostraría
un cero
8. SQL: DML. 8.1 Consulta
Función COALESCE()
Si se desea mostrar una cadena de caracteres cuando hay
NULL en una columna de tipo NUMBER, hay que pasarle el
primer argumento convertido a caracteres, usando la función
TO_CHAR de Oracle SQL: Da error “INVALID NUMBER”,
porque “nssjefe” es
SELECT nss, nombre, COALESCE(nssjefe, 'SIN JEFE’) NUMBER y el 2º argumento
FROM empleado; es CHAR
SELECT nss, nombre, COALESCE(TO_CHAR(nssjefe), 'SIN JEFE’)
FROM empleado;
Se suele usar con las reuniones externas:
* Nombre de cada empleado y de su departamento; deben aparecer todos los
empleados; para los que no tienen departamento, mostrar ‘SIN DEPARTAMENTO’
SELECT e.nombre, COALESCE(d.nombre, 'SIN DEPARTAMENTO')
FROM (empleado e LEFT JOIN departamento d
ON dep=coddep);
8. SQL: DML. 8.1 Consulta
Operación UNION
La unión entre dos tablas obtiene una tabla con todas las
filas de las dos tablas de origen (y sin duplicados)
Como el resultado de una SELECT es una tabla, es posible
hacer la UNION entre dos consultas (entre dos SELECT)
* Empleados veteranos (nacidos antes de 1965), o con familiares
abuelos a su cargo No hace falta que las columnas se
(SELECT nss llamen igual, pero sí deben tener un
FROM empleado tipo de datos compatible
WHERE fechanacim < TO_DATE('01/01/1965', 'dd/mm/yyyy'))
nss
UNION nss nssemp
(SELECT nssemp 123 321
111
UNION =
FROM familiar 111 321
123
Operación INTERSECT
La intersección entre dos tablas obtiene una tabla con las
filas que están a la vez en las dos tablas de origen (y sin
duplicados)
Como el resultado de una SELECT es una tabla, es posible
hacer la INTERSECCIÓN entre dos consultas (entre dos
SELECT)
Operación MINUS
La resta entre dos tablas obtiene una tabla con las filas que
están en la tabla de la izquierda y que no están en la tabla
de la derecha (y sin duplicados)
Como el resultado de una SELECT es una tabla, es posible
hacer la RESTA entre dos consultas (entre dos SELECT)
* Nombres y apellidos de lxs empleadxs cuyo salario es menor que el de todxs los
empleadxs del departamento D3
SELECT nombre, apellido
FROM empleado
WHERE salario < ALL (SELECT salario
FROM empleado
WHERE dep = 'D3' );
8. SQL: DML. 8.1 Consulta
* Nombres y apellidos de los empleados cuyo salario es menor que el de todos los
empleados del departamento D3
SELECT nombre, apellido FROM empleado
WHERE salario < ALL (SELECT salario FROM empleado WHERE dep = 'D3');
salario
Primero se evalúa la
subconsulta 900
920
SELECT. Correlación
82
SELECT. Correlación
83
* Suma de salarios y salario máximo, mínimo y medio de empleados del dep. Investigación
SELECT SUM(salario), MAX(salario), MIN(salario), AVG(salario)
FROM empleado SUM(salario) MAX(salario) MIN(salario) AVG(salario)
WHERE dep IN (SELECT coddep 3300 1100 1100 1100
FROM departamento
WHERE nombre=‘INVESTIGACION’);
También pueden aparecer en cláusula HAVING (*se verá*)
8. SQL: DML. 8.1 Consulta
Función COUNT( )
Cuenta número de filas (usando *) o valores no nulos en una columna
Puede aparecer en la cláusula SELECT
Contar número de filas:
* Número total de empleados de la empresa COUNT(*)
SELECT COUNT(*) 7
FROM empleado;
* ¿Cuántos empleados hay en el departamento de Investigación?
SELECT COUNT(*) COUNT(*)
FROM familiar 3
WHERE nssemp IN (SELECT nss
FROM empleado
WHERE nombre = 'RIGOBERTA' AND apellido = 'CALAVERA’);
8. SQL: DML. 8.1 Consulta
La consulta correcta:
COUNT(DISTINCT salario)
SELECT COUNT(DISTINCT salario)
FROM empleado; OK !! 5
Ejemplo
* ¿Cuántos empleados son jefes de algún otro?
-- Con correlación:
SELECT COUNT(*)
FROM empleado j
WHERE EXISTS (SELECT *
FROM empleado e
WHERE e.nssjefe=j.nss);
-- Sin correlación:
SELECT COUNT(*)
FROM empleado
WHERE nss IN (SELECT nssjefe
FROM empleado);
-- Sin subconsulta (la mejor opción):
SELECT COUNT(DISTINCT nssjefe)
FROM empleado;
8. SQL: DML. 8.1 Consulta
SELECT. Agrupación
94
Cláusula GROUP BY
Para formar grupos de filas dentro de una tabla
Los grupos se forman según el valor de ciertas columnas
◼ Columnas de agrupación
Las filas de cada grupo tendrán el mismo valor en las
columnas de agrupación
Aplicación de funciones agregadas a grupos de filas
* Para cada departamento, obtener su código, cuántos empleados tiene y el salario medio
de los empleados del mismo
dep COUNT(*)
SELECT dep, COUNT(*), AVG(salario) D1 3
FROM empleado D2 1
GROUP BY dep ; una columna de agrupación D3 2
NULL 1
SELECT. Agrupación
95
Cláusula HAVING
Siempre junto a GROUP BY
◼ No tiene sentido que aparezca HAVING si en la SELECT no hay GROUP BY
Condición que deben cumplir los grupos de filas asociados
a cada valor de las columnas de agrupación
Un grupo que no cumple la condición es descartado, es decir,
el grupo completo no es seleccionado para el resultado
* Para cada departamento en el que el salario medio de los empleados sea inferior a 1200
euros, mostrar el nombre del departamento y el código de su director
SELECT nombre, nssdire
FROM departamento
WHERE coddep IN (SELECT dep
FROM empleado
GROUP BY dep
HAVING AVG(salario) < 1200);
8. SQL: DML. 8.1 Consulta
Ejemplos resueltos
104
Ejemplos resueltos
105
Ejemplos resueltos
106
Ejemplos resueltos
107
4. cont.
SELECT e.dni, e.nombre -- Tablas reunidas
FROM (empleado e
JOIN (departamento d
JOIN empleado m
ON d.nssdire = m.nss)
ON e.dep = d.coddep)
WHERE m.nombre = 'MACARENO' AND m.apellido = 'SOSO';
-- Serán los empleados tales que, si se cuenta sus familiares, dicho número coincide
-- con el máximo número de familiares calculado para todos los empleados.
Ejemplos resueltos
109
6. *Empleado (nombre, fechanacim) que más familiares tiene a su cargo, indicando cuántos
tiene (familiares)
-- Necesitamos acceder al número de familiares (el resultado del COUNT(*))
-- Para ello, podemos usar una online view porque una SELECT sólo puede mostrar
columnas de las tablas que aparezcan en el FROM
-- Obsérvese que la online view es igual a la subconsulta del ejercicio 5
3) La online view calcula
SELECT nombre, fechanacim, familiares para cada empleado,
FROM empleado cuántos familiares tiene.
Al estar en el FROM, es
JOIN (SELECT nssemp, COUNT(*) familiares posible sacar sus columnas
FROM familiar como resultado final de la
SELECT
GROUP BY nssemp
HAVING COUNT(*) = (SELECT MAX(COUNT(*))
2) Selecciona empleados tales que su FROM familiar
nº de familiares coincide con el máximo GROUP BY nssemp))
ON nss = nssemp;
1) La consulta anidada obtiene el máximo
nº de familiares que tienen los empleados
8. SQL: DML. 8.1
Ejemplos resueltos
110
6.cont. *Empleado (nombre, fechanacim) que más familiares tiene a su cargo, indicando
cuántos tiene (familiares)
-- Otra forma, algo menos “bonita” y eficiente que la anterior (es mejor usar HAVING)
SELECT nombre, fechanacim, familiares
FROM empleado e, (SELECT nssemp, COUNT(*) familiares
FROM familiar
GROUP BY nssemp) f
WHERE e.nss = f.nssemp
AND familiares = (SELECT MAX(COUNT(*))
FROM familiar
GROUP BY nssemp);
División en SQL
111
SELECT. División
112
SELECT. División
113
SELECT. División
114
SELECT. División
115
SELECT. División
116
SELECT. División
117
SELECT. División
118
SELECT. División
119
SOLUCIÓN 1:
-- Dos correlaciones
SELECT codigo
FROM cliente C
WHERE NOT EXISTS
(SELECT * 1. NO EXISTE una sucursal de Murcia…
FROM sucursal S
WHERE ciudad = ‘MURCIA’
AND NOT EXISTS 3. …en la que NO tenga una cuenta
(SELECT *
FROM cuenta Q
WHERE Q.cliente_cod = C.codigo
2. Esta SELECT saca AND Q.sucursal_cod= S.codigo));
las cuentas del
cliente C en la
sucursal S
8. SQL: DML. 8.1 Consulta
SELECT. División
120
SOLUCIÓN 2:
-- Una correlación (un poquito mejor que la anterior)
SELECT codigo
FROM cliente C
WHERE NOT EXISTS
(SELECT * 1. NO EXISTE una sucursal de Murcia…
FROM sucursal S
WHERE ciudad = ‘MURCIA’ NOT IN en vez de NOT EXISTS
AND S.codigo NOT IN
(SELECT sucursal_cod
FROM cuenta Q 2. …en la que NO tenga una cuenta
WHERE Q.cliente_cod = C.codigo));
La comparación que se hace en el
NOT IN evita la segunda comparación
dentro de la subconsulta
8. SQL: DML. 8.1 Consulta
SELECT. División
121
SOLUCIÓN 3:
-- Restando
SELECT codigo
FROM cliente C
WHERE NOT EXISTS -- clientes tales que la siguiente
-- subconsulta (resta) no obtiene filas
( (SELECT codigo
1. Todas las sucursales de Murcia
FROM sucursal
WHERE ciudad = 'MURCIA')
MINUS -- EXCEPT en ANSI SQL 2. Sucursales donde el cliente C
(SELECT sucursal_cod tiene una cuenta
FROM cuenta Q
WHERE Q.cliente_cod = C.codigo) );
Si las sucursales de Murcia en las que un cliente tiene cuenta son las mismas que todas las
sucursales de Murcia, la subconsulta queda vacía y el cliente es seleccionado para el resultado
8. SQL: DML. 8.1 Consulta
SELECT. División
122
SOLUCIÓN 4:
-- Contando (es un "atajo" algo chapucilla)
2. Clientes con cuenta en
SELECT codigo alguna sucursal de Murcia
FROM cliente C JOIN cuenta Q
ON C.codigo = Q.cliente_cod
1. Códigos de las
WHERE Q.sucursal_cod IN (SELECT codigo sucursales de Murcia
FROM sucursal
3. Cuenta las
WHERE ciudad = 'MURCIA') sucursales de
GROUP BY codigo Murcia
HAVING COUNT(DISTINCT(Q.sucursal_cod))=(SELECT COUNT(*)
FROM sucursal
4. Cuenta las sucursales diferentes de Murcia
en las que cada cliente tiene cuentas WHERE ciudad='MURCIA');
Si el número de sucursales de Murcia en las que un cliente tiene cuenta coincide con el
número total de sucursales de Murcia, entonces el cliente es seleccionado para el resultado
8. SQL: DML. 8.1 Consulta
SELECT. División
123
SOLUCIÓN 4bis:
-- Igual a la anterior, pero con notación JOIN clásica (igual de “chapucilla”)
SELECT codigo
FROM cliente C, cuenta Q
WHERE C.codigo = Q.cliente_cod
AND Q.sucursal_cod IN (SELECT codigo
FROM sucursal
WHERE ciudad = 'MURCIA')
GROUP BY codigo
HAVING COUNT(DISTINCT(Q.sucursal_cod)) = (SELECT COUNT(*)
FROM sucursal
WHERE ciudad='MURCIA');
8. SQL: DML. 8.1 Consulta
SELECT. División
124
B) Esquema PRODUCTORA
PELICULA (codp, titulo, año, genero, guion, director, …)
ACTOR(coda, nombre, nomreal, nacionalidad, fechanacim,…)
ACTUA_EN (actor, film, papel, paga)
Claves ajenas: actor → ACTOR(coda)
film → PELICULA(codp)
Consulta.- Nombre de actores/actrices que participan en
todas las películas dirigidas por el director con código '103'.
Seleccionar nombres de los actores/actrices tales que
NO EXISTE una película dirigida por el director 103
en la que NO hayan participado
8. SQL: DML. 8.1 Consulta
SELECT. División
125
SOLUCIÓN 1:
-- Dos correlaciones
SELECT nombre
FROM actor a
WHERE NOT EXISTS
(SELECT *
FROM pelicula p
WHERE director = '103’
AND NOT EXISTS (SELECT *
FROM actua_en
WHERE actor = a.coda
AND film = p.codp ));
8. SQL: DML. 8.1 Consulta
SELECT. División
126
SOLUCIÓN 2:
-- Una correlación
SELECT nombre
FROM actor a
WHERE NOT EXISTS
(SELECT *
FROM pelicula
WHERE director = '103'
AND codp NOT IN
(SELECT film
FROM actua_en
WHERE actor = a.coda));
8. SQL: DML. 8.1 Consulta
SELECT. División
127
SOLUCIÓN 3:
-- Restando; una correlación
SELECT nombre
FROM actor a
WHERE NOT EXISTS (
(SELECT codp
FROM pelicula
WHERE director = '103’)
MINUS -- EXCEPT en ANSI SQL
(SELECT film
FROM actua_en
WHERE actor = a.coda) );
8. SQL: DML. 8.1 Consulta
SELECT. División
128
SOLUCIÓN 4:
--Contando (atajo algo chapucilla)
SELECT nombre 1. Actores/actrices que
FROM actor a JOIN actua_en c participan en películas
ON a.coda = c.actor del director 103
WHERE c.film IN (SELECT codp
FROM pelicula
WHERE director = '103')
GROUP BY a.coda
HAVING COUNT(DISTINCT(c.film))=(SELECT COUNT(*)
FROM pelicula
3. Cuenta las películas diferentes del
WHERE director = '103');
director 103 en las que participa cada 2. Cuenta las
actor/actriz películas del
director 103
8. SQL: DML. 8.1 Consulta
SELECT. Evaluación
129
Orden de ESCRITURA
SELECT lista columnas o funciones Lista select: lo que desea obtener
FROM lista tablas Tablas necesarias (incluso las reunidas)
WHERE condición para filas Condiciones de selección de filas o reunión
GROUP BY lista columnas agrupación Especificación del agrupamiento de filas
HAVING condición para grupos Condición de selección de grupos de filas
ORDER BY lista columnas ordenación Orden de presentación del resultado
8. SQL: DML. 8.1 Consulta
SELECT. Evaluación
130
Orden de EVALUACIÓN
FROM lista tablas Acceso a tablas, o reunión
WHERE condición para filas Descarta filas que incumplen la condición
GROUP BY lista columnas agrupación Crea grupos de filas
HAVING condición para grupos Descarta los grupos de filas que la incumplen
ORDER BY lista columnas ordenación Ordena las filas del resultado
SELECT lista columnas o funciones Para el conjunto de filas resultado, elige las
columnas indicadas, calcula las funciones y lo
muestra
Diversas formas de especificar una misma consulta
Ejemplo: es posible expresar una consulta utilizando...
◼ Lista de tablas en el FROM y condiciones de reunión en el WHERE, o
◼ Tablas reunidas en la cláusula FROM, o
◼ Consultas anidadas (correlacionadas o no ) y comparación con IN ...
Flexibilidad
8.2 Buenas Prácticas
131
- JOIN
* Nombre y departamento de los empleados jefes de otros que cobran más que él
SELECT nombre, dep SELECT j.nombre, j.dep
FROM empleado j FROM empleado j
WHERE nss IN (SELECT nssjefe JOIN empleado e
FROM empleado e ON j.nss = e.nssjefe
WHERE e.salario > j.salario); WHERE e.salario > j.salario;
8. SQL: DML. 8.2 Buenas prácticas
Rendimiento
147
Orden DELETE
Orden UPDATE
8.3 Modificación de datos
Orden INSERT
Añade una fila completa a una tabla
Incluye nombre de tabla y lista de valores para columnas,
escritos en igual orden al especificado en el CREATE TABLE
INSERT INTO empleado
VALUES ('CEFERINA', 'SALSIPUEDES', 444, '44C',
TO_DATE('30-DIC-92', 'dd-MON-yy'),
'YECLA', 'S', 3700, 'D4', NULL, 0);
INSERT INTO empleado
VALUES ('PRUDENCIO', 'SILENCIO', 456, '45S',
TO_DATE('22/01/1995', 'dd/mm/yyyy'),
'VILLENA', 'P', 2250, 'D4', 444, 0);
INSERT INTO empleado
VALUES ('FERDINANDA', 'FUERTES', 567, '56F',
TO_DATE('12-AGO-88', 'dd-MON-yy'),
'MAZARRÓN', 'C’, 1560, 'D4’, 456, 0);
8.3 Modificación de datos. Orden INSERT
Omisión de valores
151
* Inserción de empleado del que sólo se conoce nombre, apellido, NSS, DNI y dep
INSERT INTO empleado (nombre, apellido, nss, dni, dep)
VALUES ('GILDA', 'ROLLER', 678, '67R', 'D2');
nombre apellido nss dni fechanacim ciudad est_civil salario nssjefe dep cuantos_familiares
…
GILDA ROLLER 678 67R NULL NULL NULL 1000 NULL D2 0
…
8.3 Modificación de datos. Orden INSERT
Control de la integridad
152
INFO_DEP
nombre_dep num_empleados suma_salarios
INFO_DEP puede
ADMINISTRACION 3 3300
contener información
PERSONAL 2 1820
no actualizada
Si se modifican filas o
INVESTIGACION 2 3100
valores en EMPLEADO y/o
TRAINNING 3 7510
en DEPARTAMENTO, esos
Por supuesto, es posible cambios no se reflejarán en
manipular el contenido de la esta tabla INFO_DEP
tabla mediante sentencias SELECT Esta tabla no se actualiza
SELECT nombre_dep, suma_salarios automáticamente
FROM info_dep Si en vez de una tabla se
WHERE num_empleados < 3; definiera una VISTA con “la
misma estructura”, sí
nombre_dep suma_salarios mostraría siempre los datos
PERSONAL 1820 actualizados
INVESTIGACION 3100 Veremos el concepto de
VISTA más adelante
8.3 Modificación de datos. Orden INSERT
* Crear una tabla para almacenar datos de empleados nacidos antes de 1960
CREATE TABLE emp_veterano (nss, nombre, jefe, depto)
AS SELECT nss, nombre||' '||apellido, nssjefe, dep
FROM empleado
WHERE EXTRACT(YEAR FROM fechanacim) < 1960;
EMP_VETERANO
nss nombre jefe depto
111 MACARENO SOSO NULL D1
123 JONÁS SOLANO 111 D1
333 CASIANA FABERGÉ 123 D3
8.3 Modificación de datos
Eliminación de filas
156
Orden DELETE
Elimina filas completas de una tabla (sólo una en el FROM)
Cláusula WHERE para seleccionar las filas que se desea
eliminar DELETE FROM empleado
WHERE apellido = 'ROLLER';
DELETE FROM departamento
WHERE nssdire = 111;
1º se accede a la tabla
DELETE FROM empleado 2º se ejecuta el WHERE
WHERE dep IN 3º se ejecuta el borrado
(SELECT coddep
FROM departamento
WHERE nombre = 'INVESTIGACION');
Propagación de eliminaciones vía claves ajenas
Según las acciones de mantenimiento de la Integridad
Referencial (ON DELETE…) en los CREATE TABLE
8.3 Modificación de datos. Orden DELETE
Eliminación de filas
157
Si no hay WHERE, se
eliminan TODAS las filas:
la tabla permanece,
pero queda vacía
DELETE
FROM empleado;
8.3 Modificación de datos
Actualización de Datos
158
Orden UPDATE
Modifica valores de columnas en una o más filas de una tabla
* Cambiar el nombre del departamento D4 por ‘FORMACION’ y asignarle un director
UPDATE departamento 1º se accede a la tabla
SET nombre = 'FORMACION', nssdire = 444 2º se ejecuta el WHERE
WHERE coddep = 'D4'; 3º se ejecuta el SET
Cláusula WHERE para seleccionar las filas que actualizar
◼ Si no hay WHERE, se aplica la modificación a TODAS las filas
Cláusula SET con las columnas que modificar y los nuevos
valores
NULL o DEFAULT como nuevo valor de una columna
UPDATE empleado SET nssjefe = NULL
WHERE apellido = 'FUERTES'; Estos ejemplos de UPDATE
sólo modifican una fila
UPDATE empleado SET salario = DEFAULT de la tabla, pues sólo una
WHERE nss = 333; de ellas hace TRUE lo
indicado en el WHERE
8.3 Modificación de datos. Orden UPDATE