SQL SELECT INTO
Инструкцията е разширение на Sybase, което може да се използва за вмъкване на резултатите от заявка в таблица (или променлива, в зависимост от СУБД).
В СУБД като SQL Server и PostgreSQL, SELECT INTO
оператор създава нова таблица и вмъква получените редове от заявката в нея.
В MariaDB той вмъква резултатния набор в променлива. В Oracle той присвоява избраните стойности на променливи или колекции.
MySQL и SQLite не поддържат SELECT INTO
изявление изобщо.
Примерите в тази статия вмъкват наборите от резултати в таблица. В MariaDB и Oracle таблицата на местоназначението може да бъде заменена с име на променлива (или името на колекцията, ако използвате Oracle).
Основен пример
Ето основен пример за демонстриране на избор и вмъкване на данни в нова таблица.
SELECT * INTO Pets2
FROM Pets;
Този пример създава таблица, наречена Pets2
със същата дефиниция на таблицата, наречена Pets
и вмъква всички данни от Pets
в Pets2
.
Можем да проверим това, като изберем съдържанието и на двете таблици.
SELECT * FROM Pets;
SELECT * FROM Pets2;
Резултат:
+---------+-------------+-----------+-----------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | |---------+-------------+-----------+-----------+------------| | 1 | 2 | 3 | Fluffy | 2020-11-20 | | 2 | 3 | 3 | Fetch | 2019-08-16 | | 3 | 2 | 2 | Scratch | 2018-10-01 | | 4 | 3 | 3 | Wag | 2020-03-15 | | 5 | 1 | 1 | Tweet | 2020-11-28 | | 6 | 3 | 4 | Fluffy | 2020-09-17 | | 7 | 3 | 2 | Bark | NULL | | 8 | 2 | 4 | Meow | NULL | +---------+-------------+-----------+-----------+------------+ (8 rows affected) +---------+-------------+-----------+-----------+------------+ | PetId | PetTypeId | OwnerId | PetName | DOB | |---------+-------------+-----------+-----------+------------| | 1 | 2 | 3 | Fluffy | 2020-11-20 | | 2 | 3 | 3 | Fetch | 2019-08-16 | | 3 | 2 | 2 | Scratch | 2018-10-01 | | 4 | 3 | 3 | Wag | 2020-03-15 | | 5 | 1 | 1 | Tweet | 2020-11-28 | | 6 | 3 | 4 | Fluffy | 2020-09-17 | | 7 | 3 | 2 | Bark | NULL | | 8 | 2 | 4 | Meow | NULL | +---------+-------------+-----------+-----------+------------+ (8 rows affected)
Когато таблицата вече съществува
Ако се опитаме да изпълним SELECT INTO
отново получаваме грешка, поради вече съществуващата таблица.
SELECT * INTO Pets2
FROM Pets;
Резултат:
Msg 2714, Level 16, State 6, Line 1 There is already an object named 'Pets2' in the database.
Ако искате да вмъкнете данни в таблица, която вече съществува, използвайте INSERT INTO... SELECT
изявление. Това ще добави данните към всички съществуващи данни. Тоест, той ще добавя нови редове към таблицата, като запазва всички съществуващи редове
Филтриране на резултатите
SELECT
оператор може да направи обичайния SELECT
неща, като например филтриране на резултатите с WHERE
клауза.
SELECT * INTO Pets3
FROM Pets
WHERE DOB < '2020-06-01';
В този пример филтрирам данните само за онези домашни любимци, които имат дата на раждане (DOB) от преди 1 юни 2020 г.
Избиране от множество таблици
Можете да изберете данни от множество таблици, след което дефиницията на таблицата местоназначение да се базира на набора от резултати.
SELECT
p.PetId,
p.PetName,
p.DOB,
pt.PetTypeId,
pt.PetType,
o.OwnerId,
o.FirstName,
o.LastName,
o.Phone,
o.Email
INTO PetsTypesOwners
FROM Pets p
INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId
INNER JOIN Owners o
ON p.OwnerId = o.OwnerId;
Тук правим заявка за три таблици и вмъкваме резултатите в таблица, наречена PetsTypesOwners
.
Имайте предвид, че изброих всяка колона тук, защото не исках да включвам всички колони.
По-конкретно, не исках да удвоявам колоните за външен ключ/първичен ключ. В моя случай външните ключове споделят същите имена като техните двойници на първичния ключ в родителската таблица и бих получил грешка поради създаване на дублиращи се имена на колони в таблицата местоназначение.
Ето какво имам предвид.
SELECT *
INTO PetsTypesOwners2
FROM Pets p
INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId
INNER JOIN Owners o
ON p.OwnerId = o.OwnerId;
Резултат:
Msg 2705, Level 16, State 3, Line 1 Column names in each table must be unique. Column name 'PetTypeId' in table 'PetsTypesOwners2' is specified more than once.
Ако вашите външни ключове използват различни имена на колони спрямо първичните ключове, тогава вероятно ще се окажете с целева таблица, която съдържа ненужни колони (една за първичния ключ, една за външния ключ и всяка съдържаща едни и същи стойности).
Ако наистина искате да включите такива дублиращи се колони, но те споделят едно и също име, винаги можете да използвате псевдоними, за да им присвоите различно име в целевата таблица.
SELECT
p.PetId,
p.OwnerId AS PetOwnerId,
p.PetTypeId AS PetPetTypeId,
p.PetName,
p.DOB,
pt.PetTypeId,
pt.PetType,
o.OwnerId,
o.FirstName,
o.LastName,
o.Phone,
o.Email
INTO PetsTypesOwners3
FROM Pets p
INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId
INNER JOIN Owners o
ON p.OwnerId = o.OwnerId;
В този случай използвах псевдоними на колони, за да пренастроя името на две колони на PetOwnerId
и PetPetTypeId
.
ИЗБЕРЕТЕ В от изглед
Можете също да изберете данни от изглед, ако е необходимо.
SELECT * INTO PetTypeCount
FROM vPetTypeCount;
Това избира данни от vPetTypeCount
преглед и го вмъква в нова таблица, наречена PetTypeCount
.
Можем да проверим това с SELECT
изявление.
SELECT * FROM vPetTypeCount;
SELECT * FROM PetTypeCount;
Резултат:
+-----------+---------+ | PetType | Count | |-----------+---------| | Bird | 1 | | Cat | 3 | | Dog | 4 | +-----------+---------+ (3 rows affected) +-----------+---------+ | PetType | Count | |-----------+---------| | Bird | 1 | | Cat | 3 | | Dog | 4 | +-----------+---------+ (3 rows affected)
Поддръжка на СУБД
Както споменахме, SELECT INTO
операторът е разширение на Sybase и не се поддържа от всички основни СУБД. Например MySQL и SQLite не го поддържат.
Освен това от СУБД, които го поддържат, действителната реализация варира донякъде между СУБД. Горните примери са направени в SQL Server. В MariaDB и Oracle можете да замените целевата таблица с име на променлива (или име на колекция в Oracle).
Ако вашата СУБД не поддържа SELECT INTO
изявление, има вероятност да поддържа INSERT INTO... SELECT
изявление, така че трябва да опитате това вместо това.