posted by 준치 2008. 11. 29. 22:39

tomcat 5.0 사용 중 이런 에러가 발생해서 아침부터 욕 쳐먹었더니 기분이 매우 우울하네.

 

org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (IO 예외 상황: The Network Adapter could not establish the connection)
org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (IO 예외 상황: The Network Adapter could not establish the connection)
 at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:855)
 at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:540)
 at com.feelingk.dbcp.DbcpUtil.<init>(DbcpUtil.java:47)
 at com.feelingk.dbcp.DbcpUtil.<init>(DbcpUtil.java:36)
 at com.feelingk.lgt_fb_web.dao.TbRenewMenuVoDAO.selectList(TbRenewMenuVoDAO.java:137)
 at com.feelingk.lgt_fb_web.ctl.DirectoryCtl.selectExtList(DirectoryCtl.java:299)
 at org.apache.jsp.FB.ContentsView_jsp._jspService(ContentsView_jsp.java:817)
 at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
 at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:324)
 at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:292)
 at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:236)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
 at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
 at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
 at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
 at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
 at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
 at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:535)
 at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
 at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
 at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
 at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
 at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:300)
 at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:374)
 at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:743)
 at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:675)
 at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:866)
 at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
 at java.lang.Thread.run(Thread.java:534)
Caused by: java.sql.SQLException: IO 예외 상황: The Network Adapter could not establish the connection
 at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
 at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
 at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255)
 at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387)
 at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:439)
 at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
 at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
 at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
 at org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:37)
 at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:290)
 at org.apache.commons.dbcp.BasicDataSource.validateConnectionFactory(BasicDataSource.java:877)
 at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:851)
 ... 40 more

 

이런 메세지가 발생한다.

눈여겨 볼거는 맨 첫째줄만 보면 될 듯하다.

 

이유인즉슨

"네트워크 상태가 불안하여 오라클 DB 서버에 접속 할 수 없습니다."

라는데

오라클 DB 에 접속하지 못하는 이유로는

첫째, 오라클 DB 서버 자체가 죽어있을 때

둘째, 오라클 DB 서버에 접속하는 리스너가 죽어 있을 때

셋째, 둘 다 죽어 있을 때

이다.


SQL
posted by 준치 2008. 11. 28. 16:53

 

CREATE SEQUENCE MYSQ INCREMENT BY 1 START WITH 10000;"

시퀀스라는 것은 자동 증가 칼럼을 만들 때 사용한다.

 

SQL> CREATE TABLE SQTEST 2> (SQ_ID NUMBER, 3> SQ_NAME VARCHAR2(20));  

SQL> CREATE SEQUENCE MYSQ INCREMENT BY 1 START WITH 10000;  

 

CREATE SEQUENCE 라는 문장을 사용하여 MYSQ라는 이름의 시퀀스를 만들었다.  

INCREMENT BY 1 자동 증가 칼럼의 증가치가 1이고,  

START WITH 10000 자동 증가 칼럼이 10000부터 증가한다는 뜻이다.  

 

SQL> INSERT INTO SQTEST VALUES(MYSQ.NEXTVAL,'홍길동');  

SQL> SELECT * FROM SQTEST;

 

SQ_ID SQ_NAME

--------------------- ---------------------------------------------

10000 홍길동

 

SQL> INSERT INTO SQTEST VALUES(MYSQ.NEXTVAL,'고길동');

 

SQ_ID SQ_NAME

--------------------- ---------------------------------------------

10000 홍길동

10001 고길동

 

SQL> DELETE FROM SQTESET WHERE SQ_NAME='고길동';

 

SQ_ID SQ_NAME

--------------------- ---------------------------------------------

10000 홍길동

 

SQL> INSERT INTO SQTEST VALUES(MYSQ.NEXTVAL,'홍제동');

SQL> SELECT * FROM SQTEST;

 

SQ_ID SQ_NAME

--------------------- ---------------------------------------------

10000 홍길동

10002 상도동

 

원본 위치 <http://blog.daum.net/_hdn/blank_article.html>

SQL
posted by 준치 2008. 11. 26. 23:10
 
Error 관련 내장함수
---------------------------------------------------------------------
SQLCODE        현재 발생한 오류에 따른 오류 코드를 반환한다.
SQLERRM        오라클 오류 코드와 연결된 오류 메시지를 반환한다.

