배경

T-SQL에서 동적 쿼리를 실행하는 방법은 크게 두 가지가 있음

  • EXEC(@sql)로 문자열 그대로 실행
  • sp_executesql로 파라미터화된 쿼리 실행 핵심 차이는 실행 계획 재사용성과 파라미터 처리 방식에 있음

sp_executesql 기본

  • @stmt는 NVARCHAR 계열 입력 요구, N 접두 사용 권장
  • 긴 문장은 nvarchar(max) 사용 권장, nvarchar(4000) 사용 시 4000자 제한 발생
  • VARCHAR로도 암시적 변환은 되지만 유니코드 손실 및 길이 이슈 가능, N’’ 사용 권장

예시

DECLARE @sql nvarchar(max) = N'SELECT 1'
EXEC sp_executesql @sql

파라미터 바인딩 예시

DECLARE @id int = 1
DECLARE @sql nvarchar(max) = N'SELECT * FROM UserTable WHERE Id = @id'
EXEC sp_executesql @sql, N'@id int', @id = @id

EXEC 기본

문자열을 그대로 실행함

DECLARE @sql varchar(max) = 'SELECT 1'
EXEC(@sql)

테이블명이나 컬럼명 등 식별자 자체를 동적으로 바꿔야 할 때 유용하나 값 파라미터 바인딩은 불가

EXEC vs sp_executesql

  • 실행 계획 재사용
    • EXEC는 값이 문자열에 포함되면 텍스트가 달라져 캐시 분산 발생 가능
    • sp_executesql은 파라미터화로 동일 텍스트 유지, 계획 재사용 기대
  • 성능과 안정성
    • sp_executesql은 파라미터 바인딩으로 SQL 인젝션 리스크 감소 및 파싱/컴파일 오버헤드 완화
    • EXEC는 빠르게 시도 가능하나 값 치환 방식이면 계획 캐시 파편화 유발 가능
  • 사용 적합성
    • 값만 바뀌는 조건 필터링 등은 sp_executesql 권장
    • 동적 객체명 변경이 필요한 경우 EXEC 또는 sp_executesql로 문자열 조합 후 실행, 단 객체명은 파라미터화 불가

주의사항

  • 항상 N’’ 접두와 nvarchar(max) 변수 사용 권장
  • 값은 파라미터로 바인딩, 문자열 연결로 값 삽입 금지
  • 계획 재사용이 과도해 성능 편차 발생 시 옵션 튜닝 검토 가능, 예를 들어 필요한 경우에 한해 OPTION(RECOMPILE) 고려

정리

값 변화에 따른 반복 실행이 예상되면 sp_executesql로 파라미터화해 계획 재사용과 보안을 동시에 확보 식별자 자체를 바꿔야 하면 EXEC로 문자열을 조합하되, 값은 여전히 파라미터화 전략 우선 nvarchar(max)와 N 접두 사용으로 길이와 유니코드 이슈 방지

참고자료