In MySQL, i VALUES
istruzione restituisce un insieme di una o più righe come tabella. Fondamentalmente, è un costruttore di valori di tabella in conformità con lo standard SQL, che funziona anche come un'istruzione SQL autonoma.
I VALUES
istruzione è stata introdotta in MySQL 8.0.19.
Sintassi
La sintassi ufficiale è questa:
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
Esempio
Ecco un semplice esempio per dimostrare come funziona:
VALUES ROW(1, 2, 3), ROW(4, 5, 6);
Risultato:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Le colonne risultanti sono implicitamente denominate column_0
, column_1
, column_2
, e così via, iniziando sempre con 0
.
Possiamo vedere che ogni ROW()
La clausola del costruttore di riga genera una nuova riga nella tabella risultante.
Ogni ROW()
contiene un elenco di valori di uno o più valori scalari racchiusi tra parentesi. Un valore può essere un valore letterale di qualsiasi tipo di dati MySQL o un'espressione che si risolve in un valore scalare.
Pertanto possiamo anche fare quanto segue:
VALUES ROW("Black", "Cat"), ROW("Yellow", "Dog");
Risultato:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
O cose come questa:
VALUES
ROW(CURDATE(), DATE_ADD(CURDATE(), INTERVAL 10 YEAR)),
ROW(CURTIME(), DATE_ADD(CURTIME(), INTERVAL 2 HOUR));
Risultato:
+---------------------+---------------------+ | 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 | +---------------------+---------------------+
Il ORDER BY
Clausola
La sintassi consente l'utilizzo di ORDER BY
clausola per ordinare i risultati. Tuttavia, ho scoperto che il ORDER BY
La clausola non funziona come previsto sui sistemi su cui ho provato a eseguirla.
Ecco come dovrebbe lavoro (secondo la documentazione MySQL):
VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8) ORDER BY column_1;
Risultato:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | -2 | 3 | | 4 | 6 | 8 | | 5 | 7 | 9 | +----------+----------+----------+
Ma sui due sistemi su cui ho eseguito quell'istruzione (MySQL 8.0.26 su Ubuntu 20.04.3 e MySQL 8.0.27 Homebrew su MacOS Monterery), il ORDER BY
la clausola non funziona affatto. Forse questo è un bug.
Il LIMIT
Clausola
Possiamo usare il LIMIT
clausola per limitare il numero di righe che vengono emesse:
VALUES
ROW('Black', 'Cat'),
ROW('Yellow', 'Dog'),
ROW('Aqua', 'Fish')
LIMIT 2;
Risultato:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Con un SELECT
Dichiarazione
Possiamo anche usare i VALUES
istruzione all'interno di un SELECT
istruzione, come se il VALUES
costruttore di tabelle erano una tabella reale:
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;
Risultato:
+---------+---------+ | PetName | PetType | +---------+---------+ | Bark | Dog | +---------+---------+
ROW()
Non può essere vuoto
Un costruttore di riga non può essere vuoto, a meno che non venga utilizzato come origine in un INSERT
dichiarazione.
Ecco cosa succede se proviamo a utilizzare un costruttore di righe vuoto:
VALUES ROW();
Risultato:
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()
Può contenere valori nulli
Sebbene i costruttori di riga non possano essere vuoti, possono contenere valori Null:
VALUES ROW(null, null);
Risultato:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | NULL | NULL | +----------+----------+
Ogni ROW()
Deve contenere lo stesso numero di valori
Ogni ROW()
nello stesso VALUES
l'istruzione deve avere lo stesso numero di valori nella sua lista valori.
Pertanto, non possiamo farlo:
VALUES ROW(1, 2), ROW(3);
Risultato:
ERROR 1136 (21S01): Column count doesn't match value count at row 2
Utilizzo di VALUES
per inserire dati
Possiamo usare i VALUES
istruzione insieme a INSERT
e REPLACE
istruzioni per inserire dati in una tabella.
Esempio:
INSERT INTO Pets VALUES
ROW(9, 3, 1, 'Woof', '2020-10-03'),
ROW(10, 4, 5, 'Ears', '2022-01-11');
Che ha inserito due righe in una tabella chiamata Pets
. Ciò presuppone che la tabella esista già.
Ora possiamo usare un SELECT
istruzione per vedere i nuovi valori nella tabella:
SELECT * FROM Pets
WHERE PetId IN (9, 10);
Risultato:
+-------+-----------+---------+---------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | +-------+-----------+---------+---------+------------+ | 9 | 3 | 1 | Woof | 2020-10-03 | | 10 | 4 | 5 | Ears | 2022-01-11 | +-------+-----------+---------+---------+------------+
Quanto sopra INSERT
istruzione equivale a fare quanto segue:
INSERT INTO Pets VALUES
(9, 3, 1, 'Woof', '2020-10-03'),
(10, 4, 5, 'Ears', '2022-01-11');
Quando si creano tabelle
I VALUES
l'istruzione può essere utilizzata anche al posto della tabella di origine in CREATE TABLE … SELECT
e CREATE VIEW … SELECT
dichiarazioni.
Ecco un esempio:
CREATE TABLE t1 VALUES ROW(1,2,3), ROW(4,5,6);
SELECT * FROM t1;
Risultato:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Possiamo anche fare questo:
CREATE TABLE t2 SELECT * FROM (VALUES ROW(1,2,3), ROW(4,5,6)) AS v;
SELECT * FROM t2;
Risultato:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Quei due CREATE TABLE
le dichiarazioni sono come fare questo:
CREATE TABLE t3 SELECT * FROM t2;
SELECT * FROM t3;
Risultato:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
In questo caso, ho usato il t2
table come tabella di origine, invece di fornire i valori in un VALUES
dichiarazione.