Tabla de Contenidos

Lenguaje SQL en MYSQL

Creación de tablas

Formato básico

La forma más básica de crear una tabla es de la siguiente manera:

CREATE TABLE [IF NOT EXISTS] NombreTabla (
    NombreColumna TipoDato [,
    NombreColumna TipoDato] ...);

Ésta es una tabla simple sin restricciones.
Ejemplo:

CREATE TABLE socios (
    socio_no INT(4),
    apellidos VARCHAR(14),
    telefono CHAR(9),
    fecha_alta DATE,
    direccion VARCHAR(20),
    codigo_postal INT(5));

Restricciones

Las restricciones son importantes en cuanto a la implementación del modelo relacional, y su función es especificar limitaciones en los valores que pueden tomar los datos en cada columna de la tabla.
Hay varios tipos:

Creación de tablas con restricciones (CONSTRAINTS)

Hay dos maneras de definir las restricciones en una tabla: a nivel de columna o a nivel de tabla.
Es posible dar un nombre a las restricciones o CONSTRAINTS, de forma que podamos referirnos a ellas después, si las queremos borrar o modificar.

Creación de tablas con restricciones a nivel de columna

De esta manera las restricciones afectan sólo a una columna, la que se está definiendo en cada momento. Definimos la restricción cuando definimos cada columna:

CREATE TABLE [IF NOT EXISTS] NombreTabla (

  NombreColumna TipoDato [Restricción1] [,
  NombreColumna TipoDato [Restricción2]] ...]);

De esta forma se pueden definir las siguientes restricciones:

Ejemplos:

CREATE TABLE socios (
    socio_no INT(4) PRIMARY KEY AUTO_INCREMENT,
    apellidos VARCHAR(14) UNIQUE,
    telefono CHAR(9) NOT NULL,
    fecha_alta DATE DEFAULT CURDATE(),
    direccion VARCHAR(20),
    codigo_postal INT(5) CHECK (codigo_postal BETWEEN 28000 AND 28999) );
CREATE TABLE prestamos (
    num_prestamo INT(2) PRIMARY KEY AUTO_INCREMENT,
    socio_no INT(4) REFERENCES socios (socio_no) );

Creación de tablas con restricciones a nivel de tabla

De esta manera las restricciones pueden afectar a una única columna o a varias y puede darse un nombre a cada restricción.
Definimos las restricciones al final de la sentencia, cuando ya hemos definimos todas las columnas:

CREATE TABLE [IF NOT EXISTS] NombreTabla (

  NombreColumna TipoDato [,
  NombreColumna TipoDato] ... [,
  Restricción1, 
  Restricción2, ...]);

En este caso las restricciones que pueden definirse son más limitadas:

Ejemplos:

CREATE TABLE socios (
    socio_no INT(4),
    apellidos VARCHAR(14),
    telefono CHAR(9),
    fecha_alta DATE,
    direccion VARCHAR(20),
    codigo_postal INT(5),
    CONSTRAINT pk_socios PRIMARY KEY (socio_no),
    CONSTRAINT uq_apellidos UNIQUE (apellidos),
    CONSTRAINT ck_codpostal CHECK (codigo_postal BETWEEN 28000 AND 28999) );
CREATE TABLE prestamos (
    num_prestamo INT(2),
    socio_no INT(4),
    CONSTRAINT pk_prestamos PRIMARY KEY (num_prestamo),
    CONSTRAINT fk_socios FOREIGN KEY (socio_no) REFERENCES socios(socio_no) );

Integridad referencial

La definición de claves ajenas nos permiten mantener la integridad referencial de una base de datos relacional.
Para mantener la integridad de los datos al borrar (DELETE) o modificar (UPDATE) una fila referenciada, por defecto el sistema no nos dejará llevarlo a cabo si existe una fila con el valor referenciado. También se conoce como RESTRICT.

Al definir la clave ajena existen varias opciones para mantener la integridad referencial:

El formato es el siguiente:

  REFERENCES NombreTabla [ ( NombreColumna [, NombreColumna ] ) ]
      [ON DELETE {CASCADE | SET NULL | NO ACTION | SET DEFAULT | RESTRICT} ]
      [ON UPDATE {CASCADE | SET NULL | NO ACTION | SET DEFAULT | RESTRICT} ]

Vemos un ejemplo:

CREATE TABLE prestamos (
    num_prestamo INT(2),
    socio_no INT(4),
    CONSTRAINT pk_prestamos PRIMARY KEY (num_prestamo),
    CONSTRAINT fk_socios FOREIGN KEY (socio_no) REFERENCES socios(socio_no) 
      ON DELETE NO ACTION
      ON UPDATE CASCADE);

Formato completo de la creación de tablas

  CREATE TABLE [IF NOT EXISTS] NombreTabla (
      NombreColumna TipoDato [RestriccionTipoColumna1]
      [, NombreColumna TipoDato [RestriccionTipoColumna2] ...]
      [, RestriccionTipoTabla1] 
      [, restriccionTipoTabla2]... );

Pueden utilizarse en la misma sentencia ambos tipos de restricciones (tabla y columna), siempre que afecten a columnas distintas.

Edición y borrado de tablas

Modificación de tablas

Una vez ya existe una tabla, es posible realizar modificaciones en su estructura. Para ello usamos la sentencia ALTER TABLE:

  ALTER TABLE NombreTabla
  EspecificacionModificacion [, EspecificacionModificacion...];

A continuación se especifican las posibles modificaciones que pueden realizarse en la estructura de una tabla:

Eliminación de tablas

Para eliminar una tabla, se utiliza la siguiente sentencia:

  DROP TABLE [IF EXISTS] NombreTabla
  [CASCADE | RESTRICT];

Renombrado de una tabla

Para cambiar el nombre de una tabla, usamos el siguiente formato:

  RENAME TABLE NombreTablaAntiguo TO NombreTablaNuevo
  [, NombreTablaAntiguo TO NombreTablaNuevo ...];

Como se observa en la caja superior, en una misma sentencia es posible renombrar varias tablas.

Actualización de tablas

Inserción de nuevas filas en la base de datos

El formato para añadir nuevas filas en una tabla es:

  INSERT INTO NombreTabla [ (NombreColumna [, NombreColumna ...]) ]
  VALUES (Expresion [,Expresion ...] );

Como se ve en la caja superior, la lista de columnas a introducir es opcional, ya que es posible no indicarla, en cuyo caso se esperarán valores para todas las columnas. Además, la lista de valores a insertar deberá coincidir en número y posición con las columnas de la tabla.

Modificación de filas

Es posible modificar datos en las columnas de las filas ya insertadas:

  UPDATE NombreTabla
  SET NombreColumna = Expresion 
      [, NombreColumna = Expresion ...]
  [WHERE Condicion];

Como se ve, puede indicarse una condición opcional, de forma que podamos filtrar las filas que serán modificadas.

Eliminación de filas

Para eliminar filas usamos la sentencia:

  DELETE FROM NombreTabla
  [WHERE Condicion];

De nuevo, puede indicarse una condición opcional, de forma que podamos filtrar las filas que serán eliminadas. Si no se especifica ninguna condición serán borradas TODAS las filas de la tabla.

Consultas sencillas

La forma más básica de hacer consultas es a través de la siguiente sentencia:

  SELECT { *|[ALL/DISTINCT] ExpresionColumna [[AS] AliasColumna]
                           [, ExpresionColumna [[AS] AliasColumna]...] }
  FROM NombreTabla [AliasTabla]
  [WHERE CondicionSeleccion]
  [ORDER BY {ExpresionColumna|Posicion}[ASC|DESC]
          [,{ExpresionColumna|Posicion}[ASC|DESC]...] ]
  [LIMIT [m,]n];