Number 관련 내장함수
---------------------------------------------------------------------
ABS            어떤 수의 절대값을 반환한다.
ACOS         어떤 수의 아크코사인을 라디안 단위로 반환한다.
ASIN           어떤 수의 아크사인을 라디안 단위로 반환한다.
ATAN          어떤 수(x)의 아크탄젠트를 라디안 단위로 반환한다.
ATAN2        어떤 수(y/x)의 아크탄젠트를 라디안 단위로 반환한다.
CEIL           지정된 수보다 크거나 같은 최소 정수 값을 반환한다.
COS            어떤 수의 코사인을 라디안 단위로 반환한다.
COSH         어떤 수의 쌍곡선 코사인을 라디안 단위로 반환한다.
EXP            어떤 수의 지수 값을 반환한다. e=2.7182818
FLOOR        지정된 수보다 크거나 같은 최대 정수 값을 반환한다.
LN             어떤 수 x의 대수 값을 반환한다.
LOG            어떤 수 y에서 x를 밑으로 한 대수 값을 반환한다.
MOD            어떤 수 x를 y로 나눈 나머지를 반환한다.
POWER          어떤 수 x에 y 제곱한 값을 반환한다.
ROUND          x를 y자리에서 반올림한 값을 반환한다.
SIGN           숫자 x의 부호에 따라 양수이면 +1, 음수이면 -1, 0이면 0을 반환한다.
SIN            어떤 수의 사인을 라디안 단위로 반환한다.
SINH           어떤 수의 쌍곡선 사인을 라디안 단위로 반환한다.
SQRT           어떤 수 x의 제곱근을 반환한다. x는 반드시 양의 실수이다.
TAN            어떤 수의 탄젠트를 라디안 단위로 반환한다.
TANH           어떤 수의 쌍곡선 탄젠트를 라디안 단위로 반환한다.
TRUNC          어떤 수 x를 y 위치에서 잘라낸다.  

Character 관련 내장함수
---------------------------------------------------------------------
ASCII          문자의 ASCII 코드를 반환한다.
CHR            주어진 ASCII 값에 해당하는 문자를 반환한다.
CONCAT         두 개의 스트링을 서로 연결한다. (|| 연산자를 사용한 것과 같다)
INITCAP        각 단어의 첫 글자를 대문자로 나머지는 소문자로 변환한 스트링을 반환한
                다(문자가 아닌 값에는 영향이 없다)
INSTR          어떤 스트링에서 특정 스트링의 위치를 반환한다.
INSTRB         어떤 스트링에서 특정 스트링의 위치를 반환하는데,  값을 싱글 바이트 문
                자 시스템에 대한 바이트 단위로 반환한다.
LENGTH         뒤에 따라오는 공백을 포함하여 문자 스트링의 길이를 반환한다. 값이 null
                이면 null을 반환한다.
LENGTHB        문자 스트링의 길이를 반환하는데, 이것은 값을 싱글 바이트 문자 셋에 대
                한 바이트 단위로 반환한다.
LOWER          전체 문자 스트링을 소문자로 바꾼다. 문자가 아닌 값에는 영향이 없다
LPAD           스트링의 왼쪽에 지정한 어떤 스트링을 덧붙인다.
LTRIM          왼쪽에 있는 문자 스트링을 잘라낸다.
NLS_INITCAP    NLSSORT에 의해 지정된 다른 정렬방법을 사용할 수 있다는 것을 제외하
                고는 INITCAP 함수와 같다.
NLS_LOWER      NLSSORT에 의해 지정된 다른 정렬방법을 사용할 수 있다는 것을 제외하
                고는 LOWER 함수와 같다.
NLS_UPPER      NLSSORT에 의해 지정된 다른 정렬 방법을 사용할 수 있다는  것을 제외
                하고는 UPPER 함수와 같다.
NLSSORT        문자를 정렬하는 방법을 바꾼다. 이것은 NLS 함수를  사용하기 전에 지정
                해야 한다. 그렇지 않으면 기본 정렬이 사용된다.
REPLACE        어떤 스트링이 나타나는 곳마다 다른 스트링으로 바꾼다.
RPAD           스트링의 오른쪽에 지정된 어떤 스트링을 덧붙인다.
RTRIM          오른쪽에 있는 문자 스트링을 잘라낸다.
SOUNDEX        스트링의 음향을 반환한다. 철자는 다르지만 소리는 비슷한 단어에 유용하다.
SUBSTR         어떤 스트링에서 스트링의 일부를 반환한다.
SUBSTRB        싱글 바이트 문자 시스템을 처리하기 위해 파라미터가 문자가 아닌 바이트  
                     단위로 표현된다는 것을 제외하고는 SUBSTR 함수와 같다.
