SQL SELECT INTO
ステートメントは、クエリの結果をテーブル(またはDBMSによっては変数)に挿入するために使用できるSybase拡張機能です。
SQL ServerやPostgreSQLなどのDBMSでは、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';
この例では、2020年6月1日より前の生年月日(DOB)を持つペットのみにデータをフィルタリングします。
複数のテーブルからの選択
複数のテーブルからデータを選択し、結果セットに基づいて宛先テーブルの定義を設定できます。
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;
ここでは、3つのテーブルをクエリし、その結果をPetsTypesOwners
というテーブルに挿入します。 。
すべての列を含めたくなかったので、ここに各列をリストしたことに注意してください。
具体的には、外部キー/主キーの列を2倍にしたくありませんでした。私の場合、外部キーは親テーブルの主キーと同じ名前を共有しており、宛先テーブルに重複する列名が作成されているため、エラーが発生していました。
これが私の言いたいことです。
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.
外部キーが主キーとは異なる列名を使用している場合、不要な列を含む宛先テーブルが作成される可能性があります(1つは主キー用、もう1つは外部キー用で、それぞれに同じ値が含まれます)。
このような重複する列を本当に含めたいが、それらが同じ名前を共有している場合は、いつでもエイリアスを使用して、宛先テーブルで別の名前を割り当てることができます。
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;
この場合、列エイリアスを使用して、2つの列の名前を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)
DBMSサポート
前述のように、SELECT INTO
ステートメントはSybaseの拡張機能であり、すべての主要なDBMSでサポートされているわけではありません。たとえば、MySQLとSQLiteはそれをサポートしていません。
また、それをサポートするDBMSのうち、実際の実装はDBMS間で多少異なります。上記の例はSQLServerで実行されました。 MariaDBとOracleでは、宛先テーブルを変数名(またはOracleのコレクション名)に置き換えることができます。
DBMSがSELECT INTO
をサポートしていない場合 ステートメント、おそらくINSERT INTO... SELECT
をサポートしています ステートメントなので、代わりに試してみてください。