문제 26. 커미션이 null 이 아닌 사원들의 이름과 월급과 커미션을 출력하시오!
 
SQL>  select ename, sal, comm
          from emp
       where comm is not null;



문제 27. 직업이 SALESMAN이고 월급이 1000 이상인 사원들의 이름과 월급과 직업을 출력하시오!

 SQL> select ename, sal, job
           from emp 
           where job = 'SALESMAN' and sal >= 1000

Tip.
  컬럼 별칭을 정할 수 있다.
  ex) sal as 월급

주위! 아래와 같은 경우는  오라클 실행 순서에 의해서 에러가 남

    SQL>  select ename, sal as 월급, job
              from emp 
            where job = 'SALESMAN' and 월급 >= 1000
 


문제 28. EMP 테이블의 모든 컬럼을 출력하시오! 

SQL > select *
          from emp;


문제 29. dept 테이블의 모든 컬럼을 출력하시오! 

SQL > select * 
          from dept;

'*'의 의미 
 - 'asterisk'가 불리며 select 절에 사용 시 해당 테이블의 모든 컬럼을 출력한다.  


문제 30. SQL 작성 규칙이 어떻게 되는가?
    
   1. SQL은 대소문자를 구분하지 않는다. (주로 keyword를 대문자로 구분)
   2. 한줄 또는 여러줄에 입력할 수 있다. (아래로 작성할 수 있다는 것이 중요)
   3. 키워드는 약어로 표시하거나 여러줄에 나뉠 수 없다. (keyword는 select, from 과 같은 것들)
   4. 절은 별도의 절에 입력해야 하는 것이 좋다 
   5. 가독성을 높이기 위해서 들여쓰기를 사용해라 
 

문제 31. 아래의 쿼리의 컬럼명은 대문자로 출력되는가 소문자로 출력되는가?

SQL > select ename, sal, deptno
            from emp; 

answer) 대문자로 출력 됨 


문제 32. 위의 컬럼명을 소문자로 출력되게하시오! 

SQL > select ename, sal, deptno
            from emp; 

answer > select ename as "ename", sal as "sal", deptno
            from emp; 

* " "(더블쿼테이션 마크)를 사용해야 하는 때는

  1. 컬럼별칭 사용시 대소문자를 구분하고 싶을때 
  2. 컬럼별칭 사용시 공백문자나 특수문자를 출력하고 싶을때  


문제 33. 사원이름과 월급을 출력하는데 컬럼 별칭을 이용해서 아래와 같이 결과가 출력되게 하시오! 

컬럼명  ---> Employee, Salary

SQL > select ename as "Employee", sal as "Salary"
            from emp;

* 여기서 'as'는 생략 가능


문제 34. 연봉이 36000이상인 이름과 연봉(sal*12)을 출력하는데 컬럼명이 한글로 이름, 연봉으로 출력되게 하시오  !

SQL > select ename as 이름, sal*12  as 연봉 
           from emp
           where sal*12 >= 36000;

주의! 연산 순서도 중요하다 
sal*12+300 은 sal+300*12와 다르다.


문제 35. 이름과 직업을 출력하는데 아래와 같이 컬럼명을 사원의 이름, 사원의 직업이라고 출력하시오!
   
            - 사원의 이름, 사원의 직업 

SQL > select ename as "사원의 이름", job as "사원의 직업"
            from emp;


문제 36. 직업을 출력하는데 중복을 제거해서 출력하시오!

SQL > select distinct job
            from emp;


문제 37. 부서번호를 출력하는데 중복제거해서 출력하시오!

SQL > select distinct deptno
            from emp;


문제 38. 이름과 월급을 연결해서 출력하시오!

SQL >  select ename ||'의 월급은' ||sal
             from emp; 


*연결 연산자  :  '||'(수직바 2개)

* MS SQL 은 concat을 사용해서 연결한다 
  SQL> select concat (ename, '의 월급은', sal) 
            from emp ;

문제 39. 아래와 같이 결과를 출력하시오!

    KING 의 직업은 PRESIDENT 입니다. 

SQL > select ename||' 의 직업은 '||job||' 입니다.'
           from emp;


문제 40. 1-23쪽 (대체 인용 연산자)을 참고해서 문제를 해결하시오!

             아래와 같이 결과를 출력하시오 !

             SMITH의 부서번호는 '20'번 이고 직업은 CLERK 입니다. 

 SQL > select ename||'의'|| q'['부서번호'는]'||deptno||'번 이고 직업은'||job||'입니다'
           from emp;

