메뉴 건너뛰기

tnt_db

Oracle LENGTH/LENGTHB,SUBSTR/SUBSTRB,INSTR/INSTRB

운영자 2002.09.18 14:04 조회 수 : 4292 추천:13

LENGTH/LENGTHB,SUBSTR/SUBSTRB,INSTR/INSTRB

조건.
    우리가 이미 만들어 놓은 테이블 중 T_MANAGER라는 테이블이 있다.

    UTILITY               MAIN_EMP  SUB1_EMP  SUB2_EMP
    -------------------- --------- --------- ---------
    소방시설                  7366
    전기시설                  7499      7521
    전산장비                  7782
    저장시설                  7698
    수송설비                  8854
    냉방시설                  7566      7654      7844
    수도시설                  7876      7900      7844

문제.
    이번 주제에서 하고자 하는 일은 ORACLE 함수중 STRING과 관련되어
    그 길이를 이용하는 함수중 LENGTH,SUBSTR,INSTR  함수이다.
    그 차이점에 대해서 알아보자.

    SELECT INSTR(UTILITY,'시')  I1,INSTRB(UTILITY,'시')  I2,
           INSTR(MAIN_EMP,4)    I3,INSTRB(MAIN_EMP,4)    I3,  
           SUBSTR(UTILITY,2,2)  S1,SUBSTRB(UTILITY,2,2)  S2,
           SUBSTRB(UTILITY,3,2) S3,SUBSTRB(UTILITY,3,1)  S4,
           SUBSTR(MAIN_EMP,2,1) S5,SUBSTRB(MAIN_EMP,2,1) S6,
           LENGTH(UTILITY)      L1,LENGTHB(UTILITY)      L2,
           LENGTH(MAIN_EMP)     L3,LENGTHB(MAIN_EMP)     L4
    FROM   T_MANAGER;

생각.
    SELECT USERENV('LANGUAGE') FROM DUAL;  

    위의 문장을 실행시키면

    ----------------------------------------------------
    KOREAN_KOREA.KO16KSC5601                            

    처럼 INIT.ORA의 LANGUAGE PARAMETER 로 지정되어 있는 언어가
    리턴된다.
    LANGUAGE PARAMETER가 영문일 경우는 SUBSTR,LENGTH,INSTR 이나
    그 뒤에 B 가 붙으나 똑같은 값을 RETURN하고 DATA가 한글일 경우는
    위의 함수들중 SUBSTR/SUBSTRB 는 깨짐현상이 일어나는 것으로
    알고 있다.
    어쨌든 LANGUAGE PARAMETER 가 한글일 경우 그차이는 분명히 있다.
    위의 8가지 경우에대한 결과 값을 생각해보자.
    INSTR,SUBSTR,LENGTH 는 DATA가 한글이든 영문이든 문자수를 이용해
    처리한다.
    하지만 INSTRB,SUBSTRB,LENGTHB는 한글1자는 2바이트,영문1자는
    1바이트로 처리한다.
    문제의 문장을 수행한 결과가 어떻게 나올지 상상해 보자.
    
해법.

    I1  I2  I3  I3  S1   S2 S3 S4 S5 S6 L1   L2   L3   L4
    --- --- --- --- ---- -- -- -- -- -- ---- ---- ---- ----
      3   5   0   0 방시    방    5   5    4    8    4    4
      3   5   2   2 기시    기    4   4    4    8    4    4
      3   5   0   0 도시    도    8   8    4    8    4    4
      0   0   0   0 산장    산    7   7    4    8    4    4
      3   5   0   0 장시    장    6   6    4    8    4    4
      3   5   0   0 방시    방    5   5    4    8    4    4
      0   0   4   4 송설    송    8   8    4    8    4    4
      3   5   0   0 명시    명    9   9    4    8    4    4

    실행 결과다.
    첫번째 RECORD를 하나씩 분석해 보자.
    INSTR(UTILITY,'시') 는 '소방시설' 에서 '시'가 나타나는 첫번째 자리가
    얼마인가에 대한 답을 요구하고 있다.
    결과는 3 이다. 한글 한자를 1개의 문자로 처리했다는 얘기다.
    반면 INSTRB(UTILITY,'시') 는 어떤가?. 답이 5를 리턴했다.
    한글 1글자를 2개의 바이트로 인식했다는 뜻이다.
    숫자를 이용해 비슷한 요구를 한 I3,I4는 두번째 ROW에서 같은 결과인    
    4를 리턴했다. 영문도 마찬가지다.
    영문/숫자 에서는 INSTR이나 INSTRB 가 같은 결과를 리턴한다는 것을
    알 수 있다.
    LENGTH 와 LENGTHB,SUBSTR 과 SUBSTRB 도 같은 방식이다.
    S2 컬럼 즉 SUBSTRB(UTILITY,2,2)을 보자.
    '소방시설' 에서 바이트 단위로 2번째에서 2자를 요구했다.
    결과는 어떤가?
    NULL이 나왔다. 2바이트가 1개의 글자인 한글에서  
    2번째 바이트 부터의 값을 요구했기 때문에 답을 내줄 수 없었던
    것이다.
    하지만 S3 에서 SUBSTRB(UTILITY,3,2) 와 같이 3번째부터 2개의
    문자를 요구하자
    '방' 이라는 하나의 글자를 RETURN 했다.
    당연한 결과일 것이다.
    S4는 어떤가?.
    한글을 3번째부터 1개의 바이트만 요구하고 있다.
    결과는 물론 NULL이다.
    2바이트가 한개의 문자인 한글을 바이트 단위로 끊어서 결과를
    내 줄수 없다는 것을 알 수 있다.
    한글과 영문에 있어서의 LENGTH와 LENGTHB는 더 이상
    설명하지 않아도 같은 원칙이 적용된다.

뒷풀이.
    아주 사소한 문제 같지만 자주 실수를 하는 부분이며,
    애초에 SUBSTRB,LENGTHB,INSTRB 에 대해서 모르고 있는 경우도
    허다하다.
    그러니 둘의 차이에 대해서 모르는 것은 말할 나위도 없을 것이다.
    알아두면 손해볼 것은 없을 것 같은데...
    반면
    SELECT USERENV('LANGUAGE') FROM DUAL;  
    을 실행 했을때
    AMERICAN_AMERICA.US7ASCII
    처럼 영문 PARAMETER로 지정된경우를 보자.

    SELECT INSTR(UTILITY,'시') I1,INSTRB(UTILITY,'시') I2,
           SUBSTR(UTILITY,2,2) S1,SUBSTRB(UTILITY,2,2) S2,
           LENGTH(UTILITY) L1,LENGTHB(UTILITY) L2
    FROM T_MANAGER
    
    를 실행하면 아래의 결과가 나온다.

           I1        I2 S1 S2        L1        L2
    --------- --------- -- -- --------- ---------
            5         5 拈 拈         8         8
            5         5 ??nbsp;        8         8
            0         0 ??nbsp;        8         8
            5         5 ??nbsp;        8         8
            0         0 梔 梔         8         8
            5         5 첫 첫         8         8
            5         5 層 層         8         8
위로