T-SQL에서 테이블 변수를 SELECT INTO


372

테이블 변수에 모든 행을 삽입하려는 복잡한 SELECT 쿼리가 있지만 T-SQL에서는 허용하지 않습니다.

같은 행을 따라 SELECT INTO 또는 INSERT EXEC 쿼리에 테이블 변수를 사용할 수 없습니다. http://odetocode.com/Articles/365.aspx

간단한 예 :

declare @userData TABLE(
                        name varchar(30) NOT NULL,
                        oldlocation varchar(30) NOT NULL
                       )

SELECT name, location
INTO @userData
FROM myTable
    INNER JOIN otherTable ON ...
WHERE age > 30

테이블 변수의 데이터는 나중에 다른 테이블에 다시 삽입 / 업데이트하는 데 사용됩니다 (대부분 작은 업데이트로 동일한 데이터의 사본). 이 작업의 목적은 SELECT INTO올바른 테이블에 직접 액세스 하는 것보다 스크립트를 좀 더 읽기 쉽고 쉽게 사용자 정의 할 수 있도록하는 것 입니다. 성능은 문제가되지 않습니다. rowcount상당히 작고 필요할 때만 수동으로 실행되기 때문입니다.
... 또는 내가 잘못하고 있는지 말 해주세요.

답변:


601

다음과 같이 해보십시오 :

DECLARE @userData TABLE(
    name varchar(30) NOT NULL,
    oldlocation varchar(30) NOT NULL
);

INSERT INTO @userData (name, oldlocation)
SELECT name, location FROM myTable
INNER JOIN otherTable ON ...
WHERE age > 30;

2
UserData 테이블에 삽입 할 값으로 "SELECT name, location FROM myTable"을 선택하는 경우 select의 변수 이름이 테이블 정의의 이름과 일치하는지 여부는 중요하지 않습니다. 'name'을 선택하여 UserData 'name'변수로 이동하지만 'location'을 선택하고 어떻게 든 UserData 'oldlocation'변수에 지정합니다. SQL이 이것들을 자동으로 매핑합니까 아니면 예외가 발생합니까?
— Aran Mulholland

이름은 중요하지 않으며 열 유형 만 중요합니다.
— CristiC

5
와우 그런 종류의 말이되지만 동시에 파서는 기분이 상쾌합니다 :)
— Aran Mulholland

나는 이것을 UPDATE 문에서 사용할 수없는 것 같습니다 : gist link
— Paul-Sebastian Manole

1
insert 문에서 열을 명시 적으로 선언하지 않으면 select *와 마찬가지로 원래 create table 문에 선언 된 순서대로 열이 매핑됩니다. 따라서 select의 결과 세트에서 location이 위치 2에 있고 테이블 정의에서 oldlocation이 열 2이므로 select 문의 위치가 @userData 테이블의 oldlocation에 맵핑됩니다. 그렇게 말하지 마십시오. 열 또는 행의 데이터베이스 순서는 의존하지 않습니다. 항상 이것에 대해 명시하십시오.
— absmiths

94

의 목적 SELECT INTO은 (문서마다, 나의 강조점)

다른 테이블의 값에서 새 테이블 을 만들려면

하지만 당신은 이미 이 목표 테이블을! 그래서 당신이 원하는 것은

INSERT문은 테이블에 하나 개 이상의 새 행을 추가합니다

다음과 같은 방법으로 데이터 값을 지정할 수 있습니다.

...

이용함으로써 SELECT같은 하나 이상의 행에 대한 데이터 값을 지정하는 서브 쿼리 :

  INSERT INTO MyTable 
 (PriKey, Description)
        SELECT ForeignKey, Description
        FROM SomeView

그리고에서 이 구문, 그것은 수있어 MyTable테이블 변수가 될 수 있습니다.


1
허용 된 답변에이 정보가 포함되기를 바랍니다.
— 데이비 브라운

MyTable이 "Invalid Object Name"으로이 작업을 수행 하므로이 답변에서 누락 된 것이 있습니다.
— Mike Flynn

@MikeFlynn은 MyTable여기입니다 자리 의 이름 당신의 실제 테이블 . 이름이 MyTable... 인 테이블이있는 실제 데이터베이스는 없다고 생각합니다 .
— AakashM

그리고 SELECT INTO ...를 사용하여 테이블 변수를 만들고 선언하려면 ...? 예를 들어, 테이블 변수의 열을 t1.somecolumn, t1.othercolumn, t2. *로 정의하려면
— Armando

27

공통 테이블 표현식을 사용하여 임시 데이터 세트를 저장할 수도 있습니다. 그들은 더 우아하고 친절합니다.

WITH userData (name, oldlocation)
AS
(
  SELECT name, location 
  FROM   myTable    INNER JOIN 
         otherTable ON ...
  WHERE  age>30
)
SELECT * 
FROM   userData -- you can also reuse the recordset in subqueries and joins

이거 너무 좋아! 감사합니다.
— fourpastmidnight

userData에서 삭제하거나 업데이트하면 원본 테이블의 레코드가 삭제되고 업데이트되지 않습니까?
— atreeon

예. CTE가 조인, 공용체 등을 사용하여 여러 테이블을 참조하지 않는 한 CTE의 DELETE 및 UPDATE는 소스 테이블을 수정합니다.
— nanestev

