메뉴 건너뛰기

tnt_db

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

운영자 2002.09.18 14:04 조회 수 : 4050 추천: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
번호 제목 글쓴이 날짜 조회 수
» LENGTH/LENGTHB,SUBSTR/SUBSTRB,INSTR/INSTRB 운영자 2002.09.18 4050
85 PARAMETER값 변경에따른 유연한 GROUP BY 운영자 2002.09.18 4040
84 최대값과 최소값을 뺀 평균 운영자 2002.09.18 3941
83 한번 읽은 테이블로 백분율 구하기 운영자 2002.09.18 3834
82 plan table(sql실행계획) 보는 select문 운영자 2003.01.28 3831
81 다중 Row 결과를 단일행으로 컴마로 분리해 출력하는 방법 (2) 박상현 2006.06.13 3816
80 sybase DB에서 파일로 백업을 받구 그파일을 다시 DB2로 임포트하는방법 원우석 2004.07.31 3748
79 특정문자까지의 왼쪽 문자열 반환 function 운영자 2002.10.18 3743
78 row데이터 연결하여 조회 구퍼 2009.03.31 3663
77 년중 몇번째 주간인지 알아내기(FUNCTION) - ORACLE이 제공하는 것과 다름 운영자 2002.09.17 3630
76 최단거리찾기 혹은 멀리 떨어진 두지점간의 거리의 합구하기 박상현 2006.11.07 3608
75 다수 NULL 허용 COLUMN의 명칭을 가져올때 운영자 2002.09.18 3572
74 문자열 행으로 분리하기 박상현 2006.06.13 3552
73 다중 Row 결과를 단일행으로 컴마로 분리해 출력하는 방법 (1) 박상현 2006.06.13 3537
72 복제를이용한 합계계에서 비율계산 운영자 2002.09.18 3534
71 RECORD단위 DATA를 COLUMN단위로 운영자 2002.09.18 3507
70 sql 문 실행명령 원우석 2004.07.31 3500
69 최대공약수, 최소공배수 구하기 박상현 2006.06.13 3479
68 PL/SQL에서 쿼리시 Array Processing 처리방법 박상현 2006.10.27 3469
67 반올림 DATA의 오차보정 운영자 2002.09.18 3463
위로