MySQL에서 UPDATE 문은 단순한 정적 데이터 수정에 그치지 않는다.
서브쿼리(Subquery)를 활용하면 다른 테이블의 계산 결과나 조건을 기반으로 동적으로 값을 수정할 수 있다.
이는 실무에서 집계 기반 수정, 참조 기반 갱신, 조건부 연산 등을 구현할 때 매우 강력한 도구가 된다.
✅ 서브쿼리를 이용한 UPDATE 기본 문법
UPDATE 테이블명
SET 컬럼명 = (SELECT 컬럼 FROM 다른테이블 WHERE 조건)
WHERE 조건;
SET 구문에서 괄호로 감싼 SELECT 문이 서브쿼리이다.
해당 서브쿼리는 한 개의 값을 반환해야 하며, 복수 행을 반환하면 오류가 발생한다.
✅ 기본 예제: 회원별 총 주문 수 갱신
UPDATE users
SET total_orders = (
SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id
);
이 예제는 orders 테이블에서 사용자별 주문 수를 집계하여, users 테이블의 total_orders 필드를 동기화한다.
다른 테이블의 통계 데이터를 기준으로 업데이트하는 대표적인 활용 사례이다.
✅ 다중 서브쿼리 예제
UPDATE users
SET total_spent = (
SELECT SUM(total_price)
FROM orders
WHERE orders.user_id = users.id
),
last_order_at = (
SELECT MAX(order_date)
FROM orders
WHERE orders.user_id = users.id
);
이 쿼리는 사용자의 총 지출 금액과 마지막 주문일을 각각 계산해서 users 테이블에 반영한다.
두 개 이상의 서브쿼리를 조합하여 다중 컬럼 업데이트도 가능하다.
✅ WHERE 조건에도 서브쿼리 사용 가능
UPDATE products
SET discount = 0
WHERE category_id IN (
SELECT id FROM categories WHERE type = '단종'
);
이 쿼리는 categories 테이블에서 type = '단종'인 항목만 필터링하여, 해당 카테고리에 속한 상품들의 할인율을 초기화한다.
WHERE 절에 사용하는 서브쿼리는 대상 범위를 동적으로 지정할 때 매우 유용하다.
✅ EXISTS를 활용한 조건 기반 UPDATE
UPDATE members m
SET status = '활성'
WHERE EXISTS (
SELECT 1 FROM logins l
WHERE l.member_id = m.id AND l.login_at >= CURDATE() - INTERVAL 30 DAY
);
최근 30일 이내 로그인 기록이 있는 회원만 활성 상태로 전환하는 예제이다.
EXISTS는 특정 조건을 만족하는 데이터가 존재하는지만 판단하므로, 성능과 로직 제어에 효과적이다.
✅ 서브쿼리 + JOIN 조합 불가할 때의 대안
MySQL에서는 UPDATE JOIN과 UPDATE + 서브쿼리는 둘 다 지원되지만, 복잡한 다중 JOIN을 서브쿼리 안에서 사용하면 성능 저하 또는 오류가 발생할 수 있다.
이럴 때는 뷰(VIEW)를 만들거나, 서브쿼리를 별도 테이블로 분리해서 처리하는 방법이 있다.
CREATE TEMPORARY TABLE recent_orders AS
SELECT user_id, MAX(order_date) AS last_order
FROM orders
GROUP BY user_id;
UPDATE users u
JOIN recent_orders ro ON u.id = ro.user_id
SET u.last_order_at = ro.last_order;
서브쿼리를 임시 테이블로 분리한 후 JOIN으로 처리하면 복잡한 쿼리도 안정적으로 관리할 수 있다.
✅ 다형성 조건 처리 (CASE + 서브쿼리)
UPDATE users
SET grade = (
SELECT CASE
WHEN SUM(total_price) >= 100000 THEN 'VIP'
WHEN SUM(total_price) >= 50000 THEN 'GOLD'
ELSE 'SILVER'
END
FROM orders
WHERE orders.user_id = users.id
);
이 쿼리는 사용자의 총 구매 금액에 따라 등급을 자동으로 분류하여 반영한다.
서브쿼리와 CASE 문을 조합하면 복잡한 조건 분기를 우아하게 처리할 수 있다.
✅ UPDATE 서브쿼리 사용 시 주의사항
항목 | 설명 |
단일 값만 반환 가능 | 서브쿼리는 하나의 스칼라 값만 반환해야 한다 |
다중 행 반환 시 오류 발생 | Subquery returns more than 1 row 에러 발생 가능 |
성능 고려 | WHERE 조건 없이 전체 행 반복 조회 시 성능 저하 |
인덱스 적극 활용 | 서브쿼리 내부도 인덱스를 활용할 수 있어야 빠르다 |
항상 SELECT로 서브쿼리 결과를 먼저 확인한 후 UPDATE에 적용하는 것이 안전하다.
✅ 공식 문서 참고 링크
'DB' 카테고리의 다른 글
[MySQL] UPDATE 트랜잭션 적용하기: 데이터 무결성을 지키는 안전한 수정 전략 (1) | 2025.07.01 |
---|---|
[MySQL] UPDATE 문에서 NULL 처리하는 방법 완전 정리 (0) | 2025.07.01 |
[MySQL] UPDATE + NOW() 함수로 날짜 자동 수정하는 실전 활용법 (0) | 2025.06.30 |
[MySQL] UPDATE + IF / CASE 문으로 조건부 데이터 수정하는 실전 가이드 (1) | 2025.06.30 |
[MySQL] UPDATE + JOIN 활용법 완전 정리 – 다중 테이블을 수정하는 강력한 방법 (0) | 2025.06.30 |
[MySQL] UPDATE + WHERE (안전하고 정확한 데이터 수정 가이드) (0) | 2025.06.30 |
[MySQL] UPDATE로 다중 컬럼 동시에 수정하는 방법 완벽 정리 (0) | 2025.06.30 |
[MySQL] UPDATE 기본 문법 완벽 정리 – 데이터 수정 (2) | 2025.06.30 |