Como se observa, muchas sentencias son opcionales, y sirven para filtrar los posibles resultados.
A continuación se verá el significado de cada parte de esta sentencia.

SELECT ... FROM

Es la sentencia obligatoria más básica:

Alias

Se pueden utilizar alias, tanto para tablas como para columnas. Los alias especifican un nombre alternativo para la tabla o columna, a través del cual nos podemos referir a ella.
Puede haber dos motivos para asignar alias:

Se puede definir un alias con la cláusula AS, o poniendo directamente el nombre entre comillas dobles o simples.

WHERE

Con la sentencia opcional WHERE podemos filtrar los valores a recuperar, a través de una condición. Para cada fila se evalúa la condición, y retornará las expresiones siempre que el resultado de la expresión sea TRUE.

ORDER BY

Con esta sentencia ordenamos los resultados (expresiones) devueltas por la consulta. En caso de que haya varias expresiones para ordenar, se comenzará ordenando de izquierda a derecha.
Se puede ordenar seleccionando una expresión de columna o una determinada expresión de la sentencia SELECT, indicando la posición de la expresión en la sentencia SELECT por la que se quiere ordenar.

LIMIT

Con la sentencia LIMIT, se pueden establecer límite al número de resultados devuelto por la sentencia SELECT. Los parámetros a definir son:

Ejemplo

A continuación veremos algunos ejemplos de consulta sencilla.

Tenemos la tabla “EMPLEADOS”:

emp_no apellido oficio director fecha_alta salario Comisión dep_no
7499 ALONSO VENDEDOR 7698 20/02/81 1400.0 400.00 30
7521 LOPEZ EMPLEADO 7782 08/05/81 1350.0 NULL 10
7654 MARTIN VENDEDOR 7698 28/09/81 1500.0 1600.00 30
7698 GARRIDO DIRECTOR 7839 01/05/81 3850.0 NULL 30
7782 MARTINEZ DIRECTOR 7839 09/06/81 2450.0 NULL 10
7839 REY PRESIDENTE NULL 17/11/81 6000.0 NULL 10
7844 CALVO VENDEDOR 7698 08/09/81 1800.0 0.00 30
7876 GIL ANALISTA 7782 06/05/82 3350.0 NULL 20
7900 JIMENEZ EMPLEADO 7782 24/03/82 1400.0 NULL 20

Ejemplo 1: Devolver los datos emp_no, apellido, salario, dep_no, de los 5 empleados que más salario tengan.

SELECT emp_no, apellido, salario, dep_no
FROM empleados
ORDER by salario 
LIMIT 5;
emp_noapellidosalariodep_no
7521LOPEZ1350.5010
7499ALONSO1400.0030
7900JIMENEZ1400.0020
7654MARTIN1500.0030
7844CALVO1800.0030

Ejemplo 2: Devolver los datos emp_no, apellido, salario, dep_no, de los empleados que figura en las posiciones 5ª, 6ª y 7ª, del listado de empleados ordenado por orden alfabético de apellido.

SELECT emp_no, apellido, salario, dep_no
FROM empleados
ORDER by apellido 
LIMIT 4,3;
emp_noapellidosalariodep_no
7900JIMENEZ1400.0020
7521LOPEZ1350.5010
7654MARTIN1500.0030

Ejemplo 3: Devolver los apellidos de los tres empleados que más ganan, junto con su salario anual (salario + comisión en 14 pagas), ordenados de mayor a menor.

SELECT apellido, 
       (salario + IFNULL(comision,0))*14 "Salario anual"
FROM empleados
ORDER by (salario+IFNULL(comision,0))*14 DESC
LIMIT 3;
apellidoSalario anual
REY84000.00
GARRIDO53901.68
GIL46900.00

Consultas con agrupamiento y funciones de grupo

Consultas de selección con agrupamientos

SQL permite agrupar las filas de una tabla, seleccionadas en una consulta formando grupos según el contenido de una o varias expresiones, y obtener salidas calculadas a partir de los grupos formados.
Las salidas obtenidas son los resultados de agrupar y aplicar las funciones a cada uno de los grupos de las filas seleccionadas en la tabla.

