SELECT - INTO 절(Transact-SQL)

적용 대상: SQL Server(지원되는 모든 버전) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System(PDW)

SELECT...INTO는 기본 파일 그룹에 새 테이블을 만들고 쿼리의 결과 행을 이 테이블에 삽입합니다. 전체 SELECT 구문을 보려면 SELECT(Transact-SQL)를 참조하세요.

Topic link iconTransact-SQL 구문 규칙

Syntax

[ INTO new_table ]
[ ON filegroup ]

참고

SQL Server 2014 이전 버전의 Transact-SQL 구문을 보려면 이전 버전 설명서를 참조하세요.

인수

new_table
선택 목록에 있는 열과 데이터 원본에서 선택한 행을 기반으로 만들려는 새 테이블의 이름을 지정합니다.

new_table의 형식은 선택 목록의 식을 평가하여 결정됩니다. new_table의 열은 선택 목록에서 지정한 순서대로 만들어집니다. new_table의 각 열은 선택 목록에 있는 해당 식의 이름, 데이터 형식, Null 허용 여부 및 값과 동일합니다. 열의 IDENTITY 속성은 주의 섹션의 "ID 열 작업"에 정의된 경우를 제외하고는 전송됩니다.

동일한 SQL Server 인스턴스에서 다른 데이터베이스에 테이블을 만들려면 new_tabledatabase.schema.table_name 형식의 정규화된 이름으로 지정합니다.

원격 서버에는 new_table을 만들 수 없지만, 원격 데이터 원본에서 new_table을 채울 수 있습니다. 원격 원본 테이블에서 new_table을 만들려면 네 부분으로 구성된 linked_server.catalog.schema.object 형식의 이름을 사용하여 SELECT 문의 FROM 절에 원본 테이블을 지정합니다. 또는 FROM 절에서 OPENQUERY 함수 또는 OPENDATASOURCE 함수를 사용하여 원격 데이터 원본을 지정할 수 있습니다.

filegroup
새 테이블을 만들 파일 그룹의 이름을 지정합니다. 지정한 파일 그룹이 데이터베이스에 있어야 합니다. 그렇지 않으면 SQL Server 엔진에서 오류를 throw합니다.

적용 대상: SQL Server 2016(13.x) SP2 이상.

데이터 형식

FILESTREAM 특성은 새 테이블로 전송되지 않습니다. FILESTREAM BLOB은 varbinary(max) BLOB으로 복사되어 새 테이블에 저장됩니다. FILESTREAM 특성이 없으면 varbinary(max) 데이터 형식이 2GB로 제한됩니다. FILESTREAM BLOB이 이 값을 초과하면 오류 7119가 발생하고 해당 문이 중지됩니다.

기존 ID 열을 새 테이블로 선택하여 넣을 때 다음 조건 중 만족하는 것이 없는 경우 새 열은 IDENTITY 속성을 상속합니다.

  • SELECT 문은 조인을 포함합니다.

  • UNION을 사용하여 여러 SELECT 문을 조인합니다.

  • 선택 목록에서 ID 열이 두 번 이상 나열됩니다.

  • ID 열이 식의 일부입니다.

  • ID 열을 원격 데이터 원본에서 가져옵니다.

위의 조건 중 만족하는 것이 있으면 열은 IDENTITY 속성을 상속하지 않고 NOT NULL로 만들어집니다. 새 테이블에 ID 열이 필요한데 그러한 열을 사용할 수 없는 경우 또는 원본 ID 열과 다른 초기값이나 증가값이 필요할 경우에는 IDENTITY 함수를 사용하여 선택 목록에 열을 정의합니다. 아래에 있는 예 섹션에서 "IDENTITY 함수를 사용하여 ID 열 만들기"를 참조하세요.

설명

SELECT...INTO 문은 두 부분으로 작동합니다. 새 테이블이 생성된 다음, 행을 삽입합니다. 이는 삽입이 실패하면 모두 롤백되지만 새(빈) 테이블은 남아 있음을 의미합니다. 전체 작업이 전반적으로 성공 또는 실패하는 데 필요한 경우 명시적 트랜잭션을 사용합니다.

제한 사항

테이블 변수나 테이블 반환 매개 변수를 새 테이블로 지정할 수는 없습니다.

