INTO 子句 (Transact-SQL)

SELECT…INTO 會在預設的檔案群組中建立新的資料表,然後將查詢的結果資料列插入其中。若要檢視完整的 SELECT 語法,請參閱<SELECT (Transact-SQL)>。

主題連結圖示Transact-SQL 語法慣例

語法

[ INTO new_table ]

引數

  • new_table
    根據 SELECT 清單中的資料行以及從資料來源中選擇的資料列,指定要建立之新資料表的名稱。

    new_table 的格式是藉由評估 SELECT 清單中的運算式所決定。new_table 中的資料行依照選取清單所指定的順序來建立。new_table 中每個資料行的名稱、資料類型、Null 屬性和值,都與 SELECT 清單中對應的運算式相同。此時,系統會傳送資料行的 IDENTITY 屬性,但是「備註」一節中「使用識別欄位」內定義的狀況除外。

    若要針對相同的 SQL Server 執行個體,在另一個資料庫中建立資料表,請使用 database.schema.table_name 格式,將 new_table 指定為完整名稱。

    雖然您無法在遠端伺服器上建立 new_table,不過可以根據遠端資料來源擴展 new_table。若要根據遠端來源資料表建立 new_table,請在 SELECT 陳述式的 FROM 子句中,使用 linked_server.catalog.schema.object 格式的四部分名稱來指定來源資料表。或者,您也可以在 FROM 子句中使用 OPENQUERY 函數或 OPENDATASOURCE 函數來指定遠端資料來源。

資料類型

當您將現有的識別欄位選入新的資料表時,除非下列其中一個狀況成立,否則新資料行會繼承 IDENTITY 屬性:

  • SELECT 陳述式包含聯結、GROUP BY 子句或彙總函數。

  • 利用 UNION 來聯結多個 SELECT 陳述式。

  • 在選取清單中,重複列出識別欄位。

  • 識別欄位是運算式的一部分。

  • 識別欄位來自遠端資料來源。

如果其中任何一個狀況成立,都會將資料行建立成 NOT NULL,而不是繼承 IDENTITY 屬性。如果新的資料表需要識別欄位,但是無法使用這種資料行,或者您想要與來源識別欄位不同的初始或遞增值,請使用 IDENTITY 函數在選取清單中定義此資料行。請參閱下面「範例」一節中的「使用 IDENTITY 函數來建立識別欄位」。

限制事項

下列限制適用於 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 的記錄數量主要取決於資料庫目前使用的復原模式。在簡單復原模式或大量記錄復原模式下,大量作業會進行最低限度記錄。透過最低限度記錄,使用 SELECT… INTO 陳述式可能會比建立資料表,然後使用 INSERT 陳述式來擴展資料表更有效率。如需詳細資訊,請參閱<可以進行最低限度記錄的作業>。

權限

需要目的地資料庫中的 CREATE TABLE 權限。

範例

A. 指定多個來源的資料行,藉以建立資料表

下列範例會從各個員工相關和地址相關的資料表中選取七個資料行,藉以建立 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 函數來建立識別欄位

下列範例會使用 IDENTITY 函數,在新的資料表 Person.USAddress 中建立識別欄位。因為定義此資料表的 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. 指定遠端資料來源的資料行,藉以建立資料表

下列範例將示範三種根據遠端資料來源在本機伺服器上建立新資料表的方法。此範例一開始會建立遠端資料來源的連結。然後,連結的伺服器名稱 MyLinkServer, 會指定於第一個 SELECT...INTO 陳述式的 FROM 子句和第二個 SELECT...INTO 陳述式的 OPENQUERY 函數中。最後,第三個 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