서론
서브쿼리를 사용해 DELETE 명령과 SELECT 명령을 결합할 수 있었다.
스칼라 서브쿼리가 사용하기 쉬운 서브쿼리란 것도 알았다.
이번 챕터에서는 서브쿼리의 일종인 '상관 서브쿼리'
를 EXISTS
술어로 조합시켜서 서브쿼리를 사용하는 방법에 관해 알아보겠다.
1. EXISTS
서브쿼리를 사용해 검색할 때 '데이터가 존재하는지 아닌지'
판별하기 위해 조건을 지정할 수 있다.
이런 경우 EXISTS
술어를 사용해 조사할 수 있다.
EXISTS 의 용법을 자세히 설명하기 위해 다음과 같이 두 개의 샘플 테이블을 사용하겠다.
SELECT * FROM sample_table;
SELECT * FROM sample_table2;
sample_table
에는 id 열에 1 에서 5 까지의 데이터가 저장되어 있다.
한편 sample_table2
에는 3 과 5 가 저장되어 있다.
여기서 sample_table 의 a 열은 문자열형이지만 값은 모두 NULL
이다.
이 열을 UPDATE로 갱신하려 한다.
지금부터 sample_table2에 id 열의 값과 같은 행이 있다면 '있음'
이라는 값으로, 행이 없으면 '없음'
이라는 값으로 갱신하도록 하겠다.
몇 가지 갱신 방법이 있지만, 여기서는 WHERE 구에 조건을 지정해 '있음'으로 갱신하는 경우와 '없음'으로 갱신하는 경우로 나누어 처리하겠다.
'있음'
의 경우, 행이 존재하는 경우에 대해 참
으로 설정한다.
즉, 다음과 같이 EXISTS를 사용하면 조건에 맞는 행을 갱신할 수 있다.
UPDATE sample_table AS st SET a='있음' WHERE
EXISTS (SELECT * FROM sample_table2 AS st2 WHERE st2.id = st.id);
EXISTS 술어에 서브쿼리를 지정하면 서브쿼리가 행을 반환할 경우에 참을 돌려준다.
2. NOT EXISTS
'없음'
의 경우, 행이 존재하지 않는 상태
가 참
이 되므로 이때는 NOT EXISTS
를 사용한다.
UPDATE sample_table AS st SET a='없음' WHERE
NOT EXISTS (SELECT * FROM sample_table2 AS st2 WHERE st2.id = st.id);
이처럼 서브쿼리를 이용해 다른 테이블의 상황을 판단하고 UPDATE로 갱신할 수 있다.
여기서는 UPDATE 명령을 예제로 다루었지만 SELECT 명령이나 DELETE 명령에서도 EXISTS 를 사용하여 명령을 실행할 수 있다.
3. 상관 서브쿼리
서브쿼리에는 명령 안에 중첩구조로 된 SELECT 명령이 존재한다.
지금부터 '있음'
으로 갱신하는 UPDATE 명령을 다시 살펴보겠다.
UPDATE sample_table AS st SET a='있음' WHERE
EXISTS (SELECT * FROM sample_table2 AS st2 WHERE st2.id = st.id);
UPDATE 명령
(부모)에서 WHERE 구에 괄호로 묶은 부분
이 서브쿼리(자식)가 된다.
부모 명령에서는 sample_table을 갱신한다.
자식인 서브쿼리에서는 sample_table2 테이블의 id 열 값이 부모의 id 열 값과 일치하는 행을 검색한다.
이처럼 부모 명령
과 자식인 서브쿼리
가 특정 관계를 맺는 것을 '상관 서브쿼리'
라 부른다.
4. IN
스칼라 값끼리 비교할 때는 =
연산자를 사용한다.
다만 집합
을 비교할 때는 사용할 수 없다.
IN
을 사용하면 집합 안의 값이 존재하는지를 조사
할 수 있다.
서브쿼리를 사용할 때 IN을 통해 비교하는 경우도 많다.
더 자세한 내용은 지금부터 sample_table과 sample_table2 테이블을 사용해 설명하겠다.
sample_table2 에는 3 과 5 라는 값이 존재한다.
서브쿼리를 사용하지 않고 WHERE 구로 간단하게 처리한다면 다음과 같이 조건을 붙일 수 있겠다.
WHERE id=3 OR id=5;
IN 에서는 오른쪽에 집합
을 지정한다.
왼쪽에 지정된 값과 같은 값이 집합 안에 존재
하면 참을 반환한다.
집합은 상수 리스트
를 괄호
로 묶어 기술한다.
앞의 WHERE 조건식을 IN을 사용하도록 수정하면 다음과 같다.
SELECT * FROM sample_table WHERE id IN (3, 5);
한편, 집합 부분은 서브쿼리
로도 지정할 수 있다.
상수 리스트 부분을 서브쿼리로 바꾸어 보겠다.
SELECT * FROM sample_table WHERE id IN (SELECT id FROM sample_table2);
이 같은 경우 서브쿼리는 스칼라 서브쿼리
가 될 필요는 없다.
IN에는 집합을 지정할 수 있기 때문에 행이 여러 개 반환되는 서브쿼리도 사용할 수 있다.
단, 열이 여러 개 반환되는 서브쿼리는 사용할 수 없다.