원본 테이블이 분할된 경우에도 SELECT...INTO를 사용하여 분할된 테이블을 만들 수 없습니다. SELECT...INTO는 원본 테이블의 파티션 구성표를 사용하지 않는 대신, 기본 파일 그룹에 새 테이블이 만들어집니다. 분할된 테이블에 행을 삽입하려면 먼저 분할된 테이블을 만든 다음, INSERT INTO...SELECT...FROM 문을 사용해야 합니다.

원본 테이블에 정의된 인덱스, 제약 조건 및 트리거는 새 테이블로 전송되지 않으며 SELECT...INTO 문에 지정할 수도 없습니다. 이러한 개체가 필요하면 SELECT...INTO 문을 실행한 후에 개체를 만들 수 있습니다.

ORDER BY 절을 지정해도 행이 지정된 순서로 삽입되지는 않습니다.

SELECT 목록에 스파스 열이 있는 경우 스파스 열 속성은 새 테이블의 열로 전송되지 않습니다. 새 테이블에 이 속성이 필요하면 SELECT...INTO 문을 실행한 후 열 정의를 변경하여 이 속성을 포함하세요.

선택 목록에 계산 열이 있으면 새 테이블의 해당 열은 계산 열이 아닙니다. 새 열의 값은 SELECT...INTO가 실행될 때 계산된 값입니다.

로깅 동작

SELECT...INTO에 대한 로깅의 양은 데이터베이스에 적용되는 복구 모델에 따라 다릅니다. 단순 복구 모델 또는 대량 로그 복구 모델에서는 대량 작업이 최소 로깅됩니다. 최소 로깅으로 SELECT...INTO 문을 사용하면 테이블을 만든 다음, INSERT 문을 사용하여 해당 테이블을 채우는 것보다 더 효율적일 수 있습니다. 자세한 내용은 트랜잭션 로그(SQL Server)를 참조하세요.

사용자 정의 함수(UDF)를 포함하는 SELECT...INTO 문은 완전히 로그되는 작업입니다. SELECT...INTO 문에 사용되는 사용자 정의 함수가 데이터 액세스 작업을 수행하지 않는 경우 사용자 정의 함수의 SCHEMABINDING 절을 지정하면 해당 사용자 정의 함수의 파생 UserDataAccess 속성이 0으로 설정됩니다. 이 변경 후에는 SELECT...INTO 문이 최소 로그됩니다. SELECT...INTO 문이 이 속성이 1로 설정된 사용자 정의 함수 하나 이상을 여전히 참조하는 경우 작업이 완전히 로그됩니다.

사용 권한

대상 데이터베이스에서 CREATE TABLE 권한이 필요합니다.

예제

A. 여러 원본에서 열을 지정하여 테이블 만들기

다음 예에서는 다양한 직원 관련 테이블 및 주소 관련 테이블에서 7개의 열을 선택하여 AdventureWorks2019 데이터베이스에서 dbo.EmployeeAddresses 테이블을 만듭니다.

SELECT c.FirstName, c.LastName, e.JobTitle, a.AddressLine1, a.City,   
    sp.Name AS [State/Province], a.PostalCode  
INTO dbo.EmployeeAddresses  
FROM Person.Person AS c  
    JOIN HumanResources.Employee AS e   
    ON e.BusinessEntityID = c.BusinessEntityID  
    JOIN Person.BusinessEntityAddress AS bea  
    ON e.BusinessEntityID = bea.BusinessEntityID  
    JOIN Person.Address AS a  
    ON bea.AddressID = a.AddressID  
    JOIN Person.StateProvince as sp   
    ON sp.StateProvinceID = a.StateProvinceID;  
GO  

B. 최소 로깅을 사용하여 행 삽입

다음 예에서는 dbo.NewProducts 테이블을 만든 후 Production.Product 테이블의 행을 삽입합니다. 여기에서는 AdventureWorks2019 데이터베이스의 복구 모델이 FULL로 설정되었다고 가정합니다. 최소 로깅을 사용할 수 있도록 행 삽입 전에 AdventureWorks2019 데이터베이스의 복구 모델이 BULK_LOGGED로 설정되고 SELECT...INTO 문 다음에 FULL로 재설정됩니다. 이 프로세스를 통해 SELECT...INTO 문은 트랜잭션 로그에 최소 공간을 사용하여 효율적으로 수행됩니다.

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

C. IDENTITY 함수를 사용하여 ID 열 만들기

