2014년 10월 31일 금요일

MYSQL CONNECT BY 예제

MYSQL에서 CONNECT BY를 구현하는 방법 중 함수를 만들어서 구현하는 방법이 있다.

CONNECT BY를 사용하기 위한 함수는 해당 테이블에서만 사용 가능한 함수이다.



DROP FUNCTION IF EXISTS DEV_UCI_DB.FN_CONNECT_BY_ROOT_MTTR;
CREATE FUNCTION DEV_UCI_DB.`FN_CONNECT_BY_ROOT_MTTR`(v_no INT) RETURNS int(11)
    READS SQL DATA
BEGIN
        DECLARE v_mttr_iem_no INT;
        DECLARE v_upper_mttr_iem_no INT; -- 부모 항목
        DECLARE v_count INT;
        SET v_mttr_iem_no := v_no;
        SET v_count := 0;
       
        IF v_mttr_iem_no IS NULL THEN
                RETURN NULL;
        END IF;
        LOOP
                SELECT UPPER_MTTR_IEM_NO
                  INTO v_upper_mttr_iem_no
                  FROM TN_MM_MTTR_IEM_I
                 WHERE MTTR_IEM_NO = v_mttr_iem_no;
                IF v_upper_mttr_iem_no = 0 THEN
                        RETURN v_mttr_iem_no;
                END IF;
                SET v_mttr_iem_no := v_upper_mttr_iem_no;
                SET v_count := v_count + 1;
               
                IF v_count >= 10 THEN
                  RETURN 0;
                END IF;
        END LOOP;
END;

함수를 이용해서 CONNECT BY 기능을 구현할 수 있다.

SELECT A.MTTR_IEM_NM -- 물질 항목 명
     , A.MTTR_IEM_NO -- 물질 항목 번호
     , A.UPPER_MTTR_IEM_NO -- 상위 물질 항목 번호
     , LEVEL
     , (SELECT COUNT(*) C_CNT
          FROM TN_MM_MTTR_IEM_D
         WHERE MTTR_ID = '91235'
           AND MTTR_IEM_NO = A.MTTR_IEM_NO
           AND USE_AT = 'Y'
       ) C_CNT  -- 항목 내용 결과 수
     , (SELECT COUNT(*) I_CNT
          FROM TN_MM_MTTR_IEM_I
         WHERE UPPER_MTTR_IEM_NO = A.MTTR_IEM_NO
           AND USE_AT = 'Y'
               LIMIT 1
       ) I_CNT  -- 상위 물질 항목 번호 수 (0이면 최하위 항목)
  FROM (
       SELECT CONCAT(REPEAT('   ', LEVEL - 1) , CAST(B.MTTR_IEM_NM AS CHAR)) AS MTTR_IEM_NM
            , B.MTTR_IEM_NO
            , LEVEL
            , B.UPPER_MTTR_IEM_NO
         FROM (
              SELECT FN_CONNECT_BY_MTTR(MTTR_IEM_NO) AS UPPER_MTTR_IEM_NO
                   , MTTR_IEM_NO
                   , @LEVEL AS LEVEL
                FROM (
                     -- 0 : 전체, 1 : 기본정보, 87 : 위험유해성정보, 200 : 법규 규제 정보, 229 : INVENTORY, 484 : 안전관리정보, 539 : 측정방법
                     SELECT @START_WITH := 1 -- 2단계 표준항목 번호 (파라미터)
                          , @ID := @START_WITH
                          , @LEVEL := 0
                     ) VARS
                   , TN_MM_MTTR_IEM_I -- 물질관리 물질 항목 정보엔티티
              WHERE @ID IS NOT NULL
                AND USE_AT = 'Y'
              ) A
              JOIN TN_MM_MTTR_IEM_I B -- 물질관리 물질 항목 정보엔티티
                ON A.UPPER_MTTR_IEM_NO = B.MTTR_IEM_NO
       ) A
;

-- CONNECT BY ROOT