* MS SQL 에서 싱글쿼테이셥 select 방법 
 SQL> select concat (ename, '''의 월급은''', sal) 
          from emp ;


문제41. DEPT 테이블의 구조를 확인하시오!

 SQL > desc dept 

* MS SQL 에서 테이블 컬럼 구조 확인 

 SQL> sp_columns dept ;




2장. data 검색 제한과 정렬 



1. where 절
2. order by 절

문제 42. 20번 부서번호에서 근무하는 사원들의 이름과 월급과 부서번호를 출력하시오!

SQL > select ename, sal, deptno
          from emp
          where deptno = 20;


문제 43. 부서번호가 20, 30번에서 근무하는 사원들의 이름과 부서번호를 출력하시오! 

SQL > select ename, deptno
          from emp
          where deptno in (20,30);


문제 44. 80년 12월 11일에 입사한 사원들의 이름과 입사일을 출력하시오! 

SQL > select ename, hiredate
          from emp
          where hiredate = '81/12/11'; (or '81-12-11' , '81.12.11')
                                    '년/달/일'

*양쪽에 싱글 쿼테이션 마크를 사용해야 하느 경우는?
 1) 문자 
 2) 날짜 

 * 날짜를 검색하기 전에 반드시 확인해봐야할 사항 
       - 현재 재가 접속한 세션의 날짜 형식을 확인해야한다. 
*NLS_DATE_FORMAT      RR/MM/DD
                                       년/월/일
         
Tip. 날짜 형식을 확인 하는 방법
          SQL> select* 
                     from nls_session_parameters;
                     (nls/ National Language Support) 
         
 Tip. 컬럼 출력 포맷 변경 방법
        column parameter(column 명) format a20(a숫자) 
        keyword 'column'은 SQL*PLUS  명령어

* MS SQL 에서 날짜 형식 확인 방법 
   SQL> select GETUTCDATE() ;


문제 45. 현재 세션의 날짜 형식중 년도를 4자리로 표시되게 하시오!

SQL> alter session set nls_date_format='RRRR/MM/DD';

Tip.
    접속하고 나서 접속을 끊을때까지가 하나의 'session'
    so. 그래서 현재 상태는 하나의 세션에서만 유요함 (=종료하기 전까지만) 

*MS SQL도 날짜 형식 변환은 가능하지만 현재까지의 자료로는 시스템의 날짜 형식의 변환은 안되는 것으로 보인다. 
   - 추후 더 알아봐야 함 


문제 46. 1983년 1월 15일에 입사한 사원들의 이름과 입사일을 출력하시오!

SQL> select ename, hiredate
          from emp
          where hiredate = '1983/01/15'

* MS SQL 에서는 날짜 변환의 개념이 오라클과 약간 다르다. 

1) 아래의 명령을 사용하면 조회시 사용하고자 하는 날짜 형식을 바꿀 수 있다.  
  SQL> select CONVERT(char(10),current_timestamp,111) ;

  SQL> select ename, hiredate
           from emp 
         where hiredate = '1981/11/17' ;

2) 그러나, select 시 나오는 날짜 형식은 변하지 않았다. 
   아래의 문장 출력 시 기존에 입력된 날짜 형식으로 출력되어서 나온다. 

  SQL> select ename, hiredate
           from emp 
         where hiredate = '1981/11/17' ;

3) 또한, 날짜 형식을 바꿔도 시스템 현재의 날짜 형식은 바뀌지 않는다. 
 
  SQL> select GETUTCDATE() ;


문제 47. 1981년도에 입사한 사원들의 이름과 입사일을 출력하시오 !

SQL> select ename, hiredate
         from emp
         where hiredate like '1981%' or('1981/%/%'로 하면 날짜까지 가능함)

SQL> select ename, hiredate
         from emp
         where hiredate between '1981/01/01' and '1981/12/31';
         (이것이 좋은, 효율적인 SQL 이다.)

* '=' 은 완벽하게 같을 때만 사용한다.


문제 48. 이름에 끝글자가 T로 끝나는 사원들의 이름을 출력하시오!

SQL> select ename
         from emp
         where ename like '%T'


문제 49. 이름의 두번째 철자가 %인 사원의 이름을 출력하시오!