다음 예제에서는 IDENTITY 함수를 사용하여 AdventureWorks2019 데이터베이스의 새 Person.USAddress 테이블에 ID 열을 만듭니다. 이렇게 하는 이유는 테이블을 정의하는 SELECT 문에 조인이 포함되어 있기 때문입니다. 조인이 포함되어 있으면 IDENTITY 속성이 새 테이블에 전송되지 않습니다. IDENTITY 함수에 지정된 초기값과 증가값은 원본 테이블 AddressIDPerson.Address 열에 있는 해당 값과 다릅니다.

-- 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. 원격 데이터 원본에서 열을 지정하여 테이블 만들기

다음 예에서는 원격 데이터 원본의 로컬 서버에 새 테이블을 만드는 세 가지 방법을 보여 줍니다. 먼저 원격 데이터 원본과의 링크를 만듭니다. 그런 다음 첫 번째 SELECT...INTO 문의 FROM 절과 두 번째 SELECT...INTO 문의 OPENQUERY 함수에 연결된 서버 이름 MyLinkServer,를 지정합니다. 세 번째 SELECT...INTO 문에서는 연결된 서버 이름을 사용하는 대신 OPENDATASOURCE 함수를 사용하여 원격 데이터 원본을 직접 지정합니다.

적용 대상: SQL Server 2008 이상

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'AdventureWorks2012';  
GO  

USE AdventureWorks2012;  
GO  
-- Specify the remote data source in the FROM clause using a four-part name   
-- in the form linked_server.catalog.schema.object.  
SELECT DepartmentID, Name, GroupName, ModifiedDate  
INTO dbo.Departments  
FROM MyLinkServer.AdventureWorks2012.HumanResources.Department  
GO  
-- Use the OPENQUERY function to access the remote data source.  
SELECT DepartmentID, Name, GroupName, ModifiedDate  
INTO dbo.DepartmentsUsingOpenQuery  
FROM OPENQUERY(MyLinkServer, 'SELECT *  
               FROM AdventureWorks2012.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 DepartmentID, Name, GroupName, ModifiedDate  
INTO dbo.DepartmentsUsingOpenDataSource  
FROM OPENDATASOURCE('SQLNCLI',  
    'Data Source=server_name;Integrated Security=SSPI')  
    .AdventureWorks2012.HumanResources.Department;  
GO  

E. PolyBase를 사용하여 만든 외부 테이블에서 가져오기

Hadoop 또는 Azure Storage의 데이터를 영구적으로 스토리지하기 위해 SQL Server로 가져옵니다. SELECT INTO를 사용하여 SQL Server의 영구 스토리지에 대한 외부 테이블에서 참조하는 데이터를 가져옵니다. 먼저 대략적인 관계형 테이블을 만든 다음 두 번째 단계에서 테이블 위에 columnstore 인덱스를 만듭니다.

적용 대상: SQL Server.

-- Import data for car drivers into SQL Server to do more in-depth analysis.  
SELECT DISTINCT   
        Insured_Customers.FirstName, Insured_Customers.LastName,   
        Insured_Customers.YearlyIncome, Insured_Customers.MaritalStatus  
INTO Fast_Customers from Insured_Customers INNER JOIN   
(  
        SELECT * FROM CarSensor_Data where Speed > 35   
) AS SensorD  
ON Insured_Customers.CustomerKey = SensorD.CustomerKey  
ORDER BY YearlyIncome;  

F. 테이블 간에 데이터를 복사하고 지정된 파일 그룹에 새 테이블 만들기

다음 예제에서는 새 테이블을 다른 테이블의 복사본으로 만들고, 이를 사용자의 기본 파일 그룹과 다른 지정된 파일 그룹에 로드하는 방법을 보여 줍니다.

적용 대상: SQL Server 2016(13.x) SP2 이상.

ALTER DATABASE [AdventureWorksDW2016] ADD FILEGROUP FG2;
ALTER DATABASE [AdventureWorksDW2016]
ADD FILE
(
NAME='FG2_Data',
FILENAME = '/var/opt/mssql/data/AdventureWorksDW2016_Data1.mdf'
)
TO FILEGROUP FG2;
GO
SELECT * INTO [dbo].[FactResellerSalesXL] ON FG2 FROM [dbo].[FactResellerSales];

참고 항목

SELECT(Transact-SQL)
SELECT 예(Transact-SQL)
INSERT(Transact-SQL)
IDENTITY(함수)(Transact-SQL)