DROP FUNCTION IF EXISTS DEV_UCI_DB.FN_CONNECT_BY_ROOT_MTTR;
CREATE FUNCTION DEV_UCI_DB.`FN_CONNECT_BY_ROOT_MTTR`(v_no INT) RETURNS int(11)
    READS SQL DATA
BEGIN
        DECLARE v_mttr_iem_no INT;
        DECLARE v_upper_mttr_iem_no INT; -- 부모 항목
        DECLARE v_count INT;
        SET v_mttr_iem_no := v_no;
        SET v_count := 0;
       
        IF v_mttr_iem_no IS NULL THEN
                RETURN NULL;
        END IF;
        LOOP
                SELECT UPPER_MTTR_IEM_NO
                  INTO v_upper_mttr_iem_no
                  FROM TN_MM_MTTR_IEM_I
                 WHERE MTTR_IEM_NO = v_mttr_iem_no;
                IF v_upper_mttr_iem_no = 0 THEN
                        RETURN v_mttr_iem_no;
                END IF;
                SET v_mttr_iem_no := v_upper_mttr_iem_no;
                SET v_count := v_count + 1;
               
                IF v_count >= 10 THEN
                  RETURN 0;
                END IF;
        END LOOP;
END;

ERWIN에서 MYSQL SCRIPT 생성시 COMMENT 생성하는 방법

Physical > Database > Pre & Post Scipts 에서 아래 코드 입력

%ForEachTable()
{
 alter TABLE %TableName COMMENT = '%EntityName';

 %ForEachColumn()
 {       
ALTER TABLE %TableName CHANGE COLUMN %ColName %ColName %AttDatatype %AttNullOption COMMENT '%AttName';
 }
}


Tools > Forwoard Engineer > Schema Generation > Schema > Post-Script 선택

2013년 12월 12일 목요일

테이블 변경 중인 락 확인

-- 락 확인

SELECT CC.SID,CC.SERIAL#
     , BB.OWNER,BB.OBJECT_NAME
     , CC.MACHINE
     , CC.PROGRAM
     , CC.TERMINAL
     , DD.SPID BG_PID
     , CC.PROCESS FG_PID
  FROM V$LOCKED_OBJECT AA
     , ALL_OBJECTS BB
     , V$SESSION CC
     , V$PROCESS DD
 WHERE BB.OBJECT_ID = AA.OBJECT_ID
   AND CC.SID = AA.SESSION_ID
   AND CC.PADDR = DD.ADDR
;
-- KILL

ALTER SYSTEM KILL SESSION '921,3217';

SELECT * FROM V$SESSION WHERE SID='921';

-- 롤백시 남은 레코드및 블럭수
--USED_UBLK(사용된 언두 블럭) USED_UREC(사용된 언두 레코드)
SELECT S.SID
     , S.MACHINE
     , R.NAME ROLLNAME
     , T.USED_UBLK USED_UBLK
     , T.USED_UREC
  FROM V$SESSION S
     , V$ROLLNAME R
     , V$TRANSACTION T
 WHERE S.SADDR=T.SES_ADDR
   AND T.XIDUSN=R.USN
 --AND USED_UBLK > 10
 --AND R.NAME IN ('R18')
   AND S.SID = '921'
 ORDER BY USED_UBLK
;

오라클 테이블스페이스 확인

-- 테이블스페이스 용량 확인

SELECT A.TABLESPACE_NAME
     , ROUND(SUM(A.BYTES) / (1024 * 1024 * 1024), 2) || 'G' "전체"
     , ROUND(SUM(B.FREES) / (1024 * 1024 * 1024), 2) || 'G' "여유"
  FROM ( SELECT FILE_ID, TABLESPACE_NAME, SUM(BYTES) BYTES
            FROM DBA_DATA_FILES
          GROUP BY FILE_ID, TABLESPACE_NAME
       ) A
     , ( SELECT TABLESPACE_NAME, FILE_ID, SUM(BYTES) FREES
           FROM DBA_FREE_SPACE
          GROUP BY TABLESPACE_NAME, FILE_ID
       ) B
 WHERE A.TABLESPACE_NAME = B.TABLESPACE_NAME
   AND A.FILE_ID = B.FILE_ID
