변수를 지정할 때 SET 대 SELECT?


답변:


412

이 기사 에서 요약 한 인용문 :

  1. SET는 변수 할당에 대한 ANSI 표준이며 SELECT는 아닙니다.
  2. SET은 한 번에 하나의 변수 만 할당 할 수 있으며 SELECT는 한 번에 여러 개의 할당을 수행 할 수 있습니다.
  3. 쿼리에서 할당하는 경우 SET는 스칼라 값만 할당 할 수 있습니다. 쿼리가 여러 값 / 행을 반환하면 SET에서 오류가 발생합니다. SELECT는 값 중 하나를 변수에 할당하고 여러 값이 반환되었다는 사실을 숨 깁니다 (따라서 다른 곳에서 왜 문제가 발생했는지 알 수 없을 것입니다. 문제를 해결하는 것이 재미 있습니다)
  4. 반환 된 값이없는 경우 쿼리에서 할당 할 경우 SET은 NULL을 할당합니다. 여기서 SELECT는 할당을 전혀 수행하지 않으므로 변수는 이전 값에서 변경되지 않습니다.
  5. 속도 차이는 SET과 SELECT간에 직접적인 차이가 없습니다. 그러나 한 번에 여러 번 할당 할 수있는 SELECT 기능은 SET보다 약간의 속도 이점을 제공합니다.

3
속도를 줄이지 않았지만 다음과 같은 내용은 정확하지 않습니다. "속도 차이로는 SET과 SELECT간에 직접적인 차이가 없습니다." 하나의 슬레이트에 여러 값을 할당하면 여러 세트를 사용하는 것보다 훨씬 빠릅니다. "한 번의 SELECT로 여러 변수를 빠르게 할당"
AK

14
@ AlexKuznetsov : 그 문장은 나중에 정확하게 말합니다.
OMG Ponies

3
@OMG Ponies : 10 배 이상 빠를 수 있으므로 "약간의 속도 이점"인지 확실하지 않습니다.
AK

2
특히 While-Loop을 사용할 때 one-Select와 many-Set을 사용하여 모든 변수를 설정 / 재 초기화하여 엄청난 성능 향상을 보았습니다. 또한 Select에서 모든 변수 논리를 한 번에 모두 실행하도록 통합 할 수도 있습니다. 예 : 0으로 시작 SELECT @Int = @Int + 1, @Int = @Int + 1하면 @Int2로 끝납니다. 이는 연속적인 문자열 조작을 수행 할 때 매우 유용 할 수 있습니다.
MikeTeeVee

성능 차이에 대한 흥미로운 토론. select를 통해 여러 값을 설정하는 것이 더 빠르면 (코딩 및 실행) 포인트 4 (쿼리가 null을 반환하는 경우 변수 값이 변경되지 않음)를 피하는 안전한 방법 중 하나는 선택하기 전에 변수를 null로 명시 적으로 설정하는 것입니다. 일단 당신이 그것을 고려하면, 둘은 성능을 어떻게 비교합니까? (Side note : 쿼리가 null을 반환하는 경우 변수를 null로 설정하지 않는 select의 이론적 근거를 이해하지 못합니다. 언제 원하십니까?)
youcantryreachingme

155

나는 SETANSI 표준 이라고 생각 하지만 SELECT그렇지 않습니다. 또한 값을 찾을 수없는 경우 아래 예에서 SETvs 의 다른 동작에 유의하십시오 SELECT.

declare @var varchar(20)
set @var = 'Joe'
set @var = (select name from master.sys.tables where name = 'qwerty')
select @var /* @var is now NULL */

set @var = 'Joe'
select @var = name from master.sys.tables where name = 'qwerty'
select @var /* @var is still equal to 'Joe' */

4
하나는 이해하기 위해서는, 검사, 놀이, 암기에 한 번 실행하는 것이 좋습니다 그 바로 읽을 수 있지만 다른 답변은 텍스트입니다에
겐 나디 Vanin Геннадий Ванин

4
실제로 사용 select @var = (select name from master.sys.tables where name = 'qwerty')하면 @var이 null로 표시됩니다. 당신이주는 예제는 같은 쿼리가 아닙니다.

