En MySQL, los VALUES
declaración devuelve un conjunto de una o más filas como una tabla. Básicamente, es un constructor de valores de tabla de acuerdo con el estándar SQL, que también funciona como una declaración SQL independiente.
Los VALUES
declaración se introdujo en MySQL 8.0.19.
Sintaxis
La sintaxis oficial es así:
VALUES row_constructor_list [ORDER BY column_designator] [LIMIT number]
row_constructor_list:
ROW(value_list)[, ROW(value_list)][, ...]
value_list:
value[, value][, ...]
column_designator:
column_index
Ejemplo
Aquí hay un ejemplo simple para demostrar cómo funciona:
VALUES ROW(1, 2, 3), ROW(4, 5, 6);
Resultado:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Las columnas resultantes se denominan implícitamente column_0
, column_1
, column_2
, y así sucesivamente, siempre comenzando con 0
.
Podemos ver que cada ROW()
la cláusula del constructor de filas da como resultado una nueva fila en la tabla resultante.
Cada ROW()
contiene una lista de valores de uno o más valores escalares entre paréntesis. Un valor puede ser un literal de cualquier tipo de datos de MySQL o una expresión que se resuelve en un valor escalar.
Por lo tanto también podemos hacer lo siguiente:
VALUES ROW("Black", "Cat"), ROW("Yellow", "Dog");
Resultado:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
O cosas como esta:
VALUES
ROW(CURDATE(), DATE_ADD(CURDATE(), INTERVAL 10 YEAR)),
ROW(CURTIME(), DATE_ADD(CURTIME(), INTERVAL 2 HOUR));
Resultado:
+---------------------+---------------------+ | column_0 | column_1 | +---------------------+---------------------+ | 2022-02-17 00:00:00 | 2032-02-17 00:00:00 | | 2022-02-17 09:30:46 | 2022-02-17 11:30:46 | +---------------------+---------------------+
El ORDER BY
Cláusula
La sintaxis permite el uso de ORDER BY
cláusula para ordenar los resultados. Sin embargo, descubrí que ORDER BY
la cláusula no funciona como se esperaba en los sistemas en los que he intentado ejecutarla.
Así es como debería trabajo (según la documentación de MySQL):
VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8) ORDER BY column_1;
Resultado:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | -2 | 3 | | 4 | 6 | 8 | | 5 | 7 | 9 | +----------+----------+----------+
Pero en los dos sistemas en los que ejecuté esa declaración (MySQL 8.0.26 en Ubuntu 20.04.3 y MySQL 8.0.27 Homebrew en MacOS Monterery), el ORDER BY
la cláusula no funciona en absoluto. Tal vez esto sea un error.
El LIMIT
Cláusula
Podemos usar el LIMIT
cláusula para limitar el número de filas que se generan:
VALUES
ROW('Black', 'Cat'),
ROW('Yellow', 'Dog'),
ROW('Aqua', 'Fish')
LIMIT 2;
Resultado:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Con SELECT
Declaración
También podemos usar los VALUES
declaración dentro de un SELECT
declaración, como si los VALUES
el constructor de la tabla fuera una tabla real:
SELECT
PetName,
PetType
FROM
(VALUES
ROW(1, "Fluffy", "Cat"),
ROW(2, "Bark", "Dog"),
ROW(3, "Gallop", "Horse")
) AS Pets(PetId, PetName, PetType)
WHERE PetId = 2;
Resultado:
+---------+---------+ | PetName | PetType | +---------+---------+ | Bark | Dog | +---------+---------+
ROW()
No puede estar vacío
Un constructor de fila no puede estar vacío, a menos que se use como fuente en un INSERT
declaración.
Esto es lo que sucede si tratamos de usar un constructor de fila vacío:
VALUES ROW();
Resultado:
ERROR 3942 (HY000): Each row of a VALUES clause must have at least one column, unless when used as source in an INSERT statement.
ROW()
Puede contener valores nulos
Aunque los constructores de filas no pueden estar vacíos, pueden contener valores nulos:
VALUES ROW(null, null);
Resultado:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | NULL | NULL | +----------+----------+
Cada ROW()
Debe contener el mismo número de valores
Cada ROW()
en el mismo VALUES
declaración debe tener el mismo número de valores en su lista de valores.
Por lo tanto, no podemos hacer esto:
VALUES ROW(1, 2), ROW(3);
Resultado:
ERROR 1136 (21S01): Column count doesn't match value count at row 2
Usando VALUES
para insertar datos
Podemos usar los VALUES
instrucción junto con INSERT
y REPLACE
instrucciones para insertar datos en una tabla.
Ejemplo:
INSERT INTO Pets VALUES
ROW(9, 3, 1, 'Woof', '2020-10-03'),
ROW(10, 4, 5, 'Ears', '2022-01-11');
Eso insertó dos filas en una tabla llamada Pets
. Esto supone que la tabla ya existe.
Ahora podemos usar un SELECT
instrucción para ver los nuevos valores en la tabla:
SELECT * FROM Pets
WHERE PetId IN (9, 10);
Resultado:
+-------+-----------+---------+---------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | +-------+-----------+---------+---------+------------+ | 9 | 3 | 1 | Woof | 2020-10-03 | | 10 | 4 | 5 | Ears | 2022-01-11 | +-------+-----------+---------+---------+------------+
El INSERT
anterior declaración es el equivalente de hacer lo siguiente:
INSERT INTO Pets VALUES
(9, 3, 1, 'Woof', '2020-10-03'),
(10, 4, 5, 'Ears', '2022-01-11');
Al crear tablas
Los VALUES
La declaración también se puede usar en lugar de la tabla de origen en CREATE TABLE … SELECT
y CREATE VIEW … SELECT
declaraciones.
He aquí un ejemplo:
CREATE TABLE t1 VALUES ROW(1,2,3), ROW(4,5,6);
SELECT * FROM t1;
Resultado:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
También podemos hacer esto:
CREATE TABLE t2 SELECT * FROM (VALUES ROW(1,2,3), ROW(4,5,6)) AS v;
SELECT * FROM t2;
Resultado:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Esos dos CREATE TABLE
declaraciones son como hacer esto:
CREATE TABLE t3 SELECT * FROM t2;
SELECT * FROM t3;
Resultado:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
En este caso, utilicé el t2
como tabla de origen, en lugar de proporcionar los valores en un VALUES
declaración.