In MySQL zijn de VALUES
instructie retourneert een set van een of meer rijen als een tabel. Kortom, het is een tabelwaardeconstructor in overeenstemming met de SQL-standaard, die ook functioneert als een op zichzelf staande SQL-instructie.
De VALUES
statement is geïntroduceerd in MySQL 8.0.19.
Syntaxis
De officiële syntaxis gaat als volgt:
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
Voorbeeld
Hier is een eenvoudig voorbeeld om te demonstreren hoe het werkt:
VALUES ROW(1, 2, 3), ROW(4, 5, 6);
Resultaat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
De resulterende kolommen hebben impliciet de naam column_0
, column_1
, column_2
, enzovoort, altijd beginnend met 0
.
We kunnen zien dat elke ROW()
row constructor-clausule resulteert in een nieuwe rij in de resulterende tabel.
Elke ROW()
bevat een waardenlijst van een of meer scalaire waarden tussen haakjes. Een waarde kan een letterlijke waarde zijn van elk MySQL-gegevenstype of een uitdrukking die wordt omgezet in een scalaire waarde.
Daarom kunnen we ook het volgende doen:
VALUES ROW("Black", "Cat"), ROW("Yellow", "Dog");
Resultaat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Of dingen als dit:
VALUES
ROW(CURDATE(), DATE_ADD(CURDATE(), INTERVAL 10 YEAR)),
ROW(CURTIME(), DATE_ADD(CURTIME(), INTERVAL 2 HOUR));
Resultaat:
+---------------------+---------------------+ | 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 | +---------------------+---------------------+
De ORDER BY
Clausule
De syntaxis maakt het gebruik van de ORDER BY
. mogelijk clausule om de resultaten te ordenen. Ik heb echter ontdekt dat de ORDER BY
clausule werkt niet zoals verwacht op de systemen waar ik het tegen heb geprobeerd.
Hier is hoe het zou moeten werk (volgens de MySQL-documentatie):
VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8) ORDER BY column_1;
Resultaat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | -2 | 3 | | 4 | 6 | 8 | | 5 | 7 | 9 | +----------+----------+----------+
Maar op de twee systemen waar ik die verklaring tegen uitvoerde (MySQL 8.0.26 op Ubuntu 20.04.3 en MySQL 8.0.27 Homebrew op MacOS Monterery), de ORDER BY
clausule werkt helemaal niet. Misschien is dit een bug.
De LIMIT
Clausule
We kunnen de LIMIT
. gebruiken clausule om het aantal rijen dat wordt uitgevoerd te beperken:
VALUES
ROW('Black', 'Cat'),
ROW('Yellow', 'Dog'),
ROW('Aqua', 'Fish')
LIMIT 2;
Resultaat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Met een SELECT
Verklaring
We kunnen ook de VALUES
. gebruiken statement binnen een SELECT
statement, alsof de VALUES
table constructor waren een echte tabel:
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;
Resultaat:
+---------+---------+ | PetName | PetType | +---------+---------+ | Bark | Dog | +---------+---------+
ROW()
Mag niet leeg zijn
Een rijconstructor kan niet leeg zijn, tenzij deze wordt gebruikt als bron in een INSERT
uitspraak.
Dit is wat er gebeurt als we een lege rijconstructor proberen te gebruiken:
VALUES ROW();
Resultaat:
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()
Kan nulwaarden bevatten
Hoewel rijconstructors niet leeg kunnen zijn, kunnen ze null-waarden bevatten:
VALUES ROW(null, null);
Resultaat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | NULL | NULL | +----------+----------+
Elke ROW()
Moet hetzelfde aantal waarden bevatten
Elke ROW()
in dezelfde VALUES
statement moet hetzelfde aantal waarden in de lijst met waarden hebben.
Daarom kunnen we dit niet doen:
VALUES ROW(1, 2), ROW(3);
Resultaat:
ERROR 1136 (21S01): Column count doesn't match value count at row 2
VALUES
gebruiken om gegevens in te voegen
We kunnen de VALUES
. gebruiken statement in combinatie met de INSERT
en REPLACE
instructies om gegevens in een tabel in te voegen.
Voorbeeld:
INSERT INTO Pets VALUES
ROW(9, 3, 1, 'Woof', '2020-10-03'),
ROW(10, 4, 5, 'Ears', '2022-01-11');
Dat voegde twee rijen toe aan een tabel met de naam Pets
. Dit veronderstelt dat de tabel al bestaat.
We kunnen nu een SELECT
. gebruiken statement om de nieuwe waarden in de tabel te zien:
SELECT * FROM Pets
WHERE PetId IN (9, 10);
Resultaat:
+-------+-----------+---------+---------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | +-------+-----------+---------+---------+------------+ | 9 | 3 | 1 | Woof | 2020-10-03 | | 10 | 4 | 5 | Ears | 2022-01-11 | +-------+-----------+---------+---------+------------+
De bovenstaande INSERT
statement is het equivalent van het volgende doen:
INSERT INTO Pets VALUES
(9, 3, 1, 'Woof', '2020-10-03'),
(10, 4, 5, 'Ears', '2022-01-11');
Bij het maken van tabellen
De VALUES
statement kan ook worden gebruikt in plaats van de brontabel in CREATE TABLE … SELECT
en CREATE VIEW … SELECT
verklaringen.
Hier is een voorbeeld:
CREATE TABLE t1 VALUES ROW(1,2,3), ROW(4,5,6);
SELECT * FROM t1;
Resultaat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
We kunnen dit ook doen:
CREATE TABLE t2 SELECT * FROM (VALUES ROW(1,2,3), ROW(4,5,6)) AS v;
SELECT * FROM t2;
Resultaat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Die twee CREATE TABLE
uitspraken zijn als volgt:
CREATE TABLE t3 SELECT * FROM t2;
SELECT * FROM t3;
Resultaat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
In dit geval gebruikte ik de t2
tabel als de brontabel, in plaats van de waarden op te geven in een VALUES
verklaring.