4
당신은 (select name from master.sys.tables where name = 'qwerty')하나를 name from master.sys.tables where name = 'qwerty'위해, 다른 하나를 위해 ... 당신은 그것을 보지 않습니까?
Zack

4
@ Zack : 각각 데모하려고하는 것에 대한 올바른 구문입니다. 기본 쿼리가 결과를 반환하지 않을 때 SET와 SELECT를 사용하여 변수에 값을 할당하는 것의 차이점
Joe Stefanelli 2016 년

5
(select name from master.sys.tables where name = 'qwerty')스칼라 하위 쿼리이며 name from master.sys.tables where name = 'qwerty'간단한 쿼리입니다. 두 가지 다른 표현 은 동일한 결과를 나타내지 않아야하지만, 그들이해야한다는 것을 암시하는 것처럼 보입니다. SETSELECT키워드에 다른 구현이 있다고 말하려는 경우 예제에서 두 개의 다른 표현식 을 사용해서는 안됩니다 . msdn.microsoft.com/ko-kr/library/ms187330.aspx
Zack

27

쿼리를 작성할 때이 차이점을 명심해야합니다.

DECLARE @A INT = 2

SELECT  @A = TBL.A
FROM    ( SELECT 1 A ) TBL
WHERE   1 = 2

SELECT  @A
/* @A is 2*/

---------------------------------------------------------------

DECLARE @A INT = 2

SET @A = ( 
            SELECT  TBL.A
            FROM    ( SELECT 1 A) TBL
            WHERE   1 = 2
         )

SELECT  @A
/* @A is null*/

아주 좋은 간결한
SimplyInk

8

ANSI와 속도 등의 것 외에도 항상 중요한 차이점이 있습니다. ANSI 이상의 속도. 이 중요한 간과 때문에 수정 한 버그의 수는 많습니다. 코드 검토 중에 항상 이것을 찾습니다.

-- Arrange
create table Employee (EmployeeId int);
insert into dbo.Employee values (1);
insert into dbo.Employee values (2);
insert into dbo.Employee values (3);

-- Act
declare @employeeId int;
select @employeeId = e.EmployeeId from dbo.Employee e;

-- Assert
-- This will print 3, the last EmployeeId from the query (an arbitrary value)
-- Almost always, this is not what the developer was intending. 
print @employeeId; 

거의 항상 개발자가 의도 한 것이 아닙니다. 위의 쿼리는 간단하지만 매우 복잡하고 단일 값을 반환할지 여부를 알아내는 쿼리는 사소한 것이 아닙니다. 쿼리는 종종 이것보다 더 복잡하며 우연히 단일 값을 반환했습니다. 개발자 테스트 중에는 괜찮습니다. 그러나 이것은 똑딱 거리는 폭탄과 같으며 쿼리에서 여러 결과를 반환 할 때 문제가 발생합니다. 왜? 변수에 마지막 값을 지정하기 때문입니다.

이제 같은 것을 시도해 보자 SET.

 -- Act
 set @employeeId = (select e.EmployeeId from dbo.Employee e);

오류가 발생합니다.

하위 쿼리가 둘 이상의 값을 반환했습니다. 부속 조회가 =,! =, <, <=,>,> = 뒤에 오거나 부속 조회가 표현식으로 사용될 때는 허용되지 않습니다.

왜 "마지막으로 마지막 아이템"을에 할당하고 싶기 때문에 놀랍고 매우 중요합니다 @employeeId. select당신 과 함께 어떤 오류가 발생하지 않으며 당신은 몇 분, 디버깅 시간을 보낼 것입니다.

아마도 하나의 ID를 찾고 SET쿼리를 수정해야 할 것입니다. 따라서 다음과 같은 작업을 수행 할 수 있습니다.

-- Act
-- Notice the where clause
set @employeeId = (select e.EmployeeId from dbo.Employee e where e.EmployeeId = 1);
print @employeeId;

대청소

drop table Employee;

결론적으로 다음을 사용하십시오.

  • SET: 변수에 단일 값을 지정하고 변수가 단일 값에 대한 경우.
  • SELECT: 변수에 여러 값을 지정하려는 경우. 변수는 테이블, 임시 테이블 또는 테이블 변수 등일 수 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.