El formato de las consultas con selección de agrupamiento, se consigue al añadir al formato de consultas simples las sentencias:

  [GROUP BY ExpresionColumnaAgrupacion|Posicion]
            [,ExpresionColumnaAgrupacion|Posicion...]
  [HAVING CondicionSeleccionGrupos]]

En primer lugar debemos tener claro que en el SELECT, las expresiones deben contener columnas de agrupación y/o funciones de grupo.
Si hay más de una expresión de agrupación, éstas se realizan de izquierda a derecha.
La claúsula HAVING se emplea para controlar qué grupos se seleccionan una vez realizada la agrupación (la condición debe ser TRUE). Está asociada a GROUP BY y no tiene sentido sin ella.
La cláusula ORDER BY no puede contener funciones de grupo. Si se desea ordenar por una de estas funciones, debe hacerse referenciando la posición que ocupa en el SELECT.
Ni en la clausula GROUP BY, ni en la condición de HAVING pueden utilizarse los Alias.

Funcionamiento::

  1. Primero se realiza una selección de filas según la cláusula WHERE.
  2. Forma grupos según la clausula GROUP BY.
  3. Hace una selección de los grupos a mostrar según la cláusula HAVING.

Es importante tener en cuenta que, sólo pueden mostrarse expresiones que contengan columnas de agrupación y/o funciones de grupo. Además, si se utilizan funciones de agrupación sin la cláusula GROUP BY, no pueden mostrarse el resto de las filas de la tabla.

Funciones de grupo

Función Operación
AVG(expr) Valor medio de “expr” ignorando los valores nulos
COUNT ({*|expr}) Número de veces que “expr” tiene un valor no nulo. La opción “*” cuenta el número de filas seleccionadas
MAX(expr) Valor máximo de “expr”
MIN(expr) Valor mínimo de “expr”
STDDEV(expr) Desviación típica de “expr” sin tener en cuenta los valores nulos
SUM(expr) Suma de “expr”
VARIANCE(expr) Varianza de “expr” sin tener en cuenta los valores nulos

Ejemplo

Seleccionar los oficios que tengan dos o más empleados, cuyo salario supere los 1400 euros:

SELECT oficio, COUNT(*)
FROM empleados
WHERE SALARIO > 1400
GROUP BY oficio
HAVING COUNT(*) >= 2;
oficio COUNT(*)
DIRECTOR 2
VENDEDOR 2

Formato de consulta con agrupamiento

  SELECT { *|[ALL/DISTINCT] ExpresionColumna [[AS] AliasColumna]
                           [, ExpresionColumna [[AS] AliasColumna]...] }
  FROM NombreTabla [AliasTabla]
  [WHERE CondicionSeleccion]
  [GROUP BY ExpresionColumnaAgrupacion|Posicion]
            [,ExpresionColumnaAgrupacion|Posicion...]
   [HAVING CondicionSeleccionGrupos]]
  [ORDER BY {ExpresionColumna|Posicion}[ASC|DESC]
          [,{ExpresionColumna|Posicion}[ASC|DESC]...] ]
  [LIMIT [m,]n];

Subconsultas

Una subconsulta en SQL consiste en utilizar los resultados de una consulta dentro de otra, que se considera principal. Esta posibilidad fue la razón original para la palabra “estructurada” que da el nombre al SQL de Lenguaje de Consultas Estrucutradas (Structured Query Language).

Su uso se corresponde con la necesidad de ser capaces de tomar el resultado de una consulta, como valores a comparar por una consulta “principal”, por no ser éstos constantes, con el fin de filtrar los resultados. Las subconsultas pueden encontrarse tanto en la cláusula WHERE, como en la HAVING, en el caso de la selección por agrupamiento de filas.
Es posible anidar subconsultas dentro de otras subconsultas, lo que le da una gran potencia a la cláusula SELECT.