--   AND A.TABLESPACE_NAME LIKE 'SP_FMC%'
 GROUP BY A.TABLESPACE_NAME;
;

-- 테이블스페이스 데이터 파일 용량 확인

SELECT A.TABLESPACE_NAME                                    "테이블스페이스명"
     , ROUND((A.BYTES - B.FREE) / (1024 * 1024 * 1024), 2)  "사용공간"
     , ROUND(B.FREE / (1024 * 1024 * 1024),2)               "여유 공간"
     , ROUND(A.BYTES / (1024 * 1024 * 1024),2)              "총크기"
     , TO_CHAR((B.FREE / A.BYTES * 100) , '999.99')||'%'    "여유공간"
  FROM ( SELECT FILE_ID,
                TABLESPACE_NAME,
                SUBSTR(FILE_NAME,1,200) FILE_NM,
                SUM(BYTES) BYTES
           FROM DBA_DATA_FILES
          GROUP BY FILE_ID,TABLESPACE_NAME,SUBSTR(FILE_NAME,1,200)
       ) A,
       ( SELECT TABLESPACE_NAME,
                FILE_ID,
                SUM(NVL(BYTES,0)) FREE
           FROM DBA_FREE_SPACE
          GROUP BY TABLESPACE_NAME,FILE_ID
       ) B
 WHERE A.TABLESPACE_NAME=B.TABLESPACE_NAME
   AND A.FILE_ID = B.FILE_ID
   AND A.TABLESPACE_NAME = 'SP_AS_AORM_DB'
;

2010년 10월 28일 목요일

한자를 공부하는 방법

1.한자 교재,입문서에 대한 설명
  1) 천자문(千字文)
    a. 중국 양(梁)나라의 주흥사(周興嗣)가 무제(武帝)의 명으로 지은 책.
    b. 1구 4자로 250구, 모두 1,000자로 된 고시(古詩)이다.
    c. 하룻밤 사이에 이 글을 만들고 머리가 허옇게 세었다고 하여 ‘백수문(白首文)’이라고도 한다.
    d. 한자를 배우는 입문서

 2) 사자소학(四字小學)
    a. 우리나라에서 편찬(編纂)된 『사자소학(四字小學)』은  송나라 학자 주희가 짓고  유자징이 편찬했던 『소학(小學)』을 바탕으로 하여 엮은 책(冊)임.
    b. 소학과 기타 경전의 내용을 알기 쉽게 생활한자로 편집한 한자의 입문서
    c. 어린이들이 실천할 수 있는 소중한 행동 철학을 4자씩 묶어서 한자와 한문의 기초과정을 위하여 만든 내용으로 실천 중심의 간결한 문구로 되어 있습니다.
    d. 한국에서는 조선 초기부터 중요하게 다루어져 사학(四學)·향교·서원·서당 등 모든 유학 교육기관에서 필수과목.
    e. 조선시대 사대부의 8세 전후의 아이들이 배우던 수신서(修身 書)  이며
       유학의 초보로 배워 조선시대의 충효사상을 중심으로 한 유교적 윤리관을 보급하는 데 큰 기여를 했다.
    f. 사자소학은
         첫째 부모에 대한 효도  '효행(孝行)'편
         둘째 부부와 형제의 우애 '부부/형제(夫婦/兄弟)'편
         셋째 스승과 제자의 도리 '사제(師弟)'편
         넷째 친구사이의 의리 '붕우(朋友)'편
         다섯째 스스로의 몸가짐과 수양  '수신(修身)'편
      으로 나누었다.
    g. 현재 통용되고 있는 책은 네 글자의 구절 256개와 1024자 본과, 320구절 1280자 본, 그리고 400구절에 1600자 본이 있습니다.

 3) 명심보감(明心寶鑑)
   a. 고려 충렬왕 때의 문신(文臣) 추적(秋適)이 금언(金言), 명구(名句)를 모아 놓은 책.
   b. "마음을 밝히는 보배로운 거울"이란 뜻의 명심 보감은 인간의 일상 생활에 필요한 격언과 윤리도덕 및 처세에 관한 예지와 자기 수양의 방도를 수록한 교양필독서이다.
   c. 원래 19편으로 되어 있었으나 후에 어떤 학자가 증보(增補), 팔반가(八反歌), 효행(孝行), 염의(廉義), 권학(勸學) 등 5편을 더하여 총 24편으로 구성되어 있다.

 4) 소학(小學)
   a. 중국(中國) 송(宋)나라 유학자(儒學者) 주희(朱熹)가 짓고  그 제자(弟子) 劉子澄(유자징)이 이어서 편찬(編纂)한 초학 교재(敎材).
   b. 內篇(내편)ㆍ外篇(외편) 모두 6편으로 되어 있다.
       내편은 立敎(입교)ㆍ明倫(명륜)ㆍ敬身(경신)ㆍ稽古(계고)로 나뉘고
       외편은 嘉言(가언)ㆍ善行(선행)으로 나뉘어 있다.
   c.孝(효)ㆍ弟(제)ㆍ忠(충)ㆍ信(신) 등(等) 사람의 도리(道理)와 수신의 절차(節次)가 기록(記錄)되어 있음

 5) 사서오경(四書五經) 또는 사서삼경(四書三經)
   a. 유교의 경전으로, 경전 중에 가장 핵심적인 책이다.
   b. 고대 중국의 자연현상 및 사회생활의 기록이며, 제왕의 정치, 고대의 가요, 가정생활, 공자가 태어난 노(魯)나라 역사 등의 기록이다.
   c. 사서는 논어(論語),맹자(孟子),대학(大學),중용(中庸)을 말한다.
      삼경은 시경(詩經),서경(書經),역경(易經)을 말한다.
      삼경에 춘추(春秋),예기(禮記)  합해 오경이라 부르고, 합해서 사서오경이라 부른다.

