서브쿼리는 SELECT 명령으로 괄호로 묶어 지정하는 하부의 부수적인 질의이다. 보통 SQL명령의 WHERE구에 주로 지정된다.
sample54 테이블에서 a값이 가장 작은 행을 삭제하려한다.
보통 아래와 같은 순서로 진행된다.
SELECT MIN(a)으로 가장 작은 값 검색 → DELETE문으로 해당 행을 삭제
DELETE FROM sample54 WHERE a=(SELECT MIN(a) FROM sample54);
❗ MySQL에서는 데이터를 추가/갱신할 경우 동일한 테이블을 서브쿼리에서 사용할 수 없기 때문에 에러가 발생한다.
아래와 같이 인라인 뷰로 임시 테이블을 만들도록 처리하면 결과를 볼 수 있다.
DELETE FROM sample54 WHERE a=(SELECT a FROM(SELECT MIN(a) AS a FROM sample54) AS x);
서브쿼리를 사용할 땐 그 SELECT명령이 어떤 값을 반환하는지 주의해야한다.
> SELECT MIN(a) FROM sample54;
// a열에서 가장 적은 수 출력
SELECT no FROM sample54;
// no값만 출력
SELECT MIN(a),MAX(no) FROM sample54;
// a열에서 가장 적은수, no열에서 가장 높은 수 출력
SELECT no,a FROM sample54;
열 지정하여 출력
1번 패턴만이 다른 패턴과 다르게 하나의 값을 반환한다.
- 스칼라 값을 반환하는 서브쿼리는 = 연산자로 비교가 용이하다.
- 집계함수는 WHERE구에서는 사용할 수 없지만, 스칼라 서브쿼리는 가능하다.
SELECT (SELECT COUNT(*) FROM sample51) AS sql1,(SELECT COUNT(*) FROM sample54) AS sql2;
SELECT구에서 스칼라 서브쿼리를 사용할 수 있다.
SET구에서도 서브쿼리를 사용할 수 있다.
mysql > UPDATE sample54 SET a = (SELECT a FROM (SELECT MAX(a) AS a FROM sample54) AS x);
Query OK, 1 row affected (0.00 sec)
Rows matched: 2 Changed: 1 Warnings: 0
mysql > SELECT * FROM sample54;
+------+------+
| no | a |
+------+------+
| 1 | 900 |
| 2 | 900 |
+------+------+
2 rows in set (0.00 sec)
mysql > SELECT * FROM (SELECT * FROM sample54) AS sq;
+------+------+
| no | a |
+------+------+
| 1 | 900 |
| 2 | 900 |
+------+------+
2 rows in set (0.00 sec)
위와 같은 형태를 'nasted 구조', '중첩구조' 등으로 부른다.
SELECT * FROM (
SELECT * FROM sample54 ORDER BY a DESC
) AS sq WHERE ROWNUM <= 2;
Oracle에는 LIMIT구가 없기 때문에 정렬 후 추출할 행을 제한할때 위와 같이 명령한다.
INSERT 명령에도 서브쿼리를 사용할 수 있습니다. 방법은 아래와 같이 두 가지 입니다.
①의 경우 서브쿼리는 스칼라 서브쿼리로 지정해야하며, 자료형도 일치해야 한다.
mysql > INSERT
INTO sample541
VALUES((SELECT COUNT(*)
FROM sample51),
(SELECT COUNT(*)
FROM sample54));
Query OK, 1 row affected (0.00 sec)
mysql > SELECT * FROM sample541;
+------+------+
| a | b |
+------+------+
| 5 | 2 |
+------+------+
1 row in set (0.00 sec)```
정수형 a,b열로 이루어진 빈 테이블 sample541에 위와 같이 값을 추가할 수 있다.
②의 경우는 INSERT SELECT라고 불리는 명령이다.
$ mysql > INSERT INTO sample541 SELECT 1, 2;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
$ mysql > SELECT * FROM sample541;
+------+------+
| a | b |
+------+------+
| 5 | 2 |
| 1 | 2 |
+------+------+
2 rows in set (0.00 sec)
mysql > SELECT 1, 2;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+
1 row in set (0.00 sec)