sql >> データベース >  >> RDS >> Database

SQLSELECTINTOステートメント

    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をサポートしています ステートメントなので、代わりに試してみてください。


    1. SQL varchar内の特定のサブストリングの出現回数をどのようにカウントしますか?

    2. 別の列に基づくPostgreSQLシーケンス

    3. プラグ可能なデータベースの名前を変更する

    4. 列の平均を計算し、それをOracleの選択クエリに含めるにはどうすればよいですか?