SQL SELECT INTO
statement är en Sybase-tillägg som kan användas för att infoga resultaten av en fråga i en tabell (eller en variabel, beroende på DBMS).
I DBMS som SQL Server och PostgreSQL, SELECT INTO
uttalandet skapar en ny tabell och infogar de resulterande raderna från frågan i den.
I MariaDB infogar den resultatuppsättningen i en variabel. I Oracle tilldelar den de valda värdena till variabler eller samlingar.
MySQL och SQLite stöder inte SELECT INTO
uttalande överhuvudtaget.
Exemplen i den här artikeln infogar resultatuppsättningarna i en tabell. I MariaDB och Oracle kan destinationstabellen ersättas med ett variabelnamn (eller samlingsnamnet om du använder Oracle).
Grundläggande exempel
Här är ett grundläggande exempel för att visa hur du väljer och infogar data i en ny tabell.
SELECT * INTO Pets2
FROM Pets;
Detta exempel skapar en tabell som heter Pets2
med samma definition av tabellen som heter Pets
och infogar all data från Pets
till Pets2
.
Vi kan verifiera detta genom att välja innehållet i båda tabellerna.
SELECT * FROM Pets;
SELECT * FROM Pets2;
Resultat:
+---------+-------------+-----------+-----------+------------+ | 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)
När tabellen redan finns
Om vi försöker köra SELECT INTO
uttalande igen, får vi ett fel, på grund av att tabellen redan finns.
SELECT * INTO Pets2
FROM Pets;
Resultat:
Msg 2714, Level 16, State 6, Line 1 There is already an object named 'Pets2' in the database.
Om du vill infoga data i en tabell som redan finns, använd INSERT INTO... SELECT
påstående. Detta kommer att lägga till data till alla befintliga data. Det vill säga, det kommer att lägga till nya rader i tabellen, samtidigt som befintliga rader behålls
Filtrera resultaten
SELECT
uttalande kan göra den vanliga SELECT
satser, som att filtrera resultaten med en WHERE
klausul.
SELECT * INTO Pets3
FROM Pets
WHERE DOB < '2020-06-01';
I det här exemplet filtrerar jag data till bara de husdjur som har ett födelsedatum (DOB) från före den 1 juni 2020.
Välja från flera tabeller
Du kan välja data från flera tabeller och sedan låta destinationstabellens definition baseras på resultatuppsättningen.
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;
Här frågar vi tre tabeller och infogar resultaten i en tabell som heter PetsTypesOwners
.
Observera att jag listade varje kolumn här eftersom jag inte ville inkludera alla kolumner.
Specifikt ville jag inte dubbla upp kolumnerna för främmande nyckel/primärnyckel. I mitt fall delar de främmande nycklarna samma namn som deras motsvarigheter för primärnyckeln i den överordnade tabellen, och jag skulle ha fått ett felmeddelande på grund av att dubbla kolumnnamn skapades i destinationstabellen.
Det här är vad jag menar.
SELECT *
INTO PetsTypesOwners2
FROM Pets p
INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId
INNER JOIN Owners o
ON p.OwnerId = o.OwnerId;
Resultat:
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.
Om dina främmande nycklar använder olika kolumnnamn än de primära nycklarna, skulle du förmodligen sluta med en destinationstabell som innehåller onödiga kolumner (en för primärnyckeln, en för den främmande nyckeln och var och en innehåller samma värden).
Om du verkligen vill inkludera sådana dubbletter av kolumner, men de delar samma namn, kan du alltid använda alias för att tilldela dem ett annat namn i destinationstabellen.
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;
I det här fallet använde jag kolumnalias för att tilldela namnet på två kolumner till PetOwnerId
och PetPetTypeId
.
VÄLJ IN från en vy
Du kan också välja data från en vy om det behövs.
SELECT * INTO PetTypeCount
FROM vPetTypeCount;
Detta väljer data från vPetTypeCount
visa och infogar den i en ny tabell som heter PetTypeCount
.
Vi kan verifiera detta med en SELECT
uttalande.
SELECT * FROM vPetTypeCount;
SELECT * FROM PetTypeCount;
Resultat:
+-----------+---------+ | PetType | Count | |-----------+---------| | Bird | 1 | | Cat | 3 | | Dog | 4 | +-----------+---------+ (3 rows affected) +-----------+---------+ | PetType | Count | |-----------+---------| | Bird | 1 | | Cat | 3 | | Dog | 4 | +-----------+---------+ (3 rows affected)
DBMS-stöd
Som nämnts, SELECT INTO
statement är ett Sybase-tillägg och det stöds inte av alla större DBMS. Till exempel, MySQL och SQLite stöder det inte.
Dessutom, av de DBMS som stöder det, varierar den faktiska implementeringen något mellan DBMS. Ovanstående exempel gjordes i SQL Server. I MariaDB och Oracle kan du ersätta destinationstabellen med ett variabelnamn (eller samlingsnamn i Oracle).
Om din DBMS inte stöder SELECT INTO
uttalandet, är chansen stor att den stöder INSERT INTO... SELECT
uttalande, så du borde prova det istället.