2.예전 서당에 한자 학습의 순서
   1) 입문 : 천자문,유합,사자소학,추구
   2) 초급 : 계몽편 ,동몽선습,격몽요결,명심보감
   3) 중급 : 소학,십팔사략,통감절요
   4) 고급 : 대학,논어,맹자,중용, 시경,예기,서경,역경,춘추

   ※ 초급 '명심보감'까지가 한문독해력의 50% 완성이고 고급 '중용'까지 하면 한문독해력의 거의대부분을 할수 있고 그 이후는 고문의 격식과 아름다움을 공부하게 된다.

한자란 무엇인가?

1.한자의 발생
    1) 한자는 창힐이라는 사람이 사물의 모양이나 새와짐승의 발자국을 본떠 한자를 만들었다는 기록이 있다.
   2) 그러나 창힐에 대하여 세 가지의 설로 나누어져 있다.
        첫째는 창힐을 상고의 제왕(帝王)으로 보는 견해,
        둘째는 황제(黃帝)의 사관(史官)으로 보는 견해,
        셋째는 시대의 의인화(擬人化)로 보는 견해인데,
     이 중에서 황제의 사관으로 보는 둘째 견해가 널리 알려진 것이다.
   3) 실존하는 자료로서 가장 오래된 문자는 1903년 은허(殷墟)에서 출토된
        은대(殷代)의 갑골문자(甲骨文字)가 있다.
   4) BC 14세기∼BC 12세기에 사용된 것으로 추정되는 이 문자는 당시의 중대사(重大事)를
        거북의 등이나 짐승 뼈에 새겨 놓은 실용적인 것이었다
2.한자의 특성
  한자는 글자마다 어떤 뜻을 가지고 있는 '뜻 글자','표의문자' 이다.
  한자는 사물의 모양을 본떠 만든 글자이기 때문에 글자마다 그 뜻을 가지고 있다.

