07.05.2013 Views

Tema 3: Lenguaje de consulta SQL

Tema 3: Lenguaje de consulta SQL

Tema 3: Lenguaje de consulta SQL

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!