Formato de subconsultas:

  ( SELECT [ALL/DISTINCT] ExpresionColumna 
                       [, ExpresionColumna ...]
    FROM NombreTabla [, NombreTabla]
    [WHERE CondicionSeleccion]
    [GROUP BY ExpresionColumnaAgrupacion
            [,ExpresionColumnaAgrupacion...]
     [HAVING CondicionSeleccionGrupos]] )

El formato de una subconsulta, es el mismo que el de una consulta con las siguientes diferencias:

Funcionamiento:

  1. Para cada fila de la consulta, se ejecuta la subconsulta.
  2. Con ése resultado, se evalúa la fila correspondiente a la consulta.
  3. Se muestra si el resultado de la evaluación es verdadero.

Dado que los resultados de las subconsultas son usados para realizar una comparación con los valores de la consulta principal, con el fin de seleccionar los valores adecuados, la comparación con dicha consulta principal puede realizarse de diferentes formas, según las expresiones que retorne la subconsulta:

Subconsultas correlacionadas

En una subconsulta podemos hacer referencias a las columnas de la tabla de la consulta principal. Cuando los nombre de las columnas que aparecen en una subconsulta, son nombres de columnas de la consulta principal o de otra subconsulta más externa, se dice que son referencias externas y que la subconsulta es correlacionada.

Cuando en una subconsulta nos queremos referir a los datos de la columna de una tabla que ya han sido referenciados en la consulta principal, debemos especificar un alias para diferenciar ambas tablas (que en realidad son la misma). Según cada caso, se podrá (o no) poner un alias sólo a la tabla de la consulta, o se deberá poner en ambas.

Ejemplo 1:

SELECT e1.dep_no "Nº departamento", e1.oficio, salario
FROM empleados e1
WEHERE e1.salario > (SELECT AVG (e2.salario)
                     FROM empleados e2
                     WHERE e2.dep_no = e1.dep_no);

Da el mismo resultado que:

SELECT dep_no "Nº departamento", oficio, salario
FROM empleados e1
WEHERE salario > (SELECT AVG (salario)
                  FROM empleados
                  WHERE dep_no = e1.dep_no);

La 2ª opción es válida porque, si no se indica nada, la subconsulta siempre toma los valores correspondientes a esa subconsulta. Para referenciar nombre externos siempre es necesario anteponer el nombre de la tabla de la consulta. Si además ambas tablas (en consulta y subconsulta) son la misma, es imprescindible usar alias.

Ejemplo 2: Tabla EMPLEADOS:

emp_no apellido oficio director fecha_alta salario Comisión dep_no
7499 ALONSO VENDEDOR 7698 20/02/81 1400.0 400.00 30
7521 LOPEZ EMPLEADO 7782 08/05/81 1350.0 NULL 10
7654 MARTIN VENDEDOR 7698 28/09/81 1500.0 1600.00 30
7698 GARRIDO DIRECTOR 7839 01/05/81 3850.0 NULL 30
7782 MARTINEZ DIRECTOR 7839 09/06/81 2450.0 NULL 10
7839 REY PRESIDENTE NULL 17/11/81 6000.0 NULL 10
7844 CALVO VENDEDOR 7698 08/09/81 1800.0 0.00 30
7876 GIL ANALISTA 7782 06/05/82 3350.0 NULL 20
7900 JIMENEZ EMPLEADO 7782 24/03/82 1400.0 NULL 20

Tabla DEPARTAMENTOS:

DEP_NO DNOMBRE LOCALIDAD
10 Contabilidad Barcelona
20 Investigación Valencia
30 Ventas Madrid
40 Producción Sevilla

Visualizar los departamentos en los que hay más de un trabajador:

SELECT dep_no, dnombre
FROM departamentos e
WHERE EXISTS ( SELECT *
               FROM empleados d
               WHERE e.dep_no = d.dep_no
               GROUP BY dep_no
               HAVING COUNT(*) > 1);