TRIM           LTRIM과 RTRIM 함수의 기능을 조합한  것이다. 스트링에서 앞 뒤 문자 를 잘라낸다.
TRANSLATE      REPLACE와 똑 같지만 이것은  스트링 단위가 아닌 문자  단위로 작동한다.
UPPER          전체 문자 스트링을 대문자로 바꾼다. 문자가 아닌 값에는 영향이 없다.

Conversion 관련 내장함수
---------------------------------------------------------------------
CHARTOROWID    오라클이 제공하는 외부형식으로  된 CHAR이나 VARCHAR2를  그 내부  
                바이너리 형식으로 변환한다.
CONVERT        한 문자 셋을 다른 문자 셋으로 변환한다.
HEXTORAW       16진 스트링 값을 내부 원시 값으로 변환한다.
RAWTOHEX       내부 원시 값을 외부 16진 스트링으로 변환한다.
ROWIDTOCHAR    ROWID를 외부적인 18 문자 스트링 표현으로 변환한다.
TO_CHAR        DATES, MLSLABELS, NUMBERS를 VARCHAR2 스트링으로 변환한다.
TO_DATE        CHAR이나 VARCHAR2 스트링을 DATE 값으로 변환한다.
TO_LABEL       CHAR이나 VARCHAR2 스트링을 MLSLABEL 값으로 변환한다.
TO_MULTI_BYTE  싱글 바이트 스트링으로 된 문자를 멀티 바이트 스트링으로 변환한다.
TO_NUMBER      CHAR이나 VARCHAR2 스트링을 NUMBER 값으로 변환한다.
TO_SINGLE_BYTE 멀티 바이트 스트링으로 된 문자를 싱글 바이트 스트링으로 변환한다.

Date 관련 내장함수
---------------------------------------------------------------------
ADD_MONTHS     지정된 날짜에 1달을 더한다.  만일 결과로 나온 달이  현재일수보다 작은  
                일수를 갖고 있는 달로 변경되면 그 달의 마지막 날을 반환한다.
LAST_DAY       주어진 달의 마지막 날을 반환한다.  
MONTHS_BETWEEN 두 날짜 사이의 개월 수를 계산한다. 만일 두 날짜가 그 달의 마지막 날이
                라면 정수를 반환하고 그렇지 않으면 한 달을 31일로 계산한 분수 값을 반
                환한다.
NEW_TIME       사용자가 지정한 시간대에 대한 시간/날짜 값을 반환한다.
NEXT_DAY       시작 날짜 다음에 지정된 요일이 처음으로 나오는 날짜를 반환한다.
ROUND          월, 연도, 세기 등과 같이 선택한 날짜 파라미터를 반올림한다.
SYSDATE        시스템 날짜와 시간을 DATE 형식으로 반환한다.
TRUNC          일, 월 등과 같이 지정된 날짜 파라미터를 잘라낸다.

집합함수
---------------------------------------------------------------------
AVG            지정된 컬럼 값의 평균을 구한다.
COUNT          쿼리에서 반환되는 행의 개수를 구한다.
GLC            MLSLABEL의 최대 아래쪽 한계를 구한다.
LUB            MLSLABEL의 최대 위쪽 한계를 구한다.
MAX            쿼리에서 지정된 컬럼의 값 중 가장 큰 값을 반환한다.
MIN            쿼리에서 지정된 컬럼의 값 중 가장 작은 값을 반환한다.
STDDEV         쿼리에서 선택된 컬럼의 표준 편차를 반환한다.
SUM            쿼리에서 선택된 컬럼의 합계를 구한다.
VARIANCE       쿼리에서 선택된 컬럼의 분산을 구한다.
DISTINCT       쿼리의 유일값만 구한다.

【예제】
SQL> select COUNT(DISTINCT job) from emp;
SQL> select COUNT(job) from emp;
SQL> select COUNT(*) from emp;


기타 내장함수
---------------------------------------------------------------------
BFILENAME      파일이 저장되어 있는 물리적 LOB  바이너리 파일과 연결되어 있는 포인
                터를 반환한다. 오라클에서는 포인터를 locator라고 부른다.
