I MySQL, VALUES
sats returnerar en uppsättning av en eller flera rader som en tabell. I grund och botten är det en tabellvärdekonstruktor i enlighet med SQL-standarden, som också fungerar som en fristående SQL-sats.
VALUES
uttalandet introducerades i MySQL 8.0.19.
Syntax
Den officiella syntaxen ser ut så här:
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
Exempel
Här är ett enkelt exempel för att visa hur det fungerar:
VALUES ROW(1, 2, 3), ROW(4, 5, 6);
Resultat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
De resulterande kolumnerna heter implicit column_0
, column_1
, column_2
, och så vidare, som alltid börjar med 0
.
Vi kan se att varje ROW()
radkonstruktorsatsen resulterar i en ny rad i den resulterande tabellen.
Varje ROW()
innehåller en värdelista med ett eller flera skalära värden inom parentes. Ett värde kan vara en bokstavlig typ av MySQL-datatyp eller ett uttryck som löser sig till ett skalärt värde.
Därför kan vi också göra följande:
VALUES ROW("Black", "Cat"), ROW("Yellow", "Dog");
Resultat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Eller sånt här:
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
Syntaxen tillåter användning av ORDER BY
klausul för att ordna resultaten. Jag har dock upptäckt att ORDER BY
klausulen fungerar inte som förväntat på de system jag har försökt köra den mot.
Så här ska fungerar (enligt 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 två systemen som jag körde det uttalandet mot (MySQL 8.0.26 på Ubuntu 20.04.3 och MySQL 8.0.27 Homebrew på MacOS Monterery), ORDER BY
klausulen fungerar inte alls. Kanske är detta en bugg.
LIMIT
Klausul
Vi kan använda LIMIT
sats för att begränsa antalet rader som matas ut:
VALUES
ROW('Black', 'Cat'),
ROW('Yellow', 'Dog'),
ROW('Aqua', 'Fish')
LIMIT 2;
Resultat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Med en SELECT
Uttalande
Vi kan också använda VALUES
sats i en SELECT
uttalande, som om VALUES
Tabellkonstruktören var en faktisk tabell:
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 inte vara tom
En radkonstruktor kan inte vara tom om den inte används som källa i en INSERT
påstående.
Så här händer om vi försöker använda en tom radkonstruktor:
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 innehålla nollvärden
Även om radkonstruktörer inte kan vara tomma, kan de innehålla Null-värden:
VALUES ROW(null, null);
Resultat:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | NULL | NULL | +----------+----------+
Varje ROW()
Måste innehålla samma antal värden
Varje ROW()
i samma VALUES
uttalandet måste ha samma antal värden i sin värdelista.
Därför kan vi inte göra detta:
VALUES ROW(1, 2), ROW(3);
Resultat:
ERROR 1136 (21S01): Column count doesn't match value count at row 2
Använda VALUES
för att infoga data
Vi kan använda VALUES
sats i kombination med INSERT
och REPLACE
satser för att infoga data i en tabell.
Exempel:
INSERT INTO Pets VALUES
ROW(9, 3, 1, 'Woof', '2020-10-03'),
ROW(10, 4, 5, 'Ears', '2022-01-11');
Det infogade två rader i en tabell som heter Pets
. Detta förutsätter att tabellen redan finns.
Vi kan nu använda en SELECT
uttalande för att se de nya värdena 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 | +-------+-----------+---------+---------+------------+
Ovanstående INSERT
uttalande motsvarar att göra följande:
INSERT INTO Pets VALUES
(9, 3, 1, 'Woof', '2020-10-03'),
(10, 4, 5, 'Ears', '2022-01-11');
När man skapar tabeller
VALUES
satsen kan också användas i stället för källtabellen i CREATE TABLE … SELECT
och CREATE VIEW … SELECT
uttalanden.
Här är ett exempel:
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 också göra detta:
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 | +----------+----------+----------+
Dessa två CREATE TABLE
uttalanden är som att göra så här:
CREATE TABLE t3 SELECT * FROM t2;
SELECT * FROM t3;
Resultat:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
I det här fallet använde jag t2
tabellen som källtabell, istället för att tillhandahålla värdena i en VALUES
uttalande.