정규식(Regular Expression) 함수


SQL 문장에서도 유닉스에서 사용하는 정규식을 사용해 다양한 검색을 할 수 있다. 정규식은 다양한 메타 문자들을 사용해 검색방법을 확장한것. 유닉스 버전마다 조금씩 다를 수 있지만 주로 사용하는 정규식 방법은 아래와 같다


정규 표현식

^ (캐럿)

    해당 문자로 시작하는 line 출력

‘^pattern’

$ (달러) 

    해당 문자로 끝나는 line 출력

‘pattern$’

    S로 시작하여 E으로 끝나는 line ( . =1 character)

‘S . . . .E ’

*

    모든 이라는 뜻, 글자수가 0 일수도 있음

‘[a–z]*’

[ ]

    해당 문자에 해당하는 한 문자

‘[Pp]attern’

[ ^ ]

    해당 문자에 해당하지 않는 한 문자

‘[^a–m]attern’



[:문자클래스:] : alpha, blank, cntrl, digit, graph, lower, print, space, uppper, xdigit




연습용 테이블 확인

SCOTT>SELECT * FROM t_reg;

TEXT
----------
ABC123
ABC 123
ABC  123
abc 123
abc  123
a1b2c3
aabbcc123
?/!@#$*&
\~*().,
123123
123abc
abc


1. REGEXP_LIKE 함수

like 함수처럼 특정 패턴과 매칭되는 결과를 검색


