SELECT id, username, nickname
FROM member_test
WHERE
1=1
<if test="username != null">
AND username = #{username}
</if>
<if test="nickname != null">
AND nickname = #{nickname}
</if>
위의 쿼리에서 username과 nickname에 null이 들어오면 전체 데이터를 조회한다.
전체 조회가 된다는 사실을 의도하지 않거나 예상하지 못한다면 데이터 양에 따라 어플리케이션 응답 지연 문제 등이 발생할 수 있다.
만약 쿼리가 DELETE 혹은 UPDATE였다면 전체 데이터가 변하는 상황이 발생할 수도 있다.
WHERE 1=1 피하기
구글링을 해본 결과 위와 같은 이유로 여러 블로그에서 WHERE 1=1을 사용하는 것에 대해 피하자는 글들이 많았다.
WHERE 1=1 대신 대체할 수 있는 방법이 무엇이 있을까?
1. TRIM 사용(1)
TRIM 태그를 사용하면 태그 내부에서 실행할 쿼리를 생성해준다.
prefix=WHERE 은 해당 블록 안의 쿼리에 where쿼리를 추가해준다.
SELECT id, username, nickname
FROM member
<trim prefix="WHERE" prefixOverrides="AND">
<if test="username != null">
AND username = #{username}
</if>
<if test="nickname != null">
AND nickname = #{nickname}
</if>
</trim>
prefixOverrides 태그 안에서 실행될 쿼리의 가장 앞 쿼리가 속성값에 설정해둔 문자와 동일할 경우 문자를 제거해준다.
즉, FROM member WHERE AND username=#{username} 이런 문법이 되지 않도록 WHERE 다음에 AND를 제거해준다.
여기서 username, nickname이 전부 null 이면?
SELECT id, username, nickname
FROM member_test
where 1=1과 마찬가지로 전체 조회쿼리가 실행된다.
where 1=1을 사용하지 않을 순 있지만, 여전히 인자값을 검증하지 않는다면 전체 조회가 발생할 가능성이 있다.
2. TRIM 사용(2)
SELECT id, username, nickname
FROM member_test
WHERE
<trim prefixOverrides="AND">
<if test="username != null">
AND username = #{username}
</if>
<if test="nickname != null">
AND nickname = #{nickname}
</if>
</trim>
prefix="WHERE" 을 제거하였다.
위의 방법과 동일하게 동작할 것 같지만 username, nickname을 전부 null로 넘어오면 큰 차이가 생긴다.
SELECT id, username, nickname
FROM member_test WHERE
WHERE 다음에 어떤 조건이 걸리지 않기 때문에 BadSqlGrammarException이 발생한다.
검증 로직이 부족하여 username, nickname이 전부 null로 넘어온다면 Exception이 발생하기에 데이터 전체 조회가 일어나는 것을 막을 수 있다.
'BackEnd-Study > DB' 카테고리의 다른 글
[ORACLE] union all로 조인한 테이블 특정 데이터 값 수정 (0) | 2024.10.29 |
---|---|
[ORACLE] 하나의 테이블에 두개의 기본키 (0) | 2024.10.28 |
CLOB (0) | 2024.03.30 |
char varchar varchar2 차이 (0) | 2024.03.30 |
댓글