SQL - WHERE 1=1 사용 이유에 대해 알아보자 (+ WHERE 1=2 사용 이유)

반응형

개요

가끔 SQL 쿼리를 보면 WHERE절 맨 앞에 1=1이 있는 것을 볼 수가 있다.

SELECT * FROM t1 WHERE 1=1
	AND col1 = 'eunbyeol'

 

처음 볼 때에는 이게 무엇인가 싶었는데,

의미를 알고 사용하면 오히려 더 편하게 쿼리를 작성할 수도 있게 된다.

오늘은 WHERE 1=1을 왜 사용하는지에 대한 사용 이유에 대해 알아보도록 한다.

 

WHERE 1=1 사용 이유, 왜 사용할까?

동적 쿼리 조건 구성의 단순화

결론부터 말하자면, WHERE 1=1 은 주로 동적 쿼리를 작성할 때 많이 사용한다.

특정 조건에 따라 동적으로 추가되거나 제거되는 조건절을 위한 기본 쿼리 구조로 많이 사용된다.

SELECT * FROM t1 WHERE 1=1

 

위의 예시 쿼리는 동적 쿼리의 기본 구조를 심플하게 나타낸 것이다.

이 구조에서 프로그래머는 필요에 따라 AND 또는 OR 연산자를 사용하여

조건을 추가하면 쿼리를 훨씬 더 수월하게 작성할 수 있다.

SELECT * FROM t1 WHERE 1=1
-- 조건에 따라 조건식을 AND 또는 OR 로 추가해주자
    AND col1 = 'eunbyeol'
    AND col2 = 'incheon'

 

쿼리 조건의 일관성 유지

동적 쿼리에서 상황에 따라 쿼리가 다르게 작동되는 것은 당연하다.

하지만 외부에서 주어진 정해지지 않는 값을 통해 여러 가지의 쿼리를 실행하려면 그에 맞게 조건을 확인해야 할 쿼리의 수도 길어진다. 이때, 동적 쿼리의 기본 구조를 설정한 후 조건에 따라 조건 쿼리를 덧붙이는 식으로 쿼리를 짜면

상황에 따라 작성되는 쿼리의 일관성도 유지되고 잠재적 오류를 피할 수 있다.

 

아래의 예시 쿼리를 봐보자.

이 쿼리는 외부에서 받은 값을 통해 조건에 따라 쿼리를 실행시키는 프로시저이다.

조건에 따라 작성되는 쿼리는 일관적으로 AND 조건으로만 작성되었다.

  • 프로시저로 들어온 값이 1일 경우, col1 컬럼에 은별이라는 데이터를 조회하고,
  • 프로시저로 들어온 값이 2일 경우, col2 컬럼에 인천이라는 데이터를 조회한다.

[참고] 해당 프로시저는 예시를 위한 쿼리이며, MS-SQL(SSMS)을 기반으로 작성하였다.

/* 테스트 프로시저
*	파라미터에 전달 받은 값으로 특정 쿼리를 실행하는 프로시저
*	외부에서 받는 값은 숫자 1 또는 2로 한정
*/
CREATE PROC test
	@val INT -- 외부에서 전달 받는 값
AS BEGIN
	-- 동적 쿼리 기본 구조 설정
    DECLARE @sql NVARCHAR(MAX)
    SET @sql = 'SELECT * FROM t1 WHERE 1=1'

	-- 조건에 따라 쿼리 작성
	IF @val = 1
    		SET @sql = @sql + ' AND col1 = ''eunbyeol'''
   	ELSE IF @val = 2
    		SET @sql = @sql + ' AND col2 = ''incheon'''
        
    -- 쿼리 실행
    EXEC sp_executesql @sql
END

 

쿼리 디버깅 및 유지보수성 향상

동적 쿼리를 작성할 때 많이 사용하기도 하지만, 디버깅 및 유지보수를 위해서도 많이 사용한다.

WHERE절에 조건절을 위한 기본 쿼리 구조를 구성(예를 들어 1=1) 해두지 않고 쿼리를 작성하다 보면

생각보다 많이 조건절의 AND 혹은 OR을 지우고 쓰고를 반복하며 쿼리를 작성할 때가 있다.

이런 반복 작업이 쿼리를 계속 수정하다 보면 여간 귀찮은 게 아니다.

 

이는 쿼리를 보면 이해가 쉽다.

아래의 쿼리는 은별, 인천에 맞는 조건의 데이터를 조회하는 쿼리이다.

SELECT * FROM t1
WHERE 
	col1 = 'eunbyeol'
    AND col2 = 'incheon'

 

 

여기서 디버깅을 위해 여러 조건을 살펴봐야 할 때,

하나의 조건을 주석 처리하면서 쿼리를 확인해 본다는 시나리오를 작성해 보자.

그렇다면 내가 수정해야 될 부분은 조건절의 특정 조건만 주석처리하는 것이 가장 빠를 것이다. 

SELECT * FROM t1
WHERE 
	-- col1 = 'eunbyeol'
    col2 = 'incheon' -- AND 키워드 삭제
    
 /* 혹은 */
 
SELECT * FROM t1
WHERE 
	col1 = 'eunbyeol'
    -- AND col2 = 'incheon'

 

