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.