2015년 9월 17일 목요일

오라클에서의 페이징 처리


구코단의 쿠키입니다. 




질문하시는 내용 중에 오라클로 페이징 처리와 관련해서 문의하시는 분들이 있으셔서 블로그에 정리해 놓도록 하겠습니다. 


게시판 생성 SQL문입니다. 


create table tbl_board (
bno number,
title varchar2(400) not null,
content varchar2(2000) not null,
writer varchar2(50) not null,
regdate date default sysdate,
viewcnt number default 0
);

create sequence seq_board;

alter table tbl_board add constraint pk_board primary key (bno);



페이지 처리 기본 



일반적으로 오라클의 경우는 페이징 처리에 rownum을 활용합니다. rownum은 테이블에서 데이터가 출력될 때 붙는 번호라고 이해하시면 좋습니다.

rownum은 출력되면서 붙는 번호이기 때문에 어떤 식으로 SQL문이 실행되는지에 따라서(실행 계획)에 붙는 번호가 달라지게 됩니다.



위의 SQL의 경우는 오라클의 힌트를 이용해서 역순으로 데이터를 조회하는 예입니다. 이 경우 pk_board는 PK의 이름으로 해석하자면 pk_board를 역순으로 뒤지면서 데이터를 찾아내라는 뜻입니다.

rownum이 10보다 작거나 같기 때문에 10개의 데이터만 출력되는 것을 볼 수 있습니다.




2페이지 처리 하기 


rownum은 데이터가 나오면서 붙여주는 번호이기 때문에 rownum > 10 and rownum <= 20과 같은 SQL문은 제대로 결과가 나오지 않습니다.

rownu > 10 구문에서 어떤 데이터가 나오면 rownum은 1이 되기 때문에 rownum > 10조건에 맞지 않기 때문에 건너뛰게 됩니다.

이러한 이유로 흔히 rownum은 반드시 1이 포함되어야 한다고 합니다.


2페이지를 처리하기 위해서는 'in-line view'라는 기술을 알아야만 합니다. in-line view는 쉽게 말해서 from 구문에 다른 SQL문이 들어간 형태입니다.


2페이지의 데이터 처리는 다음과 같습니다.



SQL문을 자세히 보면 from  내부에 SQL문이 하나 더 사용되는 것을 볼 수 있습니다.

위의 SQL문은 rownum이 20보다 작거나 같은 데이터(2페이지까지의 모든 데이터)를 in-line view로 처리하고, rn이라는 컬럼을 만들어 냅니다.

외부에서는 rn컬럼의 값이 10보다 크다는 조건을 이용합니다.




위의 결과와 비교해 보면 2페이지의 데이터가 출력되는 것을 볼 수 있습니다.



MyBatis의 SQL문 

MySQL의 limit의 경우 사용하기 쉽지만, 오라클의 경우는 조금 복잡하므로 페이징 처리와 관련한 SQL문은 아래와 같은 형태로 수정되어야 합니다. 




작성된 SQL문은 PART 2의 예제에서 다음과 같이 출력되어야 합니다.






댓글 8개:

  1. 작가님 안녕하세여 Part2 동영상 강의는 언제쯤 나올까요? 재촉하는 것이 아니오라 언제 나오는지 궁금할 따름입니다 :D

    답글삭제
  2. PART2도 동영상 찍어야 하는건가요? ㅠㅠ

    동영상부분을 아예 유료화로 같이 제작하자는 의견이 있어서 조율중입니다.

    추석끝나고 결정될 듯 합니다.

    결정되면 블로그에 공지하겠습니다.

    답글삭제
  3. 네 감사합니다. 유료라도 상관없습니다. 책이 잘되어 있긴 하지만 제가 너무 부족해서 동영상 보면 아~하는 부분이 있어서 동영상과 책을 같이 보는 편이 저에게는 좋은 것 같습니다. 책을 또 읽고 또 읽으며 동영상을 기다리겠습니다. 재미있는 하루 보내세여~ 8-D

    답글삭제
  4. 작성자가 댓글을 삭제했습니다.

    답글삭제
  5. 작성자가 댓글을 삭제했습니다.

    답글삭제
  6. 작가님 안녕하세요 책정말 잘보고 있습니다 많은 도움주셔서 감사합니다~
    책 예제를 보다가 질문있어 여기에 남깁니다 ..ex03 예제에서 오라클로 변동해서 실행시 오류가 나더라구요
    9월 22, 2015 2:49:41 오후 org.apache.catalina.core.StandardWrapperValve invoke
    심각: Servlet.service() for servlet [appServlet] in context with path [] threw exception [Handler processing failed; nested exception is java.lang.AbstractMethodError: Method oracle/jdbc/driver/OracleResultSetImpl.isClosed()Z is abstract] with root cause
    java.lang.AbstractMethodError: Method oracle/jdbc/driver/OracleResultSetImpl.isClosed()Z is abstract
    at oracle.jdbc.driver.OracleResultSetImpl.isClosed(OracleResultSetImpl.java)
    at net.sf.log4jdbc.sql.resultsetcollector.DefaultResultSetCollector.loadMetaDataIfNeeded(DefaultResultSetCollector.java:128)
    at net.sf.log4jdbc.sql.jdbcapi.ResultSetSpy.loadMetaDataIfNeeded(ResultSetSpy.java:82)
    at net.sf.log4jdbc.sql.jdbcapi.ResultSetSpy.close(ResultSetSpy.java:1534)
    at
    이런식으로 에러가 쭉나오더라구요
    확인해보니 lo4j.xml 설정에서
    root
    priority value="info" /
    appender-ref ref="console" /
    root

    를 root
    priority value="warn" />
    appender-ref ref="console" />
    root
    으로 했을경우 에러는 안나는데 ...문제는 aop 입니다. 로그기록도 안남고 정상적으로 작동이 되지가 않습니다. 책 479페이지 에서는 분명 info 로 해주라고 했는데..전혀감이 안잡혀서 이렇게 글남깁니다.

    답글삭제
  7. 남자박현민님이 질문하신 내용은 새 글로 추가해 두었습니다.

    제가 479까지 만든 오라클 버전 코드는 https://drive.google.com/file/d/0B1CVG6b0KlWQWTl3T0twOTZjems/view?usp=sharing 에 만들어 두었습니다.

    답글삭제
  8. 오라클 예재 감사해요~
    언능 책을 완독하고 싶네요.

    답글삭제