사용예

  • 영문자가 들어가 있는 행만 출력하기

    • 소문자, 대문자, 대소문자가 들어가있는 행을 출력하는 예

      SCOTT>SELECT * FROM treg 2 WHERE REGEXP_LIKE(text, '[a-z]');
      TEXT ---------- abc 123 abc 123 a1b2c3 aabbcc123 123abc abc
      SCOTT>SELECT * FROM treg 2 WHERE REGEXP_LIKE(text, '[A-Z]'); // '[[:upper:]]' 와 같은결과
      TEXT ---------- ABC123 ABC 123 ABC 123
      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '[a-zA-Z]');
      TEXT ---------- ABC123 ABC 123 ABC 123 abc 123 abc 123 a1b2c3 aabbcc123 123abc abc

  • 영문자로 시작하고 공백을 포함하는 경우

    • 소문자로 시작, 뒤에 공백이 있는 경우
      SCOTT>SELECT * FROM treg
      2  WHERE REGEXP_LIKE(text, '[a-z] '); //소문자로 시작, 뒤에 공백이 있는 모든 행을 출력
      TEXT ---------- abc 123 abc 123
      SCOTT>SELECT * FROM treg 2 WHERE REGEXP_LIKE(text, '[a-z] [0-9]'); //소문자로 시작, 공백이 1칸있고 숫자로 끝나는 모든 행을 출력
      TEXT ---------- abc 123
      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '[[:space:]]'); //공백이 있는 데이터를 모두 출력
      TEXT ---------- ABC 123 ABC 123 abc 123 abc 123
  • 연속적인 글자 수 지정하기

    • 대문자가 연속적으로 2글자 이상 오는 경우 출력

      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '[A-Z]{2}');
      TEXT ---------- ABC123 ABC 123 ABC 123


    • 영어대문자 다음에 숫자가 함께 오는데 영어대문자와 숫자가 각각 3글자 오는 행 출력

      SCOTT>SELECT * FROM treg 2 WHERE REGEXP_LIKE(text, '[A-Z][0-9]{3}');
      TEXT -------- ABC123
      SCOTT>SELECT * FROM treg 2 WHERE REGEXP_LIKE(text, '[0-9][A-Z]{3}'); no rows selected

  • 특정 위치를 지정하여 출력

    • 시작되는 문자 지정 : ^(캐럿) cf.대괄호 안에 있는 캐럿은 NOT의 의미.
      SCOTT>SELECT * FROM treg
      2  WHERE REGEXP_LIKE(text, '^[A-Za-z]'); // 대문자나 소문자로 시작하는 행 출력 
      TEXT ---------- ABC123 ABC 123 ABC 123 abc 123 abc 123 a1b2c3 aabbcc123 abc
      SCOTT>SELECT * FROM treg 2 WHERE REGEXP_LIKE(text, '^[0-9A-Z]'); // 숫자나 대문자로 시작하는 행 출력
      TEXT ---------- ABC123 ABC 123 ABC 123 123123 123abc
      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '^[a-z]|^[0-9]'); // 소문자나 숫자로 시작하는 행 출력 (여러조건을 줄때 바(|) 기호사용해 연결가능)
      TEXT ---------- abc 123 abc 123 a1b2c3 aabbcc123 123123 123abc abc
    • 끝나는 문자 지정 : $(달러)

      SCOTT>SELECT name, id 2 FROM student 3 WHERE REGEXP_LIKE(id, '^M(a|o)'); // M으로 시작하고 두번째가 a나 o가 나오는 id 출력
      NAME ID ------------------------------ -------------------- Demi Moore Moore Steve Martin Martin
      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '[a-zA-Z]$'); // 소문자나 대문자로 끝나는 행 출력 , = '[[:alpha:]]$'
      TEXT ---------- 123abc abc

    • 대괄호안에 있는 ^(캐럿): NOT의 의미.

      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '^[^a-z]'); // 소문자로 시작하지 않는 행을 출력
      TEXT ---------- ABC123 ABC 123 ABC 123 ?/!@#$*& \~*()., 123123 123abc
      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '^[^0-9a-z]'); // 숫자나 소문자로 시작하지 않는 행 출력
      TEXT ---------- ABC123 ABC 123 ABC 123 ?/!@#$*& \~*().,
      SCOTT>SELECT * FROM t_reg 2 WHERE REGEXP_LIKE(text, '[^a-z]'); //위치와 상관없이 소문자만 들어 있는 행을 제외하고 모두 출력
      TEXT ---------- ABC123 ABC 123 ABC 123 abc 123 abc 123 a1b2c3 aabbcc123 ?/!@#$*& \~*()., 123123 123abc //t_reg 테이블의 맨 아랫줄 abc 행이 제외됨.
      SCOTT>SELECT * FROM t_reg 2 WHERE NOT REGEXP_LIKE(text, '[a-z]'); // 소문자가 들어간 모든 행을 제거하고 모두 출력
      TEXT ---------- ABC123 ABC 123 ABC 123 ?/!@#$*& \~*()., 123123


    • 다른여러 예들.

      SCOTT>SELECT name, tel 2 FROM student 3 WHERE REGEXP_LIKE(tel, '^[0-9]{2}\)[0-9]{4}'); //지역번호가 2자리고 국번이 4자리가 나오는값 출력
      NAME TEL ----------------------------- --------------- Demi Moore 02)6255-9875 Richard Dreyfus 02)6788-4861 Steve Martin 02)6175-3945 Anthony Hopkins 02)6122-2345
      SCOTT>SELECT name, id 2 FROM student 3 WHERE REGEXP_LIKE(id, '^...r..'); // 넷째 자리에 r이 있는 행을 출력
      NAME ID ------------------------------ -------------------- James Seo 75true Bill Murray Murray
      SCOTT>SELECT * FROM t_reg2 2 WHERE REGEXP_LIKE(ip, '^[172]{3}\.[16]{2}\.[168]{3}'); // 아래의 결과와 같이 대괄호 안의 숫자의 순서와는 상관없이 해당 숫자가 있는 행은 모두 출력됨.
      NO IP ---------- -------------------- 4 172.61.186.2 5 172.61.168.2

  • 특정 조건을 제외한 결과 출력하기

    • ex) 영문자(대소문자)를 포함하지 않는 모든행 출력
      SCOTT>SELECT * FROM t_reg
      2  WHERE NOT REGEXP_LIKE(text, '[a-zA-Z]');
      TEXT ---------- ?/!@#$& \~()., 123123

  • 특수문자 찾기 : ? 나 * 이 포함된 행을 출력할경우 탈출문자(\)를 사용하면됨.



  • 2. REGEXP_REPLACE 함수

    Replace 함수를 확장한 개념으로 주어진 문자열에서 특정 패턴을 찾아서 주어진 다른 형태로 치환하는 함수.

     문법: REGEXP_REPLACE(source_char, pattern
                        [, replace_string
                        [, position
                        [, occurrence
                        [, match_param]]]]
                        ) 
    
  • Source : 원본 데이터, 컬럼명이나 문자열이 오고 데이터 타입은 CHAR, VARCHAR2, NCHAR, NVARCHAR2, CLOB, NCLOB 가 올 수있다.
  • pattern : 찾고자 하는 패턴, 512byte까지의 정규 표현식을 사용, 데이터 타입은 CHAR, VARCHAR2, NCHAR, NVARCHAR2 가 올 수 있다.
  • replace_string : 변환 하고자 하는 형태.
  • position : 검색 시작위치 (default:1)
  • occurrence : 패턴과 일치가 발생하는 횟수. 0은 모든 값을 대체하고 다른 n 이란 숫자를 주면 n번째 발생하는 문자열을 대입.
  • match_parameter : 기본값으로 검색되는 옵션을 바꿀수 있다.
    • -c: 대소문자 구분해서 검색
    • -i : 대소문자 구분않고 검색
    • -m : 검색조건을 여러줄로 줌.

  • 사용예

    • ex1) 예제 테이블 t_reg에서 숫자부분을 '*' 기호로 전부 변경

    SCOTT>SELECT text, REGEXP_REPLACE(text, '[[:digit:]]', '*') "NO -> CHAR" 2 FROM t_reg;
    TEXT NO -> CHAR ---------- -------------------- ABC123 ABC*** ABC 123 ABC *** ABC 123 ABC *** abc 123 abc *** abc 123 abc *** a1b2c3 a*b*c* aabbcc123 aabbcc*** ?/!@#$*& ?/!@#$*& \~*()., \~*()., 123123 ****** 123abc ***abc abc abc

    • ex2) 특정 패턴 찾아서 변경하기
    SCOTT>SELECT text,
      2          REGEXP_REPLACE(text, '([0-9])', '\1-*') "Add Char" //숫자뒤에 -* 붙이기
      3  FROM t_reg;
    TEXT Add Char ---------- ------------------------------ ABC123 ABC1-*2-*3-* ABC 123 ABC 1-*2-*3-* ABC 123 ABC 1-*2-*3-* abc 123 abc 1-*2-*3-* abc 123 abc 1-*2-*3-* a1b2c3 a1-*b2-*c3-* aabbcc123 aabbcc1-*2-*3-* ?/!@#$*& ?/!@#$*& \~*()., \~*()., 123123 1-*2-*3-*1-*2-*3-* 123abc 1-*2-*3-*abc abc abc

    SCOTT>SELECT text, 2 REGEXP_REPLACE(text, '([0-9])', '-*') "Add Char" 3 FROM t_reg;
    TEXT Add Char ---------- ------------------------------ ABC123 ABC-*-*-* ABC 123 ABC -*-*-* ABC 123 ABC -*-*-* abc 123 abc -*-*-* abc 123 abc -*-*-* a1b2c3 a-*b-*c-* aabbcc123 aabbcc-*-*-* ?/!@#$*& ?/!@#$*& \~*()., \~*()., 123123 -*-*-*-*-*-* 123abc -*-*-*abc abc abc 12 rows selected.

    SCOTT>SELECT no, ip, 2 REGEXP_REPLACE(ip, '\.', '') "Dot Remove" 3 FROM t_reg2;
    NO IP Dot Remove ---- -------------------- -------------------- 1 10.10.0.1 101001 2 10.10.10.1 1010101 3 172.16.5.100 172165100 4 172.61.186.2 172611862 5 172.61.168.2 172611682 6 255.255.255.0 2552552550 6 rows selected.

    SCOTT>SELECT no, ip, 2 REGEXP_REPLACE(ip, '\.', '/', 1,1) "REPLACE" 3 FROM t_reg2;
    NO IP REPLACE ---- -------------------- -------------------- 1 10.10.0.1 10/10.0.1 2 10.10.10.1 10/10.10.1 3 172.16.5.100 172/16.5.100 4 172.61.186.2 172/61.186.2 5 172.61.168.2 172/61.168.2 6 255.255.255.0 255/255.255.0
    • 사용자에게 입력받은 문자중 공백이 여러개 포함돼있을 경우 그 공백을 제거시키는 방법
    SCOTT>SELECT REGEXP_REPLACE('aaa     bbb', '( ){1,}','')
      2  FROM dual;
    REGEXP ------ aaabbb

    위의 예제에서 {1,}부분을 {1}로 해도됨. { }내의 숫자는 앞문자가 나타나는 횟수 또는 범위를 의미함.

    ex) a{5} = 'a'의 5번 반복한 aaaaa 만을 의미
    ex) a{3,} = aaa, aaaa, aaaaa, .....
    ex) a{3,5} = aaa, aaaa, aaaaa
    ex) ab{2,3} = abb, abbb

    • 'abc bbb'에서 공백이 두칸이상 인 것만 공백을 제거해 출력
    SCOTT>SELECT REGEXP_REPLACE('aaa     bbb', '( ){1,}','')
      2  FROM dual;
    REGEXP ------ aaabbb

    SCOTT>SELECT REGEXP_REPLACE('aaa bbb', '( ){2,}', '') "ONE", 2 REGEXP_REPLACE('aaa bbb', '( ){2,}', '') "Two" 3 FROM dual;
    ONE Two ------- ------ aaa bbb aaabbb

    SCOTT>SELECT REGEXP_REPLACE('aaa bbb', '( ){2,}', '*') "ONE", 2 REGEXP_REPLACE('aaa bbb', '( ){2,}', '*') "Two", 3 REGEXP_REPLACE('aaa bbb', '( ){2,}', '*') "Three" 4 FROM dual;
    ONE Two Three ------- ------- ------- aaa bbb aaa*bbb aaa*bbb
    • 사용자가 입력한 단어에 공백 문자가 처음에 포함돼있고 중간에도 공백이 포함되어 있다고 가정하고 그 단어에서 모든 공백을 제거한 후 조회하는 예제.
    SCOTT>SELECT studno, name, id
      2  FROM student
      3  WHERE id = REGEXP_REPLACE('&id', '( ){1,}', '');
    Enter value for id:      75    true
    STUDNO NAME ID ---------- ------------------------------ -------------------- 9411 James Seo 75true

    SCOTT>SELECT studno, name, id 2 FROM student 3 WHERE id = LOWER(REGEXP_REPLACE('&id', '( ){1,}', '')); /소문자화 Enter value for id: 75 TRUE
    STUDNO NAME ID ---------- ------------------------------ -------------------- 9411 James Seo 75true
    • 특정 문자열의 형태를 다른 형태로 바꿀 때
    SCOTT>SELECT REGEXP_REPLACE('20160905',
      2                         '([[:digit:]]{4})([[:digit:]]{2})([[:digit:]]{2})',
      3                         '\1-\2-\3')
      4  FROM dual;
    REGEXP_REP ---------- 2016-09-05


    3. REGEXP_SUBSTR 함수

    SUBSTR 함수의 확장판. 특정 패턴에서 주어진 문자를 추출해 내는 함수.



    사용예

    • 교수테이블(professor)테이블에서 홈페이지(hpage) 주소가 있는 교수들만 조사해서 아래의 화면처럼 나오게 출력하시오.
    SCOTT>SELECT name, LTRIM(REGEXP_SUBSTR(hpage, '/([[:alnum:]]+\.?){3,4}?'), '/') "URL"
      2  FROM professor
      3  WHERE hpage IS NOT NULL ;
    NAME URL -------------------- -------------------- Audie Murphy www.abc.net Angela Bassett www.abc.net Jessica Lange www.power.com Michelle Pfeiffer num1.naver.com

    hpage 컬럼을 조회하여 ‘http://’ 부분을 제거하고 . 으로 구분되는 필드를 최소 3개에서 최대 4개까지 출력하라는 의미. 그 후에 왼쪽부분에 나오는 ‘/ ’ 기호를 LTRIM 함수로 제거함.

    • Professor 테이블에서 101번 학과와 201번 학과 교수들의 이름과 메일 주소의 도메인 주소를 출력하시오. 단 메일 주소는 @뒤에 있는 주소만 출력하시오.
    SCOTT>SELECT name, LTRIM(REGEXP_SUBSTR(email, '@([[:alnum:]]+\.?){3,4}?'), '@') domain
      2  FROM professor
      3  WHERE deptno IN (101,201) ;
    NAME DOMAIN -------------------- -------------------- Audie Murphy abc.net Angela Bassett abc.net Jessica Lange power.com Meryl Streep daum.net Susan Sarandon def.com
    • 특정기호나 문자를 기준으로 데이터를 추출할 때
    SCOTT>SELECT REGEXP_SUBSTR('sys/oracle@racdb:1521:racdb',
      2                        '[^:]+', 1, 3) result           // : 기호를 기준으로 3번재의 문자열을 추출
      3  FROM dual;
    RESULT ---------- racdb

    SCOTT>SELECT REGEXP_SUBSTR('sys/oracle@racdb:1521:racdb', 2 '[^/:]+', 1, 2) result // 슬래쉬를 기준으로 출력 3 FROM dual;
    RESULT -------------- oracle@racdb


    4. REGEXP_COUNT 함수

    특정 문자의 개수를 세는 함수


    사용예

    • 주어진 문자열에서 대문자 'A'가 몇개인지 찾아 주는 예
    SCOTT>SELECT text, REGEXP_COUNT(text, 'A')
      2  FROM t_reg;
    TEXT REGEXP_COUNT(TEXT,'A') ---------- ---------------------- ABC123 1 ABC 123 1 ABC 123 1 abc 123 0 abc 123 0 a1b2c3 0 aabbcc123 0
    • 검색 위치를 3으로 지정해서 3번째 문자 이후부터 해당 소문자 ‘c’ 가 나오는 개수를 세는 예
    SCOTT>SELECT text, REGEXP_COUNT(text, 'c', 3)
      2  FROM t_reg;
    TEXT REGEXP_COUNT(TEXT,'C',3) ---------- ------------------------ ABC123 0 ABC 123 0 ABC 123 0 abc 123 1 abc 123 1 a1b2c3 1 aabbcc123 2 ?/!@#$*& 0 \~*()., 0 123123 0 123abc 1 abc 1

    SCOTT>SELECT text, REGEXP_COUNT(text, 'c') "RESULT 1", 2 REGEXP_COUNT(text, 'c', 1, 'i') "RESULT 2" //대소문자 구분 없이 (즉 'C' 와 'c' 모두) 몇 개가 나오는 지 세어 출력 3 FROM t_reg;
    TEXT RESULT 1 RESULT 2 ---------- ---------- ---------- ABC123 0 1 ABC 123 0 1 ABC 123 0 1 abc 123 1 1 abc 123 1 1 a1b2c3 1 1 aabbcc123 2 2 ?/!@#$*& 0 0 \~*()., 0 0 123123 0 0 123abc 1 1 abc 1 1

    SCOTT>SELECT text, 2 REGEXP_COUNT(text, 'aa') RESULT1, 3 REGEXP_COUNT(text, 'a{2}') RESULT2, 4 REGEXP_COUNT(text, '(a)(a)') RESULT3 5 FROM t_reg;
    TEXT RESULT1 RESULT2 RESULT3 ---------- ---------- ---------- ---------- ABC123 0 0 0 ABC 123 0 0 0 ABC 123 0 0 0 abc 123 0 0 0 abc 123 0 0 0 a1b2c3 0 0 0 aabbcc123 1 1 1 ?/!@#$*& 0 0 0 \~*()., 0 0 0 123123 0 0 0 123abc 0 0 0 abc 0 0 0



    [출처] 다양한 예제로 쉽게 배우는 오라클 SQL과 PL/SQL 서진수 저

    'Oracle > sql' 카테고리의 다른 글

    [SQL] 4. JOIN  (796) 2016.09.12
    [SQL] 3. 복수행함수(그룹함수)  (153) 2016.09.05
    [SQL] 2. 단일행함수(일반함수)  (11) 2016.09.02
    [SQL] 2. 단일행함수(숫자, 날짜, 형변환 함수)  (993) 2016.08.30
    [SQL] 2. 단일행함수(문자함수)  (7) 2016.08.29

    일반함수

    함수의 입력되는 값이 숫자, 문자, 날짜 구분없이 모두 사용할 수 있는 함수. 일반적으로 많이 사용하는 함수 위주.



  • NVL(컬럼, 치환할 값) : 컬럼값이 null일 경우, 해당 값으로 치환
  • NVL2(Col1,Col2,Col3) : Col1의 값이 null이 아니면 Col2를, null이면 Col3 출력

    • ex) emp 테이블에서 deptno 가 30번 인 사람들의 empno , ename , sal , comm 값을 출력하되 만약 comm 값이 null 이 아니면 sal+comm 값을 출력하고 comm 값이 null 이면 sal*0 의 값을 출력

      SCOTT>SELECT empno, ename, sal, comm,
      2          NVL2(comm,sal+comm,sal*0) "NVL2"
      3  FROM emp
      4  WHERE deptno = 30;
      
      EMPNO ENAME             SAL       COMM       NVL2
      ---------- ---------- ---------- ---------- ----------
      7499 ALLEN            1600        300       1900
      7521 WARD             1250        500       1750
      7654 MARTIN           1250       1400       2650
      7698 BLAKE            2850                     0
      7844 TURNER           1500          0       1500 
  • DECODE() : 개발 언어에서 사용중인 IF 문을 오라클 SQL 안으로 가져온 함수. 오라클에서만 사용됨.

    • DECODE(A, B, '1', null) : A=B면 '1' 출력, 아니면 null출력 (null 생략가능)
    • DECODE(A, B, '1', '2') : A=B면 '1' 출력, 아니면 '2' 출력.
    • DECODE(A, B, '1', C, '2', '3') : A=B면 '1' 출력, A=C면 '2' 출력. 둘다아니면 '3' 출력.(조건과 결과 추가해 확장가능)

      • ex) Professor 테이블에서 교수의 이름과 학과 명을 출력하되 학과 번호가 101 번 이면 ‘Computer Engineering’ , 102 번이면 ‘Multimedia Engineering' , 103 번이면 ‘Software Engineering ‘ 나머지는 ‘ETC’ 로 출력
        SCOTT>SELECT deptno, name, DECODE(deptno,101,'Computer Engineering',
        2                                      102,'Multimedia Engineering',
        3                                      103,'Software Engineering',
        4                                          'ETC') "DNAME"
        5  FROM professor;
        DEPTNO NAME                      DNAME
        ------- --------------- -----------------
        
        101 Audie Murphy              Computer Engineering
        101 Angela Bassett            Computer Engineering
        101 Jessica Lange             Computer Engineering
        102 Winona Ryder              Multimedia Engineering
        102 Michelle Pfeiffer         Multimedia Engineering
        102 Whoopi Goldberg           Multimedia Engineering
        103 Emma Thompson             Software Engineering
        103 Julia Roberts             Software Engineering
        103 Sharon Stone              Software Engineering
        201 Meryl Streep              ETC
        201 Susan Sarandon            ETC
        202 Nicole Kidman             ETC
        202 Holly Hunter              ETC 

    • DECODE(A, B, DECODE(C,D, '1', null)) : A=B일 경우 C=D면 '1'출력, 아니면 null출력 (null생략가능)

      • ex) professor 테이블에서 교수의 이름과 부서번호를 출력하고 101 번 부서 중에서 이름이 "Audie Murphy" 교수에게 "BEST!" 라고 출력하고 101번 부서 중에서 이름이 "Audie Murphy" 교수가 아닌 나머지에는 NULL 값을 출력하시오. 만약 101 번 외 다른 학과에 "Audie Murphy" 교수가 있어도 "BEST!" 가 출력되면 안됨.
        SCOTT>SELECT deptno, name, DECODE(deptno, 101, DECODE(name,'Audie Murphy','BEST!',NULL)) "decode"
        2  FROM professor;
        DEPTNO NAME                 decode
        -------- ------------ --------
        
        

        101 Audie Murphy BEST! 101 Angela Bassett 101 Jessica Lange 102 Winona Ryder 102 Michelle Pfeiffer 102 Whoopi Goldberg 103 Emma Thompson 103 Julia Roberts

    • DECODE(A, B, DECODE(C, D, '1', '2')) : A=B일 경우, C=D면 '1'출력, 아니면 '2'출력.

    • DECODE(A, B, DECODE(C, D, '1', '2'), '3') : A=B일경우, C=D면 '1'출력, 아니면 '2'출력, A=B아니면 '3'출력.
      • ex) professor 테이블에서 교수의 이름과 부서번호를 출력하고 101 번 부서 중에서 이름이 "Audie Murphy" 교수에게 비고란에 “BEST!” 이라고 출력하고 101번 학과의 "Audie Murphy" 교수 외에는 비고란에 “GOOD!”을 출력하고 101번 교수가 아닐 경우는 비고란에 "N/A" 을 출력.
        SCOTT>SELECT deptno, name,
        2          DECODE(deptno, 101, DECODE(name, 'Audie Murphy', 'BEST!', 'GOOD!'), 'N/A') "ETC"
        3  FROM professor;
        DEPTNO NAME                 ETC
        ---------- -------------------- -----
        101 Audie Murphy         BEST!
        101 Angela Bassett       GOOD!
        101 Jessica Lange        GOOD!
        102 Winona Ryder         N/A
        102 Michelle Pfeiffer    N/A
        102 Whoopi Goldberg      N/A
        
  • CASE() : DECODE 함수는 주로 = 인 값을 처리하는데 주로 사용되고, CASE문은 크거나 작은 조건을 처리할 경우 쉽게 처리할 수 있음. DECODE 함수와는 다르게 함수내부가 콤마(,)로 조건들이 구분되지 않는것을 주의해야함.

     CASE(조건) WHEN 결과1 THEN 출력1
               [WHEN 결과2 THEN 출력2] 
                ELSE 출력3
     END "컬럼명" 
    • ex1) decode와 동일하게 '='조건으로 사용되는 경우. (복잡해서 주로 decode로사용)

      SCOTT>SELECT name, tel,
      2          CASE(SUBSTR(tel,1,INSTR(tel,')')-1)) WHEN '02' THEN 'SEOUL'
      3                                               WHEN '031' THEN 'GYEONGGI'
      4                                               WHEN '051' THEN 'BUSAN'
      5                                               WHEN '052' THEN 'ULSAN'
      6                                               WHEN '055' THEN 'GYEONGNAM'
      7                                                          ELSE 'ETC'
      8          END "LOC"
      9  FROM student
      10  WHERE deptno1 = 201;
      NAME                           TEL             LOC
      ---------------- ----------- -----------
      
      Demi Moore                     02)6255-9875    SEOUL
      Macaulay Culkin                02)312-9838     SEOUL
      Wesley Snipes                  053)736-4981    ETC
      Steve Martin                   02)6175-3945    SEOUL
      Sean Connery                   02)381-5440     SEOUL
      Christian Slater               031)345-5677    GYEONGGI
      
    • ex2) 비교조건이 '='이 아닌경우 (Student 테이블의 jumin 컬럼을 참조하여 학생들의 이름과 태어난 달 , 그리고 분기를 출력하세요. 태어난 달이 01-03월 은 1/4, 04 – 06월 은 2/4 , 07 – 09 월 은 3/4 , 10 – 12 월은 4/4 로 출력)

      SCOTT>SELECT name, SUBSTR(jumin,3,2) "MONTH",
      2          CASE WHEN SUBSTR(jumin,3,2) BETWEEN '01' AND '03' THEN '1/4'
      3               WHEN SUBSTR(jumin,3,2) BETWEEN '04' AND '06' THEN '2/4'
      4               WHEN SUBSTR(jumin,3,2) BETWEEN '07' AND '09' THEN '3/4'
      5               WHEN SUBSTR(jumin,3,2) BETWEEN '10' AND '12' THEN '4/4'
      6          END "Quarter"
      7  FROM student;
      NAME                           MONT Qua
      ------------------ --- ----
      
      James Seo                      10   4/4
      Rene Russo                     02   1/4
      Sandra Bullock                 06   2/4
      Demi Moore                     12   4/4
      Danny Glover                   03   1/4
      Billy Crystal                  01   1/4
      Nicholas Cage                  04   2/4
      Micheal Keaton                 09   3/4
      Bill Murray                    01   1/4
      

    decode와 비슷하지만 더 넓은 범위에서 사용할 수 있어 sql 튜닝에서 요긴하게 많이 사용됨. 함수를 많이 알수록 성능 좋은 쿼리를 작성할 수 있음.



  • QUIZ1

    Professor 테이블에서 201번 학과 교수들의 이름과 급여, bonus , 총 연봉을 아래와 같이 출력하시오. 단 총 연봉은 (pay*12+bonus) 로 계산하고 bonus 가 없는 교수는 0으로 계산.




    QUIZ2

    아래 화면과 같이 emp 테이블에서 deptno 가 30 번인 사원들을 조회하여 comm 값이 있을 경우 'Exist' 을 출력하고 comm 값이 null 일 경우 'NULL' 을 출력하시오.




    QUIZ3

    Student 테이블을 사용하여 제 1 전공 (deptno1) 이 101 번인 학과 학생들의 이름과 주민번호, 성별을 출력하되 성별은 주민번호(jumin) 컬럼을 이용하여 7번째 숫자가 1일 경우 “ 남자” , 2일 경우 “여자 ” 로 출력하시오.




    QUIZ4

    Student 테이블에서 1 전공이 (deptno1) 101번인 학생의 이름과 연락처와 지역을 출력하시오. 단,지역번호가 02 는 "SEOUL" , 031 은 "GYEONGGI" , 051 은 "BUSAN" , 052 는 "ULSAN" , 055 는 "GYEONGNAM".




    QUIZ5

    emp 테이블을 조회하여 empno , ename , sal , LEVEL(급여등급)을 아래와 같이 출력하시오. 단 급여등급은 sal 을 기준으로 1 - 1000 이면 Level 1 , 1001 - 2000 이면 Level 2 , 2001 - 3000 이면 Level 3 , 3001 - 4000 이면 Level 4 , 4001 보다 많으면 Level 5 로 출력




    [출처] 다양한 예제로 쉽게 배우는 오라클 SQL과 PL/SQL 서진수 저

    숫자 함수

      함수명

     ROUND

     반올림 한 후 출력

     ROUND(12.345, 2)    ->  12.35

     TRUNC

     버림 한 후 출력

     TRUNC(12.345, 2)     ->  12.34 

     MOD

     나머지 값 출력

     MOD(12, 10)             ->  2

     CEIL

     가장 근접한 큰 정수 출력

     CEIL(12.345)             ->  13

     FLOOR

     가장 근접한 작은 정수 출력

     FLOOR(12.345)         ->  12 

     POWER

     제곱승 출력

     POWER(3, 2)            ->  9




  • ROUND(숫자, 자리수) : 주어진숫자를 반올림 후 출력. 소수점기준(자리수)
  • TRUNC(숫자, 자리수) : 버림.
  • MOD() : 나머지값 출력 /CEIL() : 가장 가까운 큰정수 출력 / FLOOR() : 가장 가까운 작은정수
    • ex) CEIL 함수의 경우 여러 데이터들을 하나의 기준으로 묶을 때 주로 사용함. 아래의 예는 emp 테이블의 13 건의 데이터를 출력하되 3 줄씩 나누어서 한 조로 만드는 예.

      SQL> SELECT rownum "ROWNO", CEIL(rownum/3) "TEAMNO", ename    //rownum은 출력 줄번호
      2  FROM emp;
      
      ROWNO     TEAMNO ENAME
      ----- --------- ----------
       1          1 SMITH
       2          1 ALLEN
       3          1 WARD
       4          2 JONES
       5          2 MARTIN
       6          2 BLAKE
       7          3 CLARK
       8          3 SCOTT
       9          3 KING
      10          4 TURNER
      11          4 JAMES
      12          4 FORD
      13          5 MILLER 
  • POWER(2,3) : 2의 3승 값을 출력



    날짜 함수

  • SYSDATE : 현재 시스템의 시간을 출력
    • 윈도우와 유닉스(리눅스)의 날짜형식 다름
      SQL> SELECT SYSDATE FROM dual;  //리눅스형식
      SYSDATE
      -----------
      30-AUG-16
      
    • 윈도우 날짜형식으로 변환가능
      SQL> ALTER SESSION SET NLS_DATE_FORMAT='YY/MM/DD';
      Session altered. 
      SQL> ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD:HH24:MI:SS';
      
  • MONTHS_BETWEEM() : 두날짜 사이의 개월수를 출력
    • 두 날짜중 큰 날짜를 먼저 써야 양수가 출력
    • 두 날짜가 같은 달에 속해 있으면 특정 규칙으로 계산된 값이 출력(같은 1개월이라도 29일,30일,31일 같은 경우마다 모두 결과값이 다를것)
  • ADD_MONTHS() : 주어진 날짜에 숫자만큼의 달을 추가
  • NEXT_DAY() : 주어진날짜 기준으로 돌아오는 가장 최근 요일의 날짜를 반환
  • LAST_DAY() : 주어진날짜가 속한 달의 가장 마지막 날을 출력
  • ROUND() : 정오를 넘겼을경우 다음 날짜로 출력하고 안넘겼을 경우는 당일로 출력
  • TRUNC() : 무조건 당일로 출력


  • 형변환 함수

  • 묵시적(자동) 형 변환 : 오라클이 자동으로 형을 바꿔줌. 튜닝에서 뜻하지 않게 속도가 느려지는 주범이 될 수 있으므로 조심할것 (속도가 느려지는 이유는 해당 컬럼에 인덱스가 생성되어 있을 경우 묵시적 형 변환이 생기면 그 인덱스를 못쓰게 되고 그렇게 되면 Index Suppressing error 발생) / 숫자처럼 생긴 문자만 변환해줌.
  • 명시적(수동) 형 변환 : 형변환 함수를 통해 수동으로 데이터 형을 바꾸는것. 



    형변환 함수는 위 그림처럼 TO_CHAR, TO_NUMBER, TO_DATE 세가지로 나뉘고, TO_CHAR 함수는 숫자와 날짜를 문자로 변환해주는 두가지 기능을 한꺼번에 가짐.


     데이터 타입

     CHAR(n)

     고정길이의 문자를 저장. 최대값 2000 bytes

     VARCHAR2(n)

     변하는 길이의 문자를 저장. 최대값 4000 bytes

     NUMBER(p,s)

     숫자 값을 저장. p 는 전체 자리수로 1-38 자리까지 가능하고 s는 소수점 이하 자리수로 -84 ~ 127 자리까지 가능

     DATE

     7Byte로 BC 4712년 1월 1일부터 AD 9999년 12월 31일까지의 날짜를 저장.

     LONG

     가변 길이의 문자를 저장. 최대 2GB 까지 저장

     CLOB

     가변 길이의 문자를 저장. 최대 4GB 까지 저장 할 수 있음

     BLOB

     가변 길이의 바이너리 데이터를 최대 4GB 까지 저장 할 수 있음

     RAW(n)

     원시 이진 데이터로 최대 2000 bytes 까지 저장

     LONG RAW(n)

     원시 이진 데이터로 최대 2GB까지 저장

     BFILE

     외부 파일에 저장된 데이터로 최대 4GB 까지 저장


    • TO_CHAR(날짜 or 숫자,'원하는형태')
      • ex) TO_CHAR(sysdate,'RRRR-MM-DD:HH:MI:SS')
      • ex) TO_CHAR(12345, '99,999') : 12,345
        SCOTT>SELECT empno, ename, sal, comm,
        2          TO_CHAR((sal*12)+comm, '999,999') "SALARY"
        3  FROM emp
        4  WHERE ename = 'ALLEN';
        EMPNO ENAME             SAL       COMM SALARY
        ---------- ---------- ---------- ---------- --------
        7499 ALLEN            1600        300   19,500

    cf) 날짜와 숫자를 표현하는 방법

    [ 년도 ]
    ‘YYYY’ – 연도를 4자리로 표현.
    ‘RRRR’ – 2000년 이후에 Y2K 버그로 인해 등장한 날짜 표기법으로 연도 4자리 표기법.
    ‘YY’ – 연도를 끝의 2 자리만 표시. 예 : 14
    'RR' - 연도를 마지막 2 자리만 표시. 예: 14
    ‘YEAR’ – 연도의 영문 이름 전체를 표시.

    [ 월 ]
    MM – 월을 숫자 2자리로 표현. 예: 10
    MON – 유닉스용 오라클에서 월을 뜻하는 영어 3글자로 표시. 예: OCT 윈도용 오라클일 경우는 MONTH 와 동일.
    MONTH – 월을 뜻하는 이름 전체를 표시

    [ 일 ]
    DD – 일을 숫자 2자리로 표시. 예: 26
    DAY – 요일에 해당하는 명칭을 표시하는데 유닉스용 오라클에서는 영문으로 나오고 윈도용 오라클에서는 한글로 나옴.
    DDTH – 몇 번째 날인지를 표시.

    [ 시간 ]
    HH24 – 하루를 24시간으로 표시.
    HH – 하루를 12 시간으로 표시.
    분 : MI 로 표시.
    초 : SS 로 표시.

    [숫자]
    9 의 개수만큼 자리수 TO_CHAR(1234,’99999’) 1234
    빈자리를 0으로 채움 TO_CHAR(1234,’099999’) 001234
    $ 표시를 붙여서 표시 TO_CHAR(1234,’$9999’) $1234
    소수점 이하를 표시 TO_CHAR(1234,’9999.99’) 1234.00
    천 단위 구분기호를 표시 TO_CHAR(12345,’99,999’) 12,345

    • TO_NUMBER('숫자처럼 생긴 문자')
    • ASCII('문자') : 문자를 아스키 코드 값으로 출력
    • TO_DATE('날짜처럼 생긴 문자')

  • QUIZ1

    Student 테이블의 birthday 컬럼을 사용하여 생일이 1월인 학생의 이름과 birthday 를 아래 화면과 같이 출력하시오.




    QUIZ2

    emp 테이블의 hiredate 컬럼을 사용하여 입사일이 1,2,3 월인 사람들의 사번과 이름, 입사일을 출력하시오.




    QUIZ3

    emp 테이블을 조회하여 comm 값을 가지고 있는 사람들의 empno , ename , hiredate , 총연봉,15% 인상 후 연봉을 아래 화면처럼 출력하세요. 단 총연봉은 (sal*12)+comm 으로 계산하고 아래 화면에서는 SAL 로 출력되었으며 15% 인상한 값은 총연봉의 15% 인상 값임. (HIREDATE 컬럼의 날짜 형식과 SAL 컬럼 , 15% UP 컬럼의 $ 표시와 , 기호 나오게)





    [출처] 다양한 예제로 쉽게 배우는 오라클 SQL과 PL/SQL 서진수 저

    단일행 함수



    문자 함수

  • INITCAP(컬럼명 or '문자열') : 영어에서 첫 글자만 대문자로 출력(나머지는 소문자)
  • LOWER(컬럼명 or '문자열') / UPPER() : 입력되는 값을 전부 소문자/대문자로 출력
  • LENGTH(컬럼명 or '문자열') / LENGTHB() : 입력된 문자열의 길이/바이트수 를 계산
  • CONCAT('문자열1', '문자열2') = || 연산자와 동일
  • SUBSTR(컬럼명 or '문자열', 시작위치, 자릿수) : 주어진 문자열에서 특정길이의 문자만 추출/ SUBSTRB()의 자릿수에는 추출할 바이트수를 지정
    • 시작위치 숫자를 -(마이너스)로 지정할 경우 뒤에서부터(오른쪽) 세어 시작위치를 지정/ 자릿수는 left -> right 방향으로 동일
    • ex) Student 테이블에서 jumin 컬럼을 사용해서 1 전공이 101번인 학생들의 이름과 태어난 월일 , 생일 하루 전 날짜를 출력하시오
      SQL> SELECT name, SUBSTR(jumin,3,4) "Birthday",
      2               SUBSTR(jumin,3,4)-1 "Birthday - 1"
      3  FROM student
      4  WHERE deptno1 = 101;
      
      NAME                 Birthday Birthday - 1
      -------------------- -------- ------------
      James Seo            1023             1022
      Billy Crystal        0123              122
      Richard Dreyfus      1129             1128
      Danny Devito         0819              818 
  • INSTR(컬럼명 or '문자열', 찾는글자, 시작위치(기준), 몇번째(default:1)) : 특정 글자의 위치를 추출

    • 시작 위치를 -(마이너스)로 지정할 경우 left <- right(오른쪽에서 왼쪽) 으로 검색해 시작위치지정
    • 시작위치와 찾으려는 위치 값은 생략가능하며 생략할 경우자동으로 1로 설정
    • ex) 문자열 A-B-C-D에서 오른쪽에서 6번째 문자를 기준으로 2번째'-'가 나오는 위치의 값을 출력하시오.
      SQL> SELECT 'A-B-C-D' "ABCD", INSTR('A-B-C-D','-', -6, 2) "INSTR"
      2  FROM dual;
      
      ABCD         INSTR
      ----------- ---------
      A-B-C-D             0  
    • ex2) Student 테이블의 tel 컬럼을 사용하여 1 전공번호(deptno1)가 201번인 학생의 이름과 전화번호, ‘)‘ 가 나오는 위치를 출력하시오.

      SQL> SELECT name, tel, INSTR(tel, ')') "INSTR()"
       2  FROM student
      3  WHERE deptno1 = 201;
      
      NAME                 TEL                INSTR()
      -------------------- --------------- ----------
      
      Demi Moore           02)6255-9875             3
      Macaulay Culkin      02)312-9838              3
      Wesley Snipes        053)736-4981             4    
  • LPAD(컬럼 or '문자열', 전체자리수, '채울문자') / RPAD() : 원래 문자열을 제외한 나머지 자리(왼쪽/오른쪽)에 문자를 채움.

    • ex) student 테이블에서 1 전공이 201 번인 학과 학생들의 id 를 총 10자리로 출력하되 왼쪽 빈 자리는 ‘*’ 기호로 채우세요
      SQL> SELECT name, id, LPAD(id,10,'*') "LPAD()"
      2  FROM student
      3  WHERE deptno1 = 201;
      
      NAME                 ID         LPAD()
      -------------------- ---------- ------------------- 
      Demi Moore           Moore      *****Moore
      Macaulay Culkin      Culkin     ****Culkin
      Wesley Snipes        Snipes     ****Snipes 
  • LTRIM(컬럼 or '문자열', '제거할문자') / RTRIM() : 해당문자를 제거

    • ex) emp 테이블의 ename에서 마지막 글자가 'R'이 있을경우 제거함.
      SQL> SELECT ename, RTRIM(ename, 'R') "RTRIM"
      2  FROM emp
      3  WHERE deptno = 10;
      
      ENAME      RTRIM
      ------- --------
      CLARK      CLARK
      KING       KING
      MILLER     MILLE 
  • REPLACE(컬럼 or '문자열', '문자1', '문자2') : 주어진 문자열에서 문자1을 문자2로 바꿔 출력

    • ex) emp 테이블에서 이름의 첫 두글자를 *로 표시하시오.
      SQL> SELECT ename, REPLACE(ename, SUBSTR(ename, 1,2), '**') "REPLACE"
      2  FROM emp
      3  WHERE deptno = 10;
      
      ENAME      REPLACE
      ---------- --------------------
      CLARK      **ARK
      KING       **NG
      MILLER     **LLER 

  • QUIZ1

    Student 테이블을 참조해서 아래 화면과 같이 1 전공이(deptno1 컬럼) 201번인 학생의 이름과 전화번호와 지역번호를 출력하세요. 단 지역번호는 숫자만 나와야함. 

    QUIZ2

    아래 화면과 같이 emp 테이블에서 deptno 가 10번인 사원들의 이름을 총 9자리로 출력하되 오른쪽 빈자리에는 해당 자리 수에 해당되는 숫자가 출력되도록 하시오 


    QUIZ3

    Student 테이블에서 아래와 같이 deptno1 이 101 번인 학과 학생들의 이름과 전화번호와 전화번호에서 지역번호와 국번을 제외한 나머지 번호를 * 로 표시해서 출력하시오.





    [출처] 다양한 예제로 쉽게 배우는 오라클 SQL과 PL/SQL 서진수 저

    오라클 서버 접속

    오라클계정

  • 관리자용 : sys, system
  • 일반용(연습용) : scott, HR (dbca 과정에서 sample schema 체크/ 안했으면 수동으로 설치해야함)


  • 서버접속

  • 리눅스 : $ sqlplus scott/tiger (프로그램명 계정/암호)
  • db 종료 되어있어 접속안되면 관리자 계정으로 접속해 db를 시작해줘야함
  • ERROR:

    ORA-01034: ORACLE not available
    ORA-27101: shared memory realm does not exist
    Linux Error: 2: No such file or directory
    Process ID: 0
    Session ID: 0 Serial number: 0

    • Enter user-name: sys/oracle as sysdba
    • SQL>startup
    • SQL> CONN scott/tiger

  • 오라클을 처음 설치할 경우에는 보안 문제로 연습용 계정인 scott 계정을 사용 못하도록 막아두기 때문에 아래와 같은 에러가 발생할경우 관리자계정으로 접속해 계정을 풀어줘야함

  • ERROR:

    ORA-28000: the account is locked

    • Enter user-name: sys/oracle as sysdba
    • SYS> ALTER USER scott IDENTIFED BY tiger ACCOUNT UNLOCK;

  • 계정 확인: SQL>show user
  • 프롬프트를 현재 접속해 있는 계정이름으로 변경: SQL> SET sqlprompt "_USER>"



  • 데이터 가져오기

    SELECT

  • SELECT [컬럼명 or 표현식] FROM [테이블명 or 뷰(view) 명
    • SQL>SELECT * FROM emp; 모든 컬럼조회
  • DESC : 특정 테이블에 어떤 칼럼들이 있는지 조회(describe)
    • SQL> DESC dept ;
  • 모든 테이블 조회: SELECT * FROM TAB;


  • Column 변경

  • Column 길이 조정
    • 숫자 데이터: SQL> COL 컬럼명 FOR 9999 (자리수만큼 9할당)
    • 문자 데이터: SQL>COL 컬럼명 FOR a15 (자리수만큼 숫자할당)
  • 화면 길이 조정
    • 한 화면에 출력가능한 가로길이: SQL>SET LINE 200
    • 한 화면에 출력가능한 세로길이: SQL>SET PAGES 50
  • 표현식(Expression) = 리터럴 상수
    • 컬럼명 이외에 원하는 내용으로 출력할수 있음.
    • SELECT 구문 컬럼명 뒤에 '원하는내용'로 묶어서 사용
    • '를 출력하려면 ''사용
  • 기본 산술 연산자: +, -, *, / 사용해 출력가능 (우선순위 주의)
  • 별칭(column alias) 사용: 일시적으로 출력
    • 컬럼명 "별칭" // 별칭에 공백이나 특수문자, 대소문자 구분이 필요할 경우 쌍따옴표 필수
    • 컬럼명 AS "별칭"
    • 컬럼명 별칭 // 쌍따옴표 하지 않을경우는 모두대문자로 출력
  • 연결(합성) 연산자(Concatenation): - || 서로 다른 컬럼을 하나의 컬럼처럼 연결해서 출력 *백업/복구 작업이나 데이터베이스 운영 관련 작업, 튜닝 작업등에 아주 많이 사용됨.
  • SQL>SELECT ename||'''s job is '||job " NAME AND JOB"
     2  FROM emp;
    
     NAME AND JOB
    -----------------------------
    SMITH's job is CLERK
    ALLEN's job is SALESMAN
    WARD's job is SALESMAN
    


    DISTINCT

  • 중복된 값 제거하고 출력
  • 1개의 칼럼에만 적어도 모든 칼럼에 적용해 시간이 많이소요 (성능저하 발생) ​* 10g R1 까지는 정렬이용 R2부터는 hash 알고리즘 이용(성능개선)
  • 반드시SELECT 다음에 와야 하며 그렇지 않을 경우 에러발생.(ORA-00936)
  • SQL>SELECT DISTINCT job, ename
     2  FROM emp
     3  ORDER BY 1,2;
    
    JOB       ENAME
    --------- ----------
    ANALYST   FORD
    ANALYST   SCOTT
    CLERK     JAMES
    CLERK     SMITH
    
    


    WHERE

  • SELECT [컬럼 or 표현식] FROM [table or view] WHERE 조건
  • 문자 & 날짜 조회 시 ' ' 사용해야함 (숫자이외에 모두 홑따옴표 사용)
    • 문자의 경우 대소문자 구분 (날짜는 구분안함)
    • 날짜의 경우 윈도우와 리눅스 날짜 형식 다름 * 윈도우) yy/mm/dd, 리눅스) dd-MON-yy
  • 연산자 활용가능
    • = 같은 조건 검색
    • !=, <> 같지 않은 조건 검색
    • > (<) 큰(작은) 조건 검색
    • >= (<=) 크(작)거나 같은 조건 검색 숫자,문자,날짜 모두 비교가능(날짜의경우 최신날짜 일수록 값이큼)
    • BETWEEN a AND b a와 b사이에 있는 범위값 검색 ( a, b값 모두 포함/ 한글은 b포함 안됨) * 속도면에서 위의 비교연산자가 더 빠름
    • IN(a,b,c) a거나 b거나 c인 조건 검색 (속도빠름)
    • LIKE 특정 패턴 있는 조건 검색, 아래의 두 기호와 함께쓰임. 홑따옴표필수
        1. % : 글자수 제한X(0포함)
          _ : 한글자 %나 _를 먼저 쓰면 SQL성능최악임(Index때문). 주의할것.
    • IS NILL / IS NOT NULL Null 값/아닌값 검색 =연산 사용못함
    • A AND B A,B 모두 만족하는 값 검색 (우선수위: 괄호, AND > OR)
    • A OR B A,B 중 하나라도 만족하는 값 검색
    • NOT A A가 아닌 모든 조건 검색
  • 사용자에게 조건 입력받고 그 조건에 맞는 값 출력: & WHERE절 이외에 입력을 받아야 할곳에 모두 쓰일수있음


  • ORDER BY

  • 오름차순ASC(default), 내림차순DESC 컬럼명 뒤에 명시
  • SQL 문장에서 가장 마지막에 사용
  • 컬럼명대신 SELECT절에 오는 칼럼의 순서를 숫자로 사용 가능
  • 많이 쓸수록 성능저하되므로 최대한 쓰지않는게 좋음. INDEX 사용 권장.


  • SET OPERATOR (집합 연산자)

  • UNION 합집합, 중복 값 제거, 정렬
  • UNION ALL 합집합, 중복 값 제거X, 정렬X
  • INTERSECT 교집합, (정렬동반(12c기준) 데이터 많으면 속도저하)
  • MINUS 차집합, 정렬(쿼리순서 중요)
    • 두 집합의 SELECT 절에 오는 칼럼의개수와 데이터형이 동일해야함.
    • UNION & UNION ALL 많이 연결할수록 성능 저하되므로 DECODE, CASE 등 다른 방법 사용해 작성할것.


    기타

  • SQL>ed // vi 로 수정
  • SQL>/ // 마지막에 실행했던 sql 실행
  • SQL>SET verify OFF //설명부분 해제




  • [출처] 다양한 예제로 쉽게 배우는 오라클 SQL과 PL/SQL 서진수 저




    오라클 서버의 전체 구조


    (1) 메모리와 디스크

    ● INSTANCE (작업)

    메모리 부분에 생성되는 구조

    실제 작업하는 장소

    오라클은 메모리를 나눠서 관리


     

    SGA(System Global Area)

    실제 작업장소(공유메모리)

    모든 조회나 대부분의 작업이 이루어짐


    -​ Background Process

    오라클 서버가 잘 운영되도록 해주는 역할

     



    ● DATABASE (저장)

    - 데이터가 저장되는 데이터 파일

    - DB 전체의 관리정보가 들어있는 컨트롤 파일

    ​- 장애 복구 시 사용되는 Redo 로그파일





      






    (2) Instant 할당 및 관리



    ● Instance 생성과정

    1. startup 요청을 받은 최초의 Oracle Server process가 초기화 파라미터(pfile 또는 spfile)에 적혀있는 설정을 참고해 OS kernel에게 공유메모리를 사용할 수 있도록 할당해 달라고 요청

    2. 요청받은 kernel은 자신의 OS kernel 파라미터를 조회해 그 파일들에 설정되어 있는 내역으로 공유메모리(SGA)할당

    3. 세마포어 설정 값 등을 기반으로 커널이 관리를 시작

    (Server process가 종료되어도 SGA는 종료되지 않고, Instance가 종료되야 SGA가 공유메모리에서 사라짐)




    ● Kernel

    - 모든 하드웨어를 관장 (RAM을 사용해 작업하려면 kernel에게 허락받아야 함)
    - RAM 하나를 여러 프로그램이 공유해서 사용하므로 스케줄링 잘못하면 같은 메모리를 덮어쓸 수 있음 →블루스크린, kernel panic 초래

    - 커널이 메모리 관리를 잘 해야 성능이 좋아짐
    - 오라클이 요청한대로 메모리를 할당해 주는것이 아니라 커널의 설정파일에 적혀있는대로 할당(​만약, 서버의 총 RAM이 1G인데, 오라클이 2G를 요구할 수도 있기 때문)

    ○ linux 커널값 적는 파일    /etc/sysctl.conf

    ○ solaris 커널값 적는 파일   /etc/system

    ​  

    >> 예로, 오라클이 1G를 요청해도 /etc/sysctl.conf 파일에 500MB만 허락하도록 적혀있다면 그만큼만 할당해줌

    >> 물리적으로 RAM을 추가해도(10G→30G) 설정파일의 값을 바꾸지 않는다면 프로그램이 사용하는 메모리는 변화 없음



    ● 공유메모리 관리

    - 모든 Server process들이 동시에 함께 RAM(공유메모리)을 사용하기 때문에, 하나의 메모리 블록을 여러 프로그램이 동시에 중복 사용하는 사태를 막기 위해 OS차원에서 제공하는 세마포어와 몇가지 Kernel 파라미터들이 존재함

    ​   

    세마포어(Semaphore) : 깃발(flag)이란 의미로 어떤 자원의 현재 사용 여부를 표현 set unset, ​셋트로 여러개씩 사용함

    1. 사용할 메모리블록의 세마포어 상태를 먼저 확인함

    2. 만약, 사용중(set)으로 설정돼있으면 Process는 대기하고 있다가 블록이 release되어 unset이 되는 순간에 세마포어를 set으로 설정함 -> 메모리블록 사용가능


    Kernel 파라미터 : 유닉스계열 OS별로권장 수치는 다를수 있음

     SEMMSL

    시스템 내에서 여러개의 process들이 세마포어를 동시에 사용하기 때문에 세마포어 사용량이 많음 그래서 세마포어는 하나씩 사용하지 않고 여러개를 묶어서 세트로 사용함


    >정의: 하나의 세마포어 세트당 세마포어의 최대개수

    >권장: 초기화 파라미터 파일의 PROCESSES 변수의 최대값 + 10

    >기본값: 100이상


    oracle 11g 버전의 PROCESSES 기본값은 150개로 설정되어 있음

     SEMMNI

    >정의 : 리눅스 전체에서 설정 가능한 세마포어 세트의 최대 개수

    >권장 : 100이상

    SEMMNS

    >정의 : 리눅스 전체에서 사용 가능한 세마포어의 최대 개수

    >이론값 : SEMMSL X SEMMNI ≤ SEMMNS

     SEMOPM

    하나의 시스템 호출을 통해 여러개의 세마포어를 지원할 수 있으며 한 개의 세마포어 셋에서 가질 수 있는 세마포어의 최대값은 SEMMSL 파라미터를 통해 정의됨


    >정의 : 1call(1개의 시스템호출)이 초당 호출 가능한 최대 세마포어 개수 

    >권장: SEMOPM = SEMMSL

    >>  위의4가지 모두 세마포어와 관련된 파라미터로 시스템에 어떻게 설정되어 있는지 확인하려면 ipcs -ls 명령어를 사용하면 됨

     SHMMAX

     커널이 응용프로그램에게 메모리를 할당해 줄때 작게 여러번 할당X,  큰덩어리(segment)로 한번에 

    >정의: 공유 메모리 세그먼트의 최대크기(byte)

    >디폴트값: 32MB


    ex)​ 오라클이 RAM을 100MB 쓸 수 있는데 shmmax를 20MB로 설정할 경우 100MB의 메모리를 5개의 세그먼트로 나눠서 사용해야함(10명이 5개 테이블에 2명씩 따로따로 앉음) -> 성능이 좋지않음

    그렇다고 무조건 크게 설정해도 문제(10인용 테이블에 1,2명이 앉을수 있음) -> 메모리 낭비


    kernel.shmmax값을 아주 작게 주고 DB에 접속을 시도하면 서버에 접속이 되지 않거나

    ORA-27123: unable to attach to shared memory segment 라는 메시지가 발생 할 수 있음


    >> 설정값 확인 : # cat /proc/sys/kernel/shmmax  (디폴트값은 너무작아 보통 2G로 설정)

    >> 변경방법

     /proc 파일시스템에 변경사항을 직접 반영시켜 Server의 재부팅 없이 변경하는 방법

    # echo "2147483648" > /proc/sys/kernel/shmmax

    ②  sysctl 명령어를 사용해 변경

    sysctl -w kernel.shmmax=2147483648

     /etc/sysctl.conf 파일에 커널변수 값들을 추가해 변경 사항을 영구적으로 적용(vi editor로)

    sysctl -p 명령어를 수행하면 재부팅 없이 즉시적용가능

     SHMMNI

    >정의: 공유메모리 세그먼트의 최대개수 (시스템전체에서 사용가능한)

    >디폴트값: 4096 (충분)

     SHMALL

    >정의: 특정 시정에 시스템에서 사용 가능한 공유 메모리의 최대크기(page단위)

    >디폴트값: 2097152 bytes

    >권장값: 최소 ceil(SHMMAX/PAGE_SIZE) 값보다 큰 값

    SHMMIN

    >정의: 단일 공유메모리 세그먼트의 최소크기(byte) 

     SHMSEG

    >정의: 공유메모리 세그먼트의 최대개수 (1개의 Process가 사용할 수 있는)


     

    ● 커널이 위의 파라미터들을 기초로 해서 Oracle에 공유메모리를 할당하는 3가지 방법


    1. 물리적 메모리 충분할 경우 : 하나의 세그먼트에 전체 SGA 할당
    2. 하나의 세그먼트에 할당 할수 없는 경우 : 연속된 여러 세그먼트로 분산시켜 할당
    3. 연속으로 할당 할수 없는 경우: 불연속적인 여러 세그먼트에 분산시켜 할당

        

    ( Fixed Area 부분은 반드시 전체가 1개의 세그먼트에 할당 되어야 함 )






    (3) SGA 주요 구성요소


    Oracle Server process가 SGA를 생성하기 위해 커널에게 공유메모리를 할당 받아온다. 그 후 파라미터 파일과 각종 사항을 참고해서 SGA를 이루고 있는 구성 요소들을 생성함.

    - 필수 구성요소 : DB Buffer Cache, Redo Log Buffer, Shared Pool 




    Database Buffer Cache

    - 데이터의 조회와 변경 등의 실제 작업이 일어나는 공간

    - 사용자가 조회하거나 변경하려는 모든 데이터는 이 곳에 있어야 하고, 없을경우 HDD의 데이터 파일에서 해당 내용이 들어있는 Block을 복사해서 가져옴 (그렇게 하기위해서는 Buffer Cache의 Block 상태를 먼저 확인해야함)

    - 여러명의 사용자가 이 곳을 공유해서 사용하므로 하나의 메모리 Block을 여러 사용자가 동시에 I/O 하는 것을 방지하기 위해 오라클은 Buffer Cache Block의 상태를 확일할 수 있는 LRU(Least Recently Used) List를 통해 관리하고 있음


    블록 상태

     의미

     commit (여부) 

     Pinned Buffer

     다른 사용자가 현재 사용하고 있는 Buffer

     변경중

     Dirty Buffer

     현재 진행중인 작업은 없지만 다른 사용자가 내용변경 후 저장 안한 Buffer

     변경완료/저장(x)

     Free Buffer

     사용되지 않았던지 or Dirty Buffer 였다가 데이터 파일로 저장완료되어 재사용가능한 Buffer

     변경완료/저장(o)



    - LRU 알고리즘 : 공유메모리의 공간은 용량이 제한적이므로 SGA의 일부분을 덮어 써야 하는 경우가 생길 수 있는데, 이때 무작정 덮어 쓰는 것이 아니라 가장 최근까지 사용된 것은 지키고 가장 사용이 안된 것은 버리는(덮어쓰는) 알고리즘.


    - 오라클은 LRU List 스캔의 효율성을 위해 LRU List와 LRUW List로 나누어 관리하고 있음

    (Working Data Set 혹은 Working Set = LRU List + LRUW List)


    Working Data Set

     LRU List

    LRUW List 

     메인 리스트

     사용된 buffer들의 list (Hot/Cold 영역으로 나뉨)

     변경된 buffer들의 list (Dirty list)

     보조 리스트

     미사용된 buffer들이나 DBWR에 의해 기록된 Buffer들 (Free list)

     현재 DBWR에 의해 기록중인 buffer들의 list



    - 사용자가 데이터파일의 데이터를 DB Buffer Cache로 복사해와야 할 경우에 복사하기전 우선 먼저 LRU 보조 리스트에서 free buffer를 찾아서 확보해야함. 만약 보조 리스트의 free buffer가 모두 사용된 경우, LRU 메인 리스트 Cold 영역에서 free buffer를 다시 찾음

    - 특정개수(10g 기준 40%)만큼 찾았는데 못찾으면 scan 멈추고 DBWR[각주:1]한테 dirty buffer 내려쓰라고 요청함

    - 변경내용을 저장안한 dirty buffer는 DBWR에 의해 데이터파일로 저장이 완료되어 free buffer로 바뀌게 되고 LRU list의 보조리스트에 추가됨.

    - 이제 사용자는 free buffer를 확보한 후 데이터 파일에서 필요한 블록을 DB Buffer Cache로 복사해 올 수 있게됨.

    (HDD의 데이터파일에서 필요한 블록을 찾아 Buffer Cache로 복사해 오는 작업은 Server process가 함) 


    * Instance 최초 구동시 모든 buffer들은 LRU List의 보조리스트에서 관리됨


    - 위에서 살펴본 List들은 모든 사용자가 공유해서 사용하기 때문에 한번에 여러 Server process들이 동시에 이 List를 사용하려고 시도할 수 있음. 그래서 오라클은 일반적으로 대용량인 DB Buffer Cache를 빠르게 관리하기 위해 여러 구역으로 나누고 관리하는 WorkingSet을 여러개 생성해 여러 사용자가 동시에 free buffer를 찾을수 있도록 함.

    - 유한한 자원을 여러 process가 한꺼번에 사용하려고 할 경우 사용 순서를 관리하기 위해 Latch[각주:2]를 사용




    ● Redo Log Buffer

    - 데이터에 변경사항이 생길경우(DDL이나 DML 실행될 경우) 해당 변경 내용을 기록하는 메모리공간(장애 발생시 복구하기위해)

    - Redo Log File이 Redo Log Buffer의 내용을 디스크로 저장함.

    - 모든 변경사항이 전부 이곳에 기록되는것은 아님.

    ex) Direct Load(SQL Loader, insert /*+APPEND*/)나 table이나 index 생성시 nologging 옵션을 주는경우에는 Redo Log에 기록되지 않음. (단, nologging 옵션으로 생성된 table이라도 일반적인 insert, update, delete 같은 작업은 모두 기록됨)




    ● Shared Pool

    - 다른 사용자와 어떤 대상을 공유해서 사용하기 위한 공간

    - Shared_Pool_Size 파라미터(동적파라미터라서 DB를 종료하지 않아도 alter system set으로 사이즈변경가능)로 전체크기 설정가능.

    - Library Cache나, Dictionary Cache 크기는 각각 따로 관리 할 수 없음


     Library Cache

     Soft Parse할 때 사용되는 공간.

     이미 수행됐던 SQL, PL/SQL 문장의 parse code와 해당 SQL, PL/SQL 문장, 실행계획등이 저장돼있음.

     LRU 알고리즘으로 관리.

     Dictionary Cache

     구문분석이나 Optimizer가 실행계획을 세울 때 사용되는 주요 Dictionary들이 row단위로 저장돼있음.

     LRU 알고리즘으로 관리.

     Server Result Cache

     결과값을 Cache해 두는 공간. (11g에서 새로생김)

     동일한 Select가 수행됐을 경우 DB Buffer Cache까지 안가고 즉시 이곳에서 가져오도록 해 속도를 높임.

     default : 사용안함 / 사용하려면 SQL문장에 /*+ result_cache */ 힌트사용해서 수동으로 설정해야함.

     매번 힌트 쓰기 번거로우면 alter system set RESULT_CACHE_MODE=Force; 로 변경하여 사용.

     Reserved Pool

     Shared Pool에 5KB(11g기준)가 넘는 오브젝트가 적재돼야 할 경우 사용하기 위해서 예약해둔 공간.

     기본설정: Instance가 시작될때 Shared_Pool_Size 크기의 5%.

     SHARED_POOL_RESERVED_SIZE 파라미터로 용량설정.




    ● Large Pool

    - 필수 구성 요소 X, 특정 기능 사용할 경우에만 사용

    - shared server mode로 오라클 서버를 운영할 경우 UGA를 이곳에 생성함

    - 병렬처리 작업을 할 경우 각 프로세스들간의 메세지 buffer를 이곳에 생성

    - RMAN으로 백업이나 복구할 경우 RMAN이 사용하는 I/O용 buffer가 이곳에 생성됨



    ● Java Pool

    - java 관련 code나 Java Virtual Machine(JVM) 관련 데이터를 저장하기 위해 생성되는 선택적인 공간



    ● Streams Pool

    - 10g 이상 버전부터 생긴 SGA 구성요소로 Streams 기능을 사용할 경우에만 사용됨.



    ● Fixed SGA

    - 오라클이 내부적으로 사용하기 위해 생성시키는 공간

    - 주로 백그라운드 프로세스들이 필요한 데이터베이스의 전반적인 공유 정보나 각 프로세스들끼리 공유해야만 하는 Lock 정보 같은 내용들이 저장됨.

    - 이 공간의 크기는 오라클이 시작될 때 자동으로 설정되며 사용자나 관리자가 임의로 변경X



     

     


    (4) Dynamic SGA 기능(9i~)


    - 관리자가 필요에 의해 SGA의 구성요소의 크기를 변경한 후 오라클 인스턴스의 재시작 없이 즉시 적용할 수 있는 기능

    (단, Redo Log Buffer를 포함한 몇가지는 제외)

    - 8i 버전까지는 SGA의 각 구성요소 크기를 변경하고 나서 오라클 인스턴스를 중단했다가 재시작해야만 변경사항이 적용되는 Static SGA 방식이었음.

    - 오라클에서 동적으로 메모리를 할당할 때 사용하는 단위: 그래뉼(Granule)

    - 10g 이후 버전기준 SGA_MAX_SIZE가 1GB 이하면 1Granule이 4MB, 1GB 초과면 1Granule이 16MB가 됨




    ● 관련 파라미터 


    SGA_MAX_SIZE

    SHARED_POOL_SIZE

    DB_CACHE_SIZE



     




    (5) Program Global Area(PGA) 주요 구성 요소


    - 각 프로세스들이 개별적으로 사용하는 메모리 공간

    - 모든 서버 프로세스들은 각각의 PGA를 가짐

    - 주로 정렬관련 작업등이 이루어짐





    ● Private SQL Area

    - Persistent Area와 Runtime Area로 나뉨

    - 사용자가 SQL 문장을 수행하면 User Process가 Server Process에게 해당 쿼리를 전달해 주는데 이때 Server Process가 자신에게 작업을 요청한 User Process의 정보를 Session Memory부분에 저장을 한 후 해당 SQL을 Parse함

    - 해당 SQL에 Bind 변수 등이 있을경우 해당 Bind변수값을 Persistent Area에 저장함

    - 쿼리의 실행 상태정보와 쿼리를 수행하면서 임시로 정보를 저장해야 하는 경우 Runtime Area에 저장함




    ● SQL Work Area

    - Sort 관련 작업(Sort Area)이나 Hash 관련 작업을 수행하는 공간

    - 9i부터 PGA크기를 Oracle Server가 자동으로 관리할 수 있음

    - 관련 파라미터

     

     PGA_AGGREGATE_TARGET= PGA 총량 지정

     WORKAREA_SIZE_POLICY=AUTO (동적관리), MANUAL (수동관리)

     


    * 1개의 개별 Server Process가 쓸 수 있는 PGA 메모리량

     

     _SMM_MAX_SIZE

     



    - 현재 서버의 PGA관련값 조회

     

     SYS> SELECT * FROM v$pgastat;

     










    참고

    - 오라클 관리 실무 (서진수. 생능출판사. 2013)

    - 사진출처:https://docs.oracle.com/database/121/CNCPT/intro.htm#CNCPT-GUID-2B1BADE1-C36F-4555-9867-3B15B6CE858C




    각주


    1. DB Buffer Cache에 있는 변경 완료된 데이터(dirty buffer)를 데이터 파일로 저장해 주는 백그라운드 프로세스. [본문으로]
    2. 마치 은행의 번호표처럼 순서를 정해주는 역할, 모든 메모리 자원에는 각 Latch가 별도로 존재함. [본문으로]



    RAC_ASM설치 ( OEL5 + ORACLE 11g )






    6. DB생성




    - 재부팅하고 oracle계정으로 로그인후 dbca 시작


    [oracle@rac1 ~]$ dbca






















     

















     





    - DB생성 확인



    [oracle@rac1 database]crs_stat -t






     











    RAC_ASM설치 ( OEL5 + ORACLE 11g )







    4. 11g Engine 설치



    grid 설치 완료후 재부팅하고 oracle계정으로 로그인. 





     engine 설치 시작 



    [oracle@rac1 ~]$ cd database

    [oracle@rac1 database]$ ./runInstaller

     



























     



    - node1,2에서 각각 스크립트 실행



    [oracle@rac1 ~]$ su -

    [oracle@rac1 ~]# /app/oracle/11g/db/root.sh


     


    - Engine설치완료






    5. ASM 구성



    - ASM configuration assistant 실행


    [oracle@rac1 ~]$ asmca

      






     









     










            -  상태확인




    [oracle@rac1 database]$ crs_tat -t