DECODE         값 목록 중에서 IF-THEN-ELSE 문과 같이 작동한다.
DUMP           VARCHAR2 스트링으로 된 덤프 값을 제공한다. 스트링을 여러 가지 다른  
                형식으로 된 표현으로 보여주기 위해서이다.
EMPTY_BLOB     데이터를 갖고 있지 않는 컬럼이나 BLOB 변수를 초기화하는데 사용한다.
EMPTY_CLOB     데이터를 갖고 있지 않는 컬럼이나 CLOB 변수를 초기화하는데 사용한다.
GREATEST       값이나 식의 목록에서 가장 큰 값을 반환한다.
GREATEST_LB    MLSLABELS 목록에서 최대 아래쪽 한계를 반환한다.
LEAST          값이나 식의 목록에서 가장 작은 값을 반환한다.
LEAST_LB       MLSLABELS 목록에서 최소 아래쪽 한계를 반환한다.
NLS_CHARSET_ID  NLS 문자셋 이름과 연결된 NLS 문자셋 ID 번호를 반환한다.
NLS_CHARSET_NAME 함수에 전달된 ID와 연결된 NLS 문자셋 이름을 반환한다.
NVL            값이나 식의 목록에서 처음으로 NULL이 아닌 값을 선택한다.
UID            오라클 사용자에게 할당된 사용자 ID를 반환한다.
USER           현재 사용자 이름을 VARCHAR2 스트링으로 반환한다.
USERENV        현재 작업환경에 관한 정보를 반환한다.
VSIZE          어떤 값의 바이트 수를 반환한다.

【예제】
$ sqlplus scott/tiger
SQL> select * from emp;
SQL> select uid from dual;
SQL> select user from dual;
SQL> select count(user) from emp;
SQL> select avg(sal) from emp;
SQL> select max(sal) from emp;
SQL> select min(sal) from emp;
SQL> select stddev(sal) from emp;
SQL> select sysdate from dual;
SQL> select last_day(sysdate) from dual;
SQL> select to_char(sysdate) from dual;
SQL> select to_char(next_day(sysdate,'monday'),'MM/DD/yyyy')  
    2  from dual;

출처 : Tong - 난신기루다~★님의 ORCLE통


SQL
posted by 준치 2008. 11. 25. 10:57

제목

오라클 고급쿼리(1) - CONNECT BY

작성자

DEV.WON ( http://blog.naver.com/jadin1 )

작성일

2007-05-31

배포

PUBLIC (, 출처는 밝혀 주세요)

 편의상  짧은 어투 양해바라며... 

후... 강좌 올만에 올리는군요...그동안 블로그 관리에 소홀히 했는데 이제부턴 열심히 해야겠습니다. 

오라클에서 제공하는 쿼리중 좀더 고급스러운 쿼리를 사용해 보도록하자. 

처음으로 살펴볼 쿼리는 이른바 계층적 쿼리이다. 

CONNECT BY 절을 사용하는데 이 계층적 쿼리는 오라클만이 가능 기능으로써, 

데이터를 선택하여 계층적인 순서 그대로 리턴하는데 사용된다. 

scott의 emp 테이블을 기억하는가? 

그 사원테이블에는 사원번호 와 함께 사원의 메니저의 번호(fk) 를 참조하는 외부키 컬럼이 있다. 

바로 self join을 사용하는 가장 흔한 예라 하겠다. 

필자는 emp테이블로 설명을 하려 했으나, 역시나 지겨운 관계로 새로 테이블을 만들었다. 

쇼핑몰이나 기타 솔루션에서 흔히 보게 되는 카테고리 정보 테이블을 예로 들면서 강좌를 진행하도록 하겠다. 

우선 DB 데이블의 schema부터 보도록하자.

1. 카테고리 정보 테이블(PRT_CATE) 

DDL

-- Create table
create table PRT_CATE
(
  NO            NUMBER not null,
  CATE_NAME     VARCHAR2(100) not null,
  BASE_CATE_NO  NUMBER,
  CATE_MEMO     VARCHAR2(500),
  CATE_VIEW_CNT NUMBER default 0
)
tablespace USERS
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );
-- Add comments to the columns
comment on column PRT_CATE.NO
  is 'pk';