Consultas Multitabla

Hasta ahora se han utilizados sentencias SQL en las que interviene una única tabla. Cuando se necesita obtener datos de dos o más tablas al mismo tiempo, se utilizan consultas multitabla.
Estas consultas simplemente se realizan indicando en el SELECT las diferentes columnas o expresiones a obtener (como se ha hecho siempre) sin importar la tabla a la que pertenecen. Se especifica en la clausula FROM las tablas a las que pertenecen.
Si hay dos columnas que se llaman igual, pero pertenecen a tablas diferentes, hay que especificar el nombre de la tabla en cada caso, de la forma NombreTabla.NombreColumna. También pueden utilizarse Alias, de forma similar a lo que se vio en el caso de las subconsultas correlacionadas.

Cuando se realiza una consulta multitabla, se realiza una multiplicación o producto cartesiano, de las tablas. Esto quiere decir que internamente se crea una tabla en la cual cada fila de las tablas especificadas se combina con todas las filas del resto de tablas indicadas.
Esto no es muy útil, y para quedarnos con la información que nos interesa es necesario filtrar la información a través de lo que se denominan Composiciones o Combinaciones de tablas, también denominadas Join. Este filtro resulta de aplicar una condición en la cláusula WHERE, denominada Condición o Criterio de composición.

Dependiendo de la condición de composición, tendremos:

Es posible realizar composiciones o combinaciones de una tabla consigo misma. Basta con especificar un alias diferente para la misma tabla (como si fuesen tablas diferentes) en la clausula FROM.

Composiciones externas

Puede darse el caso de que al realizar una combinación multitabla, no se emparejen todas las filas que debieran, por falta de correspondencia. Esto ocurre cuando existen filas en una tabla que no tienen correspondencia con las filas de la otra tabla.
Si deseamos que aparezcan todos las filas de un determinado campo de una tabla, aunque no tenga correspondencia con las filas de la otra tabla, se realiza lo que se denomina una Composición o Combinación Externa (Outer Join).

Formato

  SELECT [ALL/DISTINCT] ExpresionColumna [, ExpresionColumna ...]
  FROM NombreTabla [AliasTabla] { LEFT|RIGHT [OUTHER] JOIN NombreTabla [AliasTabla] ...}
  ON CondicionComposicion

Ejemplos

Tabla EMPLEADOS

emp_no apellido oficio director fecha_alta salario Comisión dep_no
7499 ALONSO VENDEDOR 7698 20/02/81 1400.0 400.00 30
7521 LOPEZ EMPLEADO 7782 08/05/81 1350.0 NULL 10
7654 MARTIN VENDEDOR 7698 28/09/81 1500.0 1600.00 30
7698 GARRIDO DIRECTOR 7839 01/05/81 3850.0 NULL 30
7782 MARTINEZ DIRECTOR 7839 09/06/81 2450.0 NULL 10
7839 REY PRESIDENTE NULL 17/11/81 6000.0 NULL 10
7844 CALVO VENDEDOR 7698 08/09/81 1800.0 0.00 30
7876 GIL ANALISTA 7782 06/05/82 3350.0 NULL 20
7900 JIMENEZ EMPLEADO 7782 24/03/82 1400.0 NULL 20

Tabla DEPARTAMENTOS:

DEP_NO DNOMBRE LOCALIDAD
10 Contabilidad Barcelona
20 Investigación Valencia
30 Ventas Madrid
40 Producción Sevilla

Ejemplo de Composición o Combinación Natural

SELECT emp_no "Nº empleado",
       apellido "Apellido",
       dnombre "Departamento",
       localidad "Localidad"
FROM empleados, departamentos
WHERE empleados.dep_no = departamentos.dep_no;

Resulta:

Nº empleadoApellidoDepartamentoLocalidad
7499ALONSOVENTASMADRID
7521LOPEZCONTABILIDADBARCELONA
7654MARTINVENTASMADRID
7698GARRIDOVENTASMADRID
7782MARTINEZCONTABILIDADBARCELONA
7839REYCONTABILIDADBARCELONA
7844CALVOVENTASMADRID
7876GILINVESTIGACIONVALENCIA
7900JIMENEZINVESTIGACIONVALENCIA

Ejemplo de composición basada en la desigualdad
Listar los empleados de departamentos con códigos menores que el código de departamento de Barcelona:

SELECT e.emp_no "Nº Empleado",
       e.apellido
FROM empleados e, departamentos d
WHERE d.localidad = 'Barcelona'
      AND e.dep_no > d.dep_no;

Resulta:

Nº Empleadoapellido
7499ALONSO
7654MARTIN
7698GARRIDO
7844CALVO
7876GIL
7900JIMENEZ

Ejemplo de consulta de una tabla consigo misma
Obtener la lista de empleados con los nombres de sus directores.

SELECT e1.emp_no "Nº Empleado", 
       e1.apellido "Nombre empleado", 
       e1.director "Nº Director", 
       e2.apellido "Nombre Director"
FROM empleados e1, empleados e2
WHERE e1.director = e2.emp_no;

Obteniendo como resultado:

Nº EmpleadoNombre empleadoNº DirectorNombre Director
7499ALONSO7698GARRIDO
7521LOPEZ7782MARTINEZ
7654MARTIN7698GARRIDO
7698GARRIDO7839REY
7782MARTINEZ7839REY
7844CALVO7698GARRIDO
7876GIL7782MARTINEZ
7900JIMENEZ7782MARTINEZ

Ejemplo de combinaciones externas
Obtener los departamentos con su nombre, localidad y número de empleados trabajando en ellos, incluyendo los que no tienen empleados.

SELECT dnombre "Departamento", 
       localidad "localidad", 
       COUNT(emp_no) "Nº empleados"
FROM departamentos d LEFT JOIN empleados e
ON d.dep_no = e.dep_no
GROUP BY dnombre, localidad;

Resulta:

DepartamentolocalidadNº empleados
CONTABILIDADBARCELONA3
INVESTIGACIONVALENCIA2
PRODUCCIONSEVILLA0
VENTASMADRID4

Composiciones y subconsultas

Hay ocasiones que una consulta puede resolverse con una composición o combinación (Join) de tablas, o una subconsulta.

Si puede solucionarse de ambas formas, siempre será preferible hacerlo con una subconsulta, ya que las consultas multitabla siempre requerirán más tiempo y recursos.

En general, si no se necesitan visualizar columnas de más de una tabla, de utilizarán subconsultas. En caso contrario, se usará un join.

Formato completo de consultas

  SELECT { *|[ALL/DISTINCT] ExpresionColumna [AliasColumna]
                         [, ExpresionColumna [AliasColumna]...] }
  FROM NombreTabla [AliasTabla] 
    [, NombreTabla [AliasTabla] ...]
  [WHERE {CondicionSeleccion|CondicionComposicion}]
  [GROUP BY ExpresionColumnaAgrupacion|Posicion]
          [,ExpresionColumnaAgrupacion|Posicion...]
   [HAVING CondicionSeleccionGrupos]]
  [ORDER BY {ExpresionColumna|Posicion}[ASC|DESC]
          [,{ExpresionColumna|Posicion}[ASC|DESC]...] ]
  [LIMIT [m,]n];

Consultas dentro de otras instrucciones

Creación de una tabla a partir de una selección de otra tabla

CREATE TABLE [IF NOT EXISTS] NombreTabla
 [( DefinicionColumna [, DefinicionColumna ...] )] [IGNORE|REPLACE]
SentenciaSelect

Los nombres de las columnas de la nueva tabla son opcionales y en caso de que no se especifiquen, recibirán los valores de la otra tabla, o sus alias correspondientes. Si hay expresiones o funciones en la lista del SELECT, deben indicarse nombre o alias, ya que en caso contrario estos valores no podrán referenciarse.