SQL> select ename
         from emp
         where ename like '_m%%'  escape 'm'
        

문제 50. 아래의 data를 입력하고 이름의 두번째 철자와 세번째 철자가 %인 사원의 이름을 출력하시오!

             insert into emp(empno, ename, sal)
               values(3456,'A%%B',4500);

           commit;

SQL > select ename
            from emp
            where ename like '_m%m%%' escape 'm'


문제 51. 직업이 SALESMAN이고 30번 부서번호에서 근무하는사원들 중 월급이 1000아상인 사원들의 이름과 월급과 직업과 부서번호를 출력하시오! 

SQL > select ename, sal, job, deptno
           from emp
           where job ='SALESMAN' and deptno = 30 and sal >= 1000;

*우선 순위 규칙이 있다. 
  (참고 and 는 or 보다 우선작동한다, or를 먼저 우선하고 싶으면 괄호를 사용한다.)


문제 52.  이름과 월급을 출력하는데 월급이 낮은 사원부터 높은 사원순으로 출력하시오! 

SQL > select ename, sal
           from emp
           order by sal asc;

*order by 절 사용법 
  - order by 절은 코딩 & 실행 순서 모두 맨 마지막에 실행된다. 

Tip. asc는 ascend의 약자 


문제 53. 이름과 월급을 출력하는데 월급이 높은 사원부터 출력하시오!

SQL > select ename, sal
           from emp
           order by sal desc

Tip. desc는 descend의 약자 


문제 54. 직업이 SALESMAN인 사원들의 이름과 직업과 월급을 출력하는데 월급이 높은 사원부터 출력하시오! 

 SQL>  SELECT ename, JOB, sal
              FROM EMP
              WHERE job='SALESMAN'
             ORDER BY sal DESC;

(이 문제 부터 SQL Gate 2010 사용)


문제 55. 3번 부서번호인 사원들의 이름과 입사일을 출력하는데 최근에 입사한 사원부터 출력하시오! 

 SQL> SELECT ename, hiredate
            FROM EMP
            WHERE deptno = 30
            ORDER BY hiredate DESC;


문제 56. 자살데이터를 입력받기 위한 테이블을 생성하시오!

SQL > create table sucide
            (country varchar2(40),
              male number(10),
              female number(10),
              average number(10) ); 

* create talbe '테이블명'


문제 57. 나라이름과 남자 자살 데이터를 출력하는데 남자 자살 데이터가 많은 순서대로 출력하시오! 

SQL > SELECT country, male
             FROM sucide
             ORDER BY male DESC nulls last;

Tip. 
nulls last를 쓰면 null data를 가장 뒤로 보낸다. 


문제 58. 우리나라의 평균 자살수가 어떻게 되는지 출력하시오! 

SQL > SELECT average
            FROM sucide
            WHERE country ='South Korea6 ';
 


* 추가할 내용 _ SQL gate에서 데이터 추가하는 법*

1. '도구' 옵션 클릭 
2. '데이터 가져오기' 클릭
3. 테이블 찾기 (미리 생성한)
4. 데이터 종류 선택
5. 데이터를 찾아서 선택
6. 필드 구분 기호 (쉼표)
7. 첫열 '2'로 변경  













가끔 프랑스 영화를 본다. 

내가 본 프랑스 영화들을 솔직히 별로 재미 없었지만, 

보게 된 이유는 소재의 참신함 때문이었다. 

이번에 보게 된 '이웃집에 신이 산다' 또한 소재의 참신함으로 보게 되었다. 

이웃집에 신이 산다는 소재 (솔직히 말하면 이웃집은 아니지만) 즉 우리와 비슷한 일상으로 신이 산다는 발상이 참신하였다. 

그 발상의 참신함에 다시 한 번 믿어보기로 했고 보게 되었다. 

그러나 역시나 아직 나의 식견과 생각의 깊이가 부족했던 것인지 무슨 말을 하고 싶었던 것인지 알지 못하였다. 

뭐 억지로 감정과 감동을 지어내자면 못하는 것도 아니지만 실제로 느꼈고 이해하지 못했다. 

그래도 한 가지 생각해보았던 것은 있다. 

만약 영화에서 처럼 나에게 남은 수명을 알게 된다면 그리고 그 남은 수명이 얼마 남지 않았다면 나는 무엇이 하고 싶을까?