comment on column PRT_CATE.BASE_CATE_NO
  is '상위 카테고리 의 FK';
comment on column PRT_CATE.CATE_MEMO
  is '카테고리의 설명.';
comment on column PRT_CATE.CATE_VIEW_CNT
  is '카테고리 열람 횟수';
-- Create/Recreate primary, unique and foreign key constraints
alter table PRT_CATE
  add constraint PRT_CATE_PK primary key (NO)
  using index
  tablespace SYSTEM
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  ); 


  2. 상품 테이블(PRT)

-- Create table
create table PRT
(
  NO          NUMBER not null,
  PRT_NAME    VARCHAR2(100) not null,
  PRT_PRICE   NUMBER not null,
  PRT_CATE_NO NUMBER
)
tablespace USERS
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );
-- Add comments to the columns
comment on column PRT.NO
  is 'PK';
comment on column PRT.PRT_NAME
  is 'NAME';
comment on column PRT.PRT_PRICE
  is '가격';
comment on column PRT.PRT_CATE_NO
  is '상품이 속한 카테고리 FK';
-- Create/Recreate primary, unique and foreign key constraints
alter table PRT
  add constraint PRT_PK primary key (NO)
  using index
  tablespace SYSTEM
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  ); 


 3. R-R

 

 역시나 필자의 귀차니즘에 의한 엄청나게 허술한 그림이 돋보인다..(예전의 열정은 사라졌다. ㅎ)

위의 schema를 쭉 본 독자들이라면 거의 모두다 파악이 될것이다. 

주목할 점은 바로 저, self join을 해야할 PRT_CATE테이블이다. 

자 독자라면 여기서 카테고리의 계층 구조를 쿼리로 나타내어 보라.

(8번PK의 DB카테고리의 계층구조는 컴퓨터 > 소프트웨어 > DB 이다.)

 

우선 필자는 이렇게 처리하였다.

 

---------------------------------------------------------------------------------------------

CREATE OR REPLACE PROCEDURE CATE_LISTING
       (p_cateName VARCHAR2, p_level NUMBER DEFAULT
0)
AS
BEGIN
    
--PRINT
     DBMS_OUTPUT.put_line(lpad(
' ',p_level * 3,' ') || p_cateName);

     FOR CATE_ROW IN         
             (
             SELECT * FROM PRT_CATE C
             WHERE C.BASE_CATE_NO IN (
                                       SELECT C2.NO FROM PRT_CATE C2
                                       WHERE C2.CATE_NAME = p_cateName        
                                     ) 
             ORDER BY C.NO
             )
         LOOP
      
      
-- PROCEDURE CALL   
       CATE_LISTING(CATE_ROW.CATE_NAME,p_level +
1);
    
     END LOOP;   

END ;      


-- EXECUTE
CALL CATE_LISTING(
'컴퓨터',0);

---------------------------------------------------------------------------------------------

 결과>

--------------

컴퓨터
   소프트웨어
      DB
      Tools
   주변제품
--------------- 

재귀 프로시져 기법으로 처리하였다. 

커서등을 사용하는것도 하나의 방법이 될수 있겠다.하지만, 너무 복잡하지않은가? 

자 이쯤에서 오라클이 자랑하는(?) 기능중 계층적 쿼리를 사용해 보도록하자. 

필자는 똑같은 결과를 이렇게 바꾸었다. 

---------------------------------------------------------------------------------------------

SELECT LPAD(' ' , (LEVEL - 1) * 3 , ' ')  || C.CATE_NAME CATE_HIER
FROM PRT_CATE C
START WITH C.CATE_NAME =
'컴퓨터'
CONNECT BY PRIOR C.NO = C.BASE_CATE_NO;

---------------------------------------------------------------------------------------------

 결과>



 오, 놀랍지않은가? 엄청나게 코드가 줄었다.(그렇다면 퍼포먼스는?? 오라클 도큐먼트를 살펴보길 바란다.) 

우선 START WITH 절부터 보도록 하자. 

SELECT 구문의 START WITH 절은 계층 구조가 어떤 행으로부터 시작하는지 지정하는 절이다. 

일종의 WHERE절이라 생각해도 좋다. 

      START WITH <조건> 

필자는 예제에서

START WITH C.CATE_NAME = '컴퓨터'

라고 작성하였다. 

바로 카테고리 이름이 '컴퓨터' 인 레코드부터 계층적 쿼리를 수행하라는 의미이다. 