Para saber qué acción tomar cuando se produce la repetición de un campo UNIQUE o PRIMARY KEY, podemos indicar IGNORE (no se guarda el nuevo dato y es ignorado) o REPLACE (el dato reemplaza al anterior). Si no se indica nada y ocurre la coincidencia, se producirá un error.

LA nueva tabla creada no hereda las constraints, por lo que habría que crearlas en la definición de la misma, o añadirlas posteriormente con ALTER TABLE.

Al crear la nueva tabla, se insertan las filas correspondientes de la tabla resultado de la sentencia SELECT.

Actualización de una tabla a partir de una subconsulta

INSERT INTO NombreTabla [( NombreColumna [,NombreColumna ...] )]
SELECT FormatoSelect

La lista de columnas es opcional, pero deberá especificarse si las columnas que devuelve la consulta no coinciden en número u orden con las columnas de la tabla destino.

Modificaciones con subconsultas

En este caso, la condición que deben cumplir las filas que deseamos modificar implica la realización de una subconsulta a otras tablas.
La forma de hacerlo es incluyendo la subconsulta en la cláusula WHERE.

Existen algunas limitaciones:

Ejemplo Se desea elevar 500 euros el salario de todos los empleados cuyo departamento no esté en Madrid.

UPDATE empleados
SET salario = salario + 500
WHERE dep_no NOT IN ( SELECT dep_no
                      FROM departamentos
                      WHERE localidad <> 'Madrid' );

Eliminaciones con subconsultas

En ocasiones la condición que deben cumplir las filas que queremos eliminar implica realizar una subconsulta a otras tablas. En estos casos se incluirá la subconsulta en la cláusula WHERE con las mismas restricciones que las modificaciones:

Se pueden utilizar subconsultas anidadas a varios niveles, pero respetando la siguiente restricción: La tabla destino no puede aparecer en la cláusula FROM de ninguna de las subconsultas que intervienen en la selección. Sí se permiten referencias externas.

Ejemplo

DELETE FROM departamentos
WHERE NOT EXISTS ( SELECT *
                   FROM empleados
                   WHERE empleados.dep_no = departamentos.dep_no );

Vistas

Una vista es una “tabla virtual” que se almacena en memoria y que se crea a partir de una consulta. Esta “tabla virtual” o “Vista”, está “conectada” directamente a las tablas de origen, de forma que se mantiene constantemente actualizada en tiempo real. Podemos operar sobre la vista como si de una tabla corriente se tratase, sirviendo de interfaz con el usuario y los datos de interés.

Ventajas del uso de vistas:

Creación de vistas

  CREATE VIEW NombreVista 
    [( DefinicionColumna [,DefinicionColumna ...] )]
  AS Consulta;

Deben tenerse en cuenta algunas consideraciones cuando se crean vistas:

Se pueden realizar consultas a las vistas, de la misma manera que se hacía a las tablas.

Ejemplo

Creamos una vista para trabajar con los datos de dos tablas agrupados y seleccionando las filas que interesen (todos los departamentos que tengan más de dos empleados):

CREATE VIEW resumen_emp_dep
  (departamento, 
   num_empleados,
   suma_salario)
 AS SELECT dnombre,
           COUNT(emp_no),
           SUM(salario)
    FROM empleados, departamentos
    WHERE empleados.dep_no = departamentos.dep_no
    GROUP BY empleados.dep_no, dnombre
     HAVING COUNT(*) > 2;

Consultamos los datos del número de empleados por departamento:

SELECT departamento, num_empleados
FROM resumen_emp_dep;

Que resulta:

departamentonum_empleados
CONTABILIDAD3
VENTAS4

Eliminación de vistas

  DROP VIEW [IF EXISTS] NombreVista
   [RESTRICT|CASCADE]

RESTRICT y CASCADE están permitidas pero no implementadas en la versión 5 de MySQL.