MySQL 8.0 의 연산자 우선순위 (Operator Precedence)
개발을 하면서 AND조건과 OR조건을 함께 사용하다보면 굉장히 혼란스러워질때가 간혹 있다.
내 논리로 예상한 결과값과 실제 MySQL이 검색을 수행한 결과가 다른 건 MySQL이 연산자 우선순위에 따라 처리하기 때문이다.
No | Operator | |
1 | INTERVAL | SELECT DATE_ADD('2021-07-01', INTERVAL 5 DAY); 과 같이 DATE 연산에 사용되는 연산자 |
2 | BINARY, COLLATE | 문자열 비교시 사용하는 연산자 |
3 | ! | |
4 | - (unary minus), ~ (unary bit minus) | |
5 | ^ | |
6 | *, /, DIV, %, MOD | |
7 | -, + | |
8 | <<, >> | |
9 | & | |
10 | ! | |
11 | =, <=>, >=, <=, <, <>, !=, IS, LIKE, REGEXP, BETWEEN, CASE, WHEN, THEN, ELSE |
여기서의 =는 할당이 아닌 비교(Comparison) 연산자다 |
12 | NOT | |
13 | AND, && | |
14 | XOR | |
15 | OR, || | |
16 | =, := | 여기서의 =는 대입 연산자 |
참고 : https://dev.mysql.com/doc/refman/8.0/en/operator-precedence.html
평소에 조회할 때 자주 사용하는 연산자는 아무래도 LIKE, BETWEEN, AND, OR 등 일 것이다.
IS, LIKE, BETEEN > AND > OR 의 순서로 쿼리를 실행한다는 것을 유의해야 한다.
이렇게는 조금 감이 잡히지 않아. 테스트 DB로 실습해보기로 했다.
실습용 데이터는 여기서 구했다 → (https://justinsomnia.org/2009/04/the-emp-and-dept-tables-for-mysql/)
위와 같은 EMP 테이블 데이터가 있을 때, 이 쿼리를 실행시킨다고 가정해보자. 만약 MySQL의 연산자 우선순위를 알지못하고 순서대로 조건을 실행할것이라고 생각한다면 다음과 같은 결과를 예상하게 된다.
AND (A) ENAME LIKE 'A%' : 이름이 A로 시작하는 직원 (7499, 7876) 2명
OR (B) JOB = 'SALESMAN' : 직업이 SALESMAN인 직원 (7499, 7521, 7654, 7844) 4명을 합집합(UNION)한 결과에
AND DEPTNO != '20' : 부서번호가 20인 직원 (7876)을 제외한 결과로
최종적으로 (7499, ALLEN), (7521, WARD), (7654, MARTIN), (7844, TURNER)를 예상하게 된다.
그러나 실제 쿼리 실행 결과는 아래와 같다.
어? 위 4행은 이해가는데.. 마지막 ADAMS는 뭐지.. 심지어 부서번호가 20인데..
이런 결과가 나온 이유는 OR 연산자보다 AND 연산자의 우선순위가 더 높기 때문에 JOB = 'SALESMAN' AND DEPTNO != '20' 이 더 먼저 실행되기 때문이다.
원래의 쿼리를 이해하기 쉽게 묶어놓자면 아래와 같다. 결국 OR 앞에 있는 조건 - 이름이 'A'로 시작되는 직원에 한에서는 부서번호가 20이 아니라는 제약이 걸리지 않았다.
따로 실행해보자면 이렇다


이 두 결과의 합집합(중복 제외)인 아래와 같은 결과가 조회된 것이다.
연산자의 우선순위에서 AND가 OR보다 높다는 것이 이해하기에 크게 어렵지 않은 것으로 들리지만.. 가끔 굉장히 헷갈릴 때도 있으니 유의하면서 작성하자!
끗 ㅎ