Contents
see ListOracle 계층구조(답글, 댓글) 전부 삭제하기
게시판에서 원글을 삭제할 때 하위 답글, 댓글까지 모두 삭제하는 Oracle 쿼리입니다.
언제 사용하나요?
- 게시글 삭제 시 모든 답글/대댓글 함께 삭제
- 카테고리 삭제 시 하위 카테고리 함께 삭제
- 조직도에서 부서 삭제 시 하위 부서 포함 삭제
- 트리 구조 데이터의 일괄 삭제
테이블 구조 예시
CREATE TABLE board (
board_seq NUMBER PRIMARY KEY,
parent_seq NUMBER, -- 부모글 번호 (NULL이면 원글)
title VARCHAR2(200),
content CLOB,
use_yn CHAR(1) DEFAULT \047Y\047
);
-- 답글 구조
-- board_seq=1 (원글)
-- └ board_seq=2 (답글, parent_seq=1)
-- └ board_seq=3 (대댓글, parent_seq=2)
-- └ board_seq=4 (답글, parent_seq=1)계층 구조 조회 (CONNECT BY)
-- 특정 글과 모든 하위 글 조회
SELECT board_seq, parent_seq, title, LEVEL
FROM board
START WITH board_seq = 1 -- 시작점 (원글)
CONNECT BY PRIOR board_seq = parent_seq -- 부모-자식 연결
ORDER SIBLINGS BY board_seq;계층 구조 삭제 (서브쿼리 사용)
-- 방법 1: 서브쿼리로 삭제
DELETE FROM board
WHERE board_seq IN (
SELECT board_seq
FROM board
START WITH board_seq = :delete_seq
CONNECT BY PRIOR board_seq = parent_seq
);논리적 삭제 (USE_YN 업데이트)
-- 실제 삭제 대신 USE_YN = \047N\047으로 변경
UPDATE board
SET use_yn = \047N\047
WHERE board_seq IN (
SELECT board_seq
FROM board
START WITH board_seq = :delete_seq
CONNECT BY PRIOR board_seq = parent_seq
);MyBatis 적용
<!-- BoardMapper.xml -->
<delete id="deleteWithReplies" parameterType="long">
DELETE FROM board
WHERE board_seq IN (
SELECT board_seq
FROM board
START WITH board_seq = #{boardSeq}
CONNECT BY PRIOR board_seq = parent_seq
)
</delete>
<update id="softDeleteWithReplies" parameterType="long">
UPDATE board
SET use_yn = \047N\047,
upd_date = SYSDATE
WHERE board_seq IN (
SELECT board_seq
FROM board
START WITH board_seq = #{boardSeq}
CONNECT BY PRIOR board_seq = parent_seq
)
</update>CTE(Common Table Expression) 방식
-- Oracle 11g R2 이상
WITH RECURSIVE tree AS (
SELECT board_seq
FROM board
WHERE board_seq = :delete_seq
UNION ALL
SELECT b.board_seq
FROM board b
INNER JOIN tree t ON b.parent_seq = t.board_seq
)
DELETE FROM board
WHERE board_seq IN (SELECT board_seq FROM tree);외래키 CASCADE 설정
-- 테이블 생성 시 CASCADE 설정
CREATE TABLE board (
board_seq NUMBER PRIMARY KEY,
parent_seq NUMBER REFERENCES board(board_seq) ON DELETE CASCADE,
title VARCHAR2(200)
);
-- 이렇게 하면 부모 삭제 시 자식 자동 삭제
DELETE FROM board WHERE board_seq = 1; -- 하위 글도 자동 삭제삭제 전 하위 글 개수 확인
SELECT COUNT(*) as total_count
FROM board
START WITH board_seq = :board_seq
CONNECT BY PRIOR board_seq = parent_seq;주의사항
- 삭제 전 트랜잭션 시작 필수
- 대용량 삭제 시 배치 처리 고려
- 실제 DELETE 전 SELECT로 영향 받는 데이터 확인
- 첨부파일 등 연관 데이터도 함께 처리 필요
연관 테이블 함께 삭제
-- 첨부파일, 댓글 등도 함께 삭제
DELETE FROM board_file
WHERE board_seq IN (
SELECT board_seq
FROM board
START WITH board_seq = :delete_seq
CONNECT BY PRIOR board_seq = parent_seq
);
DELETE FROM board_comment
WHERE board_seq IN (
SELECT board_seq
FROM board
START WITH board_seq = :delete_seq
CONNECT BY PRIOR board_seq = parent_seq
);
DELETE FROM board
WHERE board_seq IN (
SELECT board_seq
FROM board
START WITH board_seq = :delete_seq
CONNECT BY PRIOR board_seq = parent_seq
);