2
이것의 단점은 바로 다음 명령에서만 CTE 테이블을 사용할 수 있다는 것입니다. CTE가 작동하지 않는 어떤 이유로 든 결과 세트를 두 번 이상 통과해야하는 경우. OP는 여러 번 수정해야 함을 암시하는 것처럼 보입니다.이 경우에는 작동하지 않습니다. "테이블 변수의 데이터는 나중에 다른 테이블에 다시 삽입 / 업데이트하는 데 사용됩니다 (주로 동일한 데이터의 사본은 마이너 업데이트). "
— Tony

16

응용 프로그램에서 임시 테이블을 사용하지 않는 경우 임시 테이블을 사용해 볼 수 있습니다. (수동으로 실행해도 괜찮습니다)

SELECT name, location INTO #userData FROM myTable
INNER JOIN otherTable ON ...
WHERE age>30

그런 식으로 테이블을 선언하는 노력을 건너 뜁니다 ... 임시 쿼리에 대한 도움말 ... 이것은 동일한 세션에 있지 않으면 다른 세션에 표시되지 않는 로컬 임시 테이블을 만듭니다. 앱에서 쿼리를 실행하는 경우 문제가 될 수 있습니다.

앱에서 실행 해야하는 경우 다음과 같이 선언 된 변수를 사용하십시오.

DECLARE @userData TABLE(
    name varchar(30) NOT NULL,
    oldlocation varchar(30) NOT NULL
);

INSERT INTO @userData
SELECT name, location FROM myTable
INNER JOIN otherTable ON ...
WHERE age > 30;

편집 : 많은 사람들이 연결에서 세션에 대한 가시성을 업데이트했다고 언급했습니다. 세션을 재사용 할 수 있으므로 임시 테이블을 작성하는 것은 웹 애플리케이션의 옵션이 아닙니다.


2
죄송합니다. CREATE TABLE에 대한 권한이 없습니다.
— Indrek

6
임시 직원을 만드는 데 약간의 오버 헤드가 있습니다.
— paparazzo

2
임시 테이블을 사용하는 것이 항상 안전하지는 않습니다. 예를 들어, 웹 서비스. 서버에서 최대 연결을 제한하고 SQL을 조금 더 보호하기 위해 단일 연결을 사용하는 웹 서비스를 사용하면 모든 쿼리가 통과 할 때 임시 테이블이 존재하며 현재 사용중인 누군가를 덮어 쓸 수 있습니다.
— Franck

12
@Franck-전역 임시 테이블 (두 개의 해시 접두사)을 사용하면 맞습니다. 그러나 로컬 임시 테이블 (하나의 해시 접두사)은 단일 세션 (일명 단일 연결)으로 격리되므로 모든 요청에 ​​대해 단일 연결을 사용하지 않는 한 암시적인 동시성 문제가 발생하지 않습니다 ( 조언). 그러나 가능한 성능 영향은 여전히 ​​남아 있습니다.
— maf748

@GazB 물론 부작용이있는 진술은에서 사용되지 않습니다 function. 내 경험상, 누군가가 그러한 진술이 필요하다고 생각하는 대부분의 경우, 이것은 실제로 자신의 생각을 다시 생각 function하거나 적어도 리팩토링 해야한다는 것을 의미 합니다 procedure. 적어도 나 자신을 위해 말하기. :-)
— underscore_d 13


5

먼저 임시 테이블을 만듭니다.

1 단계:

create table #tblOm_Temp (

    Name varchar(100),
    Age Int ,
    RollNumber bigint
)

** 2 단계 : ** 임시 테이블에 일부 값 삽입.

insert into #tblom_temp values('Om Pandey',102,1347)

3 단계 : 임시 테이블 데이터를 보유 할 테이블 변수 선언

declare   @tblOm_Variable table(

    Name Varchar(100),
    Age int,
    RollNumber bigint
)

4 단계 : 임시 테이블에서 값을 선택하고 테이블 변수에 삽입하십시오.

insert into @tblOm_Variable select * from #tblom_temp

마지막으로 임시 테이블에서 테이블 변수로 값이 삽입됩니다.

5 단계 : 테이블 변수에 삽입 된 값을 확인할 수 있습니다.

select * from @tblOm_Variable

1

OK, 이제 충분한 노력으로 아래를 사용하여 @table에 삽입 할 수 있습니다.

INSERT @TempWithheldTable SELECT
a.SuspendedReason, a.SuspendedNotes, a.SuspendedBy, a.ReasonCode FROM OPENROWSET (BULK 'C : \ DataBases \ WithHeld.csv', FORMATFILE = N'C : \ DataBases \ Format.txt ',
ERRORFILE = N'C : \ Temp \ MovieLensRatings.txt ') AS a;

여기서 중요한 것은 삽입 할 열을 선택하는 것입니다.


'테이블 변수를 선언해야합니다 "@TempWithheldTable"컴파일 오류 메시지
— atreeon

-5

SELECT INTO를 사용하는 한 가지 이유는 IDENTITY를 사용할 수 있기 때문입니다.

SELECT IDENTITY(INT,1,1) AS Id, name
INTO #MyTable 
FROM (SELECT name FROM AnotherTable) AS t

이것은 너무 나쁜 테이블 변수와 함께 작동하지 않습니다 ...


6
IDENTITY그래도 열을 사용 하여 테이블 변수를 선언 할 수 있습니다 .
— Martin Smith
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.