1. 구현 조건


1) 원글은 내림차순, 답변글은 오름차순 정렬을 하도록 한다.
2) 원글이 삭제된 경우에도 답변글은 유지하도록 한다.  
 - 기본적으로 계층처리시 level을 유지시키기 위해 데이터를 삭제하더라도
   실제로 삭제하지는 않고 삭제를 의미하는 칼럼을 추가하여 삭제여부를 저장한다.
   실제로 삭제를 하게 되면 delete가 아니라 update를 통해 해당 칼럼을
   수정하고, 해당 레코드의 바로 아래 자식의 title에 [원글삭제] 라는 접두어를 추가하는
   procedure를 만들어서 삭제 수행시 해당 procedure를 사용하도록 하자.
   이렇게 되면 원글이 삭제되더라도 filtering하여 원글은 보이지 않지만
   답변글은 level이 유지된 채로 확인이 가능하다.


 


 


2. 테스트용 테이블 생성


create table t_replayboard_test(
 board_no number(10),    --기본키
 title varchar2(100),    --제목
 c_date date default sysdate,  --등록일
 parent_no number(10),    --상위조상
 prototype_no number(10) not null, --최상위조상(그룹번호)
 del_yn char(1) default 'N'
);


--기본키 생성
alter table t_replayboard_test add constraint t_replayboard_test_pk
primary key (board_no);


--자기참조 모델링

--바로 위의 부모를 나타내는 parent_no의 경우 board_no에 존재하는 번호가 등록가능하다.​
--기본적으로 답변글이 있는 데이터는 삭제할 수 없도록 한다.
alter table t_replayboard_test add constraint t_replayboard_test_fk01
foreign key (parent_no) references t_replayboard_test(board_no);


--최상위조상 을 나타내는 번호의 경우 board_no에 존재하는 번호만 등록가능하다.
alter table t_replayboard_test add constraint t_replayboard_test_fk02
foreign key (prototype_no) references t_replayboard_test(board_no);


--del_yn 입력값 제한
alter table t_replayboard_test add constraint t_replayboard_test_ck01
check (del_yn in('Y','N'));


--계층처리 및 삭제로직을 위한 인덱스 생성
create index t_replayboard_test_idx02
on t_replayboard_test(parent_no);


 


 


2. 테스트용 데이터 입력


--원글 등록
begin
  for i in 1..10
  loop
    insert into t_replayboard_test(board_no, title, c_date, prototype_no)
    values(i, '원글'||i, sysdate+(i/24/60/60), i); --등록시간은 1초의 차이가 나도록    
  end loop;
  commit;
end;

--답변등록

--답변1
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(11, '[RE]원글1의 답변', 1, 1, sysdate+(1/24/60/60));
--values(시퀀스, [RE]가 앞에 붙은 제목, 부모키, 최고조상키, 등록일);

--답변1의 답변1
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(12, '[RE][RE]원글1의 답변의 답변1', 11, 1, sysdate+(2/24/60/60));

--답변1의 답변1의 답변1
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(13, '[RE][RE][RE]원글1의 답변의 답변의 답변', 12, 1, sysdate+(3/24/60/60));

--답변1의 답변2
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(14, '[RE][RE]원글1의 답변의 답변2', 11, 1, sysdate+(4/24/60/60));


--답변2
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(15, '[RE]원글9의 답변', 9, 9, sysdate+(5/24/60/60));

--답변2의 답변1
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(16, '[RE][RE]원글9의 답변의 답변1', 15, 9, sysdate+(6/24/60/60));

--답변2의 답변2
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(17, '[RE][RE]원글9의 답변의 답변2', 15, 9, sysdate+(7/24/60/60));

--답변2의 답변1의 답변1
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(18, '[RE][RE][RE]원글9의 답변의 답변1의 답변1', 16, 9, sysdate+(8/24/60/60));

--답변2의 답변1의 답변2
insert into t_replayboard_test(board_no, title, parent_no, prototype_no, c_date)
values(19, '[RE][RE][RE]원글9의 답변의 답변2의 답변2', 16, 9, sysdate+(9/24/60/60));

commit;

 


 


4. 계층데이터 select 쿼리

 

select lpad(' ', (level-1)*5)||title title,
       board_no,
       parent_no,
       prototype_no,
       c_date      
from t_replayboard_test
where del_yn = 'N'
start with parent_no is null
connect by parent_no = prior board_no
order siblings by prototype_no desc, board_no asc;


 



4. 글 삭제 로직

 - 아래는 익명블록으로 생성하였지만 실제 시스템에서는 procedure로 만들어서 사용하면 되겠다.


--삭제로직
--board_no=16 삭제
declare
  p_board_no number(10);
begin
  p_board_no := 16;
 
  update t_replayboard_test
  set del_yn = 'Y'
  where board_no = p_board_no;
 
  update t_replayboard_test
  set title = '[원글삭제] '||title
  where parent_no = p_board_no;
 
  commit;
end; 

 

Posted by mypiece
,