You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Ficheros y Bases <strong>de</strong> Datos<br />
<strong>Tema</strong> 3<br />
<strong>Lenguaje</strong> <strong>SQL</strong><br />
<strong>Lenguaje</strong> <strong>SQL</strong> 1<br />
Introducción a <strong>SQL</strong><br />
Structured Query Language (<strong>SQL</strong>)<br />
<strong>Lenguaje</strong> <strong>de</strong>clarativo <strong>de</strong> acceso a bases <strong>de</strong> datos que combina<br />
construcciones <strong>de</strong>l álgebra relacional y el cálculo relacional.<br />
Originalmente <strong>de</strong>sarrollado en los '70 por IBM en su Research<br />
Laboratory <strong>de</strong> San José a partir <strong>de</strong>l cálculo <strong>de</strong> predicados creado por<br />
Codd.<br />
<strong>Lenguaje</strong> estándar <strong>de</strong> facto en los SGBD comerciales<br />
Estándares:<br />
SEQUEL(Structured English QUEry Language), IBM 1976<br />
<strong>SQL</strong>-86 (ANSI <strong>SQL</strong>)<br />
<strong>SQL</strong>-89 (<strong>SQL</strong>1)<br />
<strong>SQL</strong>-92 (<strong>SQL</strong>2), gran revisión <strong>de</strong>l estándar<br />
<strong>SQL</strong>:1999 (<strong>SQL</strong>3), Aña<strong>de</strong> disparadores, algo <strong>de</strong> OO, ...<br />
<strong>SQL</strong>:2003. Aña<strong>de</strong> XML, secuencias y columnas autonuméricas.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 2
Características <strong>de</strong> <strong>SQL</strong><br />
El Lenguage <strong>de</strong> Definición <strong>de</strong> Datos (LDD)<br />
Proporciona comandos para la creación, borrado y modificación <strong>de</strong><br />
esquemas relacionales<br />
El <strong>Lenguaje</strong> <strong>de</strong> Manipulación <strong>de</strong> Datos (LMD)<br />
Basado en el álgebra relacional y el cálculo relacional permite realizar<br />
<strong>consulta</strong>s y adicionalmente insertar, borrar y actualizar <strong>de</strong> tuplas<br />
Ejecutado en una consola interactiva<br />
Embebido <strong>de</strong>ntro <strong>de</strong> un lenguaje <strong>de</strong> programación <strong>de</strong> propósito general<br />
Definición <strong>de</strong> vistas<br />
Autorización<br />
Definición <strong>de</strong> usuarios y privilegios<br />
Integridad <strong>de</strong> datos<br />
Control <strong>de</strong> Transacciones<br />
SELECT A1, …, An<br />
FROM T1, …, Tn<br />
WHERE P<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 3<br />
Estructura <strong>de</strong> la sentencia SELECT<br />
GROUP BY Ai1, …, Ain<br />
HAVING Q<br />
ORDER BY Aj1, …, Ajn<br />
-Describe la salida <strong>de</strong>seada con:<br />
•Nombres <strong>de</strong> columnas<br />
•Expresiones aritméticas<br />
•Literales<br />
•Funciones escalares<br />
•Funciones <strong>de</strong> columna<br />
- Nombres <strong>de</strong> las tablas / vistas<br />
- Condiciones <strong>de</strong> selección <strong>de</strong> filas<br />
- Nombre <strong>de</strong> las columnas<br />
- Condiciones <strong>de</strong> selección <strong>de</strong> grupo<br />
- Nombres <strong>de</strong> columnas<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 4
Estructura básica <strong>de</strong> la sentencia SELECT<br />
Consta <strong>de</strong> tres cláusulas: SELECT, FROM y WHERE.<br />
SELECT correspon<strong>de</strong> a la operación <strong>de</strong> proyección <strong>de</strong>l álgebra<br />
relacional.<br />
La lista <strong>de</strong> los atributos que se incluirán en el resultado <strong>de</strong> una <strong>consulta</strong>.<br />
FROM correspon<strong>de</strong> al producto cartesiano <strong>de</strong>l álgebra relacional.<br />
Especifica las relaciones que se van a usar como origen en el proceso <strong>de</strong><br />
la <strong>consulta</strong>.<br />
WHERE correspon<strong>de</strong> al predicado <strong>de</strong> selección <strong>de</strong>l álgebra relacional.<br />
Consta <strong>de</strong> un predicado que implica atributos <strong>de</strong> las relaciones <strong>de</strong> la<br />
cláusula FROM.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 5<br />
Estructura básica <strong>de</strong> la sentencia SELECT<br />
Una <strong>consulta</strong> <strong>SQL</strong> tiene la forma:<br />
SELECT A1, ..., An /* Lista <strong>de</strong> atributos */<br />
FROM R1, ..., Rm /* Lista <strong>de</strong> relaciones */<br />
WHERE P; /* Condición. Cláusula OPCIONAL */<br />
Es posible que existan el mismo nombre <strong>de</strong> atributo en dos relaciones<br />
distintas.<br />
Se aña<strong>de</strong> "NOMBRE_RELACION." antes <strong>de</strong>l nombre para <strong>de</strong>sambiguar.<br />
Es equivalente a la siguiente expresión <strong>de</strong>l álgebra relacional:<br />
Π A1,A2,...,An ( σ P ( R1 × R2 × … × Rm ) )<br />
El or<strong>de</strong>n <strong>de</strong> ejecución <strong>de</strong> la expresión anterior es el mismo que el <strong>de</strong> la<br />
<strong>consulta</strong> <strong>SQL</strong>.<br />
ADVERTENCIA: la selección <strong>de</strong>l AR y el SELECT <strong>de</strong> <strong>SQL</strong> no<br />
funcionan igual.<br />
El resultado <strong>de</strong> una <strong>consulta</strong> SELECT pue<strong>de</strong> tener tuplas repetidas.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 6
Proyección <strong>de</strong> algunas columnas<br />
DEPTNO DEPTNAME<br />
A00<br />
B01<br />
C01<br />
D01<br />
D11<br />
D21<br />
E01<br />
E11<br />
E21<br />
SPIFFY COMPUTER SERVICE DIV.<br />
PLANNING<br />
INFORMATION CENTER<br />
DEVELOPMENTCENTER<br />
MANUFACTURING SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
SUPPORT SERVICES<br />
OPERATIONS<br />
SOFTWARE SUPPORT<br />
SELECT DEPTNO, DEPTNAME, ADMRDEPT<br />
FROM DEPARTMENT<br />
ADMRDEPT<br />
A00<br />
A00<br />
A00<br />
A00<br />
D01<br />
D01<br />
A00<br />
E01<br />
E01<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 7<br />
Eliminación <strong>de</strong> filas duplicadas<br />
<strong>SQL</strong> permite duplicados <strong>de</strong>bido a la gran cantidad <strong>de</strong> tiempo<br />
que pue<strong>de</strong> llevar eliminarlos<br />
Para eliminar las tuplas repetidas se utiliza la cláusula<br />
DISTINCT.<br />
También es posible pedir explícitamente la inclusión <strong>de</strong><br />
tuplas repetidas mediante el uso <strong>de</strong> la cláusula ALL.<br />
SELECT ADMRDEPT<br />
FROM DEPARTMENT<br />
ADMRDEPT<br />
A00<br />
A00<br />
A00<br />
A00<br />
D01<br />
D01<br />
A00<br />
E01<br />
E01<br />
SELECT ALL ADMRDEPT<br />
FROM DEPARTMENT<br />
SELECT DISTINCT ADMRDEPT<br />
FROM DEPARTMENT<br />
ADMRDEPT<br />
A00<br />
D01<br />
E01<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 8
Eliminación <strong>de</strong> filas duplicadas<br />
¿Qué trabajos realiza cada <strong>de</strong>partamento?<br />
WORKDEPT JOB<br />
A00 CLERK<br />
A00<br />
A00<br />
PRES<br />
SALESREP<br />
B01<br />
C01<br />
MANAGER<br />
ANALYST<br />
C01 MANAGER<br />
D11 DESIGNER<br />
D11 MANAGER<br />
D21 CLERK<br />
D21 MANAGER<br />
E01 MANAGER<br />
E11 MANAGER<br />
E11 OPERATOR<br />
E21 FIELDREP<br />
E21 MANAGER<br />
SELECT DISTINCT WORKDEPT, JOB<br />
FROM EMPLOYEE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 9<br />
Proyección <strong>de</strong> todos los atributos<br />
Se pue<strong>de</strong> pedir la proyección <strong>de</strong> todos los atributos <strong>de</strong> la<br />
<strong>consulta</strong> mediante utilizando el símbolo '*'<br />
La tabla resultante contendrá todos los atributos <strong>de</strong> las tablas que<br />
aparecen en la cláusula FROM.<br />
DEPTNO<br />
A00<br />
B01<br />
C01<br />
D01<br />
D11<br />
D21<br />
E01<br />
E11<br />
E21<br />
SPIFFY COMPUTER SERVICE DIV.<br />
PLANNING<br />
INFORMATION CENTER<br />
DEVELOPMENTCENTER<br />
MANUFACTURING SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
SUPPORT SERVICES<br />
OPERATIONS<br />
SOFTWARE SUPPORT<br />
SELECT * FROM DEPARTMENT<br />
DEPTNAME MGRNO ADMRDEPT LOCATION<br />
000010<br />
000020<br />
000030<br />
------<br />
000060<br />
000070<br />
000050<br />
000090<br />
000100<br />
A00<br />
A00<br />
A00<br />
A00<br />
D01<br />
D01<br />
A00<br />
E01<br />
E01<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 10
Salida or<strong>de</strong>nada<br />
<strong>SQL</strong> permite controlar el or<strong>de</strong>n en el que se presentan las<br />
tuplas <strong>de</strong> una relación mediante la cláusula ORDER BY.<br />
La cláusula ORDER BY tiene la forma<br />
ORDER BY A1 , ..., An <br />
A1, ..., An son atributos <strong>de</strong> la relación resultante <strong>de</strong> la <strong>consulta</strong><br />
Ai controla si la or<strong>de</strong>nación es Ascen<strong>de</strong>nte 'ASC' o<br />
<strong>de</strong>scen<strong>de</strong>nte 'DESC' por el campo Ai. Por <strong>de</strong>fecto la or<strong>de</strong>nación se<br />
realiza <strong>de</strong> manera ascen<strong>de</strong>nte.<br />
La or<strong>de</strong>nación se realiza tras haber ejecutado la <strong>consulta</strong><br />
sobre las tuplas resultantes.<br />
La or<strong>de</strong>nación pue<strong>de</strong> convertirse en una operación costosa<br />
<strong>de</strong>pendiendo <strong>de</strong>l tamaño <strong>de</strong> la relación resultante.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 11<br />
Salida or<strong>de</strong>nada (cont.)<br />
DEPTNO DEPTNAME ADMRDEPT<br />
A00<br />
C01<br />
B01<br />
E01<br />
D01<br />
D11<br />
D21<br />
E21<br />
E11<br />
SPIFFY COMPUTER SERVICE DIV.<br />
INFORMATION CENTER<br />
PLANNING<br />
SUPPORTSERVICES<br />
DEVELOPMENTCENTER<br />
MANUFACTURING SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
SOFTWARE SUPPORT<br />
OPERATIONS<br />
SELECT DEPTNO, DEPTNAME, ADMRDEPT<br />
FROM DEPARTMENT<br />
ORDER BY ADMRDEPT ASC<br />
A00<br />
A00<br />
A00<br />
A00<br />
A00<br />
D01<br />
D01<br />
E01<br />
E01<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 12
Salida or<strong>de</strong>nada (cont.)<br />
ADMRDEPT DEPTNAME DEPTNO<br />
A00<br />
A00<br />
A00<br />
A00<br />
A00<br />
D01<br />
D01<br />
E01<br />
E01<br />
SUPPORT SERVICES<br />
DEVELOPMENT CENTER<br />
INFORMATION CENTER<br />
PLANNING<br />
SPIFFY COMPUTER SERVICE DIV.<br />
ADMINISTRATION SYSTEMS<br />
MANUFACTURING SYSTEMS<br />
SOFTWARE SUPPORT<br />
OPERATIONS<br />
SELECT DEPTNO, DEPTNAME, ADMRDEPT<br />
FROM DEPARTMENT<br />
ORDER BY ADMRDEPT ASC, DEPTNO DESC<br />
E01<br />
D01<br />
C01<br />
B01<br />
A00<br />
D21<br />
D11<br />
E21<br />
E11<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 13<br />
Salida or<strong>de</strong>nada (cont.)<br />
En Oracle, IBM DB2 y MS-<strong>SQL</strong> Server entre otros es<br />
posible indicar la columna <strong>de</strong> or<strong>de</strong>nación mediante un entero<br />
El entero hace referencia a la posición <strong>de</strong> la columna en la relación<br />
resultante <strong>de</strong> la <strong>consulta</strong><br />
SELECT LASTNAME, FIRSTNME, WORKDEPT, JOB, SEX<br />
FROM EMPLOYEE<br />
ORDER BY WORKDEPT DESC, JOB, LASTNAME, SEX DESC<br />
ORDER BY WORKDEPT DESC, JOB ASC, LASTNAME ASC, SEX DESC<br />
ORDER BY 3 DESC, 4, 1, 5 DESC<br />
ORDER BY 3 DESC, 4 ASC, 1 ASC, 5 DESC<br />
ORDER BY 3 DESC, JOB, LASTNAME, 5 DESC<br />
ORDER BY WORKDEPT DESC, 4 ASC, 1 ASC, SEX DESC<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 14
Selección <strong>de</strong> filas<br />
La cláusula WHERE permite filtrar las filas <strong>de</strong> la relación resultante.<br />
La condición <strong>de</strong> filtrado se especifica como un predicado.<br />
El predicado <strong>de</strong> la cláusula WHERE pue<strong>de</strong> ser simple o complejo<br />
Se utilizan los conectores lógicos AND, OR y NOT en lugar <strong>de</strong> los símbolos<br />
matemáticos ∧, ∨, ¬.<br />
Las expresiones pue<strong>de</strong>n contener<br />
Predicados <strong>de</strong> comparación<br />
BETWEEN / NOT BETWEEN<br />
IN / NOT IN (con y sin sub<strong>consulta</strong>s)<br />
LIKE / NOT LIKE<br />
IS NULL / IS NOT NULL<br />
ALL, SOME/ANY (sub<strong>consulta</strong>s)<br />
EXISTS (sub<strong>consulta</strong>s)<br />
Predicados <strong>de</strong> comparación<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 15<br />
Selección <strong>de</strong> filas (cont.)<br />
Operadores: =, (es el ≠), <br />
BETWEEN es el operador <strong>de</strong> comparación para intervalos <strong>de</strong><br />
valores o fechas.<br />
IN es el operador que permite comprobar si un valor se<br />
encuentra en un conjunto.<br />
Pue<strong>de</strong> especificarse un conjunto <strong>de</strong> valores.<br />
Pue<strong>de</strong> utilizarse el resultado <strong>de</strong> otra <strong>consulta</strong>.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 16
Selección <strong>de</strong> filas (cont.)<br />
LIKE es el operador <strong>de</strong> comparación <strong>de</strong> ca<strong>de</strong>nas <strong>de</strong><br />
caracteres.<br />
<strong>SQL</strong> distingue entre mayúsculas y minúsculas<br />
Las ca<strong>de</strong>nas <strong>de</strong> caracteres se incluyen entre comillas simples<br />
<strong>SQL</strong> permite <strong>de</strong>finir patrones a través <strong>de</strong> los siguientes caracteres:<br />
'%', que es equivalente a "cualquier subca<strong>de</strong>na <strong>de</strong> caracteres"<br />
'_', que es equivalente a "cualquier carácter"<br />
IS NULL es el operador <strong>de</strong> comparación <strong>de</strong> valores nulos.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 17<br />
Ejemplo <strong>de</strong> selección <strong>de</strong> filas<br />
¿Qué <strong>de</strong>partamentos reportan al A00?<br />
SELECT DEPTNO, ADMRDEPT<br />
FROM DEPARTMENT<br />
WHERE ADMRDEPT='A00'<br />
DEPTNO ADMRDEPT<br />
A00<br />
B01<br />
C01<br />
D01<br />
E01<br />
A00<br />
A00<br />
A00<br />
A00<br />
A00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 18
Ejemplo <strong>de</strong> selección <strong>de</strong> filas<br />
Necesito el apellido y el nivel <strong>de</strong> formación <strong>de</strong> los empleados<br />
cuyo nivel <strong>de</strong> formación es mayor o igual a 19<br />
SELECT LASTNAME, EDLEVEL<br />
FROM EMPLOYEE<br />
WHERE EDLEVEL >= 19<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 19<br />
Ejemplo <strong>de</strong> selección <strong>de</strong> filas<br />
Necesito el número <strong>de</strong> empleado, apellido y fecha <strong>de</strong><br />
nacimiento <strong>de</strong> aquellos que hayan nacido <strong>de</strong>spués <strong>de</strong>l 1 <strong>de</strong><br />
enero <strong>de</strong> 1955 (inclusive).<br />
SELECT EMPNO, LASTNAME, BIRTHDATE<br />
FROM EMPLOYEE<br />
WHERE BIRTHDATE >='1955-01-01'<br />
ORDER BY BIRTHDATE<br />
EMPNO<br />
000160<br />
000100<br />
LASTNAME<br />
PIANKA<br />
SPENCER<br />
BIRTHDATE<br />
1955-04-12<br />
1956-12-18<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 20
Múltiples condiciones - AND<br />
Necesito el número <strong>de</strong> empleado, el trabajo y el nivel <strong>de</strong><br />
formación <strong>de</strong> los analistas con un nivel <strong>de</strong> educación 16<br />
EMPNO JOB EDLEVEL<br />
000130 ANALYST 16<br />
SELECT EMPNO, JOB, EDLEVEL<br />
FROM EMPLOYEE<br />
WHERE JOB='ANALYST' AND EDLEVEL=16<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 21<br />
Múltiples condiciones – AND/OR<br />
Obtener el número <strong>de</strong> empleado, el trabajo y el nivel <strong>de</strong><br />
formación <strong>de</strong> todos los analistas con un nivel 16 y <strong>de</strong> todos<br />
los empleados <strong>de</strong> nivel 18. La salida se clasifica por trabajo y<br />
nivel<br />
SELECT EMPNO, JOB, EDLEVEL<br />
FROM EMPLOYEE<br />
WHERE (JOB='ANALYST' AND EDLEVEL=16)<br />
OR EDLEVEL=18<br />
ORDER BY JOB, EDLEVEL<br />
EMPNO JOB EDLEVEL<br />
000130<br />
000140<br />
000220<br />
000020<br />
000010<br />
ANALYST<br />
ANALYST<br />
DESIGNER<br />
MANAGER<br />
PRES<br />
16<br />
18<br />
18<br />
18<br />
18<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 22
SELECT con BETWEEN<br />
Obtener el número <strong>de</strong> empleado y el nivel <strong>de</strong> todos los<br />
empleados con un nivel entre 12 y 15<br />
EMPNO EDLEVEL<br />
000310<br />
000290<br />
000300<br />
000330<br />
000100<br />
000230<br />
000120<br />
000270<br />
000250<br />
12<br />
12<br />
14<br />
14<br />
14<br />
14<br />
14<br />
15<br />
15<br />
SELECT EMPNO, EDLEVEL<br />
FROM EMPLOYEE<br />
WHERE EDLEVEL BETWEEN 12 AND 15<br />
ORDER BY EDLEVEL<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 23<br />
SELECT con IN<br />
Listar los apellidos y nivel <strong>de</strong> formación <strong>de</strong> todos los<br />
empleados <strong>de</strong> nivel 14, 19 o 20.<br />
El resultado clasificado por nivel y apellido<br />
LASTNAME EDLEVEL<br />
JEFFERSON<br />
LEE<br />
O'CONNELL<br />
SMITH<br />
SPENSER<br />
LUCCHESI<br />
KWAN<br />
14<br />
14<br />
14<br />
14<br />
14<br />
19<br />
20<br />
SELECT LASTNAME, EDLEVEL<br />
FROM EMPLOYEE<br />
WHERE EDLEVEL IN (14, 19, 20)<br />
ORDER BY EDLEVEL, LASTNAME<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 24
Selección <strong>de</strong> valores NULL<br />
Listar el número y el nombre <strong>de</strong> los <strong>de</strong>partamentos sin<br />
director asignado<br />
DEPTNO DEPTNAME MGRNO<br />
D01 DEVELOPMENTCENTER ------<br />
SELECT DEPTNO, DEPTNAME, MGRNO<br />
FROM DEPARTMENT<br />
WHERE MGRNO IS NULL;<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 25<br />
Búsqueda parcial - LIKE<br />
Obtener el apellido <strong>de</strong> todos los empleados cuyo apellido<br />
empiece por G<br />
SELECT LASTNAME<br />
FROM EMPLOYEE<br />
WHERE LASTNAME LIKE 'G%';<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 26
Búsqueda parcial – LIKE<br />
Ejemplos con %<br />
SELECT LASTNAME<br />
FROM EMPLOYEE<br />
WHERE LASTNAME LIKE '%SON';<br />
SELECT LASTNAME<br />
FROM EMPLOYEE<br />
WHERE LASTNAME LIKE '%M%N%';<br />
THOMPSON<br />
HENDERSON<br />
ADAMSON<br />
JEFFERSON<br />
JOHNSON<br />
THOMPSON<br />
ADAMSON<br />
MARINO<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 27<br />
Búsqueda parcial – LIKE<br />
Ejemplos con _<br />
¿Qué empleados tienen una C como segunda letra <strong>de</strong> su<br />
apellido?<br />
SELECT LASTNAME<br />
FROM EMPLOYEE<br />
WHERE LASTNAME LIKE '_C%';<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 28
Búsqueda parcial – NOT LIKE<br />
Necesito todos los <strong>de</strong>partamentos excepto aquellos cuyo<br />
número empiece por 'D'<br />
DEPTNO<br />
A00<br />
B01<br />
C01<br />
E01<br />
E11<br />
E21<br />
EMPNO<br />
000210<br />
000250<br />
000260<br />
000290<br />
000300<br />
000310<br />
000320<br />
DEPTNAME<br />
SPIFFY COMPUTER SERVICE DIV.<br />
PLANNING<br />
INFORMATION CENTER<br />
SUPPORT SERVICES<br />
OPERATIONS<br />
SOFTWARE SUPPORT<br />
SELECT DEPTNO, DEPTNAME<br />
FROM DEPARTMENT<br />
WHERE DEPTNO NOT LIKE 'D%';<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 29<br />
Renombramiento <strong>de</strong> columnas<br />
SALARY COMM INCOME<br />
18270.00<br />
19180.00<br />
17250.00<br />
15340.00<br />
17750.00<br />
15900.00<br />
19950.00<br />
1462.00<br />
1534.00<br />
1380.00<br />
1227.00<br />
1420.00<br />
1272.00<br />
1596.00<br />
SELECT EMPNO, SALARY, COMM,<br />
SALARY+COMM AS INCOME<br />
FROM EMPLOYEE<br />
WHERE SALARY < 20000<br />
ORDER BY EMPNO<br />
19732.00<br />
20714.00<br />
18630.00<br />
16567.00<br />
19170.00<br />
17172.00<br />
21546.00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 30
Renombramiento <strong>de</strong> tablas<br />
Es posible obtener “copias” <strong>de</strong> una tabla situando etiquetas<br />
junto al nombre <strong>de</strong> las tablas.<br />
Ejemplo: en el siguiente esquema <strong>de</strong> base <strong>de</strong> datos,<br />
queremos obtener el nombre <strong>de</strong> los empleados con al menos<br />
dos hijos.<br />
EMP (DNI, NOM) HIJOS (DNI, NOMH)<br />
SELECT NOM<br />
FROM EMP, HIJOS H1, HIJOS H2<br />
WHERE EMP.DNI = H1.DNI AND EMP.DNI = H2.DNI AND<br />
H1.NOMH H2.NOMH;<br />
Realiza el producto cartesiano <strong>de</strong> las tres tablas y da como<br />
resultado aquellas tuplas con igual DNI en las tres y con<br />
distinto nombre en los hijos. ¿Solución a la repetición <strong>de</strong><br />
nombres <strong>de</strong> distintos empleados?<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 31<br />
Renombramiento <strong>de</strong> tablas (cont.)<br />
Utilizar clausula DISTINCT (elimina filas repetidas) e<br />
incluir la clave <strong>de</strong> la tabla:<br />
SELECT DISTINCT EMP.NOM, EMP.DNI<br />
FROM EMP, HIJOS H1, HIJOS H2<br />
WHERE EMP.DNI = H1.DNI AND EMP.DNI = H2.DNI AND<br />
H1.NOMH H2.NOMH;<br />
Ejemplo: en el siguiente esquema <strong>de</strong> base <strong>de</strong> datos, se pi<strong>de</strong>n<br />
los apellidos <strong>de</strong> cada empleado y <strong>de</strong> su supervisor.<br />
EMP (DNI, NOM, AP, SUELDO, ND, DNISUPERV)<br />
SELECT E.AP, S.AP<br />
FROM EMP E, EMP S<br />
WHERE E.DNISUPERV = S.DNI;<br />
Las etiquetas también sirven para <strong>de</strong>sambiguar.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 32
Tipos <strong>SQL</strong> y valores literales<br />
La norma <strong>SQL</strong> <strong>de</strong>fine un conjunto <strong>de</strong> tipos para las columnas<br />
<strong>de</strong> las tablas.<br />
Habitualmente cada SGBD tiene tipos propios o particularida<strong>de</strong>s<br />
para los tipos <strong>de</strong> la norma <strong>SQL</strong>.<br />
Es necesario <strong>consulta</strong>r el manual <strong>de</strong>l SGBD para obtener<br />
información acerca <strong>de</strong> los tamaños máximos <strong>de</strong><br />
almacenamiento.<br />
En el caso <strong>de</strong> ca<strong>de</strong>nas, cual es la longitud máxima <strong>de</strong><br />
almacenamiento.<br />
En el caso <strong>de</strong> tipos numéricos, cual es el rango <strong>de</strong> valores posibles.<br />
BIGINT<br />
INTEGER<br />
SMALLINT<br />
REAL<br />
FLOAT<br />
VARCHAR(n)<br />
DATE<br />
TIME<br />
TIMESTAMP<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 33<br />
Tipos <strong>SQL</strong> y valores literales<br />
Tipo<br />
NUMERIC(8,2)<br />
DECIMAL(8,2)<br />
DOUBLE PRECISION<br />
CHARACTER(max)<br />
8589934592<br />
186282<br />
186<br />
999999.99 (precisión, escala)<br />
999999.99 (precisión, escala)<br />
6.02257E23<br />
3.141592653589<br />
6.02257E23<br />
'GREECE ' (15 caracteres)<br />
'hola'<br />
date 'YYYY-MM-DD'<br />
time 'hh:mm:ss.ccc'<br />
Ejemplo<br />
timestamp 'YYYY-MM-DD hh:mm:ss.ccc'<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 34
Expresiones<br />
Aunque <strong>SQL</strong> no es un lenguaje <strong>de</strong> programación <strong>de</strong><br />
propósito general, permite <strong>de</strong>finir expresiones calculadas.<br />
Estas expresiones pue<strong>de</strong>n contener<br />
Referencias a columnas<br />
Valores literales<br />
Operadores aritméticos<br />
Llamadas a funciones<br />
Los operadores aritméticos son los habituales: +, -, * y /<br />
Estos operadores sólo funcionan con valores numéricos.<br />
Los operadores '+' y '–' habitualmente funcionan para fechas.<br />
Aunque las normas <strong>SQL</strong> <strong>de</strong>finen un conjunto mínimo <strong>de</strong><br />
funciones, los SGBD proporcionan una gran variedad.<br />
Es necesario <strong>consulta</strong>r el manual <strong>de</strong>l SGBD particular.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 35<br />
Funciones matemáticas comunes<br />
Descripción<br />
Valor absoluto<br />
Menor entero >= valor<br />
Menor entero
Convierte todos los caracteres a<br />
minúsculas<br />
Convierte todos los caracteres a<br />
mayúsculas<br />
Elimina los blancos <strong>de</strong>l final <strong>de</strong> la<br />
ca<strong>de</strong>na<br />
Elimina los blancos <strong>de</strong>l comienzo<br />
<strong>de</strong> la ca<strong>de</strong>na<br />
Devuelve una subca<strong>de</strong>na<br />
Concatena dos ca<strong>de</strong>nas<br />
Funciones <strong>de</strong> ca<strong>de</strong>na<br />
Descripción IBM DB2 <strong>SQL</strong> Server Oracle My<strong>SQL</strong><br />
LOWER<br />
UPPER<br />
RTRIM<br />
LTRIM<br />
SUBSTR<br />
CONCAT<br />
LOWER<br />
UPPER<br />
RTRIM<br />
LTRIM<br />
SUBSTRING<br />
+<br />
LOWER<br />
UPPER<br />
RTRIM<br />
LTRIM<br />
SUBSTR<br />
CONCAT<br />
LOWER<br />
UPPER<br />
RTRIM<br />
LTRIM<br />
SUBSTRING<br />
CONCAT<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 37<br />
Operaciones aritméticas<br />
Necesito obtener el salario, la comisión y los ingresos totales<br />
<strong>de</strong> todos los empleados que tengan un salario menor <strong>de</strong><br />
20000€ , clasificado por número <strong>de</strong> empleado<br />
EMPNO<br />
000210<br />
000250<br />
000260<br />
000290<br />
000300<br />
000310<br />
000320<br />
SALARY COMM<br />
18270.00<br />
19180.00<br />
17250.00<br />
15340.00<br />
17750.00<br />
15900.00<br />
19950.00<br />
1462.00<br />
1534.00<br />
1380.00<br />
1227.00<br />
1420.00<br />
1272.00<br />
1596.00<br />
SELECT EMPNO, SALARY, COMM,<br />
SALARY + COMM<br />
FROM EMPLOYEE<br />
WHERE SALARY < 20000<br />
ORDER BY EMPNO<br />
19732.00<br />
20714.00<br />
18630.00<br />
16567.00<br />
19170.00<br />
17172.00<br />
21546.00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 38
EMPNO<br />
000210<br />
000250<br />
000260<br />
000290<br />
000300<br />
000310<br />
000320<br />
EMPNO<br />
000140<br />
000210<br />
000240<br />
000330<br />
Operaciones aritméticas (cont.)<br />
SALARY<br />
18270.00<br />
19180.00<br />
17250.00<br />
15340.00<br />
17750.00<br />
15900.00<br />
19950.00<br />
COMM<br />
2274.00<br />
1462.00<br />
2301.00<br />
2030.00<br />
18955.125000<br />
19899.250000<br />
17896.875000<br />
15915.250000<br />
18415.625000<br />
16496.250000<br />
20698.125000<br />
SELECT EMPNO, SALARY,<br />
SALARY*1.0375<br />
FROM EMPLOYEE<br />
WHERE SALARY < 20000<br />
ORDER BY EMPNO<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 39<br />
Expresiones en predicados<br />
SALARY<br />
28420.00<br />
18270.00<br />
28760.00<br />
25370.00<br />
SELECT EMPNO, SALARY,<br />
(COMM/SALARY)*100<br />
FROM EMPLOYEE<br />
WHERE (COMM/SALARY) * 100 > 8<br />
ORDER BY EMPNO<br />
8.001400<br />
8.002100<br />
8.000600<br />
8.001500<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 40
EMPNO<br />
000210<br />
000250<br />
000260<br />
000290<br />
000300<br />
000310<br />
000320<br />
SALARY<br />
18270.00<br />
19180.00<br />
17250.00<br />
15340.00<br />
17750.00<br />
15900.00<br />
19950.00<br />
Uso <strong>de</strong> funciones<br />
SELECT EMPNO, SALARY,<br />
TRUNC(SALARY*1.0375, 2)<br />
FROM EMPLOYEE<br />
WHERE SALARY < 20000<br />
ORDER BY EMPNO<br />
18955.12<br />
19899.25<br />
17896.87<br />
15915.25<br />
18415.62<br />
16496.25<br />
20698.12<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 41<br />
Uso <strong>de</strong> funciones (cont.)<br />
SELECT CONCAT(LASTNAME || ',', FIRSTNAME ) AS NAME<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT = 'A00'<br />
ORDER BY NAME<br />
NAME<br />
HAAS, CHRISTA<br />
LUCCHESI, VINCENZO<br />
O'CONNELL, SEAN<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 42
<strong>SQL</strong> incluye las operaciones:<br />
UNION<br />
INTERSECT<br />
EXCEPT (MINUS en Oracle)<br />
Operadores <strong>de</strong> conjunto<br />
Por <strong>de</strong>finición los operadores <strong>de</strong> conjunto eliminan las tuplas<br />
duplicadas.<br />
Para retener duplicados se <strong>de</strong>be utilizar ALL<br />
YY<br />
Y<br />
R<br />
R<br />
R<br />
R<br />
Y<br />
Y<br />
REDONDOS<br />
Seleccionar<br />
elementos<br />
AMARILLOS<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 43<br />
UNION - Concepto<br />
Seleccionar<br />
elementos UNION<br />
Y<br />
R<br />
Y<br />
Y<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 44<br />
R<br />
Y<br />
Y
SELECT<br />
FROM<br />
WHERE<br />
SELECT<br />
FROM<br />
WHERE<br />
SELECT<br />
FROM<br />
WHERE<br />
UNION<br />
SELECT<br />
FROM<br />
WHERE<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
JOB = 'ANALYST'<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
EDLEVEL = 18<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
JOB = 'ANALYST'<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
EDLEVEL = 18<br />
UNION<br />
LASTNAME<br />
NICHOLLS<br />
QUINTANA<br />
LASTNAME<br />
HAAS<br />
LUTZ<br />
NICHOLLS<br />
THOMPSON<br />
LASTNAME<br />
HAAS<br />
LUTZ<br />
NICHOLLS<br />
QUINTANA<br />
THOMPSON<br />
EDLEVEL<br />
18<br />
16<br />
EDLEVEL<br />
18<br />
18<br />
18<br />
18<br />
EDLEVEL<br />
18<br />
18<br />
18<br />
16<br />
18<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 45<br />
UNION<br />
Cada SELECT <strong>de</strong>be tener el mismo número <strong>de</strong> columnas<br />
Las columnas correspondientes <strong>de</strong>ben tener tipos <strong>de</strong> datos<br />
compatibles<br />
UNION elimina duplicados<br />
Si se indica, el ORDER BY <strong>de</strong>be ser la última cláusula <strong>de</strong> la<br />
sentencia<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 46
Cada entrada <strong>de</strong>be tener 2 lineas: la<br />
primera <strong>de</strong>be incluir el número y<br />
nombre <strong>de</strong>l director y la seguna el<br />
número y el nombre <strong>de</strong>l<br />
<strong>de</strong>partamento.<br />
MGRNO<br />
000010<br />
000010<br />
000020<br />
000020<br />
000030<br />
000030<br />
000050<br />
000050<br />
Mgr.:<br />
Dept.:<br />
Mgr.:<br />
Dept.:<br />
Mgr.:<br />
Dept.:<br />
Mgr.:<br />
Dept.:<br />
UNION<br />
SELECT MGRNO , 'Dept.:', DEPTNAME<br />
FROM DEPARTMENT<br />
UNION<br />
SELECT MGRNO, 'Mgr.:', LASTNAME<br />
FROM DEPARTMENT D, EMPLOYEE E<br />
WHERE D.MGRNO = E.EMPNO<br />
ORDER BY 1,2 DESC<br />
DEPTNAME<br />
HAAS<br />
SPIFFY COMPUTER SERVICE DIV.<br />
THOMPSON<br />
PLANNING<br />
KWAN<br />
INFORMATION CENTER<br />
GEYER<br />
<strong>Lenguaje</strong> SUPPORT <strong>SQL</strong>SERVICES 47<br />
UNION<br />
SELECT EMPNO, SUBSTR(FIRSTNME, 1, 1) || '.' || MIDINT,<br />
LASTNAME, SALARY AS INCOME, 1 AS SORT FROM EMPLOYEE<br />
UNION<br />
SELECT EMPNO, '', '', BONUS, 2 AS SORT FROM EMPLOYEE<br />
UNION<br />
SELECT EMPNO, '', '', COMM, 3 AS SORT FROM EMPYOYEE<br />
UNION<br />
SELECT EMPNO, '', 'SUM:', SALARY+BONUS+COMM, 4 AS SORT FROM EMPLOYEE<br />
ORDER BY EMPNO, SORT<br />
EMPNO LASTNAME INCOME SORT<br />
000010 C.I HAAS 52750.00 1<br />
000010<br />
1000.00 2<br />
000010<br />
4220.00 3<br />
000010 SUM: 57970.00 4<br />
000020 M.L THOMPSON 41250.00 1<br />
000020<br />
800.00 2<br />
000020<br />
3300.00 3<br />
000020 . . SUM: . 45350.00 . 4.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 48
Y<br />
Y<br />
R<br />
R<br />
R<br />
R<br />
SELECT<br />
FROM<br />
WHERE<br />
SELECT<br />
FROM<br />
WHERE<br />
Y<br />
Y<br />
SELECT<br />
FROM<br />
WHERE<br />
UNION ALL<br />
SELECT<br />
FROM<br />
WHERE<br />
Seleccionar<br />
elementos<br />
REDONDOS<br />
Seleccionar<br />
elementos<br />
AMARILLOS<br />
UNION ALL. Concepto<br />
Y<br />
R<br />
Y<br />
Y<br />
UNION ALL<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 49<br />
UNION ALL. Concepto<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
JOB = 'ANALYST'<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
EDLEVEL = 18<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
JOB = 'ANALYST'<br />
LASTNAME, EDLEVEL<br />
EMPLOYEE<br />
EDLEVEL = 18<br />
LASTNAME<br />
QUINTANA<br />
NICHOLLS<br />
LASTNAME<br />
HAAS<br />
THOMPSON<br />
NICHOLLS<br />
LUTZ<br />
LASTNAME<br />
QUINTANA<br />
NICHOLLS<br />
HAAS<br />
THOMPSON<br />
NICHOLLS<br />
LUTZ<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 50<br />
Y<br />
R<br />
Y<br />
Y<br />
EDLEVEL<br />
16<br />
18<br />
EDLEVEL<br />
18<br />
18<br />
18<br />
18<br />
EDLEVEL<br />
16<br />
18<br />
18<br />
18<br />
18<br />
18
EMPNO<br />
000010<br />
EMPLOYEE<br />
EMPNO<br />
000010<br />
000020<br />
000030<br />
000040<br />
DEPARTMENT<br />
DEPTNO<br />
A00<br />
C01<br />
D01<br />
D21<br />
LASTNAME<br />
HAAS<br />
Consultar más <strong>de</strong> una tabla<br />
LASTNAME WORKDEPT.<br />
. .<br />
HAAS<br />
THOMPSON<br />
KWAN<br />
PULASKI<br />
DEPTNAME<br />
A00<br />
C01<br />
C01<br />
D21<br />
SPIFFY COMPUTER SERVICE DIV.<br />
INFORMATION CENTER<br />
DEVELOPMENT CENTER<br />
ADMINISTRATION SYSTEMS<br />
. . .<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 51<br />
Sintaxis <strong>de</strong>l JOIN: formato 1<br />
SELECT EMPNO, LASTNAME, WORKDEPT, DEPTNAME<br />
FROM EMPLOYEE,<br />
DEPARTMENT<br />
WHERE WORKDEPT = DEPTNO<br />
AND LASTNAME = 'HAAS'<br />
WORKDEPT DEPTNAME<br />
A00 SPIFFY COMPUTER SERVICE DIV.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 52
PROJNO<br />
AD3100<br />
AD3110<br />
AD3111<br />
AD3112<br />
AD3113<br />
IF1000<br />
PROJECT<br />
PROJNAME DEPTNO<br />
ADMIN SERVICES<br />
GENERAL AD SYSTEMS<br />
PAYROLL PROGRAMMING<br />
PERSONELL PROGRAMMING<br />
ACCOUNT. PROGRAMMING<br />
QUERY SERVICES<br />
EMPNO<br />
000010<br />
000020<br />
000030<br />
000050<br />
000060<br />
000070<br />
000090<br />
000100<br />
JOIN <strong>de</strong> tres tablas<br />
D01<br />
D21<br />
D21<br />
D21<br />
D21<br />
C01<br />
. . .<br />
DEPARTMENT<br />
DEPTNO DEPTNAME<br />
A00 SPIFFY COMPUTER SERVICE DIV.<br />
B01 PLANNING<br />
C01 INFORMATION CENTER<br />
D01 DEVELOPMENT CENTER<br />
D11 MANUFACTURING SYSTEMS<br />
D21 ADMINISTRATION SYSTEMS<br />
E01 SUPPORT SERVICES<br />
EMPLOYEE<br />
FIRSTNME MIDINIT LASTNAME<br />
CHRISTA<br />
I HAAS<br />
MICHAEL<br />
L THOMPSON<br />
SALLY<br />
A KWAN<br />
JOHN<br />
B GEYER<br />
IRVING<br />
F STERN<br />
EVA<br />
D PULASKI<br />
EILEEN<br />
W HENDERSON<br />
THEODORE Q SPENSER<br />
. . .<br />
MGRNO<br />
000010<br />
000020<br />
000030<br />
------<br />
000060<br />
000070<br />
000050<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 53<br />
JOIN <strong>de</strong> tres tablas<br />
SELECT PROJNO, PROJECT.DEPTNO, DEPTNAME, MGRNO, LASTNAME<br />
FROM PROJECT,<br />
DEPARTMENT,<br />
EMPLOYEE<br />
WHERE PROJECT.DEPTNO = DEPARTMENT.DEPTNO<br />
AND DEPARTMENT.MGRNO = EMPLOYEE.EMPNO<br />
AND DEPARTMENT.DEPTNO = 'D21'<br />
ORDER BY PROJNO<br />
PROJNO<br />
AD3110<br />
AD3111<br />
AD3112<br />
AD3113<br />
DEPTNO DEPTNAME MGRNO LASTNAME<br />
D21<br />
D21<br />
D21<br />
D21<br />
ADMINISTRATION SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
000070<br />
000070<br />
000070<br />
000070<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 54<br />
. . .<br />
PULASKI<br />
PULASKI<br />
PULASKI<br />
PULASKI
PROJNO<br />
AD3110<br />
AD3111<br />
AD3112<br />
AD3113<br />
Nombre <strong>de</strong> correlación (P, D, E)<br />
SELECT PROJNO, P.DEPTNO, DEPTNAME, MGRNO, LASTNAME<br />
FROM PROJECT P,<br />
DEPARTMENT D,<br />
EMPLOYEE E<br />
WHERE P.DEPTNO = D.DEPTNO<br />
AND D.MGRNO = E.EMPNO<br />
AND D.DEPTNO = 'D21'<br />
ORDER BY PROJNO<br />
EMPNO<br />
. . .<br />
DEPTNO DEPTNAME MGRNO LASTNAME<br />
D21<br />
D21<br />
D21<br />
D21<br />
ADMINISTRATION SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
ADMINISTRATION SYSTEMS<br />
000070<br />
000070<br />
000070<br />
000070<br />
PULASKI<br />
PULASKI<br />
PULASKI<br />
PULASKI<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 55<br />
JOIN <strong>de</strong> una tabla consigo misma<br />
1. Recuperar la fila <strong>de</strong> un empleado <strong>de</strong> la tabla EMPLOYEE (E)<br />
000100<br />
000330<br />
LASTNAME<br />
WORKDEPT<br />
. . . BIRTHDATE . . .<br />
2. Recuperar el nº <strong>de</strong>paratamento <strong>de</strong> DEPARTMENT (D)<br />
DEPTNO DEPTNAME MGRNO ADMRDEPT<br />
3. Recuperar el director en EMPLOYEE (M)<br />
EMPNO<br />
SPENSER<br />
LEE<br />
E21<br />
E21<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
.<br />
E21 SOFTWARE SUPPORT 000100 E21<br />
000100<br />
000330<br />
1956-12-18<br />
1941-07-18<br />
. . . LASTNAME WORKDEPT . . . BIRTHDATE . . .<br />
SPENSER<br />
LEE<br />
E21<br />
E21<br />
1956-12-18<br />
1941-07-18<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 56
JOIN <strong>de</strong> una tabla consigo misma<br />
¿Qué empleados<br />
son mayores que<br />
su director? SELECT E.EMPNO, E.LASTNAME,<br />
E.BIRTHDATE, M.BIRTHDATE, M.EMPNO<br />
FROM EMPLOYEE E, EMPLOYEE M,<br />
DEPARTMENT D<br />
WHERE E.WORKDEPT = D.DEPTNO<br />
AND D.MGRNO = M.EMPNO<br />
AND E.BIRTHDATE < M.BIRTHDATE<br />
EMPNO LASTNAME BIRTHDATE BIRTHDATE EMPNO<br />
000110<br />
000130<br />
000200<br />
000230<br />
000250<br />
000260<br />
000280<br />
000300<br />
000310<br />
000320<br />
000330<br />
000340<br />
LUCCHESI<br />
QUINTANA<br />
BROWN<br />
JEFFERSON<br />
SMITH<br />
JOHNSON<br />
SCHNEIDER<br />
SMITH<br />
SETRIGHT<br />
MEHTA<br />
LEE<br />
GOUNOT<br />
1929-11-05<br />
1925-09-15<br />
1941-05-29<br />
1935-05-30<br />
1939-11-12<br />
1936-10-05<br />
1936-03-28<br />
1936-10-27<br />
1931-04-21<br />
1932-08-11<br />
1941-07-18<br />
1926-05-17<br />
1933-08-14<br />
1941-05-11<br />
1945-07-07<br />
1953-05-26<br />
1953-05-26<br />
1953-05-26<br />
1941-05-15<br />
1941-05-15<br />
1941-05-15<br />
1956-12-18<br />
1956-12-18<br />
1956-12-18<br />
000010<br />
000030<br />
000060<br />
000070<br />
000070<br />
000070<br />
000090<br />
000090<br />
000090<br />
000100<br />
000100<br />
000100<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 57<br />
Sintaxis <strong>de</strong>l JOIN: formato 2<br />
SELECT EMPNO, LASTNAME, DEPTNO, DEPTNAME<br />
FROM EMPLOYEE<br />
[INNER] JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
EMPNO LASTNAME DEPTNO DEPTNAME<br />
000010 HAAS<br />
A00 SPIFFY COMPUTER SERVICE DIV.<br />
000120 O'CONNELL A00 SPIFFY COMPUTER SERVICE DIV.<br />
000030 KWAN C01 INFORMATION CENTER<br />
000140 NICHOLLS C01 INFORMATION CENTER<br />
000130 QUINTANA C01 INFORMATION CENTER<br />
RESULTADO<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 58
Otros JOIN: RIGHT [OUTER] JOIN<br />
SELECT EMPNO, LASTNAME, DEPTNO, DEPTNAME<br />
FROM EMPLOYEE<br />
RIGHT OUTER JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
EMPNO LASTNAME DEPTNO DEPTNAME<br />
000010 HAAS<br />
A00 SPIFFY COMPUTER SERVICE DIV.<br />
000120 O'CONNELL A00 SPIFFY COMPUTER SERVICE DIV.<br />
000030 KWAN C01 INFORMATION CENTER<br />
000130 QUINTANA C01 INFORMATION CENTER<br />
000140 NICHOLLS C01 INFORMATION CENTER<br />
D01 DEVELOPMENT CENTER<br />
- -<br />
RESULTADO<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 59<br />
Otros JOIN: LEFT [OUTER] JOIN<br />
SELECT EMPNO, LASTNAME, DEPTNO, DEPTNAME<br />
FROM EMPLOYEE<br />
LEFT OUTER JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
EMPNO LASTNAME DEPTNO DEPTNAME<br />
000010 HAAS<br />
A00 SPIFFY COMPUTER SERVICE DIV.<br />
000030 KWAN C01 INFORMATION CENTER<br />
000120 O'CONNELL A00 SPIFFY COMPUTER SERVICE DIV.<br />
000130 QUINTANA C01 INFORMATION CENTER<br />
000140 NICHOLLS C01 INFORMATION CENTER<br />
000400 WILSON - -<br />
RESULTADO<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 60
Otros JOIN: FULL [OUTER] JOIN<br />
SELECT EMPNO, LASTNAME, DEPTNO, DEPTNAME<br />
FROM EMPLOYEE<br />
FULL OUTER JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
EMPNO LASTNAME DEPTNO DEPTNAME<br />
000120 O'CONNELL A00 SPIFFY COMPUTER SERVICE DIV.<br />
000010 HAAS A00 SPIFFY COMPUTER SERVICE DIV.<br />
000030 KWAN C01 INFORMATION CENTER<br />
000130 QUINTANA C01 INFORMATION CENTER<br />
000140 NICHOLLS C01 INFORMATION CENTER<br />
- -<br />
D01 DEVELOPMENT CENTER<br />
000400 WILSON - -<br />
RESULTADO<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 61<br />
JOINs y predicados locales<br />
SELECT EMPNO, LASTNAME, SALARY,<br />
DEPTNO, DEPTNAME<br />
FROM EMPLOYEE<br />
FULL OUTER JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
WHERE SALARY > 30000 AND<br />
DEPTNAME LIKE '%CENTER%'<br />
EMPNO LASTNAME WORKDEPT SALARY DEPTNO DEPTNAME<br />
MGRNO<br />
000120 O'CONNELL A00 29250.00<br />
000010 HAAS A00 52750.00<br />
000030 KWAN C01 38250.00<br />
000130 QUINTANA C01 23800.00<br />
000140 NICHOLLS C01 28420.00<br />
- - - -<br />
SPIFFY COMPUTER SERVICE DIV.<br />
A00 000010<br />
A00 SPIFFY COMPUTER SERVICE DIV. 000010<br />
C01 INFORMATION CENTER 000030<br />
C01 INFORMATION CENTER 000030<br />
C01 INFORMATION CENTER 000030<br />
D01 DEVELOPMENT CENTER<br />
-<br />
000400 WILSON - 25400.00 - -<br />
-<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 62
JOINs y predicados locales<br />
SELECT EMPNO, LASTNAME, SALARY,<br />
DEPTNO, DEPTNAME<br />
FROM EMPLOYEE<br />
FULL OUTER JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
EMPNO LASTNAME WORKDEPT SALARY DEPTNO DEPTNAME<br />
MGRNO<br />
000120 O'CONNELL A00 29250.00<br />
000010 HAAS A00 52750.00<br />
000030 KWAN C01 38250.00<br />
000130 QUINTANA C01 23800.00<br />
000140 NICHOLLS C01 28420.00<br />
- - - -<br />
A00 SPIFFY COMPUTER SERVICE DIV. 000010<br />
A00 SPIFFY COMPUTER SERVICE DIV. 000010<br />
C01 INFORMATION CENTER 000030<br />
C01 INFORMATION CENTER 000030<br />
C01 INFORMATION CENTER 000030<br />
D01 DEVELOPMENT CENTER<br />
-<br />
000400 WILSON - 25400.00 - -<br />
-<br />
WHERE SALARY > 30000 AND<br />
DEPTNAME LIKE '%CENTER%'<br />
EMPNO LASTNAME SALARY DEPTNO DEPTNAME<br />
000030 KWAN 38250.00 C01 INFORMATION CENTER<br />
Resumen<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 63<br />
JOINs<br />
Existen 4 tipos <strong>de</strong> reunión y 3 condiciones <strong>de</strong> reunión que se pue<strong>de</strong>n<br />
combinar<br />
Tipos <strong>de</strong> reunión<br />
INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL<br />
OUTER JOIN<br />
Condiciones <strong>de</strong> reunión<br />
ON <br />
Respecto al predicado<br />
No elimina duplicados <strong>de</strong> atributos comunes<br />
NATURAL<br />
Respecto a todos los atributos comunes<br />
Elimina duplicados <strong>de</strong> atributos comunes<br />
USING (A1, …, An)<br />
Respecto a los atributos comunes indicados entre paréntesis<br />
Elimina duplicados <strong>de</strong> atributos comunes indicados<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 64
Funciones <strong>de</strong> columna<br />
Las funciones <strong>de</strong> columna o funciones <strong>de</strong> agregación son<br />
funciones que toman una colección (conjunto o<br />
multiconjunto) <strong>de</strong> valores <strong>de</strong> entrada y <strong>de</strong>vuelve un solo<br />
valor.<br />
Las funciones <strong>de</strong> columna disponibles son: AVG, MIN, MAX,<br />
SUM, COUNT.<br />
Los datos <strong>de</strong> entrada para SUM y AVG <strong>de</strong>ben ser una<br />
colección <strong>de</strong> números, pero el resto <strong>de</strong> operadores pue<strong>de</strong>n<br />
operar sobre colecciones <strong>de</strong> datos <strong>de</strong> tipo no numérico.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 65<br />
Funciones <strong>de</strong> columna<br />
Por <strong>de</strong>fecto las funciones se aplican a todas las tuplas<br />
resultantes <strong>de</strong> la <strong>consulta</strong>.<br />
Po<strong>de</strong>mos agrupar las tuplas resultantes para po<strong>de</strong>r aplicar las<br />
funciones <strong>de</strong> columna a grupos específicos utilizando la<br />
cláusula GROUP BY.<br />
En la cláusula SELECT <strong>de</strong> <strong>consulta</strong>s que utilizan funciones<br />
<strong>de</strong> columna solamente pue<strong>de</strong>n aparecer funciones <strong>de</strong><br />
columna.<br />
En caso <strong>de</strong> utilizar GROUP BY, también pue<strong>de</strong>n aparecer columnas<br />
utilizadas en la agrupación.<br />
Adicionalmente se pue<strong>de</strong>n aplicar condiciones sobre los<br />
grupos utilizando la cláusula HAVING.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 66
Funciones <strong>de</strong> columna<br />
Cálculo <strong>de</strong>l total SUM (expresión)<br />
Cálculo <strong>de</strong> la media AVG (expresión)<br />
Obtener el valor mínimo MIN (expresión)<br />
Obtener el valor máximo MAX (expresión)<br />
Contar el número <strong>de</strong> filas que satisfacen la condición <strong>de</strong><br />
búsqueda COUNT(*)<br />
Los valores NULL SI se cuentan.<br />
Contar el número <strong>de</strong> valores distintos en una columna <br />
COUNT (DISTINCT nombre-columna)<br />
Los valores NULL NO se cuenta.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 67<br />
Funciones <strong>de</strong> columna<br />
SELECT SUM(SALARY) AS SUM,<br />
AVG(SALARY) AS AVG,<br />
MIN(SALARY ) AS MIN,<br />
MAX(SALARY) AS MAX,<br />
COUNT(*) AS COUNT,<br />
COUNT(DISTINCT WORKDEPT) AS DEPT<br />
FROM EMPLOYEE<br />
SUM<br />
873715.00<br />
AVG MIN MAX COUNT DEPT<br />
27303.59375000 15340.00 52750.00 32 8<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 68
Funciones <strong>de</strong> columna en subconjuntos<br />
Necesito conocer los salarios <strong>de</strong> todos los<br />
empleados <strong>de</strong> los <strong>de</strong>partamentos A00, B01,<br />
y C01. A<strong>de</strong>más, para estos <strong>de</strong>partamentos<br />
quiero conocer su masa salarial.<br />
SELECT WORKDEPT, SALARY<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT IN ('A00', 'B01', 'C01')<br />
ORDER BY WORKDEPT<br />
WORKDEPT<br />
A00<br />
A00<br />
A00<br />
B01<br />
C01<br />
C01<br />
C01<br />
Necesito el total <strong>de</strong><br />
salarios <strong>de</strong>l área D<br />
SELECT SUM(SALARY) AS SUM<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT LIKE 'D%'<br />
SALARY<br />
52750.00<br />
46500.00<br />
29250.00<br />
41250.00<br />
38250.00<br />
23800.00<br />
28420.00<br />
SUM<br />
373020.00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 69<br />
GROUP BY<br />
SELECT WORKDEPT, SUM(SALARY) AS SUM<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT IN ('A00', 'B01', 'C01')<br />
GROUP BY WORKDEPT<br />
ORDER BY WORKDEPT<br />
WORKDEPT<br />
A00<br />
B01<br />
C01<br />
SUM<br />
128500.00<br />
41250.00<br />
90470.00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 70
Ahora sólo quiero ver los <strong>de</strong>partamentos<br />
cuya masa salarial sea superior a 50000<br />
SELECT WORKDEPT, SUM(SALARY) AS SUM<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT IN ('A00', 'B01', 'C01')<br />
GROUP BY WORKDEPT<br />
ORDER BY WORKDEPT<br />
WORKDEPT<br />
A00<br />
B01<br />
C01<br />
SUM<br />
128500.00<br />
41250.00<br />
90470.00<br />
Necesito, agrupado por <strong>de</strong>partmento, los<br />
trabajadores que no sean managers,<br />
<strong>de</strong>signer, y fieldrep, con una media <strong>de</strong><br />
salario mayor que 25000€.<br />
WORKDEPT<br />
A00<br />
A00<br />
A00<br />
C01<br />
GROUP BY-HAVING<br />
SELECT WORKDEPT, SUM(SALARY) AS SUM<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT IN ('A00', 'B01', 'C01')<br />
GROUP BY WORKDEPT<br />
HAVING SUM(SALARY) > 50000<br />
ORDER BY WORKDEPT<br />
WORKDEPT<br />
A00<br />
C01<br />
SUM<br />
128500.00<br />
90470.00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 71<br />
GROUP BY-HAVING<br />
SELECT WORKDEPT, JOB,AVG(SALARY) AS AVG<br />
FROM EMPLOYEE<br />
WHERE JOB NOT IN ('MANAGER', 'DESIGNER', 'FIELDREP')<br />
GROUP BY WORKDEPT, JOB<br />
HAVING AVG(SALARY) > 25000<br />
ORDER BY WORKDEPT, JOB<br />
JOB AVG<br />
CLERK<br />
PRES<br />
SALESREP<br />
ANALYST<br />
29250.00000000<br />
52750.00000000<br />
46500.00000000<br />
26110.00000000<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 72
SELECT 1<br />
WORKDEPT<br />
B01<br />
E01<br />
A00<br />
C01<br />
E21<br />
E11<br />
D21<br />
D11<br />
NUMB<br />
1<br />
1<br />
3<br />
3<br />
4<br />
5<br />
6<br />
9<br />
GROUP BY-HAVING<br />
• Mostrar los <strong>de</strong>partamentos con más <strong>de</strong> un empleado<br />
SELECT WORKDEPT, COUNT(* ) AS NUMB<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT<br />
ORDER BY NUMB, WORKDEPT<br />
SELECT 2<br />
SELECT WORKDEPT, COUNT(* ) AS NUMB<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT<br />
HAVING COUNT(*) > 1<br />
ORDER BY NUMB, WORKDEPT<br />
WORKDEPT<br />
A00<br />
C01<br />
E21<br />
E11<br />
D21<br />
D11<br />
NUMB<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 73<br />
GROUP BY-HAVING<br />
SELECT 1<br />
SELECT WORKDEPT, AVG(EDLEVEL) AS ED,<br />
AVG(YEAR(CURRENT_DATE-HIREDATE))<br />
AS YEARS<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT<br />
ORDER BY 2<br />
SELECT 2<br />
SELECT WORKDEPT, AVG(EDLEVEL) AS ED,<br />
AVG(YEAR(CURRENT_DATE-HIREDATE))<br />
AS YEARS<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT<br />
HAVING AVG(YEAR(CURRENT_DATE-HIREDATE)) > = 30<br />
ORDER BY 2<br />
WORKDEPT<br />
E11<br />
E21<br />
D21<br />
E01<br />
D11<br />
A00<br />
B01<br />
C01<br />
WORKDEPT<br />
E21<br />
E01<br />
A00<br />
ED<br />
14<br />
15<br />
15<br />
16<br />
16<br />
17<br />
18<br />
18<br />
ED<br />
15<br />
16<br />
17<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 74<br />
3<br />
3<br />
4<br />
5<br />
6<br />
9<br />
YEARS<br />
27<br />
31<br />
22<br />
49<br />
24<br />
35<br />
24<br />
23<br />
YEARS<br />
31<br />
49<br />
35
SELECT 1<br />
SELECT WORKDEPT, AVG(EDLEVEL) AS ED,<br />
MIN(BONUS) AS MIN<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT<br />
SELECT 2<br />
SELECT WORKDEPT, AVG(EDLEVEL) AS ED,<br />
MIN(BONUS) AS MIN<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT<br />
HAVING MIN(BONUS) = 300<br />
ORDER BY 2<br />
GROUP BY-HAVING<br />
WORKDEPT<br />
A00<br />
B01<br />
C01<br />
D11<br />
D21<br />
E01<br />
E11<br />
WORKDEPT<br />
E11<br />
D21<br />
ED<br />
17<br />
18<br />
18<br />
16<br />
15<br />
16<br />
14<br />
ED<br />
14<br />
15<br />
MIN<br />
600.00<br />
800.00<br />
500.00<br />
400.00<br />
300.00<br />
800.00<br />
300.00<br />
MIN<br />
300.00<br />
300.00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 75<br />
Ejecución <strong>de</strong> <strong>consulta</strong>s SELECT<br />
El or<strong>de</strong>n <strong>de</strong> ejecución <strong>de</strong> una <strong>consulta</strong> es el siguiente:<br />
1. Se aplica el predicado WHERE a las tuplas <strong>de</strong>l producto<br />
cartesiano/join/vista que hay en el FROM.<br />
2. Las tuplas que satisfacen el predicado <strong>de</strong> WHERE son<br />
colocadas en grupos siguiendo el patrón GROUP BY.<br />
3. Se ejecutan la cláusula HAVING para cada grupo <strong>de</strong> tuplas<br />
anterior.<br />
4. Los grupos obtenidos tras aplicar HAVING son los que<br />
serán procesados por SELECT, que calculará, en los casos<br />
que se incluyan, las funciones <strong>de</strong> agregación que le<br />
acompañan.<br />
5. A las tuplas resultantes <strong>de</strong> los pasos anteriores se le aplica<br />
la or<strong>de</strong>nación <strong>de</strong>scrita en la cláusula ORDER BY.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 76
Expresión condicional CASE<br />
<strong>SQL</strong> tiene una sentencia CASE similar a la instrucción CASE<br />
<strong>de</strong> los lenguajes <strong>de</strong> programación.<br />
La sintaxis general <strong>de</strong> esta expresión es:<br />
CASE<br />
WHEN C1 THEN result1<br />
WHEN C2 THEN result2<br />
...<br />
WHEN Cn THEN resultn<br />
ELSE resultx<br />
END<br />
Ci Condiciones<br />
A Columna<br />
Vi Literal<br />
CASE A<br />
WHEN V1 THEN result1<br />
WHEN V2 THEN result2<br />
...<br />
WHEN Vn THEN resultn<br />
ELSE resultx<br />
END<br />
La expresión CASE pue<strong>de</strong> aparecer tanto en la cláusula<br />
SELECT como en la cláusula WHERE.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 77<br />
Ejemplo <strong>de</strong> expresión condicional CASE<br />
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME,<br />
CASE<br />
WHEN EDLEVEL < 15 THEN 'SECONDARY'<br />
WHEN EDLEVEL < 19 THEN 'COLLEGE'<br />
ELSE 'POST GRADUATE'<br />
END AS EDUCATION<br />
FROM EMPLOYEE<br />
SELECT EMPNO, FIRSTNME,<br />
LASTNAME,<br />
CASE SEX<br />
WHEN 'F' THEN 'FEMALE'<br />
WHEN 'M' THEN 'MALE'<br />
ELSE 'INVALID VALUE'<br />
END AS SEX<br />
FROM EMPLOYEE<br />
WHERE SALARY < 18000<br />
EMPNO<br />
000260<br />
000290<br />
000300<br />
000310<br />
FIRSTNME LASTNAME SEX<br />
SYBIL<br />
JOHN<br />
PHILIP<br />
MAUDE<br />
JOHNSON<br />
PARKER<br />
SMITH<br />
SETRIGHT<br />
FEMALE<br />
MALE<br />
MALE<br />
FEMALE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 78
Casos especiales <strong>de</strong> CASE<br />
Existen dos casos especiales <strong>de</strong> uso <strong>de</strong> la expresión CASE para los que<br />
existe una expresión propia.<br />
NULLIF( exp, valor) Devuelve NULL si al evaluar exp es igual a<br />
valor.<br />
CASE<br />
WHEN exp = valor THEN NULL<br />
ELSE exp<br />
END<br />
COALESCE(valor 1 , …, valor n ) Devuelve el primer valor i que<br />
no sea NULL. Si no existe se <strong>de</strong>vuelve NULL.<br />
CASE<br />
WHEN valor 1 IS NOT NULL THEN valor 1<br />
WHEN valor 2 IS NOT NULL THEN valor 2<br />
WHEN valor n IS NOT NULL THEN valor n<br />
ELSE NULL<br />
END<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 79<br />
Obtener resultados con varias <strong>consulta</strong>s<br />
¿Qué salarios son mayores que el salario medio?<br />
1ra CONSULTA SELECT AVG(SALARY)<br />
FROM EMPLOYEE<br />
2a CONSULTA SELECT EMPNO, LASTNAME<br />
FROM EMPLOYEE<br />
WHERE SALARY > 27303<br />
27303<br />
SELECT EMPNO, LASTNAME<br />
FROM EMPLOYEE<br />
WHERE SALARY > (SELECT AVG(SALARY) FROM EMPLOYEE)<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 80
Ejemplo <strong>de</strong> sub<strong>consulta</strong><br />
¿Quién tiene el menor BONUS?<br />
SELECT EMPNO, LASTNAME, BONUS<br />
FROM EMPLOYEE<br />
WHERE BONUS = (SELECT MIN(BONUS) FROM EMPLOYEE)<br />
EMPNO<br />
000290<br />
LASTNAME BONUS<br />
PARKER 300<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 81<br />
Sub<strong>consulta</strong>s<br />
Una sub<strong>consulta</strong> es una instrucción SELECT-FROM-WHERE<br />
que está anidada <strong>de</strong>ntro <strong>de</strong> otra <strong>consulta</strong>.<br />
Una sub<strong>consulta</strong> pue<strong>de</strong> aparecer en<br />
SELECT La sub<strong>consulta</strong> se utilizará como valor <strong>de</strong> la columna <strong>de</strong><br />
la tabla resultante. La sub<strong>consulta</strong> <strong>de</strong>be <strong>de</strong>volver un único valor.<br />
FROM La sub<strong>consulta</strong> se utilizará como una tabla. Es necesario<br />
que le <strong>de</strong>mos nombre a esta tabla utilizando la clásula AS.<br />
WHERE La sub<strong>consulta</strong> es utilizada <strong>de</strong>ntro <strong>de</strong> los predicados para<br />
realizar comparaciones.<br />
Las sub<strong>consulta</strong>s pue<strong>de</strong>n <strong>de</strong>volver uno o varios valores.<br />
Dependiendo <strong>de</strong>l número <strong>de</strong> valores se utilizarán unos operadores u<br />
otros.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 82
Sub<strong>consulta</strong>s<br />
SELECT lista_seleccion<br />
FROM tabla<br />
WHERE expr operador<br />
(SELECT lista_seleccion<br />
FROM tabla);<br />
La sub<strong>consulta</strong> se ejecuta una vez antes <strong>de</strong> ejecutarse la<br />
<strong>consulta</strong> principal.<br />
Los resultados <strong>de</strong> la sub<strong>consulta</strong> son utilizados en la <strong>consulta</strong><br />
principal.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 83<br />
Sub<strong>consulta</strong>s (cont.)<br />
Si estamos seguros <strong>de</strong> que la sub<strong>consulta</strong> <strong>de</strong>vuelve un único<br />
valor, es posible utilizar los operadores <strong>de</strong> comparación<br />
habituales =, , .<br />
Para sub<strong>consulta</strong>s que <strong>de</strong>vuelven múltiples valores se pue<strong>de</strong>n<br />
utilizar los operadores<br />
IN / NOT IN<br />
Los operadores <strong>de</strong> comparación habituales junto a los<br />
cuantificadores ANY/SOME y ALL.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 84
¿Qué <strong>de</strong>partamentos no<br />
tienen proyectos<br />
asignados?<br />
Sub<strong>consulta</strong> con IN<br />
Tabla DEPARTMENT<br />
DEPTNO<br />
A00<br />
B01<br />
C01<br />
. . . . . .<br />
DEPTNAME<br />
SPIFFY COMPUTER SERVICE<br />
PLANNING<br />
INFORMATION CENTER<br />
SELECT DEPTNO, DEPTNAME<br />
FROM DEPARTMENT<br />
WHERE DEPTNO NOT IN (SELECT DEPTNO<br />
FROM PROJECT)<br />
Resultado sub<strong>consulta</strong><br />
Resultado final<br />
DEPTNO DEPTNAME<br />
B01<br />
C01<br />
A00 SPIFFY COMPUTER SERVICE<br />
D01<br />
D11<br />
D21<br />
E01<br />
E11<br />
<strong>Lenguaje</strong> <strong>SQL</strong> E21<br />
85<br />
¿Qué empleados tienen<br />
un salario mayor que la<br />
media <strong>de</strong> salarios <strong>de</strong><br />
todos los<br />
<strong>de</strong>partamentos?<br />
Resultado final<br />
LASTNAME<br />
HAAS<br />
LUCCHESI<br />
SALARY<br />
52750.00<br />
46500.00<br />
Sub<strong>consulta</strong> con ALL<br />
SELECT LASTNAME, SALARY<br />
FROM EMPLOYEE<br />
WHERE SALARY > ALL (SELECT AVG(SALARY)<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT)<br />
<strong>Lenguaje</strong> <strong>SQL</strong><br />
Resultado sub<strong>consulta</strong><br />
42833.33333333<br />
41250.00000000<br />
30156.66666666<br />
24677.77777777<br />
25153.33333333<br />
40175.00000000<br />
20998.00000000<br />
23827.50000000<br />
86
Sub<strong>consulta</strong> utilizando ANY o SOME<br />
¿Qué empleados <strong>de</strong>l<br />
<strong>de</strong>partamento E11<br />
tienen el salario mayor que la<br />
media <strong>de</strong> salarios <strong>de</strong> al menos un<br />
<strong>de</strong>partamento?<br />
Resultado Final<br />
LASTNAME<br />
HENDERSON<br />
SCHNEIDER<br />
SELECT LASTNAME, SALARY, WORKDEPT<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT = 'E11'<br />
AND SALARY > ANY (SELECT AVG(SALARY)<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT)<br />
ORDER BY LASTNAME<br />
SALARY<br />
29750.00<br />
26250.00<br />
WORKDEPT<br />
E11<br />
E11<br />
Resultado sub<strong>consulta</strong><br />
42833.33333333<br />
41250.00000000<br />
30156.66666666<br />
24677.77777777<br />
25153.33333333<br />
40175.00000000<br />
20998.00000000<br />
23827.50000000<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 87<br />
Sub<strong>consulta</strong> en la cláusula HAVING<br />
Necesito un listado <strong>de</strong> los <strong>de</strong>partamentos con un<br />
salario medio por empleado (sin director) mayor<br />
que el salario medio por empleado <strong>de</strong> la compañia<br />
(también sin directores). El resultado lo quiero <strong>de</strong><br />
forma que el <strong>de</strong>partamento que tenga mayor<br />
media sea el primero.<br />
Resultado final<br />
WORKDEPT<br />
A00<br />
C01<br />
SELECT WORKDEPT, AVG(SALARY) AS AVG_WORKDEPT<br />
FROM EMPLOYEE<br />
WHERE JOB 'MANAGER'<br />
GROUP BY WORKDEPT<br />
HAVING AVG(SALARY) ><br />
(SELECT AVG(SALARY)<br />
FROM EMPLOYEE<br />
WHERE JOB 'MANAGER')<br />
ORDER BY AVG_WORKDEPT DESC<br />
AVG_WORKDEPT<br />
42833.33333333<br />
26110.00000000<br />
Resultado sub<strong>consulta</strong><br />
25188.80000000<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 88
Sub<strong>consulta</strong>s correlacionadas<br />
En una sub<strong>consulta</strong> correlacionada se utilizan las tablas <strong>de</strong> la<br />
<strong>consulta</strong> principal.<br />
El or<strong>de</strong>n <strong>de</strong> ejecución <strong>de</strong> la <strong>consulta</strong> cambia.<br />
Primero se busca la tabla y filas especificadas por la <strong>consulta</strong><br />
principal.<br />
Posteriormente se ejecuta la sub<strong>consulta</strong> en la fila <strong>de</strong> la sub<strong>consulta</strong><br />
que está correlacionada con la <strong>consulta</strong> principal.<br />
Po<strong>de</strong>mos asemejarlo al anidamiento <strong>de</strong> bucles don<strong>de</strong> el<br />
índice <strong>de</strong>l bucle externo es utilizado en el bucle interno.<br />
EMPLOYEE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 89<br />
Sub<strong>consulta</strong>s correlacionadas<br />
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
000030 KWAN<br />
000120 O'CONNELL<br />
000130 QUINTANA<br />
000140 NICHOLLS<br />
A00<br />
C01<br />
A00<br />
C01<br />
C01<br />
52750.00<br />
38250.00<br />
29250.00<br />
23800.00<br />
28420.00<br />
SELECT EMPNO, LASTNAME, SALARY<br />
FROM EMPLOYEE<br />
WHERE SALARY ><br />
Media <strong>de</strong> salarios <strong>de</strong>l <strong>de</strong>pt.<br />
correspondiente<br />
A00<br />
AVG(SALARY)<br />
41000.00000000<br />
C01<br />
¿Qué empleado tiene el<br />
salario mayor que la media <strong>de</strong><br />
salarios <strong>de</strong> su <strong>de</strong>partamento?<br />
AVG(SALARY)<br />
30156.66666666<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 90
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
A00 52750.00<br />
000030 KWAN<br />
C01 38250.00<br />
000120 O'CONNELL A00 29250.00<br />
000130 QUINTANA C01 23800.00<br />
000140 NICHOLLS C01 28420.00<br />
EMPLOYEE<br />
EMPNO LASTNAME SALARY<br />
000010 HAAS 52750.00<br />
000030 KWAN 38250.00<br />
Sub<strong>consulta</strong>s correlacionadas<br />
SELECT EMPNO, LASTNAME, SALARY<br />
FROM EMPLOYEE E<br />
WHERE SALARY ><br />
(SELECT AVG(SALARY)<br />
FROM EMPLOYEE<br />
WHERE WORKDEPT =<br />
E. WORKDEPT)<br />
A00<br />
¿Qué empleado tiene el<br />
salario mayor que la media <strong>de</strong><br />
salarios <strong>de</strong> su <strong>de</strong>partamento?<br />
AVG(SALARY)<br />
41000.00000000<br />
C01<br />
AVG(SALARY)<br />
30156.66666666<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 91<br />
Sub<strong>consulta</strong>s correlacionadas con EXISTS<br />
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
A00 52750.00<br />
000030 KWAN C01 38250.00<br />
000120 O'CONNELL A00 29250.00<br />
000130 QUINTANA C01 23800.00<br />
000140 NICHOLLS C01 28420.00<br />
000400 WILSON null 25400.00<br />
DEPTNO DEPTNAME<br />
MGRNO<br />
A00 SPIFFY COMPUTER SERVICE DIV.<br />
C01 INFORMATION CENTER<br />
D01<br />
DEVELOPMENT CENTER<br />
SELECT DEPTNO, DEPTNAME<br />
FROM DEPARTMENT D<br />
WHERE NOT EXISTS<br />
(SELECT *<br />
FROM EMPLOYEE<br />
WHERE<br />
WORKDEPT = D.DEPTNO)<br />
EMPLOYEE<br />
000010<br />
000030<br />
-<br />
DEPARTMENT<br />
¿Qué <strong>de</strong>partamentos no<br />
tienen empleados?<br />
DEPTNO DEPTNAME<br />
D01 DEVELOPMENT CENTER<br />
RESULTADO<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 92
Modificación <strong>de</strong> la BBDD<br />
Las instrucciones <strong>SQL</strong> que permiten modificar el estado <strong>de</strong><br />
la BBDD son:<br />
INSERT Aña<strong>de</strong> filas a una tabla/vista <strong>de</strong> la BBDD<br />
UPDATE Actualiza filas <strong>de</strong> una tabla/vista <strong>de</strong> la BBDD<br />
DELETE Elimina filas <strong>de</strong> una tabla/vista <strong>de</strong> la BBDD<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 93<br />
La instrucción INSERT<br />
La inserción <strong>de</strong> tuplas se realiza con la sentencia INSERT,<br />
Es posible insertar directamente valores.<br />
O bien insertar el conjunto <strong>de</strong> resultados <strong>de</strong> una <strong>consulta</strong>.<br />
En cualquier caso, los valores que se insertan <strong>de</strong>ben pertenecer al<br />
dominio <strong>de</strong> cada uno <strong>de</strong> los atributos <strong>de</strong> la relación.<br />
Ejemplos: CLIENTES (DNI, NOMBRE, DIR)<br />
La inserción<br />
INSERT INTO CLIENTES VALUES (1111,'Mario',<br />
'C/. Mayor, 3');<br />
Es equivalente a las siguientes sentencias<br />
INSERT INTO CLIENTES (NOMBRE,DIR,DNI)<br />
VALUES ('Mario','C/. Mayor, 3',1111);<br />
INSERT INTO CLIENTES (DNI,DIR,NOMBRE)<br />
VALUES (1111,'C/. Mayor, 3’,'Mario');<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 94
Añadir una fila<br />
INSERT INTO TESTEMP<br />
VALUES ('000111', 'SMITH', 'C01', '1998-06-25', 25000, NULL)<br />
INSERT INTO TESTEMP(EMPNO, LASTNAME, WORKDEPT, HIREDATE, SALARY)<br />
VALUES ('000111', 'SMITH', 'C01', '1998-06-25', 25000)<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000111<br />
Ejemplo:<br />
SMITH<br />
C01<br />
1998-06-25 25000.00 -<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 95<br />
Añadir varias filas<br />
Para la siguiente base <strong>de</strong> datos, queremos incluir en la relación GRUPOS<br />
a todos los grupos, junto con su número <strong>de</strong> álbumes publicados:<br />
GRUPOS (NOMBRE, ALBUMES) LP (TIT, GRUPO, ANIO, NUM_CANC)<br />
Solución:<br />
INSERT INTO GRUPOS<br />
SELECT GRUPO, COUNT (DISTINCT TIT) FROM LP<br />
GROUP BY GRUPO;<br />
En <strong>SQL</strong> se prohíbe que la <strong>consulta</strong> que se incluye en una cláusula<br />
INSERT haga referencia a la misma tabla en la que se quieren<br />
insertar las tuplas.<br />
En ORACLE sí está permitido<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 96
TESTEMP<br />
Añadir varias filas (cont.)<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
INSERT INTO TESTEMP<br />
SELECT EMPNO,LASTNAME,WORKDEPT,HIREDATE,SALARY,BONUS<br />
FROM EMPLOYEE<br />
WHERE EMPNO < = '000050'<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000010<br />
000020<br />
000030<br />
000050<br />
000111<br />
HAAS<br />
THOMPSON<br />
KWAN<br />
GEYER<br />
SMITH<br />
A00<br />
B01<br />
C01<br />
E01<br />
C01<br />
1965-01-01<br />
1973-10-10<br />
1975-04-05<br />
1949-08-17<br />
1998-06-25<br />
52750.00<br />
41250.00<br />
38250.00<br />
40175.00<br />
25000.00<br />
1000.00<br />
800.00<br />
800.00<br />
800.00<br />
- - - - -<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 97<br />
La instrucción UPDATE<br />
La modificación <strong>de</strong> tuplas se realiza con la sentencia UPDATE,<br />
Es posible elegir el conjunto <strong>de</strong> tuplas que se van a actualizar usando la<br />
clausula WHERE.<br />
Ejemplos: CUENTAS (COD, DNI, NSUCURS, SALDO)<br />
Suma <strong>de</strong>l 5% <strong>de</strong> interés a los saldos <strong>de</strong> todas las cuentas.<br />
UPDATE CUENTAS SET SALDO = SALDO * 1.05;<br />
Suma <strong>de</strong>l 1% <strong>de</strong> bonificación a aquellas cuentas cuyo saldo sea superior a<br />
100.000 €.<br />
UPDATE CUENTAS SET SALDO = SALDO * 1.01<br />
WHERE SALDO > 100000;<br />
Modificación <strong>de</strong> DNI y saldo simultáneamente para el código 898.<br />
UPDATE CUENTAS SET DNI='555', SALDO=10000<br />
WHERE COD LIKE '898';<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 98
Antes:<br />
Modificar datos<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000010<br />
000020<br />
000030<br />
000050<br />
000111<br />
HAAS<br />
THOMPSON<br />
KWAN<br />
GEYER<br />
SMITH<br />
A00<br />
B01<br />
C01<br />
E01<br />
C01<br />
1965-01-01<br />
1973-10-10<br />
1975-04-05<br />
1949-08-17<br />
1998-06-25<br />
UPDATE TESTEMP<br />
SET BONUS = 500,<br />
SALARY = 26000<br />
WHERE EMPNO = '000111'<br />
52750.00<br />
41250.00<br />
38250.00<br />
40175.00<br />
25000.00<br />
1000.00<br />
800.00<br />
800.00<br />
800.00<br />
- - - - -<br />
Después:<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000010 HAAS A00<br />
1965-01-01 52750.00 1000.00<br />
000020 THOMPSON B01<br />
1973-10-10 41250.00 800.00<br />
000030 KWAN C01<br />
1975-04-05 38250.00 800.00<br />
000050 GEYER E01<br />
1949-08-17 40175.00 800.00<br />
000111 SMITH C01<br />
1998-06-25 26000.00 500.00<br />
Antes:<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 99<br />
Modificar datos<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000010<br />
000020<br />
000030<br />
000050<br />
000111<br />
HAAS<br />
THOMPSON<br />
KWAN<br />
GEYER<br />
SMITH<br />
A00<br />
B01<br />
C01<br />
E01<br />
C01<br />
1965-01-01<br />
1973-10-10<br />
1975-04-05<br />
1949-08-17<br />
1998-06-25<br />
UPDATE TESTEMP<br />
SET SALARY = SALARY + 1000<br />
WHERE WORKDEPT = 'C01'<br />
52750.00<br />
41250.00<br />
38250.00<br />
40175.00<br />
25000.00<br />
1000.00<br />
800.00<br />
800.00<br />
800.00<br />
- - - - -<br />
Después:<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000010 HAAS A00<br />
1965-01-01 52750.00 1000.00<br />
000020 THOMPSON B01<br />
1973-10-10 41250.00 800.00<br />
000030 KWAN C01<br />
1975-04-05 39250.00 800.00<br />
000050 GEYER E01<br />
1949-08-17 40175.00 800.00<br />
000111<br />
SMITH C01<br />
1998-06-25 26000.00 - - - - -<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 100
La instrucción DELETE<br />
La eliminación <strong>de</strong> tuplas se realiza con la sentencia DELETE:<br />
DELETE FROM R WHERE P; -- WHERE es opcional<br />
Elimina tuplas completas, no columnas. Pue<strong>de</strong> incluir sub<strong>consulta</strong>s.<br />
Ejemplos: para la BD <strong>de</strong> CLIENTES, CUENTAS, SUCURSALES.<br />
Eliminar todas cuentas con código entre 1000 y 1100.<br />
DELETE FROM CUENTAS WHERE COD BETWEEN 1000 AND<br />
1100;<br />
Eliminar todas las cuentas <strong>de</strong>l cliente “Jose María García”.<br />
DELETE FROM CUENTAS WHERE DNI IN<br />
(SELECT DNI FROM CLIENTES<br />
WHERE NOMBRE LIKE 'Jose María García');<br />
Eliminar todas las cuentas <strong>de</strong> sucursales situadas en "Chinchón".<br />
DELETE FROM CUENTAS WHERE NSUCURS IN<br />
(SELECT NSUC FROM SUCURSALES<br />
WHERE CIUDAD LIKE 'Chinchón');<br />
Antes:<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 101<br />
Borrar filas<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000010<br />
000020<br />
000030<br />
000050<br />
000111<br />
HAAS<br />
THOMPSON<br />
KWAN<br />
GEYER<br />
SMITH<br />
A00<br />
B01<br />
C01<br />
E01<br />
C01<br />
1965-01-01<br />
1973-10-10<br />
1975-04-05<br />
1949-08-17<br />
1998-06-25<br />
DELETE FROM TESTEMP<br />
WHERE EMPNO = '000111'<br />
52750.00<br />
41250.00<br />
38250.00<br />
40175.00<br />
25000.00<br />
1000.00<br />
800.00<br />
800.00<br />
800.00<br />
- - - - -<br />
Después:<br />
EMPNO LASTNAME WORKDEPT HIREDATE SALARY BONUS<br />
000010 HAAS A00<br />
1965-01-01 52750.00 1000.00<br />
000020 THOMPSON B01<br />
1973-10-10 41250.00 800.00<br />
000030 KWAN C01<br />
1975-04-05 38250.00 800.00<br />
000050<br />
GEYER E01<br />
1949-08-17 40175.00 800.00<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 102
Creación <strong>de</strong> Tablas<br />
La creación <strong>de</strong> tablas se lleva a cabo con la sentencia<br />
CREATE TABLE.<br />
Ejemplo: creación <strong>de</strong>l siguiente esquema <strong>de</strong> BD.<br />
CLIENTES (DNI, NOMBRE, DIR) SUCURSALES (NSUC, CIUDAD)<br />
CUENTAS (COD, DNI, NSUCURS, SALDO)<br />
Se empieza por las tablas más in<strong>de</strong>pendientes:<br />
CREATE TABLE CLIENTES (<br />
DNI VARCHAR(9) NOT NULL,<br />
NOMBRE VARCHAR(20),<br />
DIR VARCHAR(30),<br />
PRIMARY KEY (DNI)<br />
);<br />
CREATE TABLE SUCURSALES (<br />
NSUC VARCHAR(4) NOT NULL,<br />
CIUDAD VARCHAR(30),<br />
PRIMARY KEY (NSUC)<br />
);<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 103<br />
Creación <strong>de</strong> Tablas (cont.)<br />
El siguiente paso es crear la tabla CUENTAS, con las claves externas:<br />
CREATE TABLE CUENTAS (<br />
COD VARCHAR(4) NOT NULL,<br />
DNI VARCHAR(9) NOT NULL,<br />
NSUCURS VARCHAR(4) NOT NULL,<br />
SALDO INT DEFAULT 0,<br />
PRIMARY KEY (COD, DNI, NSUCURS),<br />
FOREIGN KEY (DNI) REFERENCES CLIENTES (DNI),<br />
FOREIGN KEY (NSUCURS) REFERENCES SUCURSALES (NSUC) );<br />
Las claves candidatas, es <strong>de</strong>cir, aquellos atributos no pertenecientes a la<br />
clave que no <strong>de</strong>ben alojar valores repetidos, se pue<strong>de</strong>n indicar con la<br />
clausula UNIQUE.<br />
Es posible crear una tabla como resultado <strong>de</strong> una <strong>consulta</strong>:<br />
CREATE TABLE NUEVA_TABLA AS SELECT ...<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 104
Modificación y eliminación <strong>de</strong> tablas<br />
Modificación <strong>de</strong> tablas: sentencia ALTER TABLE.<br />
Es posible añadir, modificar y eliminar campos. Ejemplos:<br />
Adición <strong>de</strong>l campo PAIS a la tabla CLIENTES<br />
ALTER TABLE CLIENTES ADD PAIS VARCHAR(10);<br />
Modificación <strong>de</strong>l tipo <strong>de</strong>l campo PAIS<br />
ALTER TABLE CLIENTES MODIFY PAIS VARCHAR(20);<br />
Eliminación <strong>de</strong>l campo PAIS <strong>de</strong> la tabla CLIENTES<br />
ALTER TABLE CLIENTES DROP PAIS;<br />
También es posible añadir nuevas restricciones a la tabla (claves<br />
externas, restricciones check).<br />
Eliminación <strong>de</strong> tablas: sentencia DROP TABLE.<br />
DROP TABLE CUENTAS;<br />
-- Las tablas a las que referencia <strong>de</strong>ben haber sido<br />
eliminadas antes.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 105<br />
Vistas<br />
Una vista es una "tabla virtual".<br />
La diferencia principal con respecto a las tablas normales es que<br />
habitualmente no ocupan espacio en disco.<br />
Las vistas pue<strong>de</strong>n ser utilizadas en las <strong>consulta</strong>s como otra tabla más.<br />
Habitualmente las vistas son creadas para combinar información <strong>de</strong><br />
múltiples tablas.<br />
Integración <strong>de</strong> diferentes BBDD.<br />
También es habitual su uso por razones <strong>de</strong> seguridad.<br />
Po<strong>de</strong>mos filtrar las columnas y/o filas a las que un usuario tiene acceso.<br />
Su sintaxis es:<br />
CREATE VIEW nombre [(col1,...)]<br />
AS instruccion_select<br />
[WITH CHECK OPTION]<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 106
Tabla EMPLOYEE<br />
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
000030 KWAN<br />
000120 O'CONNELL<br />
000130 QUINTANA<br />
000140 NICHOLLS<br />
Vista EMP_DEPT<br />
A00<br />
C01<br />
A00<br />
C01<br />
C01<br />
52750.00<br />
38250.00<br />
29250.00<br />
23800.00<br />
28420.00<br />
Vistas<br />
Tabla DEPARTMENT<br />
DEPTNO DEPTNAME<br />
MGRNO<br />
A00 SPIFFY COMPUTER SERVICE DIV. 000010<br />
C01 INFORMATION CENTER<br />
000030<br />
D01<br />
DEVELOPMENT CENTER<br />
CREATE VIEW EMP_DEPT (NAME, DEPARTMENT)<br />
AS SELECT LASTNAME, DEPTNAME<br />
FROM EMPLOYEE, DEPARTMENT<br />
WHERE WORKDEPT = DEPTNO<br />
SELECT * FROM EMP_DEPT;<br />
NAME<br />
HAAS<br />
O'CONNELL<br />
KWAN<br />
NICHOLLS<br />
QUINTANA<br />
PROJNO PROJNAME<br />
DEPTNO RESPEMP<br />
AD3100 ADMIN SERVICES D01 000010<br />
IF1000 QUERY SERVICES C01 000030<br />
IF2000 USER EDUCATION C01 000030<br />
Tabla PROJECT<br />
DEPARTMENT<br />
SPIFFY COMPUTER SERVICE DIV.<br />
SPIFFY COMPUTER SERVICE DIV.<br />
INFORMATION CENTER<br />
INFORMATION CENTER<br />
INFORMATION CENTER<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 107<br />
Vistas<br />
DEPTNO DEPTNAME<br />
MGRNO<br />
A00 SPIFFY COMPUTER SERVICE DIV. 000010<br />
C01 INFORMATION CENTER<br />
000030<br />
D01<br />
Tabla DEPARTMENT<br />
PROJNAME DEPTNAME<br />
MGRNO<br />
USER EDUCATION INFORMATION CENTER<br />
000030<br />
QUERY SERVICES INFORMATION CENTER<br />
000030<br />
ADMIN SERVICES SPIFFY COMPUTER SERVICE DIV.<br />
Vista PROJ_DEPT<br />
DEVELOPMENT CENTER<br />
PROJECT DEPARTMENT<br />
MANAGER<br />
USER EDUCATION INFORMATION CENTER<br />
KWAN<br />
QUERY SERVICES INFORMATION CENTER<br />
KWAN<br />
ADMIN SERVICES SPIFFY COMPUTER SERVICE DIV.<br />
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
A00 52750.00<br />
000030 KWAN<br />
C01 38250.00<br />
000120 O'CONNELL A00 29250.00<br />
000130 QUINTANA C01 23800.00<br />
000140 NICHOLLS C01 28420.00<br />
Vista PROJ_DEPT_MGR<br />
Tabla EMPLOYEE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 108
Vistas<br />
CREATE VIEW EMP_SALARY_DEPT (NAME, SALARY, DEPARTMENT)<br />
AS SELECT LASTNAME, SALARY, DEPTNAME<br />
FROM EMPLOYEE INNER JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
WHERE DEPTNO = 'C01'<br />
SELECT NAME, SALARY<br />
FROM EMP_SALARY_DEPT<br />
WHERE SALARY > 25000<br />
ES COMO SI ...<br />
SELECT LASTNAME AS NAME, SALARY<br />
FROM EMPLOYEE INNER JOIN DEPARTMENT<br />
ON WORKDEPT = DEPTNO<br />
WHERE DEPTNO = 'C01' AND<br />
SALARY > 25000<br />
Tabla EMPLOYEE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 109<br />
Vistas<br />
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
000030 KWAN<br />
000120 O'CONNELL<br />
000130 QUINTANA<br />
000140 NICHOLLS<br />
A00<br />
C01<br />
A00<br />
C01<br />
C01<br />
52750.00<br />
38250.00<br />
29250.00<br />
23800.00<br />
28420.00<br />
CREATE VIEW DEPT_SALARIES (DEPARTMENT, TOTAL_SALARY)<br />
AS SELECT WORKDEPT, SUM(SALARY)<br />
FROM EMPLOYEE<br />
GROUP BY WORKDEPT<br />
Vista DEPT_SALARIES<br />
DEPARTMENT TOTAL_SALARY<br />
A00 82000.00<br />
C01 90470.00<br />
SELECT MAX(TOTAL_SALARY) AS MAXIMUM_SALARY<br />
FROM DEPT_SALARIES<br />
MAXIMUM_SALARY<br />
PASO 1<br />
90470.00 PASO 2<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 110
Actualización <strong>de</strong> vistas<br />
Las vistas pue<strong>de</strong>n ser utilizadas en <strong>consulta</strong>s.<br />
Sin embargo, también se pue<strong>de</strong>n <strong>de</strong>finir vistas actualizables.<br />
Estas vistas tienen que cumplir ciertas restricciones en la instrucción <strong>de</strong><br />
selección que la <strong>de</strong>fine.<br />
Restricciones <strong>de</strong> la instrucción SELECT que <strong>de</strong>fine la vista<br />
No pue<strong>de</strong> contener ningún join, es <strong>de</strong>cir, la vista <strong>de</strong>be estar <strong>de</strong>finida sobre<br />
una única tabla o vista (en este caso, la vista <strong>de</strong>be ser actualizable).<br />
Todas las columnas obligatorias (NOT NULL) <strong>de</strong>ben aparecer en la<br />
<strong>de</strong>finición <strong>de</strong> la vista.<br />
La <strong>consulta</strong> no contiene operadores <strong>de</strong> conjunto como UNION, EXCEPT o<br />
INTERSECT. La cláusula DISTINCT tampoco está permitida.<br />
Ninguna expresión <strong>de</strong> agregación pue<strong>de</strong> estar incluida en la cláusula<br />
SELECT.<br />
No se pue<strong>de</strong> utilizar la cláusula GROUP BY.<br />
Tabla EMPLOYEE<br />
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
A00 52750.00<br />
000030 KWAN<br />
C01 38250.00<br />
000120 O'CONNELL A00 29250.00<br />
000130 QUINTANA C01 23800.00<br />
000140 NICHOLLS C01 28420.00<br />
Vista EMP_DEPT<br />
NAME DEPARTMENT<br />
HAAS<br />
O'CONNELL<br />
KWAN<br />
NICHOLLS<br />
QUINTANA<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 111<br />
Vistas <strong>de</strong> lectura<br />
Tabla DEPARTMENT<br />
DEPTNO DEPTNAME<br />
MGRNO<br />
A00 SPIFFY COMPUTER SERVICE DIV. 000010<br />
C01 INFORMATION CENTER<br />
000030<br />
D01<br />
DEVELOPMENT CENTER<br />
SPIFFY COMPUTER SERVICE DIV.<br />
SPIFFY COMPUTER SERVICE DIV.<br />
INFORMATION CENTER<br />
INFORMATION CENTER<br />
INFORMATION CENTER<br />
UPDATE EMP_DEPT<br />
SET DEPARTMENT = 'DEVELOPMENT CENTER'<br />
WHERE NAME = 'KWAN'<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 112
Restricciones en las vistas<br />
<strong>SQL</strong>3 no permite <strong>de</strong>finir restricciones explícitas sobre vistas.<br />
Sin embargo, la cláusula CHECK OPTION pue<strong>de</strong><br />
consi<strong>de</strong>rarse como un tipo <strong>de</strong> restricción.<br />
Si se utiliza CHECK OPTION en la creación <strong>de</strong> una vista el<br />
SGBD no permite que una instrucción <strong>de</strong> manipulación <strong>de</strong> la<br />
BBDD genere o actualice filas que no estén incluidas en la<br />
<strong>consulta</strong> que ha generado la tabla.<br />
Tabla EMPLOYEE<br />
CREATE VIEW SALARIES_1<br />
AS<br />
SELECT EMPNO, LASTNAME, SALARY<br />
FROM EMPLOYEE<br />
WHERE SALARY < 40000<br />
UPDATE SALARIES_1<br />
SET SALARY = 42000<br />
WHERE EMPNO = '000030'<br />
FUNCIONA!<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 113<br />
Opción check<br />
EMPNO LASTNAME WORKDEPT SALARY<br />
000010 HAAS<br />
A00 52750.00<br />
000030 KWAN<br />
C01 38250.00<br />
000120 O'CONNELL A00 29250.00<br />
000130 QUINTANA C01 23800.00<br />
000140 NICHOLLS C01 28420.00<br />
CREATE VIEW SALARIES_2<br />
AS<br />
SELECT EMPNO, LASTNAME, SALARY<br />
FROM EMPLOYEE<br />
WHERE SALARY < 40000<br />
WITH CHECK OPTION<br />
UPDATE SALARIES_2<br />
SET SALARY = 42000<br />
WHERE EMPNO = '000030'<br />
NO SE PUEDE!<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 114
Cláusula WITH<br />
La norma <strong>SQL</strong> 1999 introduce la cláusula WITH con dos<br />
propósitos:<br />
Factorización <strong>de</strong> sub<strong>consulta</strong>s<br />
Definición <strong>de</strong> <strong>consulta</strong>s recursivas.<br />
Aunque WITH forma parte <strong>de</strong> la norma, el IBM DB2 es uno<br />
<strong>de</strong> los pocos SGBD que implementa el comportamiento<br />
recursivo <strong>de</strong> esta cláusula.<br />
ORACLE por su parte ofrece una sintaxis y comportamiento<br />
alternativos para la recursión.<br />
Cláusula CONNECT BY PRIOR.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 115<br />
Factorización <strong>de</strong> sub<strong>consulta</strong>s<br />
EMPNO LASTNAME WORKDEPT SALARY HIREDATE<br />
000010 HAAS<br />
A00 52750.00 1965-01-01<br />
000030 KWAN C01 38250.00 1975-04-05<br />
000120 O'CONNELL A00 29250.00 1963-12-05<br />
000130 QUINTANA C01 23800.00 1971-07-28<br />
000140 NICHOLLS C01 28420.00 1976-12-15<br />
HIREDECADE MINIMUM_SALARY<br />
1960 - 9 29250.00<br />
1970 - 9 23800.00<br />
EMPLOYEE<br />
SELECT S.HIREDECADE, MIN(S.SALARY) AS MINIMUM_SALARY<br />
FROM<br />
(<br />
SELECT SUBSTR(CHAR(HIREDATE,ISO),1,3)<br />
CONCAT '0 - 9' AS HIREDECADE,<br />
SALARY<br />
FROM EMPLOYEE<br />
) AS S<br />
GROUP BY S.HIREDECADE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 116
Factorización <strong>de</strong> sub<strong>consulta</strong>s (cont.)<br />
SELECT E.EMPNO, E.LASTNAME, E.HIREDECADE, E.SALARY, M.MINIMUM_SALARY<br />
FROM<br />
(<br />
SELECT EMPNO, LASTNAME,SALARY,<br />
SUBSTR(CHAR(HIREDATE,ISO),1,3) CONCAT '0 - 9'<br />
AS HIREDECADE<br />
FROM EMPLOYEE<br />
) AS E<br />
INNER JOIN<br />
(<br />
SELECT S.HIREDECADE, MIN(S.SALARY) AS MINIMUM_SALARY<br />
FROM<br />
(<br />
SELECT SUBSTR(CHAR(HIREDATE,ISO),1,3)<br />
CONCAT '0 - 9' AS HIREDECADE,<br />
SALARY<br />
FROM EMPLOYEE<br />
) AS S<br />
GROUP BY S.HIREDECADE<br />
) AS M<br />
ON E.HIREDECADE = M.HIREDECADE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 117<br />
Factorización <strong>de</strong> sub<strong>consulta</strong>s (cont.)<br />
WITH<br />
E AS<br />
(<br />
SELECT EMPNO, LASTNAME, SALARY,<br />
SUBSTR(CHAR(HIREDATE,ISO),1,3) CONCAT '0 - 9'<br />
AS HIREDECADE<br />
FROM EMPLOYEE<br />
),<br />
M (HIREDECATE, MINIMUM_SALARY) AS<br />
(<br />
SELECT HIREDECADE, MIN(SALARY)<br />
FROM E<br />
GROUP BY HIREDECADE<br />
)<br />
SELECT E.EMPNO, E.LASTNAME, E.HIREDECADE,<br />
E.SALARY, M.MINIMUM_SALARY<br />
FROM E INNER JOIN M<br />
ON E.HIREDECADE = M.HIREDECADE<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 118
Consultas recursivas<br />
Una <strong>consulta</strong> recursiva es una <strong>consulta</strong> que <strong>de</strong>pen<strong>de</strong> sobre<br />
si misma.<br />
Ejemplo:<br />
JEFE(NOMBRE_EMPLEADO, NOMBRE_JEFE)<br />
Determinar los empleados que supervisa directa o indirectamente<br />
Lopez.<br />
La ejecución <strong>de</strong> esta <strong>consulta</strong> se llevaría a cabo <strong>de</strong> esta<br />
manera:<br />
1. Obtención <strong>de</strong> los empleados supervisados por Lopez<br />
2. Obtención <strong>de</strong> los empleados supervisados por los supervisados por<br />
Lopez.<br />
3. Repetir el paso 2 hasta que un empleado no supervise a nadie.<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 119<br />
Consultas recursivas (cont.)<br />
A este tipo <strong>de</strong> <strong>consulta</strong>s se le <strong>de</strong>nomina cierre transitivo.<br />
Existen numerosas aplicaciones en las que es necesario<br />
calcular el cierre transitivo sobre una jerarquía.<br />
Destino <strong>de</strong> vuelos<br />
Partes <strong>de</strong> un coche<br />
Departamentos en una empresa<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 120
<strong>SQL</strong> Recursivo<br />
WITH<br />
RPL (PART, SUBPART, QUANTITY) AS<br />
(<br />
SELECT <strong>de</strong> iniciación<br />
SELECT ROOT.PART, ROOT.SUBPART, ROOT.QUANTITY<br />
FROM PARTLIST ROOT<br />
WHERE ROOT.PART = '01'<br />
UNION ALL<br />
SELECT iterativa<br />
SELECT CHILD.PART, CHILD.SUBPART, CHILD.QUANTITY<br />
FROM RPL PARENT, PARTLIST CHILD<br />
WHERE PARENT.SUBPART = CHILD.PART<br />
)<br />
SELECT principal<br />
SELECT PART, SUBPART, SUM(QUANTITY) AS QUANTITY<br />
FROM RPL<br />
GROUP BY PART, SUBPART<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 121<br />
<strong>SQL</strong> Recursivo. Iniciación<br />
SELECT ROOT.PART, ROOT.SUBPART, ROOT.QUANTITY<br />
FROM PARTLIST ROOT<br />
WHERE ROOT.PART = '01'<br />
PART SUBPART QUANTITY<br />
00 01 5<br />
00 05 3<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
05 10 10<br />
05 11 10<br />
06 12 10<br />
06 13 10<br />
07 12 8<br />
07 14 8<br />
PART SUBPART QUANTITY<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
RPL<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 122
<strong>SQL</strong> Recursivo. Iteración 1<br />
SELECT CHILD.PART, CHILD.SUBPART, CHILD.QUANTITY<br />
FROM RPL PARENT, PARTLIST CHILD<br />
WHERE PARENT.SUBPART = CHILD.PART<br />
PART SUBPART QUANTITY<br />
00 01 5<br />
00 05 3<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
05 10 10<br />
05 11 10<br />
06 12 10<br />
06 13 10<br />
07 12 8<br />
07 14 8<br />
Tabla<br />
PARTLIST<br />
PART SUBPART QUANTITY<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
06 12 10<br />
06 13 10<br />
RPL<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 123<br />
<strong>SQL</strong> Recursivo. Iteración 2<br />
SELECT CHILD.PART, CHILD.SUBPART, CHILD.QUANTITY<br />
FROM RPL PARENT, PARTLIST CHILD<br />
WHERE PARENT.SUBPART = CHILD.PART<br />
PART SUBPART QUANTITY<br />
00 01 5<br />
00 05 3<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
05 10 10<br />
05 11 10<br />
06 12 10<br />
06 13 10<br />
07 12 8<br />
07 14 8<br />
Tabla PARTLIST<br />
No hay<br />
correspon<strong>de</strong>ncia<br />
en tabla PARTLIST<br />
PART SUBPART QUANTITY<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
06 12 10<br />
06 13 10<br />
05 10 10<br />
05 11 10<br />
06 12 10<br />
06 13 10<br />
07 12 8<br />
07 14<br />
RPL<br />
8<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 124
<strong>SQL</strong> Recursivo. Resultado<br />
SELECT PART, SUBPART, SUM(QUANTITY) AS QUANTITY<br />
FROM RPL<br />
GROUP BY PART, SUBPART<br />
PART SUBPART QUANTITY<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
06 12 10<br />
06 13 10<br />
05 10 10<br />
05 11 10<br />
06 12 10<br />
06 13 10<br />
07 12 8<br />
07 14 8<br />
PART SUBPART QUANTITY<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
05 10 10<br />
05 11 10<br />
06 12 20<br />
06 13 20<br />
07 12 8<br />
07 14 8<br />
Resultado final<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 125<br />
<strong>SQL</strong> Recursivo. Control <strong>de</strong> recursión<br />
WITH<br />
RPL (LEVEL, PART, SUBPART, QUANTITY) AS<br />
(<br />
SELECT <strong>de</strong> iniciación<br />
SELECT 0, ROOT.PART, ROOT.SUBPART, ROOT.QUANTITY<br />
FROM PARTLIST ROOT<br />
WHERE ROOT.PART = '01'<br />
UNION ALL<br />
SELECT iterativa<br />
SELECT PARENT.LEVEL + 1, CHILD.PART,<br />
CHILD.SUBPART,<br />
CHILD.QUANTITY<br />
FROM RPL PARENT, PARTLIST CHILD<br />
WHERE PARENT.SUBPART = CHILD.PART AND<br />
PARENT.LEVEL < 2<br />
)<br />
SELECT LEVEL, PART, SUBPART, SUM(QUANTITY) AS QUANTITY<br />
FROM RPL<br />
GROUP BY PART, SUBPART<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 126
<strong>SQL</strong> Recursivo. Control <strong>de</strong> recursión<br />
PART SUBPART QUANTITY<br />
00 01 5<br />
00 05 3<br />
01 02 2<br />
01 03 3<br />
01 04 4<br />
01 06 3<br />
02 05 7<br />
02 06 6<br />
03 07 6<br />
04 08 10<br />
04 09 11<br />
05 10 10<br />
05 11 10<br />
06 12 10<br />
06 13 10<br />
07 12 8<br />
07 14 8<br />
Tabla PARTLIST<br />
LEVEL<br />
PART SUBPART QUANTITY<br />
0 00 01 5<br />
0 00 05 3<br />
1 01 02 2<br />
1 01 03 3<br />
1 01 04 4<br />
1 01 06 3<br />
1 05 10 10<br />
1 05 11 10<br />
2 02 05 7<br />
2 02 06 6<br />
2 03 07 6<br />
2 04 08 10<br />
2 04 09 11<br />
2 06 12 10<br />
2 06 13 10<br />
Resultado final<br />
<strong>Lenguaje</strong> <strong>SQL</strong> 127