INTO 句 (Transact-SQL)

SELECT...INTO は、既定のファイル グループに新しいテーブルを作成し、クエリの結果得られた行をそのテーブルに挿入します。SELECT の完全な構文を確認するには、「SELECT (Transact-SQL)」を参照してください。

トピック リンク アイコンTransact-SQL 構文表記規則

構文

[ INTO new_table ]

引数

  • new_table
    新しいテーブルの名前を指定します。このテーブルは選択リストで指定した列とデータ ソースから選択された行を基に作成されます。

    new_table の形式は、選択リスト内の式を評価することによって決まります。new_table 内の列は、選択リストの指定順に作成されます。new_table 内の各列の名前、データ型、NULL 値の許容属性、値は、選択リスト内の対応する式と同じになります。列の IDENTITY プロパティは、「解説」の「ID 列の使用」に示されている条件に当てはまる場合を除いて転送されます。

    同じ SQL Server インスタンスの別のデータベースにテーブルを作成するには、new_table を database.schema.table_name の形式で完全修飾名として指定します。

    リモート サーバーに new_table を作成することはできませんが、new_table にリモート データ ソースのデータを設定することはできます。リモート ソース テーブルから new_table を作成するには、SELECT ステートメントの FROM 句で、linked_server.catalog.schema.object という形式の 4 部構成の名前を使用してソース テーブルを指定します。FROM 句で OPENQUERY 関数か OPENDATASOURCE 関数を使用してリモート データ ソースを指定することもできます。

データ型

既存の ID 列が新しいテーブルに選択された場合は、次の条件のいずれかが満たされている場合を除き、新しい列には IDENTITY プロパティが継承されます。

  • SELECT ステートメントに、結合、GROUP BY 句、集計関数のいずれかが含まれている。

  • 複数の SELECT ステートメントが UNION を使用して結合されている。

  • ID 列が選択リストに 2 回以上指定されている。

  • ID 列が式の一部である。

  • ID 列がリモート データ ソースから取得されている。

これらの条件が 1 つでも満たされている場合は、列に IDENTITY プロパティは継承されず、代わりに NOT NULL として作成されます。新しいテーブルに ID 列が必要であるものの使用できる列がない場合や、ソースの ID 列とは異なるシード値や増分値が必要な場合は、選択リストで IDENTITY 関数を使用してその列を定義します。以下の「例」の「IDENTITY 関数を使用して ID 列を作成する」を参照してください。

制限事項と制約事項

INTO 句には、次の制限事項と制約事項が適用されます。

  • テーブル変数やテーブル値パラメータを新しいテーブルとして指定することはできません。

  • ソース テーブルがパーティション分割されている場合でも、SELECT...INTO を使用してパーティション テーブルを作成することはできません。SELECT...INTO では、ソース テーブルのパーティション構成が使用されず、新しいテーブルが既定のファイル グループに作成されます。パーティション テーブルに行を挿入するには、まずパーティション テーブルを作成してから INSERT INTO...SELECT FROM ステートメントを使用する必要があります。

  • リストに計算列が指定されている場合、新しいテーブル内の対応する列は計算列にはなりません。新しい列の値は、SELECT...INTO が実行された時点の計算値になります。

  • SELECT...INTO は、COMPUTE と共に使用することはできません。

  • FILESTREAM 属性は新しいテーブルに転送されません。FILESTREAM BLOB がコピーされ、varbinary(max) BLOB として新しいテーブルに格納されます。FILESTREAM 属性がない場合、varbinary(max) データ型は 2 GB までに制限されます。FILESTREAM BLOB がこの値を超えると、エラー 7119 が発生して、ステートメントが中止されます。

  • ソース テーブルに定義されているインデックス、制約、およびトリガは、新しいテーブルに転送されません。SELECT...INTO ステートメントで指定することもできません。これらのオブジェクトが必要な場合は、SELECT...INTO ステートメントの実行後に作成する必要があります。

  • ORDER BY 句を指定しても、行が指定した順序どおりに挿入されるかどうかは保証されません。

ログ記録の動作

SELECT...INTO のログ記録量は、データベースに対して有効な復旧モデルによって異なります。単純復旧モデルまたは一括ログ復旧モデルでは、一括操作は最小限しかログに記録されません。最小ログ記録を使用する場合は、テーブルを作成してから INSERT ステートメントでそのテーブルにデータを設定するより、SELECT...INTO ステートメントを使用する方が効率的である可能性があります。詳細については、「最小ログ記録が可能な操作」を参照してください。

権限

対象となるデータベースの CREATE TABLE 権限が必要です。

A. 複数のソースの列を指定してテーブルを作成する

次の例では、各種の従業員関連テーブルと住所関連テーブルから 7 つの列を選択して、テーブル dbo.EmployeeAddresses を作成します。