3.한자 3요소
  한자는 모양(형태),뜻(훈),소리(음) 의 3요소를 가지고 있다.

4.한자 형성과정에 따른 분류
  1) 상형문자 : 한자의 가장 처음 형태로, 자연이나 사물의 생김새를 흉내내서 만든 글자.
                예) 뫼 산(山), 내 천(川), 새 조(鳥)
 2) 지사문자 : 추상적인 대상을 기호화
                예) 상(上)과 끝 말(末)
 3) 회의문자 :  두 개 이상의 한자를 모아서 새로운 뜻을 만든 글자
                예) 사람(人)과 말(言)을 합하여 사람의 말은 중요하다는 믿을 신(信)자를 만들었다.
 4) 형성문자 : 형태(形)와 소리(聲)를 적절히 합하여 새로운 뜻을 갖는 글자를 만든 것
                예) 간(肝)은 신체 등을 뜻하는 고기 육(肉, 변에서는 月(육달월)처럼 쓰인다) 자  와 같은 발음을 갖는 방패 간(干)을 합한 것이다.
 5) 전주문자 : 한자의 널리 쓰이는 뜻이 시대가 바뀌어 더 확장된 뜻을 갖는 글자이다.
 6) 가차문자 : 뜻은 생각하지 않고 음만 빌려 쓴 것을 말한다.

5.한자를 쓰는 순서(필순)
    1) 위에서 아래로 쓴다.  三 (석 삼)
   2) 왼쪽에서 오른쪽으로 쓴다. 川 (내 천)
   3) 가로획,세로획이  교차때는 가로획을 먼저 쓴다. 十(열 십)
   4) 좌우대칭일때,가운데 획을 먼저 쓴다  小(적을 소)
   5) 가운데를 꿰뚫는 세로획은 맨 나중에 쓴다  中(가운데 중)
   6) 안쪽을 둘러싼 몸(둘레)이 있을때는 몸을 먼저 쓴다.  同(한가지 동)
   7) 삐침을 먼저 쓰고 파임을 나중에 쓴다. 文(글월 문)
   8) 좌우로 꿰뚫는 가로획은 맨 나중에 쓴다. 女(계집녀)
   9) 아래를 에운 획은 나중에 쓴다. 也(어조사 야)
   10) 삐침은 먼저 쓰는 것과 나중에 쓰는 것이 있다.
        먼저 쓰는 것-가로획이 길고 왼쪽 삐침이 짧으면 왼쪽 삐침부터 쓴다.  九(아홉 구)
        나중에 쓰는것-가로획이 짧고 왼쪽 삐침이 길면 가로획부터 쓴다. 力(힘 력)
   11) 오른쪽 위의 점은 맨 나중에 쓴다. 犬(개견)
   12) 받침은 맨 나중에 쓴다. 近(가까울 근)

6.한자의 부수
 1) 한자의 여러 글자에 같이 쓰이는 기본글자이다.
 2) 모두 214개의 부수 글자가 있는데 위치에 따라 7가지로 이름이 바뀐다.
    - 변 : 부수가 왼쪽에 있을때 海(바다 해)
    - 방 : 부수가 오른쪽에 있을때 朝(아침 조)
    - 머리 : 부수가 위에 있을때  安(편안 안)
    - 엄호 : 부수가 위와 왼쪽을 싸고 있을때  病(병들 병)
    - 받침 : 부수가 왼쪽과 밑에 있을때. 道(길 도)
    - 발 : 부수가 밑에 있을때 忠(충성 충)
    - 몸 : 전체를 에워 쌀때 國(나라 국)
      몸 : 옆쪽으로 에워 쌀때 區(구역 구)
      몸 : 위쪽으로 에워 쌀때  間(사이 간)
      몸 : 좌우로 에워 쌀때 術(재주 술)

데이터타입의 중요성

오라클에서 테이블 생성시 무엇보다 중요한 부분인 데이터타입이 그 중요성만큼 깊은 고려의 대상인 아닌것 같습니다.

