I MySQL er VALUES
sætning returnerer et sæt af en eller flere rækker som en tabel. Grundlæggende er det en tabelværdikonstruktør i overensstemmelse med SQL-standarden, som også fungerer som en selvstændig SQL-sætning.
VALUES
sætning blev introduceret i MySQL 8.0.19.
Syntaks
Den officielle syntaks lyder sådan her:
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
Eksempel
Her er et simpelt eksempel for at demonstrere, hvordan det virker:
VALUES ROW(1, 2, 3), ROW(4, 5, 6);
Resultat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
De resulterende kolonner er implicit navngivet column_0
, column_1
, column_2
, og så videre, altid begyndende med 0
.
Vi kan se, at hver ROW()
rækkekonstruktør-klausul resulterer i en ny række i den resulterende tabel.
Hver ROW()
indeholder en værdiliste med en eller flere skalarværdier indesluttet i parentes. En værdi kan være en bogstavelig for enhver MySQL-datatype eller et udtryk, der omdannes til en skalarværdi.
Derfor kan vi også gøre følgende:
VALUES ROW("Black", "Cat"), ROW("Yellow", "Dog");
Resultat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Eller ting som dette:
VALUES
ROW(CURDATE(), DATE_ADD(CURDATE(), INTERVAL 10 YEAR)),
ROW(CURTIME(), DATE_ADD(CURTIME(), INTERVAL 2 HOUR));
Resultat:
+---------------------+---------------------+ | 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 | +---------------------+---------------------+
ORDER BY
Klausul
Syntaksen tillader brug af ORDER BY
klausul for at bestille resultaterne. Jeg har dog fundet ud af, at ORDER BY
klausulen virker ikke som forventet på de systemer, jeg har prøvet at køre den imod.
Sådan skal det arbejde (ifølge MySQL-dokumentationen):
VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8) ORDER BY column_1;
Resultat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | -2 | 3 | | 4 | 6 | 8 | | 5 | 7 | 9 | +----------+----------+----------+
Men på de to systemer, som jeg kørte den erklæring imod (MySQL 8.0.26 på Ubuntu 20.04.3 og MySQL 8.0.27 Homebrew på MacOS Monterery), er ORDER BY
klausul virker slet ikke. Måske er dette en fejl.
LIMIT
Klausul
Vi kan bruge LIMIT
klausul for at begrænse antallet af rækker, der udskrives:
VALUES
ROW('Black', 'Cat'),
ROW('Yellow', 'Dog'),
ROW('Aqua', 'Fish')
LIMIT 2;
Resultat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Med en SELECT
Erklæring
Vi kan også bruge VALUES
sætning i en SELECT
sætning, som om VALUES
tabelkonstruktør var en faktisk 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;
Resultat:
+---------+---------+ | PetName | PetType | +---------+---------+ | Bark | Dog | +---------+---------+
ROW()
Kan ikke være tom
En rækkekonstruktør kan ikke være tom, medmindre den bruges som kilde i en INSERT
udmelding.
Her er, hvad der sker, hvis vi forsøger at bruge en tom rækkekonstruktør:
VALUES ROW();
Resultat:
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 indeholde nulværdier
Selvom rækkekonstruktører ikke kan være tomme, kan de indeholde Null-værdier:
VALUES ROW(null, null);
Resultat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | NULL | NULL | +----------+----------+
Hver ROW()
Skal indeholde det samme antal værdier
Hver ROW()
i samme VALUES
sætningen skal have det samme antal værdier i sin værdiliste.
Derfor kan vi ikke gøre dette:
VALUES ROW(1, 2), ROW(3);
Resultat:
ERROR 1136 (21S01): Column count doesn't match value count at row 2
Brug af VALUES
for at indsætte data
Vi kan bruge VALUES
sætning i forbindelse med INSERT
og REPLACE
sætninger for at indsætte data i en tabel.
Eksempel:
INSERT INTO Pets VALUES
ROW(9, 3, 1, 'Woof', '2020-10-03'),
ROW(10, 4, 5, 'Ears', '2022-01-11');
Det indsatte to rækker i en tabel kaldet Pets
. Dette forudsætter, at tabellen allerede eksisterer.
Vi kan nu bruge en SELECT
sætning for at se de nye værdier i tabellen:
SELECT * FROM Pets
WHERE PetId IN (9, 10);
Resultat:
+-------+-----------+---------+---------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | +-------+-----------+---------+---------+------------+ | 9 | 3 | 1 | Woof | 2020-10-03 | | 10 | 4 | 5 | Ears | 2022-01-11 | +-------+-----------+---------+---------+------------+
Ovenstående INSERT
sætning svarer til at gøre følgende:
INSERT INTO Pets VALUES
(9, 3, 1, 'Woof', '2020-10-03'),
(10, 4, 5, 'Ears', '2022-01-11');
Når du opretter tabeller
VALUES
sætningen kan også bruges i stedet for kildetabellen i CREATE TABLE … SELECT
og CREATE VIEW … SELECT
udsagn.
Her er et eksempel:
CREATE TABLE t1 VALUES ROW(1,2,3), ROW(4,5,6);
SELECT * FROM t1;
Resultat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Vi kan også gøre dette:
CREATE TABLE t2 SELECT * FROM (VALUES ROW(1,2,3), ROW(4,5,6)) AS v;
SELECT * FROM t2;
Resultat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Disse to CREATE TABLE
udsagn er som at gøre dette:
CREATE TABLE t3 SELECT * FROM t2;
SELECT * FROM t3;
Resultat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
I dette tilfælde brugte jeg t2
tabel som kildetabellen i stedet for at angive værdierne i en VALUES
erklæring.