위와 같이 조건을 주석 처리하여 쿼리를 실행할 때마다

AND 또는 OR 키워드가 있거나 없는 조건은 때때로 지우거나 오히려 덧붙여서 작성해야 될 때가 있다.

이는 간단하게도 WHERE 1=1을 써주면서 한결 더 작성이 쉬워질 수 있다.

굳이 이렇게까지 하나 싶지만, 의외로 회사 데이터베이스 프로시저에 많이 녹여져 있다.

생각보다 개발자들은 귀찮은걸 매우 싫어하니까 말이다.

SELECT * FROM t1
WHERE 1=1
	-- AND col1 = 'eunbyeol'
    AND col2 = 'incheon'
    
/* 혹은 */
    
SELECT * FROM t1
WHERE 1=1
	AND col1 = 'eunbyeol'
    -- AND col2 = 'incheon'

 

WHERE 1=1 쿼리 실행 속도, 데이터베이스 과부하 여부는?

대부분의 SQL 쿼리 최적화 엔진(옵티마이저)은 WHERE 1=1 조건을 무시한다.

1=1은 즉 항상 참일 수밖에 없기 때문에 쿼리의 논리적 실행 계획에서 무의미한 조건으로 처리하기 때문이다.

그래서 불필요한 조건을 제거하고 실제 필요한 조건만으로 실행 계획을 생성하기 때문에

데이터베이스 성능에 영향을 거의 미치지 않는다.

 

단, 매우 복잡한 쿼리거나 데이터가 매우 많은 데이터베이스일 경우에는

추가적인 조건 처리로 인해 발생하는 오버헤드가 미미하게 성능저하를 일으킬 수도 있다.

(대부분은 무시할 수 있는 정도라고 한다.)

 

WHERE 1=2 사용 이유, 얘는 어떨 때 사용될까?

데이터를 제외한 테이블 구조만 복사

테이블의 데이터를 제외하고 구조만 복사해야 할 때 주로 사용된다.

t1이라는 테이블은 col1, col2라는 컬럼이 존재하고, 약 천 개 정도의 데이터를 가지고 있다고 가정해 보자.

하지만 여기서 테이블의 구조만 복사하고 싶다면 아래와 같이 쿼리를 작성할 수 있다.

-- SQL Server, MS-SQL
SELECT * INTO new_t1 FROM t1 WHERE 1=2

 

이렇게 하면 t1 테이블의 데이터는 포함하지 않고 구조만 그대로 가진 빈 테이블 new_t1이 복사된다.

번외로 테이블 구조만 복사하는 방법은 출력 행의 제한을 주는 방법으로도 테이블을 복사할 수 있다.

개인적으로 테이블 구조 복사 할 때 출력행을 제한하는 것이 더 편하다.

이는 본인 편의에 맞게 사용하도록 하자.

-- SQL Server, MS-SQL
SELECT TOP 0 * INTO new_t1 FROM t1;

-- MySQL
CREATE new_t1 LIKE t1 LIMIT 0;

 

 

테스트 및 디버깅을 위한 쿼리 구문 검토

조건절의 WHERE 1=2를 테스트 및 디버깅 용도로도 사용될 수 있다.

 

첫 번째, 조회되는 데이터를 반환하지 않도록 보장하기 위한 용도로 사용된다.

이는 즉 테스트와 디버깅 과정에서 작성된 쿼리의 구조나 구문을 검토할 때 유용하다.

데이터가 많은 데이터베이스를 조회할 때에 부하가 일어날 수 있다.

작성된 쿼리의 데이터를 반환하지 않도록 하여 부하를 줄이고,

작성된 쿼리의 구조가 제대로 작성되었는지, 쿼리가 제대로 동작하는지를 검토할 수 있다.

 

두 번째, 특정 조건에서만 데이터를 반환하도록 제어할 수 있다.

아래의 쿼리는 WHERE 1=2를 이용하여 쿼리를 작성한 예시 코드이다.

AND로만 구성되어 있기 때문에 모든 조건이 맞는 데이터만 조회되도록 설계되어 있지만,

조건절의 시작 부분에 거짓(1=2)이 존재하기 때문에 데이터가 반환되지 않는다.

SELECT * FROM t1 WHERE 1=2
	AND col1 = 'eunbyeol'

 

쿼리는 그대로 두고 다른 조건을 테스트해야 될 때, 쿼리는 다음과 같이 작성될 수 있다.

SELECT * FROM t1 WHERE 1=2
	AND col1 = 'eunbyeol'
   	OR  col2 = 'incheon'

 

논리식에 의해 WHERE 1=2 AND col1 = 'eunbyeol'은 거짓이므로 조건을 조회하지 않는다.

반면, 추가된 OR col2 = 'incheon'은 둘 중 하나의 조건만 맞아도 되기 때문에

이후에 오는 특정 조건의 데이터를 손쉽게 제어할 수 있다.

이미 작성되어 있을 참(WHERE 1=1)의 논리식을 거짓(1=2)으로 바꾸어 처리하고,

쿼리는 수정 없이 그대로 둔 채 다른 조건을 추가하여 테스트 및 디버깅으로 데이터를 제어할 수 있다.

반응형