웹형태의 에플리케이션에서는 페이지 단위로 처리가 종료되는 형식을 취하게 된다.
따라서 한 페이지에 표시할 만큼만 액세스할 수 있다면 그것이 최선이 될 것이다.
고객명(cust_name) non unique index일때
select /*+ index(w cust_name_idx */
rowidtochar(rowid) rid, cust_name, ...
from cust_table w
where :v2 = 'FIRST' and cust_name like :v1 || '%'
and rownum <= 25
union all
select /*+ use_concat index(x cust_name_idx */
rowidtochar(rowid) rid, cust_name, ...
from cust_table x
where :v2 = 'NEXT'
and (cust_name > :v3 or
(cust_name = :v3 and rowid > chartorowid(:v4) ) )
and cust_name like :v1 || '%'
and rownum <= 25
union all
select /*+ use_concat index_desc(x cust_name_idx */
rowidtochar(rowid) rid, cust_name, ...
from cust_table x
where :v2 = 'PREV'
and (cust_name < :v3 or
(cust_name = :v3 and rowid < chartorowid(:v4) ) )
and cust_name like :v1 || '%'
and rownum <= 25
order by cust_name, rid
기본키(billboard_uk)는 '게시판id+작성일자+글번호'로 구성되어 있을 경우
select bbs_id, 작성일자, 글번호, rnum
from (select /*+ use_concat index_desc(a billboard_uk) */
rownum rnum, bbs_id, 작성일자, 글번호, 글내용
from billboard a
where :sw = 'NEXT'
and bbs_id = :bid
and (작성일자 < :init_dt or
(작성일자 = :init_dt and 글번호 < :v_num) )
and rownum <= 25
union all
select /*+ use_concat index_asc(a billboard_uk) */
rownum rnum, bbs_id, 작성일자, 글번호, 글내용
from billboard a
where :sw = 'PREV'
and bbs_id = :bid
and (작성일자 > :init_dt or
(작성일자 = :init_dt and 글번호 > :v_num) )
and rownum <= 25
)
order by rnum;
SELECT CDAY, CUST_NM, CID, CSEQ, CTEXT
FROM (SELECT /*+ INDEX_ASC(a IDX01) */
CDAY, CUST_NM, CID, CSEQ, CTEXT
FROM CSTAB a
WHERE :SW = 'FIRST'
AND CDAY BETWEEN :B11 AND :B12
AND ROWNUM <=25
UNION ALL
SELECT /*+ INDEX_DESC(a IDX01) */
CDAY, CUST_NM, CID, CSEQ, CTEXT
FROM CSTAB a
WHERE :SW = 'LAST'
AND CDAY BETWEEN :B11 AND :B12
AND ROWNUM <=25
UNION ALL
SELECT /*+ USE_CONCAT INDEX_ASC(a IDX01) */
CDAY, CUST_NM, CID, CSEQ, CTEXT
FROM CSTAB a
WHERE :SW = 'NEXT'
AND ((CDAY > :B100) OR (CDAY = :B100 AND CID > :B20
OR (CDAY = :B100 AND CID = :B20 AND CSEQ > :B27) )
AND CDAY BETWEEN :B11 AND :B12
AND ROWNUM <=25
UNION ALL
SELECT /*+ USE_CONCAT INDEX_DESC(a IDX01) */
CDAY, CUST_NM, CID, CSEQ, CTEXT
FROM CSTAB a
WHERE :SW = 'PREV'
AND ( (CDAY < :B100) OR (CDAY = :B100 AND CID < :B20
OR (CDAY = :B100 AND CID = :B20 AND CSEQ < :B27) )
AND CDAY BETWEEN :B11 AND :B12
AND ROWNUM <=25 )
ORDER BY CDAY, CID, CSEQ
SELECT RNUM, BBS_ID, CRE_DT, NUM
FROM (SELECT /*+ USE_CONCAT INDEX_DESC(a bbs_idx1) */
ROWNUM RNUM, BBS_ID, CRE_DT, NUM
FROM BILLBOARD a
WHERE :SW = 'NEXT' AND BBS_ID = :V_BBS
AND ( CRE_DT < :V_INIT_DT
OR ( CRE_DT = :INIT_DT AND NUM <= :V_NUM) )
AND ROWNUM <= 201
UNION ALL
SELECT /*+ USE_CONCAT INDEX_ASC(a bbs_idx1) */
((20*10)+2 - ROWNUM) RNUM, BBS_ID, CRE_DT, NUM
FROM BILLBOARD a
WHERE :SW = 'PREV' AND BBS_ID = :V_BBS
AND ( CRE_DT > :V_INIT_DT
OR ( CRE_DT = :INIT_DT AND NUM >= :V_NUM) )
AND ROWNUM <= 201
)
WHERE RNUM IN (1,21,41,61,81,101,121,141,161,181,201)
ORDER BY RNUM
페이지가 어느 단계에서 잘렸든 최상의 원본글 정보를 가지고 있어야 한다.
1. 처음 페이지를 처리하는 방법
원본글 들만 이용해 원하는 순서로 계층구조를 전개해 가다가 페이지가 채워지면 처리를 멈춘다.
이전/다음 처리를 위해서 최상위 레벨의 식별자 정보를 보유한다.
2. 다음 페이지를 처리하는 방법
마지막 글이 원본글로 부터 몇번째 순번의 글인지 알아야 한다.
해당 순번의 다음번 부터 잘라온다.
=> 추출 대상 로우는 한테이지에 나타나는 데이터의 수보다 많아진다.
3. 이전페이지를 처리하는 방법
=> SQL을 분리하여 절차형 처리를 가미해야한다.
SELECT ID, PID, C_TEXT,SUBSTR(PATH,3,3) * 1 PARENT_ID -------(e)
FROM (SELECT ROWNUM RNUM, ID, PID, WRITER,
LPAD(' ', 2*LEVEL-1)||C_TEXT C_TEXT,
SYS_CONNECT_BY_PATH(TO_CHAR(ID,'999'),'/') PATH -------(d)
FROM BILLBOARD
CONNECT BY PID = PRIOR IS
AND ROWNUM <=10 + :CNT -------(b)
START WITH PARENT_SW = 1 -------(a)
AND ID >= :START_ID
)
WHERE RNUM BETWEEN :CNT AND 10+ :CNT -------(c)