많은 개발자들이 그냥 NUMBER 타입을 선언하는 경우도 있고, 코드성의 숫자 형태를 무심코 VARCHAR2로 선언하는 경우도 있습니다.

이렇듯 테이블 생성시 컬럼의 데이터타입을 단순 데이터가 들어가면 된다라는 식으로 선언을 함으로써 데이터베이스 성능에 심각한 문제를 초래할 수 있는 테이블을 생성하고 있는 것을 많이 보았습니다.

데이터타입의 중요성에 앞서 VARCHAR 과 VARCHAR2의 차이점에 대해서 알아보겠습니다.

결과적으로는 VARCHA 과 VARCHAR2 는 아무런 차이가 없습니다. 모두가 4000 자까지 입력이 됩니다.

그럼 왜 오라클에서는 VARCHAR 이 있는데, VARCHAR2 를 만들었을가요? 그것은 ANSI SQL 에서 아직 VARCHAR 에 대한 정의를 내리지 못했기 때문입니다.

이말을 좀 풀어보겠습니다.

만약에 프로그램에서 4000자까지 입력을 받을 수 있는 항목이 있었습니다. 그리고 이 컬럼을 VARCHAR 로 선언을 했습니다.

그런데 ANSI SQL에서 VARCHAR 타입을 2000자 까지로 정한다라고 하면, 오라클에서 이후 버전에서는 VARCHAR 를 2000자 까지로 바꿔야 합니다.

그럼 VARCHAR 타입으로 선언을 한 테이블을 가진 프로그램이 오라클 상위버전으로 변환시 VARCHAR로 선언된 곳에서 에러가 발생한다는 것입니다.

이러한 이유로 오라클에서는 ANSI SQL에서 VARCHAR이 정해지지 전까지는 VARCHAR2를 사용하라는 겁니다.

ANSI SQL에서 VARCHAR를 정한다 하더라도 오라클에서는 VARCHAR2 에 대해서는 바꾸지 않을 것이기 때문입니다.

그럼 데이터타입에 대해서 자세히 알아보겠습니다.

간단히 숫자로 된 데이터를 VARCHAR2로 선언하는 것과 NUMBER로 선언했을 경우의 차이를 알아보겠습니다.

우선 NUMBER 타입은 아무런 값없이 그냥 NUMBER로 선언을 하면 NUMBER(22)로 선언되게 되어 있습니다.

그러므로 NUMBER 타입을 선언시 길이를 선언하는 것이 좋다고 보고, NUMBER 은 최대 38까지 선언 가능합니다.

그럼 VARCHAR2와 NUMBER 타입의 실제 길이에 대해서 알아보겠습니다.

어떤 컬럼에 데이터가 숫자의 형태로만 들어간다고 했을때 그 값이 1234567890 로 10개의 숫자 형태로 들어간다면 이 컬럼의 데이터 타입을 VARCHAR2 와 NUMBER 의 차이는 실제 데이터의 길이에서 차이가 납니다.

우선 VARCHAR2로 선언을 했을 경우 길이만큼인 10 BYTE 길이의 데이터가 들어가게 됩니다.

NUMBER로 선언을 했다면 10/2+1 인 6 BYTE 길이로 데이터가 들어갑니다.

두 타입의 차이로 4 BYTE 의 차이가 발생합니다. 이것이 별 차이가 없을 수도 있습니다.

하지만 데이터가 대용량으로 저장이 된다면, 만약 1000만건의 데이터가 저장이 된다면, 이 하나의 컬럼만으로도 40,000,000 BYTE 의 저장공간이 차이가 납니다.

다시 말해서 데이터 컬럼하나로 인해서 약 40M 의 저장공간이 차이가 난다는 것입니다.

이러한 이유로 데이터베이스의 테이블 설계시 컬럼의 데이터타입은 무엇보다 중요하다 할 수 있습니다.

그러므로 테이블 설계시 컬럼에 대한 데이터타입을 좀더 신중히 효율적으로 선언해야 합니다.