이 영화에서는 가끔 얼마 남지 않은 수명 또는 길게 남은 수명으로 말도 안되는 행동들을 하지만 과연 나의 경우는 무엇일까?

어쩌면 많은 사람들이 직면하고 있는 문제들이 죽음을 앞두고는 의미 없는 일을 될지도 모른다. 

특히 자신이 하고 싶은 일을 하지 못하고 미래에 생활에 대한 두려움에 원치 않는 삶을 사는 사람들은 과연 얼마 남지 않은 수명에 

자신이 진정 원했던 일을 시작할 수 있을까?

그리고 그들이 진정 원했던 것들을 무엇일까?

가끔 이와 비슷한 주제를 말하는 영화나 책들을 보면 자신이 내일 죽게 된다면 하고 싶은 일을 지금 당장하라는 메시지를 던지는 경우가 종종 있다. 

영화 '라스트 홀리데이'도 그와 비슷한 영화이다. 

그러나 실제 삶이 평범한 삶이 아니라면 오늘도 어떻게 될지 모르는 불안한 삶이라면 그들에게 얼마 남지 않은 수명의 의미는 무엇일까?

단순히 자신이 진정 원하는 일을 하라라고 모두에게 똑같이 이야기 할 만큼 사회는 세상은 그렇게 녹록하지 않다. 

그래도 물론 이 영화는 마지막은 기존과 비슷한 결론을 내린다. 

난 아직 잘 모르겠다. 

이 영화가 던지는 메시지의 깊이와 이해를 그리고 나의 생이 얼마 남지 않았다면 진정하고 싶은 것이 무엇인지  

''리뷰'' 카테고리의 다른 글

<여인의 향기>  (0) 2014.11.10
<은하수를 여행하는 히치하이커를 위한 안내서>  (0) 2014.10.26



1장. 인덱스의 원리와 활용


(1) 인덱스의 구조

  - 인덱스 키 컬럼 + rowid 

  -  null 값에는 index가 생성 되지 않는다.
  -  인덱스의 구조를 보고 싶은데 where 절에 적절하게 이용할 조건이 없다면 ?
    (인덱스를 통하려면 무조건 where 절에 해당 인덱스 컬럼이 존재해야 한다.)
    1) 숫자 > 0
    2) 문자 > ' '
    3) where ename < to_date('9999/12/31','RRRR/MM/DD')

 * 해당 index에서 ename is not null 로 걸면 index full table scan 이 된다.
 
(2) index를 사용하지 못하는 경우
   1) 인덱스 컬럼이 가공이 되면 인덱스 엑세스가 안된다.
       ( where 조건절에 인덱스 컬럼이 가공이 되면 정상적으로 인덱스를 엑세스 할 수 없다.)
  
         - 명시적 형변환
         - 묵시적(암시적) 형변환 
               - 숫자가 우선 순위에 있다.
               - 비교하는값이 문자라면 컬럼 값이 숫자여도 문자로 변환된다.     
               - 묵시적 형변환으로 인하여 함수 기반 인덱스를 생성할 경우도 있다.
                 (그러나 그렇게 추천할 만한 사항은 아니다.)  

     2) 부정형 비교시

       * 오라클 옵티마이저가 제대로 작동하지 않는다면 ( 정렬시 컬럼 값이 정렬되어 있지 않다면) SQL 문에 힌트를 사용한다.
          (힌트 (hint) - 실행계획에 영향을 미치는 명령어)
       * 와일드 카드를 앞에 사용하면 index range scan 이 안된다.

(3) 다양한 인덱스 스캔 방식

     1) Data를 엑세스 하는 방법
            ⑴ 테이블 엑세스 방법
                - rowid 에 의한 data 검색
                - full table scan
        
           ⑵ 인덱스 엑세스 방법
                - index range scan
                - index full scan
                - index unique scan
                - index skip scan
                - index fast full scan
                - index merge scan
                - index bitmap merge scan
                - index join

    2) rowid 에 의한  data 검색
         - 하나의 row를 검색하는 가장 빠른 방법

            ⑴ rowid란
                - row의 물리적 주소 (file#+block#+row#)

            ⑵ rowid hint

              - /*+ rowid(테이블명) */

            예시)
              SELECT ename ,sal
                FROM EMP
             WHERE ROWID = 'AAASlIAAEAAAALuAAL';


 * SQL_실행계획 읽는 법

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |     2 |    40 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP     |     2 |    40 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | EMP_SAL |     2 |       |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
  -> 가장 안 쪽으로 들어가 있는 부분부터 읽으면서 위로 올라간다.