USE AdventureWorks;
GO
SELECT c.FirstName, c.LastName, e.Title, a.AddressLine1, a.City, sp.Name AS [State/Province], a.PostalCode
INTO dbo.EmployeeAddresses
FROM Person.Contact AS c
JOIN HumanResources.Employee AS e ON e.ContactID = c.ContactID
JOIN HumanResources.EmployeeAddress AS ea ON ea.EmployeeID = e.EmployeeID
JOIN Person.Address AS a on a.AddressID = ea.AddressID
JOIN Person.StateProvince as sp ON sp.StateProvinceID = a.StateProvinceID;
GO

B. 最小ログ記録を使用して行を挿入する

次の例では、テーブル dbo.NewProducts を作成し、Production.Product テーブルの行を挿入します。この例では、AdventureWorks データベースの復旧モデルが FULL に設定されていると想定しています。したがって、最小ログ記録が使用されるようにするために、行を挿入する前に AdventureWorks データベースの復旧モデルを BULK_LOGGED に設定し、SELECT...INTO ステートメントの後に FULL に戻しています。これにより、SELECT...INTO ステートメントが使用するトランザクション ログの領域が最小化され、ステートメントが効率的に実行されるようになります。

USE AdventureWorks;
GO
IF OBJECT_ID ('dbo.NewProducts', 'U') IS NOT NULL
    DROP TABLE dbo.NewProducts;
GO
ALTER DATABASE AdventureWorks SET RECOVERY BULK_LOGGED;
GO

SELECT * INTO dbo.NewProducts
FROM Production.Product
WHERE ListPrice > $25 
AND ListPrice < $100;
GO
ALTER DATABASE AdventureWorks SET RECOVERY FULL;
GO

C. IDENTITY 関数を使用して ID 列を作成する

次の例では、IDENTITY 関数を使用して、新しいテーブル Person.USAddress に ID 列を作成します。この操作が必要になるのは、テーブルを定義する SELECT ステートメントに結合が含まれているため、IDENTITY プロパティが新しいテーブルに転送されないからです。IDENTITY 関数で、ソース テーブル Person.Address の AddressID 列とは異なるシード値と増分値が指定されていることに注意してください。

USE AdventureWorks;
GO
-- Determine the IDENTITY status of the source column AddressID.
SELECT OBJECT_NAME(object_id) AS TableName, name AS column_name, is_identity, seed_value, increment_value
FROM sys.identity_columns
WHERE name = 'AddressID';

-- Create a new table with columns from the existing table Person.Address. A new IDENTITY
-- column is created by using the IDENTITY function.
SELECT IDENTITY (int, 100, 5) AS AddressID, 
       a.AddressLine1, a.City, b.Name AS State, a.PostalCode
INTO Person.USAddress 
FROM Person.Address AS a
INNER JOIN Person.StateProvince AS b ON a.StateProvinceID = b.StateProvinceID
WHERE b.CountryRegionCode = N'US'; 

-- Verify the IDENTITY status of the AddressID columns in both tables.
SELECT OBJECT_NAME(object_id) AS TableName, name AS column_name, is_identity, seed_value, increment_value
FROM sys.identity_columns
WHERE name = 'AddressID';

D. リモート データ ソースの列を指定してテーブルを作成する

次の例は、ローカル サーバーで新しいテーブルをリモート データ ソースから作成するための 3 つの方法を示しています。最初にリモート データ ソースへのリンクを作成した後、リンク サーバー名の MyLinkServer を、1 つ目の SELECT...INTO ステートメントの FROM 句と、2 つ目の SELECT...INTO ステートメントの OPENQUERY 関数に指定しています。3 つ目の SELECT...INTO ステートメントでは、OPENDATASOURCE 関数を使用して、リンク サーバー名を使用する代わりに直接リモート データ ソースを指定しています。

USE master;
GO
-- Create a link to the remote data source. 
-- Specify a valid server name for @datasrc as 'server_name' or 'server_name\instance_name'.
EXEC sp_addlinkedserver @server = N'MyLinkServer',
    @srvproduct = N' ',
    @provider = N'SQLNCLI', 
    @datasrc = N'server_name',
    @catalog = N'AdventureWorks';
GO
USE AdventureWorks;
GO
-- Specify the remote data source in the FROM clause using a four-part name 
-- in the form linked_server.catalog.schema.object.
SELECT *
INTO dbo.Departments
FROM MyLinkServer.AdventureWorks.HumanResources.Department
GO
-- Use the OPENQUERY function to access the remote data source.
SELECT *
INTO dbo.DepartmentsUsingOpenQuery
FROM OPENQUERY(MyLinkServer, 'SELECT *
               FROM AdventureWorks.HumanResources.Department'); 
GO
-- Use the OPENDATASOURCE function to specify the remote data source.
-- Specify a valid server name for Data Source using the format server_name or server_name\instance_name.
SELECT *
INTO dbo.DepartmentsUsingOpenDataSource
FROM OPENDATASOURCE('SQLNCLI',
    'Data Source=server_name;Integrated Security=SSPI')
    .AdventureWorks.HumanResources.Department;
GO