No MySQL, os
VALUES
A instrução retorna um conjunto de uma ou mais linhas como uma tabela. Basicamente, é um construtor de valor de tabela de acordo com o padrão SQL, que também funciona como uma instrução SQL autônoma. Os
VALUES
foi introduzida no MySQL 8.0.19. Sintaxe
A sintaxe oficial é assim:
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
Exemplo
Aqui está um exemplo simples para demonstrar como funciona:
VALUES ROW(1, 2, 3), ROW(4, 5, 6);
Resultado:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
As colunas resultantes são chamadas implicitamente de
column_0
, column_1
, column_2
, e assim por diante, sempre começando com 0
. Podemos ver que cada
ROW()
A cláusula construtora de linha resulta em uma nova linha na tabela resultante. Cada
ROW()
contém uma lista de valores de um ou mais valores escalares entre parênteses. Um valor pode ser um literal de qualquer tipo de dados MySQL ou uma expressão que resolva para um valor escalar. Portanto, também podemos fazer o seguinte:
VALUES ROW("Black", "Cat"), ROW("Yellow", "Dog");
Resultado:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Ou coisas assim:
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 | +---------------------+---------------------+
O ORDER BY
Cláusula
A sintaxe permite o uso do
ORDER BY
cláusula para ordenar os resultados. No entanto, descobri que o ORDER BY
cláusula não funciona como esperado nos sistemas em que tentei executá-la. Veja como deveria trabalho (de acordo com a documentação do 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 | +----------+----------+----------+
Mas nos dois sistemas em que executei essa instrução (MySQL 8.0.26 no Ubuntu 20.04.3 e MySQL 8.0.27 Homebrew no MacOS Monterery), o
ORDER BY
cláusula não funciona. Talvez isso seja um bug. O LIMIT
Cláusula
Podemos usar o
LIMIT
cláusula para limitar o número de linhas que são geradas:VALUES
ROW('Black', 'Cat'),
ROW('Yellow', 'Dog'),
ROW('Aqua', 'Fish')
LIMIT 2;
Resultado:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Com um SELECT
Declaração
Também podemos usar os
VALUES
declaração dentro de um SELECT
instrução, como se os VALUES
construtor de tabela eram uma tabela 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()
Não pode estar vazio
Um construtor de linha não pode estar vazio, a menos que esteja sendo usado como fonte em um
INSERT
demonstração. Aqui está o que acontece se tentarmos usar um construtor de linha vazio:
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()
Pode conter valores nulos
Embora os construtores de linha não possam estar vazios, eles podem conter valores nulos:
VALUES ROW(null, null);
Resultado:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | NULL | NULL | +----------+----------+
Cada ROW()
Deve conter o mesmo número de valores
Cada
ROW()
no mesmo VALUES
A instrução deve ter o mesmo número de valores em sua lista de valores. Portanto, não podemos fazer isso:
VALUES ROW(1, 2), ROW(3);
Resultado:
ERROR 1136 (21S01): Column count doesn't match value count at row 2
Usando VALUES
para inserir dados
Podemos usar os
VALUES
instrução em conjunto com o INSERT
e REPLACE
instruções para inserir dados em uma tabela. Exemplo:
INSERT INTO Pets VALUES
ROW(9, 3, 1, 'Woof', '2020-10-03'),
ROW(10, 4, 5, 'Ears', '2022-01-11');
Isso inseriu duas linhas em uma tabela chamada
Pets
. Isso pressupõe que a tabela já existe. Agora podemos usar um
SELECT
instrução para ver os novos valores na tabela: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 | +-------+-----------+---------+---------+------------+
O
INSERT
acima declaração é o equivalente a fazer o seguinte:INSERT INTO Pets VALUES
(9, 3, 1, 'Woof', '2020-10-03'),
(10, 4, 5, 'Ears', '2022-01-11');
Ao criar tabelas
Os
VALUES
também pode ser usada no lugar da tabela de origem em CREATE TABLE … SELECT
e CREATE VIEW … SELECT
declarações. Aqui está um exemplo:
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 | +----------+----------+----------+
Também podemos fazer isso:
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 | +----------+----------+----------+
Esses dois
CREATE TABLE
declarações são como fazer isso:CREATE TABLE t3 SELECT * FROM t2;
SELECT * FROM t3;
Resultado:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Neste caso, usei o
t2
table como a tabela de origem, em vez de fornecer os valores em um VALUES
demonstração.