START WITH절은  기본적으로 WHERE절에서 사용가능한 sql을 모두 사용할수 있다. 

이를 테면

---------------------------------------------------------------------------------------------

SELECT LPAD(' ' , (LEVEL - 1) * 3 , ' ')  || C.CATE_NAME CATE_HIER
FROM PRT_CATE C
--START WITH C.CATE_NAME = '컴퓨터'
START WITH C.CATE_NAME IN
      (SELECT CATE_NAME FROM PRT_CATE WHERE CATE_NAME =
'컴퓨터' OR CATE_NAME = '가전제품')     
CONNECT BY PRIOR C.NO = C.BASE_CATE_NO;

--------------------------------------------------------------------------------

와 같이 바꿀수도 있다.

 

이때 주의할점은 아래의 결과값과 같이 OR 연산 에 의해 두개의 레코드로 부터 계층쿼리가 시작이 되므로

 

결과값도 아래와 같이 두세트로 나온다는것에 주의하기 바란다.

(사실 이러한 경우때문에 가능하면 명료하고 구체적인 , 결과 레코드가 적은 조건을 사용하여야 쿼리 퍼포먼스가 향상된다. )

 

 

결과값>


다음은

 

CONNECT BY PRIOR 절을 살펴보도록하자. 

 

CONNECT BY 절은 각각의 행들이 어떻게 연결되어야하는지 (여기서는 JOIN을 뜻한다.) 정보를 작성한다.

 

무슨말이냐하면, 계층적 구조 에서 각 행의 연결 관계를 설정하는것인데...

 

사원테이블의 사원번호와 , 사원테이블의 사수번호가 여기에 해당된다 하겠다. 

 

그렇다면 어떤 컬럼과 어떤 컬럼이 상위이고 하위인지 이러한 계층정보는 어떻게 설정하는 것일까?

 

바로 이때 사용하는 키워드가 PRIOR 이다.

 

 

필자가 작성한 예제를 보면

CONNECT BY PRIOR C.NO = C.BASE_CATE_NO;

와 같이 작성하였는데..

 

우선 PRIOR 키워드를 빼고 생각해보자.

 

CONNECT BY

     C.NO = C.BASE_CATE_NO;

 

이와 같이 되는데 이때 NO 컬럼과 BASE_CATE_NO이 계층적 연결 관계에 있다라고 설정하는것이다

(SELF JOIN이라 생각해도 좋다.)

 

이제 PRIOR를 생각해보자.

CONNECT BY

     PRIOR C.NO = C.BASE_CATE_NO;

 

 

 

 

OUTER JOIN을 생각해보라.

C.NO (+) = C.BASE_CATE_NO; 와 같이, PRIOR 키워드의 위치에 집중하자.

 

 

바로 C.NO 쪽에 위치하고있다.! 

 

그렇다면 어느쪽 컬럼에 PRIOR가 위치한다는것은 무엇을 의미할까?

 

이것을 말로 설명하기가 매우 어렵다. 말주변의 바닥... ㅜㅜ;;

 

"NO컬럼을 참조하는 BASE_CATE_NO 컬럼이 속한 레코드를 모두 찾아라" 정도로 이해하면 될듯싶다.

 

 

이렇게 쿼리를 작성하였기때문에 상위 '컴퓨터' 카테고리에 해당하는 하위 카테고리를 찾았고, 또 그 하위 카테고리의

 

하위 카테고리를 찾을 수 있게 된것이다.

(PRIOR 키워드의 위치를 바꾸어서 실습해보면 이해에 도움이 된다.) 

 

자 이쯤에서 다음으로 넘어가자. 

 

알면 유용한 키워드 LEVEL !

 

필자는 위의 예제에서 LEVEL 키워드 사용예를 위해 LEVEL키워드를 추가하였다.

 

--------------------------------------------------------------------------------

SELECT LPAD(' ' , (LEVEL - 1) * 3 , ' ')  || C.CATE_NAME CATE_HIER , LEVEL CATE_LEVEL
FROM PRT_CATE C
START WITH C.CATE_NAME =
'컴퓨터'
CONNECT BY PRIOR C.NO = C.BASE_CATE_NO;

--------------------------------------------------------------------------------

 

 

결과값>



눈치빠른 독자라면 LEVEL키워드의 쓰임을 알것이다.

 