문제 1. 부서번호의 인덱스를 생성하고 부서번호에 인덱스의 구조를 확인하시오!

SQL> create index emp_deptno
            on emp(deptno) ;

SQL> select deptno, rowid
           from emp
         where deptno > 0 ;


문제 2. 아래의  SQL 의 실행계획을 확인해서 SQL을 처리할 때 테이블을 엑세스 하지 않고 인덱스만 엑세스 했다는 것을 확인하시오!

SQL> select deptno, rowid
          from emp
       where deptno > 0 ;


문제 3. 사원 테이블에 월급에 인덱스르 걸고 월급에 걸린 인덱스의 구조를 확인 하시오 !

SQL> create index emp_sal
             on emp(sal) ;

SQL> select sal, rowid
          from emp
          where sal > 0;

* null 값에는 index가 생성 되지 않는다.


문제 4. 사원테이블에 ename 에 인덱스를 걸고 ename에 걸린 인덱스의 구조를 확인하시오!

SQL> create index emp_ename
             on emp(ename);

SQL> select ename, rowid
          from emp
         where  ename > ' ';

* 인덱스의 구조를 보고 싶은데 where 절에 적절하게 이용할 조건이 없다면 ?
    (인덱스를 통하려면 무조건 where 절에 해당 인덱스 컬럼이 존재해야 한다.)

1) 숫자 > 0
2) 문자 > ' '
3) where ename < to_date('9999/12/31','RRRR/MM/DD')

* 해당 index에서 ename is not null 로 걸면 index full table scan 이 걸린다.


문제 5. 입사일에 인덱스를 걸고 입사일에 걸린 인덱스의 구조를 확인하시오!

SQL> create index emp_hiredate
            on emp(hiredate) ;

SQL> SELECT /*+ index_asc(emp emp_hiredate) */ hiredate, rowid
            from emp
        WHERE hiredate < TO_DATE('9999/12/31','RRRR/MM/DD') ;

* 오라클 옵티마이저가 제대로 작동하지 않는다면 ( 정렬시 컬럼 값이 정렬되어 있지 않다면) SQL 문에 힌트를 사용한다.
* 힌트 (hint) - 실행계획에 영향을 미치는 명령어


문제 6. 월급이 1000에서 3000 사이인 사원들의 이름과 월급을 출력하는데 월급이 높은사원부터 출력하시오!

SQL> SELECT /*+ index_desc(emp emp_sal) */ ename, sal
            from emp
        WHERE sal BETWEEN 1000 AND 3000  ;

*  order by 절은 성능을 느리게 한다.
 

문제 7. 1981년도에 입사한 사원들의 이름과 입사일을 출력하는데 최근에 입사한 사원부터 출력하시오!

SQL> SELECT /*+ index_desc(emp emp_hiredate) */ ename,hiredate
        FROM emp
      WHERE hiredate between TO_DATE('1981/01/01','RRRR/MM/DD') AND TO_DATE('1981/12/31','RRRR/MM/DD');

* 위의 SQL이 Full table scan 이유
    - where  조건절에 인덱스 컬럼이 가공이 되면 정상적으로 인덱스를 엑세스 할 수 없다.


문제 8. 월급이 3000인 사원들의 이름과 월급을 출력하시오!

explain plan for
  SELECT ename, sal
  FROM emp
  WHERE sal=3000;

select * from table(dbms_xplan.display);


문제 9. 이름이 SCOTT 인 사원의 이름과 월급과 직업을 출력하는 실행계획을 출력하시오 !

SQL> explain plan for
    2   select ename, sal
    3  from emp
    4  where ename='SCOTT';

SQL> select * from table(dbms_xplan.display);


PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 106684950

-----------------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows    | Bytes | Cost (%CPU)| Time    |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |        |     1 |    20 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    20 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN        | EMP_ENAME |     1 |    |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("ENAME"='SCOTT')

Note
-----
   - dynamic sampling used for this statement (level=2)


문제 10. 아래의 SQL 을 튜닝하시오 !

튜닝 전 :

select ename, sal *12 연봉
  from emp
where sal*12 =36000;

튜닝 후 :

