WHERE 조건에서 ISNULL. 0 11 351

by 한번사는인생 [SQLServer] [2022.01.18 17:23:21]


DECLARE @A INT;
SET @A = NULL;

SELECT *
FROM BB WITH (NOLOCK)
WHERE A = ISNULL(@A, A)

저는 위에와 같이, 프로시저를 작성할때 @A라는 인풋 파라미터가 NULL로 들어오면

WHERE 조건에서 위에와 같이 처리 합니다.

 

하지만, A라는 컬럼이 NULL값이 있다면 조회가 원하는 방향으로 안나오니..조금 당황스러운데.

A라는 컬럼이 NULL 허용이라면 A = ISNULL(@A, A) 라는 조건식을 사용하면 안되나요?

by 마농 [2022.01.18 17:32:43]

네. 안됩니다.
널이 없는 항목에만 적용 가능한 방법입니다.


by 축구쟁이 [2022.01.18 17:33:03]

DBMS에 따라 다를 것 같은데 보통 NULL은 일반적인 값이 아니기 때문에 =를 사용해서 조회할 수 없습니다.

@A가 NULL일 경우 ISNULL로 인해 A = A가 되니 가능하실 거라고 생각하셨겠지만 결국 NULL = NULL이 되므로 원하시는 결과가 나오지 않겠습니다.

 


by 한번사는인생 [2022.01.18 17:34:47]

그렇다면 좋은 방법이 뭐가 있을까요?

아래 방법이 최선일까요?ㅠㅠ

WHERE (
			(@A IS NULL)
			OR
			((@A IS NOT NULL) AND (A = @A))
		)

 


by 축구쟁이 [2022.01.18 19:01:15]

프로시저로 작성하시는거라면 프로시저 내부에서 파라미터 값에 따른 쿼리 분기 처리를 해주는 것도 방법입니다.

캐시에 실행계획이 한개 더 추가되겠지만 테이블을 중복 읽는 경우는 발생하지 않습니다.

IF(@A IS NULL)

BEGIN
      --// 쿼리
END
ELSE
BEGIN
      --// 쿼리
END

 


by 한번사는인생 [2022.01.19 09:09:30]

사실 저도 동적쿼리보다는 정적쿼리로 분기처리하는 것이 더 낫다고 배웠던 것이 얼핏 기억납니다.

축구쟁이님 말씀하신거처럼, 분기처리가 좋은거 같지만.

인풋 파라미터가 많아진다면, 수 많은 IF문이 가독성면에서 떨어질까봐 무섭습니다.

축구쟁이님께서는 인풋 파라미터가 많은 경우에도, 저렇게 IF문으로 처리하시나요?


by 축구쟁이 [2022.01.19 09:47:15]

경우에 따라 다른 것 같습니다만, input이 많을 경우엔 저도 if문 사용은 잘 하지 않으려 합니다.

성능이 중요한 경우 시스템 프로시저를 통한 동적쿼리를 활용되기도 하고,

질문자님께서 생각하신 방식(동적쿼리를 정적쿼리 형태로 변환)도 종종 사용되고 있습니다.

 

단답으로 답변드릴 수는 없지만 저의 성향은 "성능 > 가독성" 입니다.

 


by 마농 [2022.01.18 17:38:39]

글쎄요?
무엇을 우선시 하느냐에 따라 다를 것입니다.
간결한 쿼리를 우선시 하는지? 성능을 우선시 하는지?
성능을 우선시 한다면? 인덱스는 존재하는지?


by 한번사는인생 [2022.01.18 17:39:59]

ㅠㅠ성능이 우선이고

그다음 간결한 쿼리를 원합니다.ㅠㅠ

인덱스도 있을때도 있고, 없을때도 있어서. 난감하네요.ㅠ.ㅠ


by 마농 [2022.01.18 17:49:08]

위에 작성하신 방법이 명확하긴 합니다만.
간결함을 원한다면? 요렇게만 해도 동일한 결과가 됩니다.
 WHERE (@A IS NULL OR A = @A)
성능을 원한다면?
여러 방법 시도해 보시면서 실행게획 및 수행시간 비교해보세요.
조건이 있을 때와 없을 때로 나누어 실행이 되어야 최선이 됩니다.
조건이 있을 경우 인덱스 스캔, 없을 경우 풀스캔
최선의 실행계획이 수립되는지 실제 확인이 필요합니다.
원하는 대로 되지 않는다면?
UNION ALL 로 쿼리를 분리하는 방법이 있습니다.
인덱스가 없다면 그냥 간결한게 좋을 듯 하네요.

SELECT *
  FROM BB WITH (NOLOCK)
 WHERE ( @A IS NULL )
 UNION ALL
SELECT *
  FROM BB WITH (NOLOCK)
 WHERE ( @A IS NOT NULL AND A = @A)
;

 


by 한번사는인생 [2022.01.18 18:00:28]

고맙습니다!

참고해서 좋은 개발 하겠습니다.


by 마농 [2022.01.19 09:23:40]

모든 파라미터 별로 분기할 필요는 없습니다.
인덱스가 없는 항목에 대해 굳이 어럽게 구현할 필요도 없습니다.
성능에 큰 영향을 끼치는 핵심이 되는 몇가지 조건에 대해서
2,3 가지 정도의실행계획으로 분기 처리를 하면 됩니다.

동적쿼리보다 정적쿼리가 좋다는 것은
바인드 변수를 사용하는게 좋다는 말이 와전된게 아닌가 생각됩니다.
 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입