LEVEL은 오라클에서 실행되는 모든 쿼리내에서 ROWNUM과 더불어 가상-컬럼 이라 할수 있는데,

 

계층적 쿼리 트리내에서 어느한 위치,또는 단계(LEVEL)에 위치하는가를 나타내는 정수값 컬럼이다.

 

 

그렇다면 당근, 계층적 쿼리가 아닌 일반 쿼리에서 LEVEL컬럼의 값이 모두 0 으로 나올것이다. 

 

자, LEVEL키워드를 어디에 사용할까??

 

예를들면 2단계까지의 카테고리 정보만을 출력하라 라는 식의 요구사항일때 유용하다.

 

예상되는 쿼리는

 

WHERE LEVEL < 3 일것같지만 사실 LEVEL키워드는 CONNECT BY절에 위치하여야한다.

 

 

--------------------------------------------------------------------------------

SELECT LPAD(' ' , (LEVEL - 1) * 3 , ' ')  || C.CATE_NAME CATE_HIER , LEVEL CATE_LEVEL
FROM PRT_CATE C
START WITH C.CATE_NAME =
'컴퓨터'
CONNECT BY PRIOR C.NO = C.BASE_CATE_NO AND LEVEL <
3;

--------------------------------------------------------------------------------

 결과값>

 이로써 오라클이 제공하는 고급쿼리중 CONNECT BY 절에 대해 마칠까 한다. 

부족한 강좌 끝까지 읽어주셔서 감사합니다.

SQL
posted by 준치 2008. 11. 14. 15:51

이번 프로젝트에서는 PL/SQL을 주로 사용하게 될 것 같다.

Oracle 잘 모르는데.. ㅜㅜ


우선 기본적인 내용부터 포스팅 해야겠다.


  • 프로시져란...
    특정 작업을 수행할 수 있고, 이름이 있는 PL/SQL 블록으로서, 매개 변수를 받을 수 있고, 반복적으로 사용할 수 있는 언어이다. 보통 연속 실행 또는 구현이 복잡한 트랜잭션을 수행하는 PS/SQL블록을 데이터 베이스에 저장하기 위해서 생성한다.

  •  프로시져 생성

CREATE OR REPLACE 구문을 사용하여 생성한다.

IS 로 PL/SQL의 블록을 시작한다.

LOCAL 변수는 IS와 DEGIN 사이에 선언한다.


CREATE OR REPLACE PROCEDURE name
  IN argument
  OUT argument
  IN OUT argument
IS
  [변수의 선언]
BEGIN   --> 필수
  [PL/SQL Block]
  -- SQL문장, PL/SQL제어 문장
  [EXCEPTION]  --> 선택
  -- error가 발생할 때 수행하는 문장
END;   --> 필수

 Feature 1. Syntax


SQL>CREATE OR REPLACE PROCEDURE update_sal
       /* IN  Parameter */
       (v_empno         IN    NUMBER)
      IS
      BEGIN
      UPDATE emp
      SET sal = sal  * 1.1
      WHERE empno = v_empno;
      COMMIT;
      END update_sal;
      /

프로시져가 생성되었습니다.  

Feature 2. Procedure 작성 예제


위의 예제는 간단한 프로시저의 예이다. 위의 예제는 oracleclub 에서 발최한 내용이다.

먼저 프로시저의 이름은 update_sal이다.
프로시저 update_sal은 사번(v_empno)를 입력받아서 급여를 update시켜주는 sql문이다.
프로시저를 끝마칠때는 항상 "/"를 지정한다.


  • Parameter

실행 환경과 program사이에 값을 주고 받는 역할을 한다.
블록 안에서의 변수와 똑같이 일시적으로 값을 저장하는 역할을 한다.
Parameter의 타입

- IN : 실행환경에서 program으로 값을 전달

- OUT : program에서 실행환경으로 값을 전달

- IN OUT : 실행환경에서 program으로 값을 전달하고, 다시 program에서 실행환경으로 변경된 값을 전달


  •  프로시져 실행

프로시저의 실행은 EXECUTE문을 이용한다.


SQL> execute update_sal(7369);

PL/SQL 처리가 정상적으로 완료되었습니다.

Feature 3. Procedure 실행


실제로 확인해 보면 7369 사번을 가진 사용자의 봉급이 10% 인상되었다.
출처 : http://whitebear.tistory.com/64