종종..어플을 개발하던 어찌하던
필드 하나에 여러개의 필드값을 구분자로 저장해야 하는 경우가 생긴다.

예를들면,
"도서>국내도서>소설" 같이

분류를 나타내야 하는데, 
하위 detph제한 없이 스키마를 구성하려면, 한필드에 구분자를 넣어서 집어 넣는 경우가 생긴다.
물론 이건 자바같은것에선 str.split('>') 같이 사용하면 되지만,

갑자기 1depth, 2depth, 3depth 의 필드로 구분된 뷰를 만들어 달라고 했다면 ???

어찌할것인가? 만약 내부함수만으로 한다면 instr과 substr등이 남발되면서
sql문이 상당히 길어지므로 개인적으론 프로시저(펑션)을 만드는것을 추천한다.

오라클 기준으로 만든 소스...


create or replace
FUNCTION FN_JMC_SPLIT (str IN VARCHAR, del IN VARCHAR,  idx IN INTEGER)
RETURN CHAR IS
/***************************************
abc:de:fghi 를 구분자(:)를
기준으로 idx번째 데이터를 가져옴

만약 해당 데이터가 없다면 null
@make by 정민철
****************************************/
temp_idxst INTEGER; --시작
temp_idxed INTEGER; --끝
temp_leng INTEGER;  --길이
temp_limit INTEGER;
cnt INTEGER;
codersb VARCHAR2(100);
BEGIN
  codersb := '';
  temp_limit := length(str);
  cnt := 0;
  temp_idxst := 1;
  temp_idxed := 1;
 
  for cnt IN 1..idx loop
      temp_idxed := instr(str, del, temp_idxst);
     
      -- 구분자를 찾을수 없을때(마지막데이터임)
      if temp_idxed = 0  then 
        temp_idxed := temp_limit + 1;
      end if;
      temp_leng  := temp_idxed - temp_idxst;
     
      -- 해당 index라면 codersb값을 세팅해줌
      if cnt = idx then
        codersb := substr(str,temp_idxst, temp_leng);
      end if;
     
      -- 시작 index를 갱신
      temp_idxst := temp_idxed + 1;
  end loop;

 
  RETURN codersb;
END FN_JMC_SPLIT;



[결과]

Select FN_JMC_SPLIT('도서>국내도서>소설','>', 1) ... from ....  ==> 도서
Select FN_JMC_SPLIT('도서>국내도서>소설','>', 2) ... from ....  ==> 국내도서
Select FN_JMC_SPLIT('도서>국내도서>소설','>', 3) ... from ....  ==> 소설
Select FN_JMC_SPLIT('도서>국내도서>소설','>', 4) ... from ....  ==> null

특정 테이블(DATA_TBL)에 대해서 트리거를 걸고,
해당 이벤트를 기록하는 테이블(LOG_TBL) 이 존재한다고 할때, 테이블당 하나씩
트리거를 걸면 되므로 심플하게 되는데...

종종 이런로그를 쌓을때, 특정 자료들을 가공해서 써야 할때가 있습니다.

 게시판코드  게시판번호 제목  본문 
 BBS_001  0001  테스트제목1  본문입니다
 BBS_001  0002   테스트제목2~  본문2
 BBS_004  001  어때..이힝  정민철 메롱

다수의 게시판이 아니라,
하나의 게시판에 게시판 코드로 구분되어 만들어 지는 경우...

게시판 코드가 아니라...
BBS_001 , BBS_002, BBS_003 게시판은 ===> 멀티미디어게시판
BBS_004 , BBS_005, BBS_006 게시판은 ===> 텍스트게시판
나머지                                              ===> 기타게시판

뭐 묶음으로 로그를 남긴다고 해야하나??
아니면 분류를 새로 해서 로그를 남긴거나 아무튼 이런겁니다.




[샘플예제]
오라클기준으로 작성하였답니다

> KONAN_TEST (트리거가 걸릴 테이블)
 BBS_CODE  TITLE  BODY
     

