동적 SQL-EXEC (@SQL) 대 EXEC SP_EXECUTESQL (@SQL)


95

SQL Server의 저장 프로 시저에서 동적 SQL 명령을 실행하는 실제 장단점은 무엇입니까?

EXEC (@SQL)

EXEC SP_EXECUTESQL @SQL

?

답변:


96

sp_executesql쿼리 계획 재사용을 촉진 할 가능성이 더 높습니다. 를 사용하는 sp_executesql경우 매개 변수는 호출 서명에서 명시 적으로 식별됩니다. 이 훌륭한 기사는이 과정을 설명합니다 .

동적 SQL의 여러 측면에 대해 자주 인용되는 참조는 Erland Sommarskog의 필독서입니다 : " The Curse and Blessings of Dynamic SQL ".


21

SP_EXECUTESQL의 가장 큰 점은 SQL 인젝션에 관심이있는 경우 매우 유용한 매개 변수화 된 쿼리를 생성 할 수 있다는 것입니다.


1
나는 당신이 그것 없이는 동적 SQL을 매개 변수화 할 수 있다고 생각하지 않는다 ??
DJ.

EXEC ( 'SELECT * FROM FOO WHERE ID =?', 123)은 매개 변수 자리 표시 자 "?"를 대체합니다. 값 123으로 쿼리를 실행 한 다음 SELECT * FROM FOO WHERE ID = 123에 대한 결과를 반환합니다.
Peter Wone

1
죄송합니다. 해당 구문은 연결된 서버에서만 사용할 수 있습니다.
Peter Wone

1
SQL 주입을 방지하기 위해 쿼리를 동적으로 작성하는 경우 sp_executesql을 사용하는 가장 큰 이유 중 하나입니다.
Steven Rogers

5

Microsoft의 Using sp_executesql 기사에서는 sp_executesql대신 execute문을 사용할 것을 권장 합니다.

이 저장 프로 시저가 매개 변수 대체를 지원하기 때문에 sp_executesql은 EXECUTE보다 더 다양합니다. sp_executesql은 SQL Server에서 재사용 할 가능성이 높은 실행 계획을 생성하기 때문에 sp_executesql 이 EXECUTE 보다 효율적 입니다.

따라서 요약 : 문을 사용하지 마십시오execute . 사용 sp_executesql.


7
당신의 테이크 아웃이 항상 존재하는 것은 아닙니다. sp_executesql을 사용하여 효율성 보너스가없는 경우가 있지만 SQL 주입 공격으로부터 코드를 보호 할 수 있습니다. 때로는 exec를 사용할 수있는 방식으로 sp_executesql을 사용할 수 없기 때문에 누군가가 말했습니다. 나는 동의한다.
OzrenTkalcecKrznaric

예, Microsoft는이를 " 효율적일 가능성 이 더 높음 "으로 표시해야했습니다 . 그리고 몇 년 동안 업계에 종사 sp_executesql하면서을 (를) 대체하는 데 사용할 수없는 경우를 보았습니다 execute. 아마도 내가 강조하려는 요점을 다음과 같이 말해야 할 것 입니다. 가능할 때마다sp_executesql 대신 사용하십시오 . execute
Gan

2

요즘에는 항상 sp_executesql을 사용합니다. 실제로 매개 변수와 변수를 처리하는 EXEC 용 래퍼입니다.

그러나 매우 큰 데이터베이스에서 쿼리를 조정할 때 OPTION RECOMPILE을 잊지 마십시오. 특히 데이터가 둘 이상의 데이터베이스에 걸쳐 있고 CONSTRAINT를 사용하여 인덱스 스캔을 제한하는 경우에 그렇습니다.

OPTION RECOMPILE을 사용하지 않는 한 SQL Server는 쿼리에 대해 "하나의 크기에 맞는"실행 계획을 만들려고 시도하고 실행될 때마다 전체 인덱스 스캔을 실행합니다.

이것은 탐색보다 훨씬 덜 효율적이며 잠재적으로 쿼리하지 않는 범위로 제한된 전체 인덱스를 스캔하고 있음을 의미합니다.


-2
  1. 변수 선언
  2. 명령으로 설정하고 sp의 매개 변수 값 사용과 같은 동적 부분을 추가하십시오 (여기서 @IsMonday 및 @IsTuesday는 sp 매개 변수입니다)
  3. 명령을 실행

    declare  @sql varchar (100)
    set @sql ='select * from #td1'
    
    if (@IsMonday+@IsTuesday !='')
    begin
    set @sql= @sql+' where PickupDay in ('''+@IsMonday+''','''+@IsTuesday+''' )'
    end
    exec( @sql)
    

15
예를 들어 "a '; DROP DATABASE DATABASE_NAME; GO;';"를 입력하면 SQL 삽입이 가능합니다. @IsMonday 변수에서
Erik A. Brandstadmoen

@IsMonday가 int이면 SQL injuction에 취약합니까?
Vikas Rana

@VikasRana @IsMonday는 int동적 SQL에 있을 수 없습니다 . 참고 @Sql는 다음과 같이 선언되어 있는지 varchar또는nvarchar
웨이 후이시 구오
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.