В MySQL, VALUES
оператор връща набор от един или повече редове като таблица. По принцип това е конструктор на стойност на таблица в съответствие със стандарта SQL, който също функционира като самостоятелен SQL израз.
VALUES
операторът беше въведен в MySQL 8.0.19.
Синтаксис
Официалният синтаксис е така:
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
Пример
Ето един прост пример, за да демонстрирате как работи:
VALUES ROW(1, 2, 3), ROW(4, 5, 6);
Резултат:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Получените колони са имплицитно наречени column_0
, column_1
, column_2
, и така нататък, винаги започвайки с 0
.
Можем да видим, че всеки ROW()
Клаузата за конструктор на ред води до нов ред в получената таблица.
Всеки ROW()
съдържа списък със стойности от една или повече скаларни стойности, затворени в скоби. Стойността може да бъде литерал на всеки тип данни на MySQL или израз, който се разрешава до скаларна стойност.
Следователно можем да направим и следното:
VALUES ROW("Black", "Cat"), ROW("Yellow", "Dog");
Резултат:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
Или неща като това:
VALUES
ROW(CURDATE(), DATE_ADD(CURDATE(), INTERVAL 10 YEAR)),
ROW(CURTIME(), DATE_ADD(CURTIME(), INTERVAL 2 HOUR));
Резултат:
+---------------------+---------------------+ | 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
Клауза
Синтаксисът позволява използването на ORDER BY
клауза, за да подредите резултатите. Установих обаче, че ORDER BY
клаузата не работи според очакванията на системите, срещу които се опитах да я стартирам.
Ето как трябва работа (според документацията на MySQL):
VALUES ROW(1,-2,3), ROW(5,7,9), ROW(4,6,8) ORDER BY column_1;
Резултат:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | -2 | 3 | | 4 | 6 | 8 | | 5 | 7 | 9 | +----------+----------+----------+
Но на двете системи, срещу които изпълних това изявление (MySQL 8.0.26 на Ubuntu 20.04.3 и MySQL 8.0.27 Homebrew на MacOS Monterery), ORDER BY
клаузата изобщо не работи. Може би това е грешка.
LIMIT
Клауза
Можем да използваме LIMIT
клауза за ограничаване на броя на извежданите редове:
VALUES
ROW('Black', 'Cat'),
ROW('Yellow', 'Dog'),
ROW('Aqua', 'Fish')
LIMIT 2;
Резултат:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | Black | Cat | | Yellow | Dog | +----------+----------+
С SELECT
Изявление
Можем също да използваме VALUES
израз в SELECT
изявление, сякаш VALUES
конструкторите на таблица бяха действителна таблица:
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;
Резултат:
+---------+---------+ | PetName | PetType | +---------+---------+ | Bark | Dog | +---------+---------+
ROW()
Не може да бъде празен
Конструкторът на ред не може да бъде празен, освен ако не се използва като източник в INSERT
изявление.
Ето какво се случва, ако се опитаме да използваме празен конструктор на ред:
VALUES ROW();
Резултат:
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()
Може да съдържа нулеви стойности
Въпреки че конструкторите на редове не могат да бъдат празни, те могат да съдържат нулеви стойности:
VALUES ROW(null, null);
Резултат:
+----------+----------+ | column_0 | column_1 | +----------+----------+ | NULL | NULL | +----------+----------+
Всеки ROW()
Трябва да съдържа същия брой стойности
Всеки ROW()
в същите VALUES
изразът трябва да има същия брой стойности в своя списък със стойности.
Следователно не можем да направим това:
VALUES ROW(1, 2), ROW(3);
Резултат:
ERROR 1136 (21S01): Column count doesn't match value count at row 2
Използване на VALUES
за вмъкване на данни
Можем да използваме VALUES
израз във връзка с INSERT
и REPLACE
оператори за вмъкване на данни в таблица.
Пример:
INSERT INTO Pets VALUES
ROW(9, 3, 1, 'Woof', '2020-10-03'),
ROW(10, 4, 5, 'Ears', '2022-01-11');
Това вмъкна два реда в таблица, наречена Pets
. Това предполага, че таблицата вече съществува.
Вече можем да използваме SELECT
оператор, за да видите новите стойности в таблицата:
SELECT * FROM Pets
WHERE PetId IN (9, 10);
Резултат:
+-------+-----------+---------+---------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | +-------+-----------+---------+---------+------------+ | 9 | 3 | 1 | Woof | 2020-10-03 | | 10 | 4 | 5 | Ears | 2022-01-11 | +-------+-----------+---------+---------+------------+
Горният INSERT
изявлението е еквивалентно на извършване на следното:
INSERT INTO Pets VALUES
(9, 3, 1, 'Woof', '2020-10-03'),
(10, 4, 5, 'Ears', '2022-01-11');
При създаване на таблици
VALUES
изразът може да се използва и вместо таблицата източник в CREATE TABLE … SELECT
и CREATE VIEW … SELECT
изявления.
Ето един пример:
CREATE TABLE t1 VALUES ROW(1,2,3), ROW(4,5,6);
SELECT * FROM t1;
Резултат:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Можем да направим и това:
CREATE TABLE t2 SELECT * FROM (VALUES ROW(1,2,3), ROW(4,5,6)) AS v;
SELECT * FROM t2;
Резултат:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
Тези две CREATE TABLE
изявленията са като да правиш това:
CREATE TABLE t3 SELECT * FROM t2;
SELECT * FROM t3;
Резултат:
+----------+----------+----------+ | column_0 | column_1 | column_2 | +----------+----------+----------+ | 1 | 2 | 3 | | 4 | 5 | 6 | +----------+----------+----------+
В този случай използвах t2
таблица като изходна таблица, вместо да предоставя стойностите в VALUES
изявление.