> KONAN_TEST_LOG (KONAN_TEST의 로그가 쌓일곳)
 LOGID (로그고유번호 rowid로함)  TABLENAME (해당 테이블명)  EVENT (업데이트, 삽입, 삭제)
     

> kw_logtest

create or replace
TRIGGER kw_logtest
AFTER INSERT OR DELETE OR UPDATE  ON KONAN_TEST
FOR EACH ROW
DECLARE 
    tbl_name VARCHAR2(30) := '';      --테이블명
BEGIN
 
  -- 테이블코드 가져오기
  IF INSERTING THEN
    IF   (UPPER(:new.BBS_CODE) in ('BBS_01', 'BBS_02', 'BBS_03')) THEN
      tbl_name := '게시판1-3';
    ELSIF (UPPER(:new.BBS_CODE) in ('BBS_04', 'BBS_05', 'BBS_06')) THEN
      tbl_name := '게시판4-6'
    ELSE
      tbl_name := '기타게시판';
    END IF;
  ELSE
    IF   (UPPER(:old.BBS_CODE) in ('BBS_01', 'BBS_02', 'BBS_03')) THEN
      tbl_name := '멀티미디어게시판';
    ELSIF (UPPER(:old.BBS_CODE) in ('BBS_04', 'BBS_05', 'BBS_06')) THEN
      tbl_name := '게시판1-3';
    ELSE
      tbl_name := '게시판4-6'
    END IF;
  END IF;
  
 
  --실제로그쌓기
 IF INSERTING THEN
  INSERT INTO KONAN_TEST_LOG(LOGID,TABLENAME, event)
               VALUES(:new.rowid, tbl_name ,'I');
 ELSIF DELETING THEN
  INSERT INTO KONAN_TEST_LOG(LOGID,TABLENAME, event)
                  VALUES(:old.rowid, tbl_name, 'D');
 ELSIF UPDATING THEN 
  INSERT INTO KONAN_TEST_LOG(LOGID,TABLENAME, event)
                  VALUES(:old.rowid,tbl_name, 'U');
 END IF;
END;

[테스트결과]

 단계1.  삽입(Insert)  단계2.  수정(Update)  단계3. 삭제(Delete)
 
 
 

이런식으로 로그테이블에 해당 이벤트와 BBS_CODE가 아닌
재정의한 게시판 1-3 같은내용이 들어가는것!

오라클DB를 설치 안하더라도,
오라클 클라이언트 혹은 instantclient 를 이용해, 오라클DB를 이용하고자 할때,
가장 많이 접하는 문제들입니다

[1] 한글깨짐
sqlplus에서 select문으로 확인해보면
한글이 ??? 같은 물음표로 나온다면 이렇게 설정해보세요

NLS_LANG=AMERICAN_AMERICA.KO16KSC5601
or
NLS_LANG=KOREAN_KOREA.KO16KSC5601

-유닉스 계열은 export NLS_LANG=AMERICAN_AMERICA.KO16KSC5601 식으로 등록하면 되고
(계속 등록해보려면 .profile 수정하시면 됩니당)

-윈도우 계열은
  시스템 등록정보 -> 고급 -> 환경변수(N)에서 시스템 변수에 넣어주시면 됩니다.

[2] TNSNAMES.ORA 설정파일 예제
>> tnsnames.ora파일은 다음과 같은 형식으로 작성되요.
TNS이름 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 아이피)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = 에스아이디 혹은 네임)
    )
  )

[3] 필수 환경변수 관련 내용들
-TNS_ADMIN=tnsnames.ora가있는폴더
예: TNS_ADMIN=C:\instantclient_11

-ORACLE_HOME=오라클이깔린폴더
예: ORACLE_HOME=C:\instantclient_11

대충 이정도면 오라클클라이언트로
select문으로 확인가능한 정도 사용가능합니다.
sqlplus같은경우는
path에 해당폴더를 추가해두면 편하구요.

sqlplus를 통한 접속방법은
$sqlplus id/pass@TNS
이렇게 접속하는건 모두 아시죠?

+ Recent posts