SELECT /*index_desc(emp emp_sal)*/ename, sal*12 연봉
FROM EMP
WHERE sal = 36000/12;


문제 11. 아래의 SQL을 튜닝하시오!

create index emp_job
on emp(job);

튜닝 전 : 
select ename, job, sal
                from emp
              where substr(job,1,5)='SALES';

튜닝 후:
SELECT /*+ index(emp emp_job) */ ename, job, sal
  FROM EMP
  WHERE job LIKE 'SALES%' ;

※ 와일드 카드를 앞에 사용하면 index range scan 이 안된다.


문제 12. 아래의 데이터를 입력하고 오늘 입사한 사원의 이름과 입사일을 출력하시오!

SELECT ename, hiredate
FROM EMP
WHERE hiredate >= to_date('16/01/08','RR/MM/DD')
AND hiredate < TO_DATE('16/01/08','RR/MM/DD')+1;


문제 13. 아래의 SQL 을 튜닝하시오 !

- 조건
CREATE TABLE EMP700
  (ename VARCHAR2(20),
   SAL VARCHAR2(20));


CREATE INDEX emp700_sal
ON emp700(sal);


튜닝전 :

select ename, sal
from emp700
where sal = 3000;

* 위의 경우 실제 실행 방법

Plan hash value: 3880125747

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |       |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| EMP700 |     1 |    24 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(TO_NUMBER("SAL")=:SYS_B_0)

Note
-----
   - dynamic sampling used for this statement (level=2)

튜닝후:

SELECT /*+ index(emp700 emp700_sal) */ ename, sal
from emp700
where sal = '3000';

* SQL*plus 에서 실제 실행계획을 보는 명령어

-  select *
from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST +alias +outline +predicate'))
/


문제 14. 아래의 SQL의 결과가 출력되겠는가?

튜닝 전 :
select ename, sal
from emp
where sal like '30%';

* 해당 경우는 모델이 잘 못 된 경우로 해당 상태는 프로그램 수정으로는 튜닝이 안된다.
    So. 프로그램 수정이 아닌 다른 방법을 사용해야 한다. 

튜닝 후 : 
( 함수 기반 인덱스를 생성한다. )
create index emp_sal_func
on emp(to_char(sal));

select /*+ index(emp emp_sal_func) */ename, sal
from emp
where sal like '30%';

select /*+ index(emp emp_sal_func) */ename, sal  
from emp 
where sal like :"SYS_B_0"

( 바인드 변수 사용 )

Plan hash value: 3983152063

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |       |       |     4 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP          |    16 |   672 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | EMP_SAL_FUNC |    16 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

문제 15. 아래의 data를 입력하고 이름이  JANE 인 사원의 이름과 월급과 직업을 출력하시오!

튜닝 전:

insert into emp(empno, ename, sal)
valuse(2345, '   JANE  ', 4600);

튜닝 후

create index emp_ename_func
on emp(TRIM(ename));

SELECT /*+ index(emp emp_ename_func)*/ ename, sal, job
  FROM EMP
  WHERE TRIM(ename) = 'JANE';


문제 16. 이름이 EN 또는 IN을 포함하고 있는 사원들의 이름과 월급, 직업과 입사일을 출력하시오!

-- 튜닝 전

SELECT ename, sal, job, hiredate
FROM EMP
WHERE ename LIKE '%EN%'
or ename LIKE '%IN%';

OR

SELECT ename, sal, job, hiredate
FROM EMP
WHERE regexp_like(ename,'(EM|IN)');

-- 튜닝 후

SELECT ename, sal, job, hiredate
FROM EMP
WHERE ROWID in (SELECT /*+ index(emp emp_ename) */ rowid
                  from emp
                where ename like '%EN%' or ename like '%IN%') ;

or

SELECT /*+ no_query_transformation rowid(emp) */ ename, sal, job, hiredate
  FROM EMP e,(SELECT /*+ index(emp emp_ename)   */ rowid
                  from EMP
                where ename like '%EN%' or ename like '%IN%') b
WHERE e.ROWID = b.rowid  ;

* 둘의 실행 계획이 다르다. 
  - 바로 검색보다는 서브쿼리르 사용해서 rowid를 먼저 조회하고 검색하는 것이 빠를 수 있다.
  - 어떤 실행계획이 달라서 실행계획을 보고 계산할 수 있을 때까지는 어느것이 더 성능이 좋을 지 모른다.


+ Recent posts