Posts

SQL Study List

SQL을 작성하면서 새롭게 알게 된 사실이나 알아두어야 하는 내용을 정리했다.

1. case - when 조건에 해당하지 않을 경우, 어떤 값 반환될까?

테이블 : TEST

이름유형KEYcomment
idintPK테이블 id
namevarchar 이름
timevarchar 총 시간
posvarchar 현재 위치

위와 같은 테이블이 있다고 가정하자.
특정 버튼을 누르면 아래의 sql이 실행된다.

1
2
3
4
5
6
7
8
update test_table
set pos =
	case
		when ifnull(time, 0) = 0 then 0
		when ifnull(pos, 0) > ifnull(time, 0) then pos
		when ifnull(time,0) > ifnull(pos, 0) then time
    end
where id = 1;

만약 pos와 time이 100으로 같다면, case의 세 조건 중 어느 곳에도 해당되지 않기 때문에 NULL을 반환한다. 즉, pos에는 NULL이 할당된다.

2. select 1

1
select 1;

위와 같이 사용할 경우, 아래와 같은 결과를 반환한다.

select1


test 테이블은 아래와 같은 데이터를 가진다.

idname
1A
2B
3C

이 테이블을 가지고 아래의 sql을 실행하면

1
2
select 1
from test;

다음과 같은 결과가 반환된다.

1
1
1
1

즉, 모든 행의 값이 1이 된다.


sql에서 1은 true를 의미하기도 한다. 때문에 조건절의 not exists or exists 안에 있는 서브 쿼리에서 많이 사용된다.

1
2
3
4
5
6
7
8
9
SELECT 
    CASE 
        WHEN EXISTS (
            SELECT 1 
            FROM test 
            WHERE id = 1
        ) THEN '존재합니다'
        ELSE '존재하지 않습니다'
    END AS 존재여부;

결과값은 아래와 같다.

존재여부
존재합니다.

즉, not exists나 exists는 실제로 1이라는 값을 반환하는 것이 아니라 조건절에 해당하는 행이 존재하는지를 확인한다.
위 예시에서는 id=1인 행이 존재하기 때문에 ‘존재합니다’ 가 반환된다.

3. concat과 null

쿼리를 확인하다가 이상한 점을 발견했다. IF 조건문 없이 단순히 CONCAT 함수만 사용했는데, 어떤 경우엔 문자열이 잘 붙어서 나오고, 어떤 경우엔 결과가 NULL로 반환되는 것이다. 처음엔 쿼리 로직이 잘못된 줄 알았지만, 알고 보니 이건 CONCAT 함수의 동작 방식 때문이었다.
SQL에서 CONCAT(a, b, c)처럼 여러 문자열을 이어붙일 때, 우리가 흔히 기대하는 동작은 null이 아닌 값들만 이어붙이는 것이다. 하지만 실제로는 그렇지 않다. CONCAT 함수는 인자 중 하나라도 NULL이면 전체 결과를 NULL로 반환한다.

1
2
SELECT CONCAT('Hello', NULL, 'World');
-- 결과: NULL

반면에 아래처럼 NULL이 아닌 값만 있으면 정상적으로 동작한다.

1
2
SELECT CONCAT('Hello', ' ', 'World');
-- 결과: Hello World

null이 반환되는 문제를 피하려면 IFNULL() 또는 COALESCE() 같은 함수로 NULL 값을 미리 처리해주는 것이 좋다.

1
SELECT CONCAT(IFNULL(col1, ''), IFNULL(col2, ''), IFNULL(col3, ''));
이 포스트는 저작권자의 CC BY 4.0 라이센스를 따릅니다.