Apuntes de BD para DAW, DAM y ASIR
José Juan Sánchez Hernández
Curso 2023/2024
SELECT
SELECT
SELECT *
)AS
SELECT
ALL
,
DISTINCT
y DISTINCTROW
ORDER BY
LIMIT
WHERE
NULL
AND
DATE
,
DATETIME
y TIMESTAMP
El DML (Data Manipulation Language) o Lenguaje de Manipulación de Datos es la parte de SQL dedicada a la manipulación de los datos. Las sentencias DML son las siguientes:
SELECT
: se utiliza para realizar consultas y extraer
información de la base de datos.INSERT
: se utiliza para insertar registros en las
tablas de la base de datos.UPDATE
: se utiliza para actualizar los registros de una
tabla.DELETE
: se utiliza para eliminar registros de una
tabla.En este tema nos vamos a centrar en el uso de la sentencia
SELECT
.
SELECT
Según la documentación
oficial de MySQL ésta sería la sintaxis para realizar una consulta
con la sentencia SELECT
en MySQL:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references]
[PARTITION partition_list]
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING having_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_COUNT | row_COUNT OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name'
[CHARACTER SET charset_name]
export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
Para empezar con consultas sencillas podemos simplificar la definición anterior y quedarnos con la siguiente:
SELECT [DISTINCT] select_expr [, select_expr ...]
[FROM table_references]
[WHERE where_condition]
[GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]]
[HAVING having_condition]
[ORDER BY {col_name | expr | position} [ASC | DESC], ...]
[LIMIT {[offset,] row_COUNT | row_COUNT OFFSET offset}]
Es muy importante conocer en qué orden se ejecuta cada una de
las cláusulas que forman la sentencia SELECT
. El
orden de ejecución es el siguiente:
FROM
.WHERE
(Es opcional, puede ser que no
aparezca).GROUP BY
(Es opcional, puede ser que no
aparezca).HAVING
(Es opcional, puede ser que no
aparezca).SELECT
.ORDER BY
(Es opcional, puede ser que no
aparezca).LIMIT
(Es opcional, puede ser que no
aparezca).Hay que tener en cuenta que el resultado de una consulta siempre será una tabla de datos, que puede tener una o varias columnas y ninguna, una o varias filas.
El hecho de que el resultado de una consulta sea una tabla es muy interesante porque nos permite realizar cosas como almacenar los resultados como una nueva en la base de datos. También será posible combinar el resultado de dos o más consultas para crear una tabla mayor con la unión de los dos resultados. Además, los resultados de una consulta también pueden consultados por otras nuevas consultas.
SELECT
Nos permite indicar cuáles serán las columnas que tendrá la tabla de resultados de la consulta que estamos realizando. Las opciones que podemos indicar son las siguientes:
El nombre de una columna de la tabla sobre la
que estamos realizando la consulta. Será una columna de la tabla que
aparece en la cláusula FROM
.
Una constante que aparecerá en todas las filas de la tabla resultado.
Una expresión que nos permite calcular nuevos valores.
SELECT *
)Ejemplo:
Vamos a utilizar la siguiente base de datos de ejemplo para MySQL.
DROP DATABASE IF EXISTS instituto;
CREATE DATABASE instituto CHARACTER SET utf8mb4;
USE instituto;
CREATE TABLE alumno (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
apellido1 VARCHAR(100) NOT NULL,
apellido2 VARCHAR(100),
fecha_nacimiento DATE NOT NULL,
es_repetidor ENUM('sí', 'no') NOT NULL,
teléfono VARCHAR(9)
);
INSERT INTO alumno VALUES(1, 'María', 'Sánchez', 'Pérez', '1990-12-01', 'no', NULL);
INSERT INTO alumno VALUES(2, 'Juan', 'Sáez', 'Vega', '1998-04-02', 'no', 618253876);
INSERT INTO alumno VALUES(3, 'Pepe', 'Ramírez', 'Gea', '1988-01-03', 'no', NULL);
INSERT INTO alumno VALUES(4, 'Lucía', 'Sánchez', 'Ortega', '1993-06-13', 'sí', 678516294);
INSERT INTO alumno VALUES(5, 'Paco', 'Martínez', 'López', '1995-11-24', 'no', 692735409);
INSERT INTO alumno VALUES(6, 'Irene', 'Gutiérrez', 'Sánchez', '1991-03-28', 'sí', NULL);
INSERT INTO alumno VALUES(7, 'Cristina', 'Fernández', 'Ramírez', '1996-09-17', 'no', 628349590);
INSERT INTO alumno VALUES(8, 'Antonio', 'Carretero', 'Ortega', '1994-05-20', 'sí', 612345633);
INSERT INTO alumno VALUES(9, 'Manuel', 'Domínguez', 'Hernández', '1999-07-08', 'no', NULL);
INSERT INTO alumno VALUES(10, 'Daniel', 'Moreno', 'Ruiz', '1998-02-03', 'no', NULL);
Supongamos que tenemos una tabla llamada alumno con la siguiente información de los alumnos matriculados en un determinado curso.
id | nombre | apellido1 | apellido2 | fecha_nacimiento | es_repetidor | teléfono |
---|---|---|---|---|---|---|
1 | María | Sánchez | Pérez | 1990/12/01 | no | NULL |
2 | Juan | Sáez | Vega | 1998/04/02 | no | 618253876 |
3 | Pepe | Ramírez | Gea | 1988/01/03 | no | NULL |
4 | Lucía | Sánchez | Ortega | 1993/06/13 | sí | 678516294 |
5 | Paco | Martínez | López | 1995/11/24 | no | 692735409 |
6 | Irene | Gutiérrez | Sánchez | 1991/03/28 | sí | NULL |
7 | Cristina | Fernández | Ramírez | 1996/09/17 | no | 628349590 |
8 | Antonio | Carretero | Ortega | 1994/05/20 | sí | 612345633 |
9 | Manuel | Domínguez | Hernández | 1999/07/08 | no | NULL |
10 | Daniel | Moreno | Ruiz | 1998/02/03 | no | NULL |
Vamos a ver qué consultas sería necesario realizar para obtener los siguientes datos.
1. Obtener todos los datos de todos los alumnos matriculados en el curso.
El carácter * es un comodín que utilizamos para indicar que queremos seleccionar todas las columnas de la tabla. La consulta anterior devolverá todos los datos de la tabla.
Tenga en cuenta que las palabras reservadas de SQL no son case sensitive, por lo tanto es posible escribir la sentencia anterior de la siguiente forma obteniendo el mismo resultado:
Otra consideración que también debemos tener en cuenta es que una consulta SQL se puede escribir en una o varias líneas. Por ejemplo, la siguiente sentencia tendría el mismo resultado que la anterior:
A lo largo del curso vamos a considerar como una buena práctica escribir las consultas SQL en varias líneas, empezando cada línea con la palabra reservada de la cláusula correspondiente que forma la consulta.
2. Obtener el nombre de todos los alumnos.
nombre |
---|
María |
Juan |
Pepe |
Lucía |
Paco |
Irene |
Cristina |
Antonio |
Manuel |
Daniel |
3. Obtener el nombre y los apellidos de todos los alumnos.
nombre | apellido1 | apellido2 |
---|---|---|
María | Sánchez | Pérez |
Juan | Sáez | Vega |
Pepe | Ramírez | Gea |
Lucía | Sánchez | Ortega |
Paco | Martínez | López |
Irene | Gutiérrez | Sánchez |
Cristina | Fernández | Ramírez |
Antonio | Carretero | Ortega |
Manuel | Domínguez | Hernández |
Daniel | Moreno | Ruiz |
Tenga en cuenta que el resultado de la consulta SQL mostrará las columnas que haya solicitado, siguiendo el orden en el que se hayan indicado. Por lo tanto la siguiente consulta:
Devolverá lo siguiente:
apellido1 | apellido2 | nombre |
---|---|---|
Sánchez | Pérez | María |
Sáez | Vega | Juan |
Ramírez | Gea | Pepe |
Sánchez | Ortega | Lucía |
Martínez | López | Paco |
Gutiérrez | Sánchez | Irene |
Fernández | Ramírez | Cristina |
Carretero | Ortega | Antonio |
Domínguez | Hernández | Manuel |
Moreno | Ruiz | Daniel |
Para escribir comentarios en nuestras sentencias SQL podemos hacerlo de diferentes formas.
-- Esto es un comentario
SELECT nombre, apellido1, apellido2 -- Esto es otro comentario
FROM alumno;
/* Esto es un comentario
de varias líneas */
SELECT nombre, apellido1, apellido2 /* Esto es otro comentario */
FROM alumno;
Ejemplo
Vamos a utilizar la siguiente base de datos de ejemplo para MySQL.
DROP DATABASE IF EXISTS tienda;
CREATE DATABASE tienda CHARACTER SET utf8mb4;
USE tienda;
CREATE TABLE ventas (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
cantidad_comprada INT UNSIGNED NOT NULL,
precio_por_elemento DECIMAL(7,2) NOT NULL
);
INSERT INTO ventas VALUES (1, 2, 1.50);
INSERT INTO ventas VALUES (2, 5, 1.75);
INSERT INTO ventas VALUES (3, 7, 2.00);
INSERT INTO ventas VALUES (4, 9, 3.50);
INSERT INTO ventas VALUES (5, 6, 9.99);
Es posible realizar cálculos aritméticos entre columnas para calcular nuevos valores. Por ejemplo, supongamos que tenemos la siguiente tabla con información sobre ventas.
id | cantidad_comprada | precio_por_elemento |
---|---|---|
1 | 2 | 1.50 |
2 | 5 | 1.75 |
3 | 7 | 2.00 |
4 | 9 | 3.50 |
5 | 6 | 9.99 |
Y queremos calcular una nueva columna con el precio total de la
venta, que sería equivalente a multiplicar el valor de la column
cantidad_comprada
por precio_por_elemento
.
Para obtener esta nueva columna podríamos realizar la siguiente consulta:
SELECT id, cantidad_comprada, precio_por_elemento, cantidad_comprada * precio_por_elemento
FROM ventas;
Y el resultado sería el siguiente:
id | cantidad_comprada | precio_por_elemento | cantidad_comprada * precio_por_elemento |
---|---|---|---|
1 | 2 | 1.50 | 3.00 |
2 | 5 | 1.75 | 8.75 |
3 | 7 | 2.00 | 14.00 |
4 | 9 | 3.50 | 31.50 |
5 | 6 | 9.99 | 59.94 |
Ejemplo
Vamos a utilizar la siguiente base de datos de ejemplo para MySQL.
DROP DATABASE IF EXISTS company;
CREATE DATABASE company CHARACTER SET utf8mb4;
USE company;
CREATE TABLE offices (
office INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
city VARCHAR(50) NOT NULL,
region VARCHAR(50) NOT NULL,
manager INT UNSIGNED,
target DECIMAL(9,2) NOT NULL,
sales DECIMAL(9,2) NOT NULL
);
INSERT INTO offices VALUES (11, 'New York', 'Eastern', 106, 575000, 692637);
INSERT INTO offices VALUES (12, 'Chicago', 'Eastern', 104, 800000, 735042);
INSERT INTO offices VALUES (13, 'Atlanta', 'Eastern', NULL, 350000, 367911);
INSERT INTO offices VALUES (21, 'Los Angeles', 'Western', 108, 725000, 835915);
INSERT INTO offices VALUES (22, 'Denver', 'Western', 108, 300000, 186042);
Supongamos que tenemos una tabla llamada oficinas
que
contiene información sobre las ventas reales que ha generado y el valor
de ventas esperado, y nos gustaría conocer si las oficinas han
conseguido el objetivo propuesto, y si están por debajo o por encima del
valor de ventas esperado.
Imagen: Imagen extraída del libro SQL: The Complete Reference de James R. Groff y otros.
En este caso podríamos realizar la siguiente consulta:
AS
Con la palabra reservada AS
podemos crear alias para las
columnas. Esto puede ser útil cuando estamos calculando nuevas columnas
a partir de valores de las columnas actuales. En el ejemplo anterior de
la tabla que contiene información sobre las ventas, podríamos crear el
siguiente alias:
SELECT id, cantidad_comprada, precio_por_elemento, cantidad_comprada * precio_por_elemento AS 'precio total'
FROM ventas;
Si el nuevo nombre que estamos creando para el alias contiene espacios en blanco es necesario usar comillas simples.
Al crear este alias obtendremos el siguiente resultado:
id | cantidad_comprada | precio_por_elemento | precio total |
---|---|---|---|
1 | 2 | 1.50 | 3.00 |
2 | 5 | 1.75 | 8.75 |
3 | 7 | 2.00 | 14.00 |
SELECT
Es posible hacer uso de funciones específicas de MySQL en la cláusula
SELECT
. MySQL nos ofrece funciones matemáticas, funciones
para trabajar con cadenas y funciones para trabajar con fechas y horas.
Algunos ejemplos de las funciones de MySQL que utilizaremos a lo largo
del curso son las siguientes.
Funciones con cadenas
Función | Descripción |
---|---|
CONCAT |
Concatena cadenas |
CONCAT_WS |
Concatena cadenas con un separador |
LOWER |
Devuelve una cadena en minúscula |
UPPER |
Devuelve una cadena en mayúscula |
SUBSTR |
Devuelve una subcadena |
Funciones matemáticas
Función | Descripción |
---|---|
ABS() |
Devuelve el valor absoluto |
POW(x,y) |
Devuelve el valor de x elevado a y |
SQRT() |
Devuelve la raíz cuadrada |
PI() |
Devuelve el valor del número PI |
ROUND() |
Redondea un valor numérico |
TRUNCATE() |
Trunca un valor numérico |
Funciones de fecha y hora
Función | Descripción |
---|---|
NOW() |
Devuelve la fecha y la hora actual |
CURTIME() |
Devuelve la hora actual |
En la documentación oficial puede encontrar la referencia completa de todas las funciones y operadores disponibles en MySQL.
Ejemplo
Obtener el nombre y los apellidos de todos los alumnos en una única columna.
nombre_completo |
---|
MaríaSánchezPérez |
JuanSáezVega |
PepeRamírezGea |
LucíaSánchezOrtega |
PacoMartínezLópez |
IreneGutiérrezSánchez |
CristinaFernándezRamírez |
AntonioCarreteroOrtega |
ManuelDomínguezHernández |
DanielMorenoRuiz |
En este caso estamos haciendo uso de la función
CONCAT
de MySQL y la palabra reservada AS
para crear un alias de la columna y renombrarla como
nombre_completo.
La función
CONCAT
de MySQL no añade ningún espacio entre las
columnas, por eso los valores de las tres columnas aparecen como una
sola cadena sin espacios entre ellas. Para resolver este problema
podemos hacer uso de la
función CONCAT_WS
que nos permite definir un carácter
separador entre cada columna. En el siguiente ejemplo haremos uso de la
función
CONCAT_WS
y usaremos un espacio en blanco como
separador.
nombre_completo |
---|
María Sánchez Pérez |
Juan Sáez Vega |
Pepe Ramírez Gea |
Lucía Sánchez Ortega |
Paco Martínez López |
Irene Gutiérrez Sánchez |
Cristina Fernández Ramírez |
Antonio Carretero Ortega |
Manuel Domínguez Hernández |
Daniel Moreno Ruiz |
Importante: La función
CONCAT
devolverá NULL
cuando alguna de las
cadenas que está concatenando es igual NULL
, mientras que
la función CONCAT_WS
omitirá todas las cadenas que sean
igual a NULL
y realizará la concatenación con el resto de
cadenas.
Ejercicios
Obtener el nombre y los apellidos de todos los alumnos en una única columna en minúscula.
Obtener el nombre y los apellidos de todos los alumnos en una única columna en mayúscula.
Obtener el nombre y los apellidos de todos los alumnos en una
única columna. Cuando el segundo apellido de un alumno sea
NULL
se devolverá el nombre y el primer apellido
concatenados en mayúscula, y cuando no lo sea, se devolverá el nombre
completo concatenado tal y como aparece en la tabla.
ALL
,
DISTINCT
y DISTINCTROW
Los modificadores ALL
y DISTINCT
indican si
se deben incluir o no filas repetidas en el resultado de la
consulta.
ALL
indica que se deben incluir todas las filas,
incluidas las repetidas. Es la opción por defecto, por lo tanto no es
necesario indicarla.DISTINCT
elimina las filas repetidas en el resultado de
la consulta.DISTINCTROW
es un sinónimo de
DISTINCT
.Ejemplo
En el siguiente ejemplo vamos a ver la diferencia que existe entre
utilizar DISTINCT
y no utilizarlo. La siguiente consulta
mostrará todas las filas que existen en la columna
apellido1
de la tabla alumno
.
apellido1 |
---|
Sánchez |
Sáez |
Ramírez |
Sánchez |
Martínez |
Gutiérrez |
Fernández |
Carretero |
Domínguez |
Moreno |
Si en la consulta anterior utilizamos DISTINCT
se
eliminarán todos los valores repetidos que existan.
apellido1 |
---|
Sánchez |
Sáez |
Ramírez |
Martínez |
Gutiérrez |
Fernández |
Carretero |
Domínguez |
Moreno |
Si en la cláusula SELECT
utilizamos
DISTINCT
con más de una columna, la consulta seguirá
eliminando todas las filas repetidas que existan. Por ejemplo, si
tenemos las columnas apellido1
, apellido2
y
nombre
, se eliminarán todas las filas que tengan los mismos
valores en las tres columnas.
apellido1 |
---|
Sánchez |
Sáez |
Ramírez |
Sánchez |
Martínez |
Gutiérrez |
Fernández |
Carretero |
Domínguez |
Moreno |
En este ejemplo no se ha eliminado ninguna fila porque no existen alumnos que tengan los mismos apellidos y el mismo nombre.
ORDER BY
ORDER BY
permite ordenar las filas que se incluyen en el
resultado de la consulta. La sintaxis de MySQL es la siguiente:
Esta cláusula nos permite ordenar el resultado de forma ascendente
ASC
o descendente DESC
, además de permitirnos
ordenar por varias columnas estableciendo diferentes niveles de
ordenación.
Ejemplo
1. Obtener el nombre y los apellidos de todos los alumnos, ordenados por su primer apellido de forma ascendente.
Si no indicamos nada en la cláusula ORDER BY
se ordenará
por defecto de forma ascendente.
La consulta anterior es equivalente a esta otra.
El resultado de ambas consultas será:
nombre | apellido1 | apellido2 |
---|---|---|
Carretero | Ortega | Antonio |
Domínguez | Hernández | Manuel |
Fernández | Ramírez | Cristina |
Gutiérrez | Sánchez | Irene |
Martínez | López | Paco |
Moreno | Ruiz | Daniel |
Ramírez | Gea | Pepe |
Sáez | Vega | Juan |
Sánchez | Pérez | María |
Sánchez | Ortega | Lucía |
Las filas están ordenadas correctamente por el primer apellido, pero
todavía hay que resolver cómo ordenar el listado cuando existen varias
filas donde coincide el valor del primer apellido. En este caso tenemos
dos filas donde el primer apellido es Sánchez
:
nombre | apellido1 | apellido2 |
---|---|---|
… | … | … |
Sánchez | Pérez | María |
Sánchez | Ortega | Lucía |
Más adelante veremos cómo podemos ordenar el listado teniendo en cuenta más de una columna.
Ejemplo
1. Obtener el nombre y los apellidos de todos los alumnos, ordenados por su primer apellido de forma ascendente.
Ejemplo
En este ejemplo vamos obtener un listado de todos los alumnos ordenados por el primer apellido, segundo apellido y nombre, de forma ascendente.
En lugar de indicar el nombre de las columnas en la cláusula
ORDER BY
podemos indicar sobre la posición donde aparecen
en la cláusula SELECT
, de modo que la consulta anterior
sería equivalente a la siguiente:
LIMIT
LIMIT
permite limitar el número de filas que se incluyen
en el resultado de la consulta. La sintaxis de MySQL es la siguiente
donde row_COUNT
es el número de filas que queremos
obtener y offset
el número de filas que nos saltamos antes
de empezar a contar. Es decir, la primera fila que se obtiene como
resultado es la que está situada en la posición
offset + 1
.
Ejemplo
DROP DATABASE IF EXISTS google;
CREATE DATABASE google CHARACTER SET utf8mb4;
USE google;
CREATE TABLE resultado (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
descripcion VARCHAR(200) NOT NULL,
url VARCHAR(512) NOT NULL
);
INSERT INTO resultado VALUES (1, 'Resultado 1', 'Descripción 1', 'http://....');
INSERT INTO resultado VALUES (2, 'Resultado 2', 'Descripción 2', 'http://....');
INSERT INTO resultado VALUES (3, 'Resultado 3', 'Descripción 3', 'http://....');
INSERT INTO resultado VALUES (4, 'Resultado 4', 'Descripción 4', 'http://....');
INSERT INTO resultado VALUES (5, 'Resultado 5', 'Descripción 5', 'http://....');
INSERT INTO resultado VALUES (6, 'Resultado 6', 'Descripción 6', 'http://....');
INSERT INTO resultado VALUES (7, 'Resultado 7', 'Descripción 7', 'http://....');
INSERT INTO resultado VALUES (8, 'Resultado 8', 'Descripción 8', 'http://....');
INSERT INTO resultado VALUES (9, 'Resultado 9', 'Descripción 9', 'http://....');
INSERT INTO resultado VALUES (10, 'Resultado 10', 'Descripción 10', 'http://....');
INSERT INTO resultado VALUES (11, 'Resultado 11', 'Descripción 11', 'http://....');
INSERT INTO resultado VALUES (12, 'Resultado 12', 'Descripción 12', 'http://....');
INSERT INTO resultado VALUES (13, 'Resultado 13', 'Descripción 13', 'http://....');
INSERT INTO resultado VALUES (14, 'Resultado 14', 'Descripción 14', 'http://....');
INSERT INTO resultado VALUES (15, 'Resultado 15', 'Descripción 15', 'http://....');
Suponga que queremos mostrar en una página web las filas que
están almacenadas en la tabla resultados
, y queremos
mostrar la información en diferentes páginas, donde cada una de las
páginas muestra solamente 5 resultados. ¿Qué consulta SQL necesitamos
realizar para incluir los primeros 5 resultados de la primera
página?
¿Qué consulta necesitaríamos para mostrar resultados de la segunda página?
¿Y los resultados de la tercera página?
WHERE
La cláusula WHERE
nos permite añadir filtros a nuestras
consultas para seleccionar sólo aquellas filas que cumplen una
determinada condición. Estas condiciones se denominan predicados y el
resultado de estas condiciones puede ser verdadero,
falso o desconocido.
Una condición tendrá un resultado desconocido cuando
alguno de los valores utilizados tiene el valor NULL
.
Podemos diferenciar cinco tipos de condiciones que pueden aparecer en
la cláusula WHERE
:
NULL
.Los operandos usados en las condiciones pueden ser nombres de columnas, constantes o expresiones. Los operadores que podemos usar en las condiciones pueden ser aritméticos, de comparación, lógicos, etc.
A continuación se muestran los operadores más utilizados en MySQL para realizar las consultas.
Operadores aritméticos
Operador | Descripción |
---|---|
+ | Suma |
- | Resta |
* | Multiplicación |
/ | División |
% | Módulo |
Operadores de comparación
Operador | Descripción |
---|---|
< | Menor que |
<= | Menor o igual |
> | Mayor que |
>= | Mayor o igual |
<> | Distinto |
!= | Distinto |
= | Igual que |
Operadores lógicos
Operador | Descripción |
---|---|
AND |
Y lógica |
&& | Y lógica |
OR |
O lógica |
|| |
O lógica |
NOT |
Negación lógica |
! |
Negación lógica |
Ejemplos
Vamos a continuar con el ejemplo de la tabla alumno que almacena la información de los alumnos matriculados en un determinado curso.
¿Qué consultas serían necesarias para obtener los siguientes datos?
1. Obtener el nombre de todos los alumnos que su primer apellido sea Martínez.
2. Obtener todos los datos del alumno que tiene un
id
igual a 9.
3. Obtener el nombre y la fecha de nacimiento de todos los alumnos nacieron después del 1 de enero de 1997.
Ejercicios
Realice las siguientes consultas teniendo en cuenta la base
de datos instituto
.
Devuelve los datos del alumno cuyo id
es igual a
1.
Devuelve los datos del alumno cuyo teléfono
es igual
a 692735409.
Devuelve un listado de todos los alumnos que son repetidores.
Devuelve un listado de todos los alumnos que no son repetidores.
Devuelve el listado de los alumnos que han nacido antes del 1 de enero de 1993.
Devuelve el listado de los alumnos que han nacido después del 1 de enero de 1994.
Devuelve el listado de los alumnos que han nacido después del 1 de enero de 1994 y no son repetidores.
Devuelve el listado de todos los alumnos que nacieron en 1998.
Devuelve el listado de todos los alumnos que no nacieron en 1998.
BETWEEN
Sintaxis:
Se utiliza para comprobar si un valor está dentro de un rango de valores. Por ejemplo, si queremos obtener los pedidos que se han realizado durante el mes de enero de 2018 podemos realizar la siguiente consulta:
Ejercicios
Realice las siguientes consultas teniendo en cuenta la base
de datos instituto
.
Devuelve los datos de los alumnos que hayan nacido entre el 1 de enero de 1998 y el 31 de mayo de 1998.
Devuelve los datos de los alumnos que no hayan nacido entre el 1 de enero de 1998 y el 31 de mayo de 1998.
IN
Este operador nos permite comprobar si el valor de una determinada columna está incluido en una lista de valores.
Ejemplo:
Obtener todos los datos de los alumnos que tengan como primer
apellido Sánchez
, Martínez
o
Domínguez
.
Ejemplo:
Obtener todos los datos de los alumnos que no tengan
como primer apellido Sánchez
, Martínez
o
Domínguez
.
LIKE
Sintaxis:
Se utiliza para comparar si una cadena de caracteres coincide con un
patrón. En el patrón podemos utilizar cualquier carácter alfanumérico,
pero hay dos caracteres que tienen un significado especial, el símbolo
del porcentaje (%
) y el carácter de subrayado
(_
).
%
: Este carácter equivale a cualquier conjunto de
caracteres._
: Este carácter equivale a cualquier carácter.Ejemplos:
Devuelva un listado de todos los alumnos que su primer apellido
empiece por la letra S
.
Devuelva un listado de todos los alumnos que su primer apellido
termine por la letra z
.
Devuelva un listado de todos los alumnos que su nombre tenga el
carácter a
.
Devuelva un listado de todos los alumnos que tengan un nombre de cuatro caracteres.
Devuelve un listado de todos los productos cuyo nombre empieza con estas cuatro letras ‘A%BC’.
En este caso, el patrón que queremos buscar contiene el carácter %, por lo tanto, tenemos que usar un carácter de escape.
Por defecto, se utiliza el carácter ’' como carácter de escape. De modo que podríamos escribir la consulta de la siguiente manera.
REGEXP
y expresiones regularesEl operador REGEXP
nos permite realizar búsquedas mucho
más potentes haciendo uso de expresiones regulares. Puede consultar la
documentación
oficial para conocer más detalles sobre cómo usar este operador.
IS
e
IS NOT
Estos operadores nos permiten comprobar si el valor de una
determinada columna es NULL
o no lo es.
Ejemplo:
Obtener la lista de alumnos que tienen un valor NULL
en
la columna teléfono
.
Ejemplo:
Obtener la lista de alumnos que no tienen un valor NULL
en la columna teléfono
.
A continuación se muestran algunas funciones disponibles en MySQL que pueden ser utilizadas para realizar consultas.
Las funciones se pueden utilizar en las cláusulas
SELECT
, WHERE
y ORDER BY
.
Función | Descripción |
---|---|
CONCAT |
Concatena cadenas |
CONCAT_WS |
Concatena cadenas con un separador |
LOWER |
Devuelve una cadena en minúscula |
UPPER |
Devuelve una cadena en mayúscula |
SUBSTR |
Devuelve una subcadena |
LEFT |
Devuelve los caracteres de una cadena, empezando por la izquierda |
RIGHT |
Devuelve los caracteres de una cadena, empezando por la derecha |
CHAR_LENGTH |
Devuelve el número de caracteres que tiene una cadena |
LENGTH |
Devuelve el número de bytes que ocupa una cadena |
REVERSE |
Devuelve una cadena invirtiendo el orden de sus caracteres |
LTRIM |
Elimina los espacios en blanco que existan al inicio de una cadena |
RTRIM |
Elimina los espacios en blanco que existan al final de una cadena |
TRIM |
Elimina los espacios en blanco que existan al inicio y al final de una cadena |
REPLACE |
Permite reemplazar un carácter dentro de una cadena |
En la documentación oficial puede encontrar la referencia completa de todas las funciones disponibles en MySQL para trabajar con cadenas de caracteres.
Ejercicios:
Devuelve un listado con dos columnas, donde aparezca en la primera columna el nombre de los alumnos y en la segunda, el nombre con todos los caracteres invertidos.
Devuelve un listado con dos columnas, donde aparezca en la primera columna el nombre y los apellidos de los alumnos y en la segunda, el nombre y los apellidos con todos los caracteres invertidos.
Devuelve un listado con dos columnas, donde aparezca en la primera columna el nombre y los apellidos de los alumnos en mayúscula y en la segunda, el nombre y los apellidos con todos los caracteres invertidos en minúscula.
Devuelve un listado con tres columnas, donde aparezca en la primera columna el nombre y los apellidos de los alumnos, en la segunda, el número de caracteres que tiene en total el nombre y los apellidos y en la tercera el número de bytes que ocupa en total.
Devuelve un listado con dos columnas, donde aparezca en la
primera columna el nombre y los dos apellidos de los alumnos. En la
segunda columna se mostrará una dirección de correo electrónico que
vamos a calcular para cada alumno. La dirección de correo estará formada
por el nombre y el primer apellido, separados por el carácter
.
y seguidos por el dominio @iescelia.org
.
Tenga en cuenta que la dirección de correo electrónico debe estar en
minúscula. Utilice un alias apropiado para cada columna.
Devuelve un listado con tres columnas, donde aparezca en la
primera columna el nombre y los dos apellidos de los alumnos. En la
segunda columna se mostrará una dirección de correo electrónico que
vamos a calcular para cada alumno. La dirección de correo estará formada
por el nombre y el primer apellido, separados por el carácter
.
y seguidos por el dominio @iescelia.org
.
Tenga en cuenta que la dirección de correo electrónico debe estar en
minúscula. La tercera columna será una contraseña que vamos a generar
formada por los caracteres invertidos del segundo apellido, seguidos de
los cuatro caracteres del año de la fecha de nacimiento. Utilice un
alias apropiado para cada columna.
Función | Descripción |
---|---|
NOW() |
Devuelve la fecha y la hora actual |
CURTIME() |
Devuelve la hora actual |
ADDDATE |
Suma un número de días a una fecha y calcula la nueva fecha |
DATE_FORMAT |
Nos permite formatear fechas |
DATEDIFF |
Calcula el número de días que hay entre dos fechas |
YEAR |
Devuelve el año de una fecha |
MONTH |
Devuelve el mes de una fecha |
MONTHNAME |
Devuelve el nombre del mes de una fecha |
DAY |
Devuelve el día de una fecha |
DAYNAME |
Devuelve el nombre del día de una fecha |
HOUR |
Devuelve las horas de un valor de tipo DATETIME |
MINUTE |
Devuelve los minutos de un valor de tipo DATETIME |
SECOND |
Devuelve los segundos de un valor de tipo DATETIME |
En la documentación oficial puede encontrar la referencia completa de todas las funciones disponibles en MySQL para trabajar con fechas y horas.
Configuración regional en MySQL Server (locale)
Importante: Tenga en cuenta que para
que los nombres de los meses y las abreviaciones aparezcan en español
deberá configurar la variable del sistema lc_time_names
.
Esta variable afecta al resultado de las funciones
DATE_FORMAT
, DAYNAME
y
MONTHNAME
.
En MySQL las variables se pueden definir como variables globales o variables de sesión. La diferencia que existe entre ellas es que una variable de sesión pierde su contenido cuando cerramos la sesión con el servidor, mientras que una variable global mantiene su valor hasta que se realiza un reinicio del servicio o se modifica por otro valor. Las variables globales sólo pueden ser configuradas por usuarios con privilegios de administración.
Para configurar la variable lc_time_names
como una
variable global, con la configuración regional de
España tendrá que utilizar la palabra reservada GLOBAL
,
como se indica en el siguiente ejemplo.
Para realizar la configuración como una variable de sesión tendría que ejecutar:
Una vez hecho esto podrá consultar sus valores haciendo:
En la documentación oficial pueden encontrar más información sobre la configuración regional en MySQL Server.
Para consultar el valor de todas las variables de sesión del sistema podemos utilizar la sentencia:
O con el modificador SESSION
:
Para consultar el valor de todas las variables globales del sistema podemos utilizar la sentencia:
Configuración de la zona horaria en MySQL Server (time zone)
Importante: Tenga en cuenta que también
será necesario configurar nuestra zona horaria para que las funciones
relacionadas con la hora devuelvan los valores de nuestra zona horaria.
En este caso tendrá que configurar la variable del sistema
time_zone
, como variable global o como
variable de sesión. A continuación, se muestra un
ejemplo de cómo habría que configurar las variables para la zona horaria
de Madrid.
Podemos comprobar el estado de las variables haciendo:
En la documentación oficial pueden encontrar más información sobre la configuración de la zona horaria en MySQL Server.
Ejemplos:
NOW()
devuelve la fecha y la hora actual.
CURTIME()
devuelve la hora actual.
Ejercicios:
Devuelva un listado con cuatro columnas, donde aparezca en la
primera columna la fecha de nacimiento completa de los alumnos, en la
segunda columna el día, en la tercera el mes y en la cuarta el año.
Utilice las funciones DAY
, MONTH
y
YEAR
.
Devuelva un listado con tres columnas, donde aparezca en la primera columna la fecha de nacimiento de los alumnos, en la segunda el nombre del día de la semana de la fecha de nacimiento y en la tercera el nombre del mes de la fecha de nacimiento.
DAYNAME
y
MONTHNAME
.DATE_FORMAT
.Devuelva un listado con dos columnas, donde aparezca en la
primera columna la fecha de nacimiento de los alumnos y en la segunda
columna el número de días que han pasado desde la fecha actual hasta la
fecha de nacimiento. Utilice las funciones DATEDIFF
y
NOW
. Consulte
la documentación oficial de MySQL para
DATEDIFF
.
Devuelva un listado con dos columnas, donde aparezca en la primera columna la fecha de nacimiento de los alumnos y en la segunda columna la edad de cada alumno/a. La edad (aproximada) la podemos calcular realizando las siguientes operaciones:
DATEDIFF
y
NOW
.Función | Descripción |
---|---|
ABS() |
Devuelve el valor absoluto |
POW(x,y) |
Devuelve el valor de x elevado a y |
SQRT |
Devuelve la raíz cuadrada |
PI() |
Devuelve el valor del número PI |
ROUND |
Redondea un valor numérico |
TRUNCATE |
Trunca un valor numérico |
CEIL |
Devuelve el entero inmediatamente superior o igual |
FLOOR |
Devuelve el entero inmediatamente inferior o igual |
MOD |
Devuelve el resto de una división |
En la documentación oficial puede encontrar la referencia completa de todas las funciones matemáticas disponibles en MySQL.
Ejemplos:
ABS
devuelve el valor absoluto de un número.
POW(x, y)
devuelve el valor de x elevado a y.
SQRT
devuelve la raíz cuadrada de un número.
PI()
devuelve el valor del número PI
.
ROUND
redondea un valor numérico
TRUNCATE
Trunca un valor numérico.
CEIL
devuelve el entero inmediatamente superior
o igual al parámetro de entrada.
FLOOR
devuelve el entero inmediatamente inferior
o igual al parámetro de entrada.
FULLTEXT
Ejemplo
En este ejemplo vamos a crear un índice FULLTEXT
sobre
las columnas nombre
y descripcion
de la tabla
producto
, para permitir realizar búsquedas más eficientes
sobre esas columnas.
Una vez creado el índice ejecutamos la consulta haciendo uso de
MATCH
y AGAINST
.
Puede encontrar más información sobre la creación de índices en MySQL en la documentación oficial.
Función | Descripción |
---|---|
CASE |
Operador para realizar condicionales múltiples |
IF() |
Permite realizar condiciones de tipo
IF /ELSE |
IFNULL() |
Devuelve el primer argumento si no es NULL , en caso
contrario devuelve el segundo argumento |
NULLIF() |
Devuelve NULL si los dos argumentos son iguales, en
caso contrario devuelve el primer argumento |
En la documentación oficial puede encontrar la referencia completa de todas las funciones de control de flujo disponibles en MySQL.
Ejemplo del operador CASE
:
Existen dos formas de utilizar el operador CASE
:
Sintaxis 1:
En este caso, junto al operador CASE
se utiliza un
valor, el nombre de una columna o una expresión y se compara con una
serie de valores. Cuando se encuentra la primera coincidencia, se
devuelve el resultado asociado y no se siguen evaluando el resto de
comapraciones.
SELECT
nombre, apellido1, apellido2,
CASE es_repetidor
WHEN 'sí' THEN 'Repite'
WHEN 'no' THEN 'No repite'
END
FROM alumno;
Sintaxis 2:
En este caso se utiliza una condición en cada comparación y cuando se encuentra la primera condición que sea cierta, se devuelve el resultado asociado y no se siguen evaluando el resto de condiciones.
SELECT
producto, cantidad,
CASE
WHEN cantidad > 100 THEN 'Stock suficiente'
WHEN cantidad > 50 THEN 'Stock moderado'
ELSE 'Stock bajo'
END AS estado
FROM
producto;
Ejemplo de la función IF
:
La sintaxis de la función IF
es la siguiente:
Si la expresión expr1
es TRUE
entonces
duvuelve el valor de expr2
, en caso contrario devuelve el
valor de expr3
.
Ejemplo de la función IFNULL
:
La sintaxis de la función IFNULL
es la siguiente:
Si la expresión expr1
no es NULL
entonces
duvuelve el valor de expr1
, en caso contrario devuelve el
valor de expr2
.
Ejemplo de la función NULLIF
:
La sintaxis de la función NULLIF
es la siguiente:
Esta función devuelve NULL
si expr1
es
igual a expr2
, en caso contrario devuelve el valor de
expr1
.
NULL
Ejemplo: Obtener la lista de alumnos que tienen un
valor NULL
en la columna teléfono
.
Consulta incorrecta.
Consulta correcta.
Ejemplo: Devuelve un listado de los alumnos cuyo
primer apellido empieza por S
.
Consulta incorrecta.
Consulta correcta.
Ejemplo: Devuelve un listado de los alumnos cuyo
primer apellido no empieza por S
.
Consulta incorrecta.
Consulta correcta.
AND
Cuando queremos comparar si un valor está dentro de un rango tenemos
que utilizar dos condiciones unidas con la operación lógica
AND
. En el siguiente ejemplo se muestra una consulta
incorrecta donde la segunda condición siempre será verdadera porque no
estamos comparando con ningún valor, estamos poniendo un valor constante
que al ser distinto de 0 siempre nos dará un valor verdadero como
resultado de la comparación.
Consulta incorrecta
Consulta correcta
Cuando se utiliza un operador con operandos de diferentes tipos de dato, MySQL realiza una conversión automática de tipo para que los operandos sean compatibles. Por ejemplo, convierte automáticamente cadenas en números según sea necesario y viceversa.
Ejemplo: Resta entre dos valores de tipo
VARCHAR
Las cadenas las convierte a datos de tipo entero de la mejor forma
posible y luego realiza la resta. En este caso la cadena
'2021-01-31'
la convierte en el número entero
2021
y la cadena '2021-02-01'
en el número
entero 2021
, por este motivo el resultado de la resta es
0
.
Ejemplo: Resta entre dos valores de tipo
DATE
En este ejemplo estamos convirtiendo las cadenas a un valor de tipo
DATE
y luego se realiza la resta. En este caso, los datos
de tipo DATE
los convierte a datos de tipo entero pero de
una forma más precisa que la conversión anterior, ya que la cadena
'2008-08-31'
la convierte en el número entero
20080831
y la cadena '2008-09-01'
en el número
entero 20080901
, por este motivo el resultado de la resta
es -70
.
Ejemplo: Resta entre dos valores de tipo
INT
Ejemplo: Resta entre dos valores de tipo DATE
utilizando la función DATEDIFF
Puede encontrar más información sobre la conversión de tipos en la evaluación de expresiones en la documentación oficial.
DATE
,
DATETIME
y TIMESTAMP
Para poder realizar operaciones de suma y resta entre datos de tipo
DATE
, DATETIME
y TIMESTAMP
es
necesario hacer uso de las funciones específicas de fecha y hora
disponibles en MySQL. Si tratamos de realizar una operación de suma o
resta entre valores de tipo DATE
, DATETIME
y
TIMESTAMP
podemos obtener un resultado incorrecto en
algunas situaciones, ya que estos valores se convierten a un dato de
tipo numérico y posteriormente se realiza la operación entre ellos.
Consulta incorrecta
fecha_esperada | fecha_entrega | fecha_entrega - fecha_esperada |
---|---|---|
2021-01-31 | 2021-02-01 | -70 |
En este ejemplo estamos realizando una resta entre dos datos de tipo
DATE
utilizando el operador -
. Lo que ocurre
en este caso, es que antes de realizar la operación de resta, MySQL
convierte los datos de tipo DATE
a datos de tipo entero. De
forma que la fecha 2008-08-31
la convierte en el número
entero 20080831
y la fecha 2008-09-01
en el
número entero 20080901
. Por este motivo el resultado que
obtenemos a realizar la resta es -70
.
Consulta correcta
fecha_esperada | fecha_entrega | DATEDIFF(fecha_entrega, fecha_esperada) |
---|---|---|
2021-01-31 | 2021-02-01 | -1 |
En este caso se está utilizando la función DATEDIFF
en
lugar del operador de resta -
. Al ser una función
específica para trabajar con este tipo de dato obtenemos el resultado
esperado.
Algunas de las imágenes utilizadas en este documento han sido extraídas de las siguientes fuentes:
Esta
página forma parte del curso
Bases de Datos de
José Juan Sánchez Hernández y
su contenido se distribuye bajo una
licencia
Creative Commons Reconocimiento-NoComercial-CompartirIgual 4.0
Internacional.