휴지통에 있는것을 복구 하며. 

show recyclebin ; 로는 검색이 안되었다. 이유는 잘 모르겠다...아무래도 DBA 권한 때문인듯도 하고.. 확인은 못함 


/


SELECT * FROM DBA_RECYCLEBIN ORDER BY 1


위 커리로 확인 하자 반드시 OWNER (사용자) 와 드랍일자 데이터 량 등을 확인 하자 

그후 플래쉬백을 사용 해야 하며 TABLE NAME 은 본래 이름이 아닌  두번째 컬럼임 오리지널 네임을 사용 해야 한다. 또한.

본래 테이블 이름의 테이블이 있다면 복구가 안됨으로 DROP CREATE  한경우에 데이터가 없는 테이블을 삭제 해야 한다. 


 flashback table "BIN$VPaE9OG4Qwa+KC0MesYKqw==$0" to before drop;


하면 테이블이 데이터 보존 상태로 그대로 복구 한다. 

'오라클' 카테고리의 다른 글

JOIN!!  (0) 2013.02.06
DB 부하율 검색 쿼리 (1등하면 안좋은것..)  (0) 2013.01.29
컬럼명으로 특정 테이블을 찾는 쿼리  (0) 2012.12.20
connect by  (0) 2012.12.17
패스워드 암호화 .  (0) 2012.12.07
Posted by 사라링

select *

   from all_tab_columns

where owner = 'IBS'

   and column_name = 'RES_NO'

 

 

select *
   from all_tab_columns
where owner = 
'계정명(사용자)'

   and column_name = '컬럼명'

'오라클' 카테고리의 다른 글

DB 부하율 검색 쿼리 (1등하면 안좋은것..)  (0) 2013.01.29
TABLE DROP 복구 하기. PURGE 를 사용한 경우 복구 X  (0) 2013.01.14
connect by  (0) 2012.12.17
패스워드 암호화 .  (0) 2012.12.07
숫자 함수.  (0) 2012.11.15
Posted by 사라링

connect by

2012. 12. 17. 11:17

START WITH ... CONNECT BY 절

설명

계층적 질의란 테이블에 포함된 행(row)간에 수직적 계층 관계가 성립되는 데이터에 대하여 계층 관계에 따라 각 행을 출력하는 질의이다. START WITH ... CONNECT BY 절은 SELECT 구문과 결합하여 사용된다.

구문

SELECT column_list

    FROM table_joins | tables

    [WHERE join_conditions and/or filtering_conditions]

    [START WITH condition]

    CONNECT BY [NOCYCLE] condition

START WITH 절

START WITH 절은 계층 관계가 시작되는 루트 행(root row)을 지정하기 위한 것으로, START WITH 절 다음에 계층 관계를 검색하기 위한 조건식을 포함한다. 만약, START WITH 절에 다음에 위치하는 조건식이 생략되면 대상 테이블 내에 존재하는 모든 행을 루트 행으로 간주하여 계층 관계를 검색할 것이다.

참고 START WITH 절이 생략되거나, START WITH 조건식을 만족하는 결과 행이 존재하지 않는 경우, 테이블 내의 모든 행을 루트 행으로 간주하여 각 루트 행에 속하는 하위 자식 행들 간 계층 관계를 검색하므로 결과 행들 중 일부는 중복되어 출력될 수 있다.

CONNECT BY [NOCYCLE] PRIOR 절
  • PRIOR : CONNECT BY 조건식은 한 쌍의 행에 대한 상-하 계층 관계(부모-자식 관계)를 정의하기 위한 것으로, 조건식 내에서 하나는 부모(parent)로 지정되고, 다른 하나는 자식(child)으로 지정된다. 이처럼 행 간의 부모-자식 간 계층 관계를 정의하기 위하여 CONNECT BY 조건식 내에PRIOR 연산자를 이용하여 부모 행의 컬럼 값을 지정한다. 즉, 부모 행의 컬럼 값과 같은 컬럼 값을 가지는 모든 행은 자식 행이 된다.
  • NOCYCLE : CONNECT BY 절의 조건식에 따른 계층 질의 결과는 루프를 포함할 수 있으며, 이것은 계층 트리를 생성할 때 무한 루프를 발생시키는 원인이 될 수 있다. 따라서, CUBRID는 루프를 발견하면 기본적으로 오류를 반환하고, 특수 연산자인 NOCYCLE CONNECT BY 절에 명시된 경우에는 오류를 발생시키지 않고 해당 루프에 의해 검색된 결과를 출력한다.
    만약, CONNECT BY 절에서 NOCYCLE이 명시되지 않은 계층 질의문을 수행 중에 루프가 감지되는 경우, CUBRID는 오류를 반환하고 해당 질의문을 취소한다. 반면, NOCYCLE이 명시된 계층 질의문에서 루프가 감지되는 경우, CUBRID는 오류를 반환하지는 않지만 루프가 감지된 행에 대해CONNECT_BY_ISCYCLE 값을 1로 설정하고, 더 이상 계층 트리의 검색을 확장하지 않을 것이다.
예제

아래 예제를 참조하여 계층 질의문을 작성할 수 있다. 예제를 실습하기 위해 필요한 데이터베이스 스키마는 다음과 같다.

tree 테이블

ID

MgrID

Name

BirthYear

1

NULL

Kim

1963

2

NULL

Moy

1958

3

1

Jonas

1976

4

1

Smith

1974

5

2

Verma

1973

6

2

Foster

1972

7

6

Brown

1981

tree_cycle 테이블

ID

MgrID

Name

1

NULL

Kim

2

11

Moy

3

1

Jonas

4

1

Smith

5

3

Verma

6

3

Foster

7

4

Brown

8

4

Lin

9

2

Edwin

10

9

Audrey

11

10

Stone

-- tree 테이블을 만들고 데이터를 삽입하기

CREATE TABLE tree(ID INT, MgrID INT, Name VARCHAR(32), BirthYear INT);

 

INSERT INTO tree VALUES (1,NULL,'Kim', 1963);

INSERT INTO tree VALUES (2,NULL,'Moy', 1958);

INSERT INTO tree VALUES (3,1,'Jonas', 1976);

INSERT INTO tree VALUES (4,1,'Smith', 1974);

INSERT INTO tree VALUES (5,2,'Verma', 1973);

INSERT INTO tree VALUES (6,2,'Foster', 1972);

INSERT INTO tree VALUES (7,6,'Brown', 1981);

 

-- tree_cycle 테이블을 만들고 데이터를 삽입하기

CREATE TABLE tree_cycle(ID INT, MgrID INT, Name VARCHAR(32));

 

INSERT INTO tree_cycle VALUES (1,NULL,'Kim');

INSERT INTO tree_cycle VALUES (2,11,'Moy');

INSERT INTO tree_cycle VALUES (3,1,'Jonas');

INSERT INTO tree_cycle VALUES (4,1,'Smith');

INSERT INTO tree_cycle VALUES (5,3,'Verma');

INSERT INTO tree_cycle VALUES (6,3,'Foster');

INSERT INTO tree_cycle VALUES (7,4,'Brown');

INSERT INTO tree_cycle VALUES (8,4,'Lin');

INSERT INTO tree_cycle VALUES (9,2,'Edwin');

INSERT INTO tree_cycle VALUES (10,9,'Audrey');

INSERT INTO tree_cycle VALUES (11,10,'Stone');

 

-- CONNECT BY 절을 이용하여 계층 질의문 수행하기

SELECT id, mgrid, name

    FROM tree

    CONNECT BY PRIOR id=mgrid

    ORDER BY id;

 

id  mgrid       name

======================

1   null        Kim

2   null        Moy

3   1       Jonas

3   1       Jonas

4   1       Smith

4   1       Smith

5   2       Verma

5   2       Verma

6   2       Foster

6   2       Foster

7   6       Brown

7   6       Brown

7   6       Brown

 

-- START WITH 절을 이용하여 계층 질의문 수행하기

SELECT id, mgrid, name

    FROM tree

    START WITH mgrid IS NULL

    CONNECT BY prior id=mgrid

    ORDER BY id;

 

id  mgrid       name

=============================

1   null        Kim

2   null        Moy

3   1       Jonas

4   1       Smith

5   2       Verma

6   2       Foster

7   6       Brown

'오라클' 카테고리의 다른 글

TABLE DROP 복구 하기. PURGE 를 사용한 경우 복구 X  (0) 2013.01.14
컬럼명으로 특정 테이블을 찾는 쿼리  (0) 2012.12.20
패스워드 암호화 .  (0) 2012.12.07
숫자 함수.  (0) 2012.11.15
계층형구조 (CONNECT BY)  (0) 2012.11.05
Posted by 사라링

패스워드 암호화 .

2012. 12. 7. 14:01

No. 12036

 

데이터 암호화 기능 소개(8.1.6 new feature)

=========================================

 

개    요

=========

Oracle 8i Release2(8.1.6)에서는 데이터를 암호화하여 저장할 수 있는 향상된

기능(DES Encryption)을 제공한다

(Oracle 8i Release3(8.1.7)에서는 Triple DES Encryption)

 

즉 신용카드번호, 패스워드 등 보안이 필요한 데이터를 암호화된 형태로 저장하여

기존의 3rd Party Tool이나, Application Logic으로 구현하던 암호화 정책을

데이터베이스 차원에서 구현할 수 있도록 해준다.

 

DBMS_OBFUSCATION_TOOLKIT

========================

암호화 기능을 이용하려면 DBMS_OBFUSCATION_TOOLKIT을 이용해야 한다.

 

이 패키지는 4개의 프로시져로 이루어져 있다.

- VARCHAR2 타입을 Encrypt/Decrypt할 수 있는 2개의 프로시져

- RAW 타입을 Encrypt/Decrypt할 수 있는 2개의 프로시져

(다른 타입은 지원하지 않으므로 number인 경우는 to_char 이용)

 

DBMS_OBFUSCATION_TOOLKIT을 이용하기 위해서는 :

1) SYS 유저로

   @$ORACLE_HOME/rdbms/admin/dbmsobtk.sql

   @$ORACLE_HOME/rdbms/admin/prvtobtk.plb

   

 

2) grant execute on dbms_obfuscation_toolkit to public;

 

 

제 한 사 항

===========

1) DES(Data Encryption Standard) symmetric key algorithm 방식을 이용.

   즉 암호화할 때 이용한 key를 분실했을 경우 데이터를 해독할 방법이 없다.

 

2) Encrypt하려는 data가 8 bytes 배수(8,16,... bytes)이어야 한다.

 

3) 미국무부의 암호화기술 수출제한조치에 의해 56-bit key를 사용.

 

4) 미국무부의 암호화기술 수출제한조치에 의해 한번 암호화된 데이터를

   또다시 암호화할 수 없다.

 

*) 많은 테이블을 Encrypt/decrypt할 경우 CPU 사용량을 증가시킬 수 있다.

*) 아래의 예제는 UTF8을 사용할 경우 한글 데이터를 암호화할 수 없다.

   (RPAD의 제약으로)

 

사 용 예

========

1) encrypt/decrypt에 이용할 FUNCTION을 만든다.

   (만약 input string이 8 byte 배수가 아니면 패딩을 한다)

*) 8.1.6에서는 key값이 8 byte 이상이어야 함(8.1.7 이후에는 제한없음)

 

 

- - - - - - - - - - - - - - - Code begins here - - - - - - - - - - - - - - -

REM ------------------------------------------------------------------------

REM DISCLAIMER:

REM    This script is provided for educational purposes only. It is NOT  

REM    supported by Oracle World Wide Technical Support.

REM    The script has been tested and appears to work as intended.

REM    You should always run new scripts on a test instance initially.

REM ------------------------------------------------------------------------

 

CREATE OR REPLACE PACKAGE CryptIT AS

   FUNCTION encrypt( Str VARCHAR2,  

                     hash VARCHAR2 ) RETURN VARCHAR2;

   FUNCTION decrypt( xCrypt VARCHAR2,

                     hash VARCHAR2 ) RETURN VARCHAR2;

END CryptIT;

/

 

CREATE OR REPLACE PACKAGE BODY CryptIT AS

   crypted_string VARCHAR2(2000);

 

   FUNCTION encrypt( Str VARCHAR2,  

                     hash VARCHAR2 ) RETURN VARCHAR2 AS

   pieces_of_eight INTEGER := ((FLOOR(LENGTH(Str)/8 + .9)) * 8);

 

   BEGIN

 

      dbms_obfuscation_toolkit.DESEncrypt(

               input_string     => RPAD( Str, pieces_of_eight ),

               key_string       => RPAD(hash,8,'#'),

               encrypted_string => crypted_string );

      RETURN crypted_string;

   END;

 

   FUNCTION decrypt( xCrypt VARCHAR2,

                     hash VARCHAR2 ) RETURN VARCHAR2 AS

   BEGIN

      dbms_obfuscation_toolkit.DESDecrypt(

               input_string     => xCrypt,

               key_string       => RPAD(hash,8,'#'),

               decrypted_string => crypted_string );

      RETURN trim(crypted_string);

   END;

END CryptIT;

/

 

- - - - - - - - - - - - - - -  Code ends here  - - - - - - - - - - - - - - -

 

 

2) Encrypt하여 데이터 입력

 

drop table encrypt_table;

create table encrypt_table( id number, passwd varchar(10) );

 

insert into encrypt_table values( 1, CryptIT.encrypt('tiger', 'key_a'));

insert into encrypt_table values( 2, CryptIT.encrypt('tiger', 'key_b'));

 

3) Decrypt하여 데이터 조회

 

SQL> select id, passwd from encrypt_table where passwd = 'tiger';

 

no rows selected

 

-> 물론 Decrypt하지 않으면 암호화된 데이터와 비교된다.

 

주의) encrypt된 데이터를 화면에 출력하면, terminal emulator가 오작동할 수 있다.

      그럴 경우, terminal emulator 프로그램 종료 후 다시 시작.

 

SQL> col passwd format a60

SQL> select id, dump(passwd) passwd from encrypt_table;

 

        ID PASSWD

---------- -------------------------------------------------------------

         1 Typ=1 Len=8: 246,27,80,184,227,225,245,31

         2 Typ=1 Len=8: 175,231,213,125,85,223,46,133

 

 

-> 저장장치에 Encrypt된 값으로 저장된다.

 

select id, CryptIT.decrypt(passwd,'key_a') passwd

from encrypt_table

where CryptIT.decrypt(passwd,'key_a') = 'tiger';

 

        ID PASSWD

---------- -------------------------------------------------------------

         1 tiger

 

select id, CryptIT.decrypt(passwd,'key_b') passwd

from encrypt_table

where CryptIT.decrypt(passwd,'key_b') = 'tiger';

 

        ID PASSWD

---------- ------------------------------------------------------------

         2 tiger

 

-> Encrypt할 때 사용한 Key로만 Decrypt할 수 있다.

 

주의) Table에 접근 권한이 있는 다른 유저도 Key값을 알면 Decrypt할 수 있다.

 

4) 관련 ORA number

ORA error 28231 "Invalid input to Obfuscation toolkit"

- input data, key값이 NULL일 경우 발생

 

ORA error 28232 "Invalid input size for Obfuscation toolkit"

- input data가 8 bytes 배수가 아닐 경우 발생

 

ORA error 28233 "Double encryption not supported by DESEncrypt in Obfuscation toolkit"

- encrypt data를 다시 encrypt경우 발생

 

 

관 련 자 료

===========

Oracle8i Supplied PL/SQL Packages Reference Release 2 (8.1.6)

'오라클' 카테고리의 다른 글

컬럼명으로 특정 테이블을 찾는 쿼리  (0) 2012.12.20
connect by  (0) 2012.12.17
숫자 함수.  (0) 2012.11.15
계층형구조 (CONNECT BY)  (0) 2012.11.05
토드 에서 벌레의 의미..;  (0) 2012.11.02
Posted by 사라링

숫자 함수.

2012. 11. 15. 19:23

ABS(n) 

ABS함수는 절대값을 계산하는 함수입니다. 

SQL>SELECT ABS Absolute FROM dual ; 

Absolute
-------- 
       10
(-10)



CEIL(n)
 

CEIL함수는 주어진 값보다는 크지만 가장 근접하는 최소값을 구하는 함수입니다. 

SQL>SELECT CEIL TEST FROM dual ; 

  TEST
------- 
      11 
(10.1)

SQL>SELECT CEIL TEST FROM dual ; 

   TEST 
------- 
     -10
(-10.1)



EXP(n)

EXP함수는 주어진 값의 e의 승수를 나타냅니다. 
e는 2.171828183..입니다. 



FLOOR(n)
FLOOR함수는 주어진 값보다 작거나 같은 최대 정수값을 구하는 함수입니다. 
CEIL 함수와 비교해 보세요. 

SQL>SELECT FLOOR TEST FROM dual ; 

    TEST 
 ------- 
       10 
(10.1)

SQL>SELECT FLOOR TEST FROM dual ; 
   
    TEST 
------- 
      -11
(-10.1)



LN(n)
 

LN함수는 주어진 값의 자연로그 값을 반환합니다. 



MOD(m, n)
 

MOD함수는 m을 n으로 나누어 남은 값을 반환한다. n이 0일 경우 m을 반환합니다. 

SQL>SELECT MOD TEST FROM dual ; 

    TEST 
  ------- 
         1
(9, 4)



POWER(m, n)
 

POWER함수는 m의 n승 값을 계산합니다. 

SQL>SELECT POWER TEST FROM dual ; 
       
      TEST 
   ------- 
         16
(4, 2)



ROUND(n, [m])

ROUND함수는 n값의 반올림을 하는 함수로 m은 소숫점 아래 자릿수를 나타낸다. 

SQL>SELECT ROUND TEST FROM dual ; 

      TEST 
   ------- 
      192.1 
(192.123, 1)

SQL>SELECT ROUND TEST FROM dual ; 

     TEST 
   ------- 
       190
(192.123, -1)



SIGN(n)
 

SIGN함수는 n<0일 경우 -1DFM N=0일 경우 0을 N>0일 경우 1을 반환합니다. 



SQRT(n)

SQRT함수는 n값의 루트값을 계산한다. n은 양수여야 합니다. 



TRUNC(n, m) 


 TRUNC함수는 n값을 m 소숫점 자리로 반내림한 값을 반환합니다. 
 ROUND 함수와 비교해 보세요..

SQL>SELECT TRUNCTEST FROM dual ; 

    TEST 
 ------- 
     7.55 

SQL>SELECT TRUNC TEST FROM dual ; 

    TEST 
 ------- 
     5200
 (5254.26, -2 )
(7.5597, 2)


'오라클' 카테고리의 다른 글

connect by  (0) 2012.12.17
패스워드 암호화 .  (0) 2012.12.07
계층형구조 (CONNECT BY)  (0) 2012.11.05
토드 에서 벌레의 의미..;  (0) 2012.11.02
TOAD 단축키  (0) 2012.10.31
Posted by 사라링

계층형구조 (CONNECT BY)

2012. 11. 5. 10:34

===================================================================

[예]


SELECT

        LEVEL AS LEV

      , MENU.*

FROM

        TBL_MENU  MENU

WHERE               MENU_TYPE_CD = '1'

START WITH          MENU.MENU_ID = 'TOP'

CONNECT BY PRIOR    MENU.MENU_ID = MENU.UP_MENU_ID

ORDER SIBLINGS BY   MENU_SEQ


===================================================================

[풀이]


UP_MENU_ID 가 'TOP'인 것부터 순환고리를 시작하며 

동일 레벨일경우(즉, UP_MENU_ID 가 'TOP'으로 하는 여러 ROW)는 MENU_SEQ가 먼저인것 부터 계층구조

그리고 마지막으로 MENU_TYPE_CD가 '1'인것만 최종 추출


===================================================================



◈ LEVEL 예약어 : depth


◈ CONNECT BY의 실행순서

    (1) START WITH 절

    (2) CONNECT BY 절

    (3) WHERE 절


◈ 

    START WITH : 시작위치 설정 (서브쿼리를 사용가능)

    CONNECT BY : 순환고리의 조건 (서브쿼리를 사용불가)

    ORDER SIBLINGS BY : 같은 레벨중 순환고리 순서를 정할때 사용


◈ PRIOR 의 위치 

    (1) CONNECT BY PRIOR 자식컬럼 =       부모컬럼  ==> 부모에서 자식으로 트리 구성

    (2) CONNECT BY       자식컬럼 = PRIOR 부모컬럼  ==> 자식에서 부모으로 트리 구성


◈ 데이터가 많아질 경우....


    - START WITH MENU_ID = 'TOP' 

          MENU_ID 컬럼에 index가 생성되어 있지 않는다면 속도를 보장할 수 없습니다.


    - CONNECT BY PRIOR MENU_ID = UP_MENU_ID 

          역시 PRIOR 쪽의 컬럼값이 상수가 되기 때문에 UP_MENU_ID컬럼에 index를 생성하여야 CONNECT BY의 속도를 보장할 수 있습니다.


    - 계층구조를 CONNECT BY, START WITH로 풀면 부분범위 처리가 불가능하고 Desc으로 표현하기가 어렵 습니다.


◈  

    (1) '상품' 메뉴는 모두 출력 안함.

    SELECT

            LEVEL AS LEV

          , MENU.*

    FROM    

            TBL_MENU  MENU

    WHERE               MENU.MENU_NAME  <> '상품'

    START WITH          MENU.MENU_ID = 'TOP'

    CONNECT BY PRIOR    MENU.MENU_ID = MENU.UP_MENU_ID

    ORDER SIBLINGS BY   MENU_SEQ 

    

    (2) '상품'메뉴 밑으로 모든 메뉴는 출력안함.

    SELECT

            LEVEL AS LEV

          , MENU.*

    FROM    

            TBL_MENU  MENU

    START WITH          MENU.MENU_ID    = 'TOP'

    CONNECT BY PRIOR    MENU.MENU_ID    = MENU.UP_MENU_ID

    AND                 MENU.MENU_NAME  <> '상품'

    ORDER SIBLINGS BY   MENU_SEQ 

    

    ** 참고) 메뉴중 2LEVEL까지만 결과 출력

    (WHERE조건으로도 LEVEL <= 2가능함. 그러나 권하지는 않는다. 

     왜? WHERE 조건은 모든 나온결과에 대해서 FILTER하지만 CONNECT BY절의 조건으로 넣으면 순환자체를 안한다. 즉 성능에 좋다)

    SELECT

            LEVEL AS LEV

          , MENU.*

    FROM    

            TBL_MENU  MENU

    START WITH          MENU.MENU_ID    = 'TOP'

    CONNECT BY PRIOR    MENU.MENU_ID    = MENU.UP_MENU_ID

    AND                 LEVEL  <= 2

    ORDER SIBLINGS BY   MENU_SEQ     

   

    

◈ 

    (1) 들여쓰기로 결과출력

    SELECT

            LPAD(’ ’, 4*(LEVEL-1)) || MENU.MENU_NAME

          , MENU.*

    FROM

            TBL_MENU  MENU

    WHERE               MENU_TYPE_CD = '1'

    START WITH          MENU.MENU_ID = 'TOP'

    CONNECT BY PRIOR    MENU.MENU_ID = MENU.UP_MENU_ID

    ORDER SIBLINGS BY   MENU_SEQ

    

    (2) 엑셀과 같이 셀 단위로 들여쓰기

    SELECT 

             DECODE(LEV, '1', MENU_NAME, '') AS LEV1

           , DECODE(LEV, '2', MENU_NAME, '') AS LEV2

           , DECODE(LEV, '3', MENU_NAME, '') AS LEV3

           , DECODE(LEV, '4', MENU_NAME, '') AS LEV4

           , DECODE(LEV, '5', MENU_NAME, '') AS LEV5

    FROM

           (

             SELECT

                     LEVEL AS LEV

                   , MENU.*

             FROM    TBL_MENU  MENU

             WHERE               MENU_TYPE_CD = '1'

             START WITH          MENU.MENU_ID = 'TOP'

             CONNECT BY PRIOR    MENU.MENU_ID = MENU.UP_MENU_ID         

             ORDER SIBLINGS BY   MENU_SEQ 

           )



'오라클' 카테고리의 다른 글

패스워드 암호화 .  (0) 2012.12.07
숫자 함수.  (0) 2012.11.15
토드 에서 벌레의 의미..;  (0) 2012.11.02
TOAD 단축키  (0) 2012.10.31
오라클 과거 데이터를 보는 방법. [SYSTIMESTAMP]  (0) 2012.10.30
Posted by 사라링


[Procedure/Function] 

초록 : 디버그와 함께 컴파일 됨


[Package]
초록 : 스펙과 바디 두가지가 디버그와 함께 컴파일 됨
회색 : 스펙만 디버그와 함께 컴파일 됨
대가리 회색 , 몸 초록색 : 바디 부분만 디버그와 함께 컴파일 됨


/
패키지에 대가리 회색 같은 경우가 많은데 . 이런경우
패키지 리스트에서 마우스 오른쪽을 누룬후에 compile > compile with debug 를 눌러 주면 된다. 
단 스크립트에 오류가 없어야 한다.. 



'오라클' 카테고리의 다른 글

숫자 함수.  (0) 2012.11.15
계층형구조 (CONNECT BY)  (0) 2012.11.05
TOAD 단축키  (0) 2012.10.31
오라클 과거 데이터를 보는 방법. [SYSTIMESTAMP]  (0) 2012.10.30
프로시져.INSERT 또는 UPDATE  (0) 2012.10.15
Posted by 사라링

TOAD 단축키

2012. 10. 31. 11:27


TOAD를 사용하면서 편리하게 이용할 수 있는 단축키를 정리한 것입니다.

 

테이블 정보 상세보기

F4 : Table, View, Proc, Funct, Package DESC(테이블명 위에 커서를 두고 F4)

 

자동완성

Ctrl+. : Table Completion (매칭되는 테이블목록 출력)

Ctrl+T : Columns Dropdown (해당테이블의 컬럼목록 표시)

 

SQL문 실행

F5 : SQL Editor내의 모든 SQL문 실행

Ctrl+Enter : 현재 커서의 SQL문 실행

F9 : SQL문 실행 후 Grid에 출력

 

히스토리(과거 수행SQL문 조회)

F8 : 과거에 실행한SQL HISTORY 목록

Alt+Up : History UP

Alt+Down : History DOWN

 

텍스트 대/소문자 변환

CTRL+L : 텍스트를 소문자로

CTRL+U : 텍스트를 대문자로

 

주석처리

Ctrl+B : 주석처리

Ctrl+Shift+B : 주석해제

 

편집 창 전환(이동)

F6 : SQL Editor와 결과창간의 이동

F2 : SQL Editor창 전체화면 전환

Shift+F2 : Grid Output창 전체화면 전환

 

기타 단축키

F7 : 화면을 모두 CLEAR

Ctrl+Shift+F : 쿼리문을 보기좋게 정렬

Ctrl+F9 : SQL Validate (SQL문을 수행하지 않음)

F1
Toad 도움말 파일의 SQL Editor 부분이 표시됩니다.
F2
전체 화면 Editor Editor/Results 패널 표시 장치 사이를 전환합니다.
<SHIFT>F2
전체 화면 그리드를 전환합니다.
F3
다음으로 일치하는 것을 찾습니다.
<SHIFT>F3
이전에 일치하는 것을 찾습니다.
F4
팝업 창의 테이블프로시저함수또는 패키지를 설명합니다.
F5
스크립트로 실행합니다.
F6
커서를 Editor Results 패널 사이로 전환합니다.
F7
모든 텍스트를 지웁니다.
F8
이전 SQL 문을 재호출합니다(SQL Statement Recall 창을 불러옵니다).
F9
실행문을 실행합니다.
<CTRL>F9
실행(구문 분석없이 실행문을 검사합니다.
<SHIFT>F9
커서 위치에서 현재 실행문을 실행합니다.
F10
오른쪽 클릭 메뉴를 표시합니다.
F11
Script 같은  실행(=F5)
F12
편집기 내용을 지정된 외부 편집기로 전달합니다.
<CTRL>A
모든 텍스트를 선택합니다.
<CTRL>C
복사
<CTRL>D
프로시저 인수를 표시합니다.
<CTRL>E
현재 실행문에서 Explain Plan 실행합니다.
<CTRL>F
텍스트를 찾습니다(Find Text 창을 불러옵니다).
<CTRL>G
라인으로 이동합니다(Goto Line 창을 불러옵니다).
<CTRL>L
텍스트를 소문자로 변환합니다.
<CTRL>M
Make Code Statement
<CTRL>N
이름이 지정된 SQL 문을 재호출합니다(SQL Statement Recall 창을 불러옵니다).
<CTRL>O
텍스트 파일을 엽니다.
<CTRL>P
Strip Code Statement(쓸데없는 태그들을 정리해 줍니다. 유용함)
<CTRL>R
검색  바꾸기(Find and Replace Text 창을 불러옵니다)
<CTRL>S
파일을 저장합니다.
<SHIFT><CTRL>S
파일을 다른 이름으로 저장합니다.
<CTRL>T
 드롭다운을 표시합니다.
<CTRL>U
텍스트를 대문자로 변환합니다.
<CTRL>V
붙여넣기
<CTRL>X
잘라내기
<SHIFT><CTRL>Z
마지막으로 취소한 작업을 재실행합니다.
<ALT><UP>
이전 실행문을 표시합니다.
<ALT><DOWN>
다음 실행문을 표시합니다(<ALT><UP> 사용한  사용)
<ALT><PgUp>
이전 탭으로 이동
<ALT><PgDn>
다음 탭으로 이동
<CTRL><ALT><PgUp>
이전 결과 패널 탭으로 이동
<CTRL><ALT><PgDn>
다음 결과 패널 탭으로 이동
<CTRL><HOME>
데이터 그리드에서는  위의 레코드셋으로 이동하며결과 그리드에서는 커서가 위치한행의  번째 열로 이동하고편집기에서는 텍스트의  번째 열과  번째 행으로 이동합니다.
<CTRL><END>
데이터 그리드에서는 레코드셋의  끝으로 이동하며편집기에서는 텍스트의 마지막 열과 마지막 행으로 이동합니다 단원의 "주의" 참조하십시오.
<CTRL><SPACE>
코드 완성 템플릿을 활성화합니다.
<CTRL><TAB>
MDI Child 창의 콜렉션을 순환합니다.
<CTRL><ENTER>
커서 이치에서 현재 SQL 문을 실행합니다.
<CTRL>. (마침표)
테이블 이름을 자동으로 완성합니다.

Posted by 사라링

SELECT*

FROM TABLE_NAME AS OF timestamp ( SYSTIMESTAMP - INTERVAL '30' MINUTE)

/


데이터를 수정한 경우 커밋한 경우 과거의 데이터를 볼수 있다. 


'오라클' 카테고리의 다른 글

토드 에서 벌레의 의미..;  (0) 2012.11.02
TOAD 단축키  (0) 2012.10.31
프로시져.INSERT 또는 UPDATE  (0) 2012.10.15
오라클 힌트 모음 (예제)  (0) 2012.08.31
BYPASS_UJVC -> MERGE 문으로 변경 하자.  (0) 2012.08.31
Posted by 사라링

<procedure id="tmSaveProj" parameterClass="map">

DECLARE

V_CNT NUMBER;

BEGIN

SELECT COUNT(*)

 INTO V_CNT

 FROM BUS_AGRMT_MST

WHERE PROJ_PLAN_NO = #PROJ_PLAN_NO#

  AND PROJ_PLAN_SEQ = #PROJ_PLAN_SEQ#

  AND PART_SHAPE = #CHRG_PART_ORG_SHAPE#

  AND PART_ORG_NO = #CHRG_PART_ORG_NO#;


IF V_CNT = 0 THEN

INSERT INTO BUS_AGRMT_MST (

PROJ_PLAN_NO,

PROJ_PLAN_SEQ,

PART_SHAPE,

PART_ORG_NO,

RCPT_BK_CD,

RCPT_ACC_NO,

INS_ID,

INS_DT,

UPT_ID,

UPT_DT

)VALUES(

#PROJ_PLAN_NO#,

#PROJ_PLAN_SEQ#,

#CHRG_PART_ORG_SHAPE#,

#CHRG_PART_ORG_NO#,

#IN_BK_CD#,

#IN_BK_ACC_NO#,

#SESS_USER_ID#,

SYSDATE,

#SESS_USER_ID#,

SYSDATE

);

ELSE

UPDATE BUS_AGRMT_MST

  SET RCPT_BK_CD = #IN_BK_CD#,

RCPT_ACC_NO = #IN_BK_ACC_NO#,

UPT_ID = #SESS_USER_ID#,

UPT_DT = SYSDATE

WHERE PROJ_PLAN_NO = #PROJ_PLAN_NO#

  AND PROJ_PLAN_SEQ = #PROJ_PLAN_SEQ#

  AND PART_SHAPE = #CHRG_PART_ORG_SHAPE#

  AND PART_ORG_NO = #CHRG_PART_ORG_NO#;

END IF;

END;

</procedure>





// V_CNT 가 0 이라면 값이 없음으로. INSERT 를 하며 1 이상이면 값이 기존에 있음으로 UPDATE 를 실행 

'오라클' 카테고리의 다른 글

TOAD 단축키  (0) 2012.10.31
오라클 과거 데이터를 보는 방법. [SYSTIMESTAMP]  (0) 2012.10.30
오라클 힌트 모음 (예제)  (0) 2012.08.31
BYPASS_UJVC -> MERGE 문으로 변경 하자.  (0) 2012.08.31
오라클 procedure 정리  (0) 2012.08.30
Posted by 사라링

HINT 사용하기 ( /*+ Hint내용 */ )
 1.ALL_ROWS
      Goal : Best Throughput
      용도 : 전체 RESOURCE 소비를 최소화 시키기 위한 힌트.
             Cost-Based 접근방식.
   
      예   : SELECT /*+ALL_ROWS */ EMPNO,ENAME
             FROM   EMP
             WHERE  EMPNO = 7655;
   
   2.FIRST_ROWS
      Goal : Best Response Time
      용도 : 조건에 맞는 첫번째 row를 리턴하기 위한 Resource
             소비를 최소화 시키기위한 힌트.
             Cost-Based 접근방식.
      특징 : - Index Scan 이 가능하다면 Optimizer가 Full Table Scan 대신
               Index Scan을 선택한다.
             - Index Scan 이 가능하다면 Optimizer가 Sort-Merge 보다 
               Nested Loop 을 선택한다. 
             - Order By절에 의해 Index Scan 이 가능하다면,
               Sort과정을 피하기 위해 Index Scan을 선택한다.
             - Delete/Update Block 에서는 무시된다.      
             - 다음을 포함한 Select 문에서도 제외된다.
               .집합연산자 (Union,Intersect,Minus,Union All)
               .Group By
               .For UpDate
               .Group 함수
               .Distinct    
   
      예   : SELECT /*+FIRST_ROWS */ EMPNO,ENAME
             FROM   EMP
             WHERE  EMPNO = 7655;
   
   3.CHOOSE
      Goal : Acess되는 테이블에 통계치 존재여부에 따라 
             Optimizer로 하여금 Rule-Based Approach와 Cost-Based Approach 
             중 하나를 선택할수 있게 한다.
      용도 : Data Dictionary가 해당테이블에 대해 통계정보를 가지고 있다면
             Optimizer는 Cost-Based Approach를 선택하고,
             그렇지 않다면 Rule-Based Approach를 선택한다. 
   
      예   : SELECT /*+CHOOSE */ EMPNO,ENAME 
             FROM   EMP
             WHERE  EMPNO = 7655;
   
   4.RULE
      용도 : Rule-Based 최적화를 사용하기위해. 
   
      예   : SELECT /*+RULE */ EMPNO,ENAME
             FROM   EMP
             WHERE  EMPNO = 7655;
   
B. Access Methods 로써의 Hints
  
   1.FULL
      용도 : 해당테이블의 Full Table Scan을 유도.
      
      예   : SELECT /*+FULL(EMP) */ EMPNO,ENAME
             FROM   EMP
             WHERE  EMPNO = 7655;
           * 테이블 Alias 가 있을 경우는 반드시 Alias 사용.
              Schema Name은 사용안함(From 에 SCOTT.EMP 라고 기술해도 hint에는 EMP사용).

   2.ROWID
      용도 : 지정된 테이블의 ROWID를 이용한 Scan 유도

   3.CLUSTER
      용도 : 지정된 테이블Access에 Cluster Scan 유도.
             Cluster된 Objects에만 적용가능.
      
      예   : SELECT /*+CLUSTER(EMP) */ ENAME,DEPTNO
             FROM   EMP,DEPT
             WHERE  DEPTNO = 10
             AND    EMP.DEPTNO = DEPT.DEPTNO;

   4.HASH 
      용도 : 지정된 테이블Access에 HASH Scan 유도. 
             /*+HASH(table) */

   5.HASH_AJ
      용도 : NOT IN SubQuery 를 HASH anti-join으로 변형 
             /*+HASH_AJ */
   
   6.HASH_SJ
      용도 : correlated Exists SubQuery 를 HASH semi-join으로 변형 
             /*+HASH_SJ */

   7.INDEX
      용도 : 지정된 테이블Access에 Index Scan 유도.
           * 하나의 index만 지정되면 optimizer는 해당index를 이용.
           * 여러개의 인덱스가 지정되면  optimizer가 각 index의 
             scan시 cost를 분석 한 후 최소비용이 드는 index사용.
             경우에 따라 optimizer는 여러 index를 사용한 후 결과를
             merge하는 acees방식도 선택.
           * index가 지정되지 않으면 optimizer는 테이블의 이용가능한 
             모든 index에 대해 scan cost를 고려후 최저비용이 드는
             index scan을 선택한다. 
      예   : SELECT /*+INDEX(EMP EMPNO_INDEX) */ EMPNO,ENAME
             FROM   EMP
             WHERE  DEPTNO=10

   8.INDEX_ASC
      용도 : INDEX HINT와 동일 단,ASCENDING 으로 SCAN함을 확실히 하기위함.
 
   9.INDEX_COMBINE
      용도 : INDEX명이 주어지지 않으면 OPTIMIZER는 해당 테이블의
             best cost 로 선택된 Boolean combination index 를 사용한다.
             index 명이 주어지면 주어진 특정 bitmap index 의 
             boolean combination 의 사용을 시도한다.
           
             /*+INDEX_COMBINE(table index) */

  10.INDEX_DESC 
      용도 : 지정된 테이블의 지정된 index를 이용 descending으로 scan
             하고자할때 사용.

             /*+INDEX_DESC(table index) */

  11.INDEX_FFS
      용도 : full table scan보다 빠른 full index scan을 유도.

             /*+INDEX_FFS(table index) */

  12.MERGE_AJ
      용도 : not in subquery를 merge anti-join으로 변형

             /*+MERGE_AJ */

  13.MERGE_SJ
      용도 : correalted EXISTS subquery를 merge semi-join으로 변형

             /*+MERGE_SJ */

  14.AND_EQUAL
      용도 : single-column index의 merge를 이용한 access path 선택.
             적어도 두개이상의 index가 지정되어야한다.

            /*+AND_EQUAL(table index1,index2...) */ 
            
  15.USE_CONCAT
      용도 : 조건절의 OR 를 Union ALL 형식으로 변형한다.
             일반적으로 변형은 비용측면에서 효율적일때만 일어난다.

           /*+USE_CONCAT */             
    
              
C. JOIN 순서를 결정하는 Hints

   1.ORDERED
      용도 : from절에 기술된 테이블 순서대로 join이 일어나도록 유도.
          
           /*+ORDERED */
      예   : SELECT /*+ORDERED */ TAB1.COL1,TAB2.COL2,TAB3.COL3
             FROM   TAB1,TAB2,TAB3
             WHERE  TAB1.COL1=TAB2.COL1
             AND    TAB2.COL1=TAB3.COL1; 

   2.STAR
      용도 : STAR QUERY PLAN이 사용가능하다면 이를 이용하기 위한 HINT.
             STAR PLAN은 규모가 가장 큰 테이블이 QUERY에서 JOIN ORDER상
             마지막으로 위치하게 하고 NESTED LOOP 으로 JOIN이 일어나도록
             유도한다. 
             적어도 3개 테이블 이상이 조인에 참여해야하며 LARGE TABLE의
             CONCATENATED INDEX는 최소 3컬럼 이상을 INDEX에 포함해야한다.(***중요)
             테이블이 ANALYZE 되어 있다면 OPTIMIZER가 가장효율적인 STAR PLAN을
             선택한다.    

          /*+STAR */ 

D. JOIN OPERATION을 결정하는 HINTS.

   1.USE_NL 
      용도 : 테이블의 JOIN 시 테이블의 각 ROW가 INNER 테이블을 NESTED LOOP
             형식으로 JOIN 한다.

          /*+USE_NL(inner_table) */
    
      예   : SELECT /*+ORDERD USE_NL(CUSTOMER) */
             FROM   ACCOUNT.BALANCE,CUSTOMER.LAST_NAME,CUSTOMER.FIRST_NAME
             WHERE  ACCOUNT.CUSTNO = CUSTOMER.CUSTNO;

   2.USE_MERGE
      용도 : 지정된 테이블들의 조인이 SORT-MERGE형식으로 일어나도록 유도.

          /*+USE_MERGE(table) */
           * 괄호안의 테이블은 JOIN ORDER상의 뒤의 테이블(?)

   3.USE_HASH
      용도 : 각 테이블간 HASH JOIN이 일어나도록 유도.

          /*+USE_HASH(table) */
           * 괄호안의 테이블은 JOIN ORDER상의 뒤의 테이블(?)

   4.DRIVING_SITE
      용도 : QUERY의 실행이 ORACLE에 의해 선택된 SITE가 아닌 다른 SITE에서 
             일어나도록 유도.

          /*+DRIVING_SITE(table) */ 
      예   : SELECT /*+DRIVING_SITE(DEPT)  */
             FROM   EMP,DEPT@RSITE
             WHERE  EMP.DEPTNO = DEPT.DEPTNO;     

             DRIVING_SITE 힌트를 안쓰면 DEPT의 ROW가 LOCAL SITE로 보내져
             LOCAL SITE에서 JOIN이 일어나지만,
             DRIVING_SITE 힌트를 쓰면 EMP의 ROW들이REMOTE SITE로 보내져
             QUERY가 실행된후 LOCAL SITE로 결과가 RETURN된다.

출처 : http://sqler.pe.kr/web_board/view_list.asp?id=285&read=699&pagec=1&gotopage=1&block=0&part=myboard8&tip=ok

##############################################################################
##############################################################################
##############################################################################


oracle hint 정리

/*+ ALL_ROWS */ 
explicitly chooses the cost-based approach to optimize a statement 
block with a goal of best throughput (that is, minimum 
total resource consumption) 
가장 좋은 단위 처리량의 목표로 문 블록을 최적화하기 위해 cost-based 
접근 방법을 선택합니다. (즉, 전체적인 최소의 자원 소비)

/*+ CHOOSE */ 
causes the optimizer to choose between the rule-based 
approach and the cost-based approach for a SQL statement 
based on the presence of statistics for the tables accessed by 
the statement 
최적자(optimizer)가 그 문에 의해 접근된 테이블을 위해 통계의 존재에 
근거를 두는 SQL 문을 위해 rule-based 접근 방법과 cot-based 접근 방법 
사이에 선택하게 합니다.

/*+ FIRST_ROWS */ 
explicitly chooses the cost-based approach to optimize a statement 
block with a goal of best response time (minimum 
resource usage to return first row) 
가장 좋은 응답 시간의 목표로 문 블록을 최적화하기 위해 cost-based 접근 
방법을 선택합니다. (첫번째 행을 되돌려 주는 최소의 자원 사용)

/*+ RULE */ 
explicitly chooses rule-based optimization for a statement 
block 
문 블록을 위하여, rule-based 최적화를 고르는

 

/*+ AND_EQUAL(table index) */ 
explicitly chooses an execution plan that uses an access path 
that merges the scans on several single-column indexes 
그만큼 실행 계획을 선택합니다. 그리고 여럿의 single-column 색인에 
그 scan을 합병하는 접근 경로를 사용합니다.

/*+ CLUSTER(table) */ 
explicitly chooses a cluster scan to access the specified table 
선택합니다. 그리고, 클러스터는 그 명시된 테이블을 접근하기 위해 살핍니다.

/*+ FULL(table) */ 
explicitly chooses a full table scan for the specified table 
그 명시된 테이블을 위하여, 전체 테이블 scan을 고르는

/*+ HASH(table) */ 
explicitly chooses a hash scan to access the specified table 
선택합니다. 그리고, 해쉬는 그 명시된 테이블을 접근하기 위해 운율을 살핍니다.

/*+ HASH_AJ(table) */ 
transforms a NOT IN subquery into a hash antijoin to access 
the specified table 
변환, 그 명시된 테이블을 접근하는 해쉬 antijoin으로의 NOT IN 부속 조회

/*+ HASH_SJ (table) */ 
transforms a NOT IN subquery into a hash anti-join to access 
the specified table 
변환, 그 명시된 테이블을 접근하는 해쉬 anti-join으로의 NOT IN 부속 조회

/*+ INDEX(table index) */ 
explicitly chooses an index scan for the specified table 
그 명시된 테이블을 위하여, 색인 scan을 고르는

/*+ INDEX_ASC(table index) */ 
explicitly chooses an ascending-range index scan for the specified 
table 
그 명시된 테이블을 위하여, ascending-range 색인 scan을 고르는

/*+ INDEX_COMBINE(table index) */ 
If no indexes are given as arguments for the INDEX_COMBINE 
hint, the optimizer uses whatever Boolean combination 
of bitmap indexes has the best cost estimate. If particular 
indexes are given as arguments, the optimizer tries to use 
some Boolean combination of those particular bitmap indexes. 
어떤 색인도 INDEX_COMBINE 암시를 위해 인수로서 주어지지 않는다면, 
bitmap 색인의 결합이 어떤 부울의를 가장 좋은 수행 난이도 평가를 가지고 
있든지 최적자는 이용합니다. 
특별한 색인이 인수로서 주어진다면, 최적자는 그 특별한 bitmap 색인의 
몇몇의 부울의 결합을 사용하려고 노력합니다.

/*+ INDEX_DESC(table index) */ 
explicitly chooses a descending-range index scan for the specified 
table 
그 명시된 테이블을 위하여, descending-range 색인 scan을 고르는

/*+ INDEX_FFS(table index) */ 
causes a fast full index scan to be performed rather than a full 
table scan 
빠른 전체 색인 scan이 전체 테이블 scan이라기보다는 수행되게 합니다.

/*+ MERGE_AJ (table) */ 
transforms a NOT IN subquery into a merge anti-join to access 
the specified table 
변환, NOT IN 부속 조회, 그 명시된 테이블을 접근하기 위해 anti-join을 
합병합니다.

/*+ MERGE_SJ (table) */ 
transforms a correlated EXISTS subquery into a merge semi-join 
to access the specified table 
변환, 관련된 EXISTS 부속 조회, 접근으로 semi-join을 합병합니다, 
그 명시된 테이블

/*+ ROWID(table) */ 
explicitly chooses a table scan by ROWID for the specified 
table 
그 명시된 테이블을 위하여, ROWID에 의해 테이블 scan을 고르는

/*+ USE_CONCAT */ 
forces combined OR conditions in the WHERE clause of a 
query to be transformed into a compound query using the 
UNION ALL set operator 
힘은 질의의 WHERE 문절에 있는 UNION ALL 집합 연산자를 사용하는 합성의 
질의로 변형되는 OR 조건을 합쳤습니다.

 

/*+ ORDERED */ 
causes Oracle to join tables in the order in which they appear 
in the FROM clause 
오라클이 어느 것에 순서로 테이블을 결합시키게 합니다.

/*+ STAR */ 
forces the large table to be joined last using a nested-loops join 
on the index 
큰 있는 테이블이 최종 사용/회전율에 nested-loops를 결합시킨 힘은 
그 색인에 결합합니다.

 

/*+ DRIVING_SITE (table) */ 
forces query execution to be done at a different site from that 
selected by Oracle 
힘은 그것과 다른 오라클에 의해 선택된 사이트에 되는 실행을 질의합니다.

/*+ USE_HASH (table) */ 
causes Oracle to join each specified table with another row 
source with a hash join 
오라클이 테이블이 다른 행 자원으로 해쉬 접합으로 명시되면서 각자와 
합치게 합니다.

/*+ USE_MERGE (table) */ 
causes Oracle to join each specified table with another row 
source with a sort-merge join 
오라클이 테이블이 다른 행 자원으로 sort-merge 접합으로 명시되면서 각자와 
합치게 합니다.

/*+ USE_NL (table) */ 
causes Oracle to join each specified table to another row 
source with a nested-loops join using the specified table as the 
inner table 
오라클이 그 명시된 테이블을 그 안의 테이블로 사용하는 nested-loops 접합과 
각자와 다른 행 자원에 대한 명시된 테이블을 합치게 합니다.

 

/*+ APPEND */ , /*+ NOAPPEND */ 
specifies that data is simply appended (or not) to a table; existing 
free space is not used. Use these hints only following the 
INSERT keyword. 
데이타가 테이블로 단순히 덧붙여진다는 (or not)것 명시합니다; 무료인 
현존하는 영역은 사용되지 않습니다. 
단지 그 삽입 키 핵심어를 따르는 이 암시를 사용하시오.

/*+ NOPARALLEL(table) */ 
disables parallel scanning of a table, even if the table was created 
with a PARALLEL clause 
그 테이블이 PARALLEL 문절로 새로 만들어졌다면 테이블의 평행의 순차 검색을 
무능하게 만듭니다.

/*+ PARALLEL(table, instances) */ 
allows you to specify the desired number of concurrent slave 
processes that can be used for the operation. 
DELETE, INSERT, and UPDATE operations are considered for 
parallelization only if the session is in a PARALLEL DML 
enabled mode. (Use ALTER SESSION PARALLEL DML to 
enter this mode.) 
당신이 그 연산을 위해 사용될 수 있는 동시의 슬레이브(slave) 프로세스의 
요구된 수를 명시하는 것을 허락합니다. 
그 세션이 가능하게 된 PARALLEL DML에 모드를 있다면, DELETE, INSERT, UPDATE 
연산은 단지 parallelization에 대해 고려됩니다. (사용은 이 모드에 들어가기 
위해 평행의 세션 DML을 변경합니다.)

/*+ PARALLEL_INDEX */ 
allows you to parallelize fast full index scan for partitioned 
and nonpartitioned indexes that have the PARALLEL attribute 
parallelize에 당신에게 빠른 가득한 색인 scan을 허락합니다. 그런데, 
그것은 PARALLEL 속성을 가지고 있는 색인을 분할했고 nonpartitioned했습니다.

/*+ NOPARALLEL_INDEX */ 
overrides a PARALLEL attribute setting on an index 
병렬이 색인을 나아가는 것을 속하게 하는 대체


/*+ CACHE */ 
specifies that the blocks retrieved for the table in the hint are 
placed at the most recently used end of the LRU list in the 
buffer cache when a full table scan is performed 
그 블록이 찾아서 가져왔다는 것을 명시합니다. 그리고 그 테이블을 위해 
그 암시에 놓여집니다. 그런데, 그것은 가장 최근에 사용된 언제 그 버퍼 캐쉬, 
가득한 테이블 scan에 있는 LRU 리스트의 끝입니다. 수행됩니다.

/*+ NOCACHE */ 
specifies that the blocks retrieved for this table are placed at 
the least recently used end of the LRU list in the buffer cache 
when a full table scan is performed 
그 명시합니다. 그리고, 그 블록은 이 테이블을 위해 검색되면서 최근에 사용된 
언제 그 버퍼 캐쉬, 가득한 테이블 scan에 있는 LRU 리스트의 가장 작은 끝에 
놓여집니다. 수행됩니다.

/*+ MERGE (table) */ 
causes Oracle to eval!uate complex views or subqueries before 
the surrounding query 
오라클이 그 둘러싸는 질의 전에 복잡한 뷰나 부속 조회를 평가하게 합니다.

/*+ NO_MERGE (table) */ 
causes Oracle not to merge mergeable views 
오라클이 mergeable 뷰를 합병하지 않게 하지 않습니다

/*+ PUSH_JOIN_PRED (table) */ 
causes the optimizer to eval!uate, on a cost basis, whether or 
not to push individual join predicates into the view 
개개 접합을 미는 것이 그 뷰 안으로 단정 하든 간에 비용 방식으로 최적자가 
평가하게 합니다.

/*+ NO_PUSH_JOIN_PRED (table) */ 
Prevents pushing of a join predicate into the view 
접합 술부 중에서 그 뷰로 밀면서, 막는

/*+ PUSH_SUBQ */ 
causes nonmerged subqueries to be eval!uated at the earliest 
possible place in the execution plan 
원인은 그 실행 계획에서의 가장 이른 가능한 장소에 평가되는 부속 조회를 
nonmerged했습니다.

/*+ STAR_TRANSFORMATION */ 
makes the optimizer use the best plan in which the transformation 
has been used. 
최적자가 그 변형이 사용된 가장 좋은 계획을 사용하는 제작

http://luke.tistory.com/entry/oracle-hint-%EC%A0%95%EB%A6%AC


Posted by 사라링

/


바이 패스 문을 머지 문으로 변경 하자. 


*목표*

   프로시져 에서 바이패스 문으로 작성된 UPDATE 문 3개를  머지문을 이용 하여 사용 할수 있도록 하라. 

   업데이트 문이 기본적으로 수정을 목표로 한다면 머지 문은 INSERT DELETE UPDATE  를 하나의 쿼리 내에서 실행 할수 잇는 개념으로 보면 될듯 하다.  


왜그래야하징? 

보통 
update(select ~) 

where col='a'

set a.d=b.d

여기서 (select ~) 안에는  join 등을 이용 하여 여러개의 테이블을 검색 하여 검색된 컬럼 내에서 의 값들을 검색된 컬럼으로 setting 한다. 


형식의 업데이트 사용. 

위의 방식은 옳지 않다 그 이유는 ? 

Undocumented HIT (잘못되어도 오라클에서 보장 하지 않음)    - 보장을 하지 않는 단다. 오라클이. .. 휴 (신상진 멍청이)
 
일반적으로 특정 테이블을 Update하기 위해서는 WHERE절에 EXISTS 또는 IN 등의 Sub-Query로 조인 조건을 만족하는
Row를 먼저 Check하고, 조건을 만족하는 Row에 대하여 SET 절에서 필요한 데이터를 검색하여 Update하는 것이 보통이다.
 
이 때, Update 해야 하는 Row가 많을 경우 WHERE절이나 SET절에서 테이블을 반복적으로 Random 액세스해야 하는 부담이
발생하므로 처리 범위가 넓은 Update문의 경우에는 'Updatable Join View'를 활용할 필요가 있다.
 
이 때, 조인되는 2개의 테이블은 반드시 1:1 또는 1:M의 관계여야 하며,
Update되는 컬럼의 테이블은 M쪽 집합이어야 한다.
이것은 1쪽 집합인 Parent table의 조인 컬럼이 UK 또는 PK로 설정되어 있어야 함을 의미한다. 
이 조건을 만족하지 못하는 Updatable Join View는 에러를 Return하며 실행되지 않는다.
(ORA-01779 cannot modify a column which maps to a non key-preserved table)
 
그러나, 일반적으로 View 또는 2개 이상의 테이블을 조인한 집합을 엑세스하는
경우가 많으므로 위의 UK나 PK Constraint를 설정하기 어려운 것이 현실이다.
 
따라서, 이러한 Constraint를 피해서 Updatable Join View를 사용할 수 있도록

BYPASS_UJVC 라는 힌트를 사용하여 튜닝할 수 있다.

update /*+ BYPASS_UJVC */
(select ~) 

where col='a'

set a.d=b.d

 

이런식으로. 말이다. 하지만 11g 이상부터는 오라클은 BYPASS_UJVC 을 지원 하지 않는다 . 따라서 merge 문을 이용 하여 

복잡한 update 문을 수행 해야 한다. 


MERGE INTO table_1 A

USING( SELECT ~  ) B

ON( A.SEQ=B.SEQ)     -- 반드시 이퀄 조인 이어야만 한다. B 의 SELECT 문은 상관 없다. 

WHEN MATCHED THEN 

SET A.DD = B.CC 

WHERE COL='a'


형식 으로 하면 된다. 


많은 데이터를 할경우 오라클 튜닝 힌트가 필요 하다. 







CREATE OR REPLACE PROCEDURE IBS.SP_ACT_BS ( P_BUSI_PLC_CD IN VARCHAR2,

                                            P_FRM_DT  IN VARCHAR2,

                                            P_TO_DT   IN VARCHAR2)

IS

V_BACK_FRM_DT   VARCHAR(20) :=SUBSTR(P_FRM_DT,0,4)-1||'0101';

V_BACK_TO_DT    VARCHAR(20) :=SUBSTR(P_FRM_DT,0,4)-1||'1231';

V_FINC_STAT_CD  VARCHAR(100) :='390-001' ;


V_BACK_YY    VARCHAR(20) :=SUBSTR(P_FRM_DT,0,4)-1;

V_THIS_YY    VARCHAR(20) :=SUBSTR(P_FRM_DT,0,4);



BEGIN

....  

END SP_ACT_BS;



1



       UPDATE /*+ BYPASS_UJVC */

            (SELECT A.THIS_REM_AMT AS SET_THIS_AMT,

                    A.BACK_REM_AMT AS SET_BACK_AMT,

                    B.THIS_AMT AS GET_THIS_AMT,

                    B.BACK_AMT AS GET_BACK_AMT 

               FROM ACT_ACCOUNT A

                    INNER JOIN(SELECT C.SEQ,

                                      SUM(CASE WHEN TEMP1 = V_THIS_YY THEN DECODE(B.DR_CR,'D',TO_NUMBER(TEMP6-TEMP7),TO_NUMBER(TEMP7-TEMP6)) ELSE 0 END) AS THIS_AMT,

                                      SUM(CASE WHEN TEMP1 = V_BACK_YY THEN DECODE(B.DR_CR,'D',TO_NUMBER(TEMP6-TEMP7),TO_NUMBER(TEMP7-TEMP6)) ELSE 0 END) AS BACK_AMT

                                 FROM ACT_PRT A 

                                      INNER JOIN ACT_ACCT_CD B ON A.TEMP3 = B.ACCT_CD

                                      INNER JOIN ACT_FS_DTL  C ON B.ACCT_CD = C.ACCT_CD AND C.BUSI_PLC_CD = P_BUSI_PLC_CD AND C.FINC_STAT_CD = V_FINC_STAT_CD

                                WHERE TEMP_CLS = 'SP_ACT_BS' 

                                  AND C.SEQ = MST.SEQ

                                GROUP BY C.SEQ)B ON A.SEQ = B.SEQ

              WHERE BUSI_PLC_CD = P_BUSI_PLC_CD AND FINC_STAT_CD = V_FINC_STAT_CD AND A.SEQ = MST.SEQ

             ) SET SET_THIS_AMT = GET_THIS_AMT,

                   SET_BACK_AMT = GET_BACK_AMT;

                                                                                              ▽

             

     MERGE INTO ACT_ACCOUNT A 

     USING (

        SELECT C.SEQ,

        SUM(CASE WHEN TEMP1 = V_THIS_YY THEN DECODE(B.DR_CR,'D',TO_NUMBER(TEMP6-TEMP7),TO_NUMBER(TEMP7-TEMP6)) ELSE 0 END) AS THIS_AMT,

        SUM(CASE WHEN TEMP1 = V_BACK_YY THEN DECODE(B.DR_CR,'D',TO_NUMBER(TEMP6-TEMP7),TO_NUMBER(TEMP7-TEMP6)) ELSE 0 END) AS BACK_AMT

        FROM ACT_PRT A 

        INNER JOIN ACT_ACCT_CD B ON A.TEMP3 = B.ACCT_CD

        INNER JOIN ACT_FS_DTL  C ON B.ACCT_CD = C.ACCT_CD AND C.BUSI_PLC_CD = P_BUSI_PLC_CD AND C.FINC_STAT_CD = V_FINC_STAT_CD

        WHERE TEMP_CLS = 'SP_ACT_BS' 

        AND C.SEQ = MST.SEQ

        GROUP BY C.SEQ    

      ) B ON (A.SEQ=B.SEQ)

      WHEN MATCHED THEN 

        UPDATE 

          SET A.THIS_REM_AMT = B.THIS_AMT,

                  A.BACK_REM_AMT = B.BACK_AMT

            WHERE  BUSI_PLC_CD = P_BUSI_PLC_CD AND FINC_STAT_CD = V_FINC_STAT_CD AND A.SEQ = MST.SEQ

          ;




2.



    UPDATE /*+ BYPASS_UJVC */

         (SELECT A.THIS_REM_AMT AS SET_THIS_REM_AMT,

                 A.BACK_REM_AMT AS SET_BACK_REM_AMT,

                 A.THIS_CN_REM_AMT AS SET_THIS_CN_REM_AMT,

                 A.BACK_CN_REM_AMT AS SET_BACK_CN_REM_AMT,

                 B.THIS_REM_AMT AS GET_THIS_REM_AMT,

                 B.BACK_REM_AMT AS GET_BACK_REM_AMT

           FROM ACT_ACCOUNT A

                INNER JOIN (SELECT THIS_REM_AMT,BACK_REM_AMT

                              FROM ACT_ACCOUNT

                             WHERE BUSI_PLC_CD = P_BUSI_PLC_CD

                               AND FINC_STAT_CD = '390-002'

                               AND SEQ = '7700')B

                   ON 1=1

          WHERE A.FINC_STAT_CD = V_FINC_STAT_CD

            AND A.SEQ = '7300'

         )  SET SET_THIS_REM_AMT = GET_THIS_REM_AMT,

                SET_BACK_REM_AMT = GET_BACK_REM_AMT,

                SET_THIS_CN_REM_AMT = GET_THIS_REM_AMT,

                SET_BACK_CN_REM_AMT = GET_BACK_REM_AMT;

                                                                                                            ▽

       

    MERGE INTO ACT_ACCOUNT  A

           USING (

           SELECT THIS_REM_AMT,BACK_REM_AMT

           FROM ACT_ACCOUNT

           WHERE BUSI_PLC_CD = P_BUSI_PLC_CD

           AND FINC_STAT_CD = '390-002'

          AND SEQ = '7700'          

           ) B 

           ON(1=1)

           WHEN MATCHED THEN 

             UPDATE 

               SET A.THIS_REM_AMT = B.THIS_REM_AMT,

                A.BACK_REM_AMT = B.BACK_REM_AMT,

                A.THIS_CN_REM_AMT = B.THIS_REM_AMT,

                A.BACK_CN_REM_AMT = B.BACK_REM_AMT

                WHERE A.FINC_STAT_CD = V_FINC_STAT_CD

                AND A.SEQ = '7300';

                

                




3.

         

    UPDATE /*+ BYPASS_UJVC */

         ( SELECT A.SEQ AS SEQ,THIS_R_AMT AS SET_THIS_R_AMT,

                  BACK_R_AMT AS SET_BACK_R_AMT,

                  THIS100,

                  BACK100,

                  THIS4600,

                  BACK4600,

                  THIS6300,

                  BACK6300

             FROM ACT_ACCOUNT A

                  INNER JOIN(SELECT SEQ, 

                                    SUM(CASE  WHEN  SEQ = '100'   THEN THIS_R_AMT ELSE 0 END) OVER() AS THIS100,

                                    SUM(CASE  WHEN  SEQ = '100'   THEN BACK_R_AMT ELSE 0 END) OVER() AS BACK100,

                                    SUM(CASE  WHEN  SEQ = '4600'  THEN THIS_R_AMT ELSE 0 END) OVER() AS THIS4600,

                                    SUM(CASE  WHEN  SEQ = '4600'  THEN BACK_R_AMT ELSE 0 END) OVER() AS BACK4600,

                                    SUM(CASE  WHEN  SEQ = '6300'  THEN THIS_R_AMT ELSE 0 END) OVER() AS THIS6300,

                                    SUM(CASE  WHEN  SEQ = '6300'  THEN BACK_R_AMT ELSE 0 END) OVER() AS BACK6300

                               FROM ACT_ACCOUNT

                              WHERE BUSI_PLC_CD = P_BUSI_PLC_CD

                                AND FINC_STAT_CD = V_FINC_STAT_CD)B ON A.SEQ = B.SEQ

            WHERE BUSI_PLC_CD = P_BUSI_PLC_CD

              AND FINC_STAT_CD = V_FINC_STAT_CD

              AND A.SEQ IN('4500','6200','7400','7500')

          ) SET SET_THIS_R_AMT = CASE WHEN SEQ = '4500' THEN THIS100

                                      WHEN SEQ = '6200' THEN THIS4600 

                                      WHEN SEQ = '7400' THEN THIS6300 

                                      WHEN SEQ = '7500' THEN THIS4600+THIS6300 END,

                SET_BACK_R_AMT = CASE WHEN SEQ = '4500' THEN BACK100

                                      WHEN SEQ = '6200' THEN BACK4600 

                                      WHEN SEQ = '7400' THEN BACK6300 

                                      WHEN SEQ = '7500' THEN BACK4600+BACK6300 END;


                                                                                                            ▽



        MERGE INTO ACT_ACCOUNT A

        USING (SELECT SEQ, 

        SUM(CASE  WHEN  SEQ = '100'   THEN THIS_R_AMT ELSE 0 END) OVER() AS THIS100,

        SUM(CASE  WHEN  SEQ = '100'   THEN BACK_R_AMT ELSE 0 END) OVER() AS BACK100,

        SUM(CASE  WHEN  SEQ = '4600'  THEN THIS_R_AMT ELSE 0 END) OVER() AS THIS4600,

        SUM(CASE  WHEN  SEQ = '4600'  THEN BACK_R_AMT ELSE 0 END) OVER() AS BACK4600,

        SUM(CASE  WHEN  SEQ = '6300'  THEN THIS_R_AMT ELSE 0 END) OVER() AS THIS6300,

        SUM(CASE  WHEN  SEQ = '6300'  THEN BACK_R_AMT ELSE 0 END) OVER() AS BACK6300

         FROM ACT_ACCOUNT

         WHERE BUSI_PLC_CD = P_BUSI_PLC_CD

         AND FINC_STAT_CD = V_FINC_STAT_CD

        ) B

        ON (A.SEQ = B.SEQ)

       WHEN MATCHED THEN

        UPDATE 

        SET  A.THIS_R_AMT = CASE WHEN SEQ = '4500' THEN THIS100

                                      WHEN SEQ = '6200' THEN THIS4600 

                                      WHEN SEQ = '7400' THEN THIS6300 

                                      WHEN SEQ = '7500' THEN THIS4600+THIS6300 END,

                A.BACK_R_AMT = CASE WHEN SEQ = '4500' THEN BACK100

                                      WHEN SEQ = '6200' THEN BACK4600 

                                      WHEN SEQ = '7400' THEN BACK6300 

                                      WHEN SEQ = '7500' THEN BACK4600+BACK6300 END

        WHERE BUSI_PLC_CD = P_BUSI_PLC_CD

              AND FINC_STAT_CD = V_FINC_STAT_CD

              AND A.SEQ IN('4500','6200','7400','7500');



머지문을 추가로 공부 하자. !!  

Listing 4. Merge delete

MERGE INTO customer as C
USING customer_trans as CT
ON C.customer_num != CT.customer_num
WHEN MATCHED THEN  DELETE
WHEN NOT MATCHED THEN INSERT VALUES (CT.customer_num, CT.fname, 
CT.lname, CT.company, CT.address1, CT.address2, CT.city, 
CT.state, CT.zipcode, CT.phone);

Listing 5 shows other usages of the merge statement where the WHEN MATCHED and WHEN NOT MATCHED clauses are optionally used. When one of these clauses is not specified, that part of the merge is ignored. In the first merge statement, all the non-matching rows would be ignored and matched rows would be updated in the sale table. Similarly, in the second mergestatement, only non-matched rows would be inserted into the customer table, and all the matched rows would be ignored.


Listing 5. Exclusive update, insert, or delete
MERGE INTO customer AS C
USING customer_trans AS CT
ON C.customer_num = CT.customer_num
WHEN MATCHED THEN UPDATE SET C.phone = CT.phone;

MERGE INTO customer as C
USING customer_trans as CT
ON C.customer_num = CT.customer_num
WHEN NOT MATCHED THEN INSERT VALUES (CT.customer_num, CT.fname, 
CT.lname, CT.company, CT.address1, CT.address2, CT.city, CT.state,
CT.zipcode, CT.phone);

The Informix implementations of the merge statement allow the flexibility of ordering the WHEN MATCHED and WHEN NOT MATCHED clauses, as shown in Listing 6.


Listing 6. Flexible ordering of update, insert, and delete clauses
MERGE INTO customer as C
USING customer_trans as CT
ON C.customer_num = CT.customer_num
WHEN NOT MATCHED THEN INSERT VALUES (CT.customer_num, CT.fname, 
CT.lname, CT.company, CT.address1, CT.address2, CT.city, CT.state,
CT.zipcode, CT.phone)
WHEN MATCHED THEN UPDATE SET C.phone = CT.phone;

하나의 쿼리에서 INSERT DELETE UPDATE 된다. 


MERGE 문 성능 최적화

SQL Server 2008 R2
이 항목은 아직 평가되지 않았습니다.이 항목 평가

SQL Server 2008에서는 MERGE 문을 사용하여 단일 문에서 여러 DML(데이터 조작 언어) 작업을 수행할 수 있습니다. 예를 들어 원본 테이블과의 차이점에 따라 대상 테이블에서 행을 삽입, 업데이트 및 삭제하여 두 테이블을 동기화해야 하는 경우가 있습니다. 일반적으로 이러한 작업은 개별 INSERT, UPDATE 및 DELETE 문을 포함하는 저장 프로시저 또는 일괄 처리를 실행하여 수행합니다. 그러나 이는 원본 테이블과 대상 테이블의 데이터가 적어도 각 문에 대해 한 번씩 여러 번 계산되고 처리됨을 의미합니다.

MERGE 문을 사용하면 여러 개의 개별 DML 문을 단일 문으로 대체할 수 있습니다. 이렇게 하면 작업이 하나의 문 내에서 수행되므로 원본 및 대상 테이블의 데이터가 처리되는 횟수가 최소화되어 쿼리 성능이 향상됩니다. 단, 성능 향상을 위해서는 인덱스, 조인 및 기타 고려 사항이 올바르게 설정되어야 합니다. 이 항목에서는 MERGE 문을 사용할 때 최적의 성능을 얻는 데 도움이 되는 최선의 방법 권장 사항에 대해 설명합니다.

MERGE 문의 성능을 높이려면 다음 인덱스 지침을 따르는 것이 좋습니다.

  • 원본 테이블의 조인 열에 고유한 포함 인덱스를 만듭니다.

  • 대상 테이블의 조인 열에 고유한 클러스터형 인덱스를 만듭니다.

이러한 인덱스를 통해 조인 키의 고유성을 확보하고 테이블의 데이터가 정렬되도록 할 수 있습니다. 쿼리 최적화 프로그램이 중복 행을 찾아 업데이트하기 위해 별도로 유효성 검사를 수행할 필요가 없고 추가 정렬 작업도 필요 없으므로 쿼리 성능이 개선됩니다.

예를 들어 다음 MERGE 문에서 원본 테이블 dbo.Purchases와 대상 테이블 dbo.FactBuyingHabits는 ProductID 및 CustomerID 열에서 조인됩니다. 이 문의 성능을 높이려면 dbo.Purchases 테이블의 ProductID 및CustomerID 열에 고유 또는 기본 키 인덱스(클러스터형 또는 비클러스터형)를 만들고 dbo.FactBuyingHabits 테이블의 ProductID 및 CustomerID 열에 클러스터형 인덱스를 만듭니다. 이 테이블을 만드는 데 사용된 코드는MERGE를 사용하여 데이터 삽입, 업데이트 및 삭제에서 볼 수 있습니다.

MERGE dbo.FactBuyingHabits AS Target
USING (SELECT CustomerID, ProductID, PurchaseDate FROM dbo.Purchases) AS Source
ON (Target.ProductID = Source.ProductID AND Target.CustomerID = Source.CustomerID)
WHEN MATCHED THEN
    UPDATE SET Target.LastPurchaseDate = Source.PurchaseDate
WHEN NOT MATCHED BY TARGET THEN
    INSERT (CustomerID, ProductID, LastPurchaseDate)
    VALUES (Source.CustomerID, Source.ProductID, Source.PurchaseDate)
OUTPUT $action, Inserted.*, Deleted.*; 


MERGE 문의 성능을 높이고 정확한 결과를 얻으려면 다음 조인 지침을 따르는 것이 좋습니다.

  • ON <merge_search_condition> 절에는 원본 및 대상 테이블의 데이터 비교를 위한 조건을 나타내는 검색 조건만 지정합니다. 즉, 대상 테이블에서 원본 테이블의 해당 열과 비교할 열만 지정해야 합니다. 상수와 같은 다른 값에 대한 비교는 포함하지 않습니다.

원본 또는 대상 테이블에서 행을 필터링하려면 다음 방법 중 하나를 사용합니다.

  • 적절한 WHEN 절에 행 필터링을 위한 검색 조건을 지정합니다(예: WHEN NOT MATCHED AND S.EmployeeName LIKE 'S%' THEN INSERT...).

  • 필터링된 행을 반환하는 원본 또는 대상에 대한 뷰를 정의하고 이 뷰를 원본 또는 대상 테이블로 참조합니다. 대상 테이블에 대해 정의된 뷰의 모든 동작은 뷰 업데이트를 위한 조건을 충족해야 합니다. 뷰를 사용하여 데이터를 업데이트하는 방법은 뷰를 통해 데이터 수정을 참조하십시오.

  • WITH <common table expression> 절을 사용하여 원본 또는 대상 테이블에서 행을 필터링합니다. 이 방법은 ON 절에 추가 검색 조건을 지정하는 것과 비슷하며 잘못된 결과를 생성할 수 있으므로 사용하지 않는 것이 좋으며 사용할 경우 구현 전에 철저히 테스트해야 합니다.

자세한 내용은 MERGE를 사용하여 데이터 삽입, 업데이트 및 삭제를 참조하십시오.

조인의 쿼리 최적화

MERGE 문의 조인 작업은 SELECT 문의 조인과 동일한 방식으로 최적화됩니다. 즉, SQL Server에서 조인을 처리할 때 쿼리 최적화 프로그램은 여러 가지 가능한 방법 중 가장 효율적인 방법을 선택합니다. 조인에 대한 자세한 내용은 조인 기본 사항 및 고급 쿼리 튜닝 개념을 참조하십시오. 원본 및 대상의 크기가 비슷하고 ‘인덱스를 위한 최선의 방법’ 섹션에 설명된 인덱스 지침을 원본 및 대상 테이블에 적용한 경우 merge join 연산자가 가장 효율적인 쿼리 계획입니다. 두 테이블 모두 한 번만 검색되고 데이터를 정렬할 필요가 없기 때문입니다. 원본 테이블이 대상 테이블보다 작은 경우 nested loops 연산자가 좋습니다.

MERGE 문에서 OPTION (<query_hint>) 절을 지정하여 특정 조인을 사용하도록 강제할 수 있습니다. 해시 조인은 인덱스를 사용하지 않으므로 MERGE 문에 대한 쿼리 힌트로는 사용하지 않는 것이 좋습니다. 쿼리 힌트에 대한 자세한 내용은 쿼리 힌트(Transact-SQL)를 참조하십시오. 다음 예에서는 OPTION 절에 중첩 루프 조인을 지정합니다.

USE AdventureWorks2008R2;
GO
BEGIN TRAN;
MERGE Production.ProductInventory AS pi
USING (SELECT ProductID, SUM(OrderQty) 
       FROM Sales.SalesOrderDetail AS sod
       JOIN Sales.SalesOrderHeader AS soh
         ON sod.SalesOrderID = soh.SalesOrderID
         AND soh.OrderDate BETWEEN '20030701' AND '20030731'
       GROUP BY ProductID) AS src(ProductID, OrderQty)
ON (pi.ProductID = src.ProductID)
WHEN MATCHED AND pi.Quantity - src.OrderQty >= 0 
    THEN UPDATE SET pi.Quantity = pi.Quantity - src.OrderQty
WHEN MATCHED AND pi.Quantity - src.OrderQty <= 0 
    THEN DELETE
OUTPUT $action, Inserted.*, Deleted.*
OPTION (LOOP JOIN);
GO
ROLLBACK TRAN;


SELECT, INSERT, UPDATE 또는 DELETE 문이 매개 변수 없이 실행되는 경우 SQL Server 쿼리 최적화 프로그램은 내부적으로 문을 매개 변수화하는 방법을 선택할 수 있습니다. 즉, 쿼리에 포함된 모든 리터럴 값이 매개 변수로 대체됩니다. 예를 들어 INSERT dbo.MyTable (Col1, Col2) VALUES (1, 10) 문은 내부적으로 INSERT dbo.MyTable (Col1, Col2) VALUES (@p1, @p2)로 구현될 수 있습니다. 단순 매개 변수화라고 하는 이 프로세스는 새 SQL 문을 이전에 컴파일된 기존의 실행 계획과 비교하는 관계형 엔진의 기능을 개선합니다. 쿼리 컴파일 및 다시 컴파일 빈도가 낮아지므로 쿼리 성능이 개선될 수 있습니다. 쿼리 최적화 프로그램은 MERGE 문에 단순 매개 변수화 프로세스를 적용하지 않습니다. 따라서 리터럴 값을 포함하는 MERGE 문의 경우 MERGE 문이 실행될 때마다 새 계획이 컴파일되므로 개별 INSERT, UPDATE 또는 DELETE 문보다 성능이 떨어집니다.

쿼리 성능을 높이려면 다음 매개 변수화 지침을 따르는 것이 좋습니다.

  • ON <merge_search_condition> 절과 MERGE 문의 WHEN 절에 있는 모든 리터럴 값을 매개 변수화합니다. 예를 들어 리터럴 값을 적절한 입력 매개 변수로 대체하여 MERGE 문을 저장 프로시저에 통합할 수 있습니다.

  • 문을 매개 변수화할 수 없는 경우 TEMPLATE 형식의 계획 지침을 만들고 PARAMETERIZATION FORCED 쿼리 힌트를 이 계획 지침에 지정합니다. 자세한 내용은 계획 지침을 사용하여 쿼리 매개 변수화 동작 지정을 참조하십시오.

  • MERGE 문이 데이터베이스에서 자주 실행되는 경우 데이터베이스의 PARAMETERIZATION 옵션을 FORCED로 설정하는 것이 좋습니다. 이 옵션을 설정할 때는 신중해야 합니다. PARAMETERIZATION 옵션은 데이터베이스 수준 설정이므로 데이터베이스에 대한 모든 쿼리의 처리 방식에 영향을 미칩니다. 자세한 내용은 강제 매개 변수화를 참조하십시오.

MERGE 문에서 TOP 절은 원본 테이블과 대상 테이블이 조인되고 삽입, 업데이트 또는 삭제 동작에 적합하지 않은 행이 제거된 후에 영향을 받는 행의 개수나 비율을 지정합니다. TOP 절은 조인된 행 수를 지정된 값으로 더 줄이며, 삽입, 업데이트 또는 삭제 동작은 나머지 조인된 행에 순서 없이 적용됩니다. 즉, 행은 WHEN 절에 정의된 동작에 순서 없이 분산됩니다. 예를 들어 TOP (10)을 지정하면 10개 행이 영향을 받습니다. 이 10개의 행 중 7개가 업데이트되고 3개가 삽입되거나, 1개가 삭제되고 5개가 업데이트되고 4개가 삽입될 수 있습니다.

일반적으로 TOP 절을 사용하여 큰 테이블에서 일괄 처리로 DML(데이터 조작 언어) 작업을 수행합니다. MERGE 문에서 TOP 절을 이러한 용도로 사용하는 경우 다음 내용을 알고 있어야 합니다.

  • I/O 성능이 영향을 받을 수 있습니다.

    MERGE 문은 원본 테이블과 대상 테이블 모두에서 전체 테이블 검색을 수행합니다. 작업을 여러 일괄 처리로 나누면 일괄 처리 하나당 수행되는 쓰기 작업의 수를 줄일 수 있지만 각 일괄 처리에서는 원본 테이블과 대상 테이블에서 전체 테이블 검색을 수행합니다. 그 결과 읽기 작업이 쿼리의 성능에 영향을 줄 수 있습니다.

  • 잘못된 결과가 발생할 수 있습니다.

    연속된 모든 일괄 처리는 새로운 행을 대상으로 해야 합니다. 그렇지 않은 경우 대상 테이블에 중복 행을 잘못 삽입하는 등의 원하지 않는 동작이 발생할 수 있습니다. 이러한 현상은 대상 일괄 처리에는 없었지만 전체 대상 테이블에는 있었던 행이 원본 테이블에 포함되는 경우 발생할 수 있습니다.

    정확한 결과를 보장하려면

    • ON 절을 사용하여 기존 대상 행에 영향을 미치는 원본 행과 완전히 새로운 행을 확인합니다.

    • WHEN MATCHED 절에 추가 조건을 사용하여 이전 일괄 처리에 의해 대상 행이 이미 업데이트되었는지 여부를 확인합니다.

    TOP 절은 이러한 절이 적용된 후에 적용되므로 문을 실행할 때마다 하나의 완전히 일치하지 않는 행이 삽입되거나 하나의 기존 행이 업데이트됩니다. 다음 예에서는 원본 및 대상 테이블을 만든 다음 일괄 처리 작업에서 올바르게 TOP 절을 사용하여 대상을 수정하는 방법을 알려 줍니다.

    CREATE TABLE dbo.inventory(item_key int NOT NULL PRIMARY KEY, amount int, is_current bit);
    GO
    CREATE TABLE dbo.net_changes(item_key int NOT NULL PRIMARY KEY, amount int);
    GO
    
    MERGE TOP(1) dbo.inventory
    USING dbo.net_changes
    ON inventory.item_key = net_changes.item_key
    WHEN MATCHED AND inventory.is_current = 0
      THEN UPDATE SET amount += net_changes.amount, is_current = 1
    WHEN NOT MATCHED BY TARGET
      THEN INSERT (item_key, amount, is_current) VALUES(item_key, amount, 1)
    OUTPUT deleted.*, $action, inserted.*;
    GO
    
    
    

    다음 예에서는 잘못된 TOP 절 구현 방법을 보여 줍니다. is_current 열 확인이 원본 테이블과의 조인 조건에 지정됩니다. 즉, 하나의 일괄 처리에 사용된 원본 행이 다음 일괄 처리에 “일치하지 않는 항목”으로 처리되어 원하지 않는 삽입 작업이 수행될 수 있습니다.

    MERGE TOP(1) dbo.inventory
    USING dbo.net_changes
    ON inventory.item_key = net_changes.item_key AND inventory.is_current = 0
    WHEN MATCHED
      THEN UPDATE SET amount += net_changes.amount, is_current = 1
    WHEN NOT MATCHED BY TARGET
      THEN INSERT (item_key, amount, is_current) values(item_key, amount, 1)
    OUTPUT deleted.*, $action, inserted.*;
    GO
    
    
    

    다음 예에서도 잘못된 방법을 보여 줍니다. CTE(공통 테이블 식)를 사용하여 일괄 처리의 행 읽기 횟수를 제한하면 TOP(1)에 의해 선택된 행이 아닌 다른 대상 행에 일치하는 모든 원본 행이 “일치하지 않는 항목”으로 처리되어 원하지 않는 삽입 작업이 수행될 수 있습니다. 또한 이 방법은 업데이트할 수 있는 행의 수만 제한하므로 각 일괄 처리에서는 “일치하지 않는” 모든 원본 행의 삽입을 시도합니다.

    WITH target_batch AS (
      SELECT TOP(1) *
      FROM dbo.inventory
      WHERE is_current = 0
      )
    MERGE target_batch
    USING dbo.net_changes
    ON target_batch.item_key = net_changes.item_key
    WHEN MATCHED
      THEN UPDATE SET amount += net_changes.amount, is_current = 1
    WHEN NOT MATCHED BY TARGET
      THEN INSERT (item_key, amount, is_current) values(item_key, amount, 1)
    OUTPUT deleted.*, $action, inserted.*;
    GO
    
    
    

MERGE 문을 사용하여 OPENROWSET(BULK…) 절을 테이블 원본으로 지정하면 원본 데이터 파일의 데이터를 대상 테이블로 효율적으로 대량 로드할 수 있습니다. 이렇게 하면 전체 파일이 하나의 일괄 처리에서 처리됩니다.

대량 병합 프로세스의 성능을 높이려면 다음 지침을 따르는 것이 좋습니다.

  • 대상 테이블의 조인 열에 클러스터형 인덱스를 만듭니다.

  • OPENROWSET(BULK…) 절에 ORDER 및 UNIQUE 힌트를 사용하여 원본 데이터 파일의 정렬 방식을 지정합니다.

    기본적으로 대량 작업은 데이터 파일이 정렬되지 않았음을 전제로 합니다. 따라서 쿼리 최적화 프로그램이 보다 효율적인 쿼리 계획을 생성할 수 있도록 원본 데이터를 대상 테이블의 클러스터형 인덱스에 따라 정렬하고, ORDER 힌트를 사용하여 순서를 나타내야 합니다. 힌트는 런타임에 유효성이 검사됩니다. 데이터 스트림이 지정된 힌트를 따르지 않으면 오류가 발생합니다.

이러한 지침을 통해 조인 키의 고유성을 확보하고 원본 파일의 데이터 정렬 순서가 대상 테이블과 일치하도록 할 수 있습니다. 추가 정렬 작업이 필요 없고 불필요한 데이터 복사가 없으므로 쿼리 성능이 향상됩니다. 다음 예에서는 MERGE 문을 사용하여 플랫 파일 StockData.txt에서 대상 테이블 dbo.Stock으로 데이터를 대량 로드합니다. 대상 테이블의 StockName에 기본 키 제약 조건을 정의하면 원본 데이터와 조인하는 데 사용되는 열에 클러스터형 인덱스가 만들어집니다. ORDER 및 UNIQUE 힌트는 대상 테이블의 클러스터형 인덱스 키 열에 매핑되는 데이터 원본의 Stock 열에 적용됩니다.

이 예를 실행하려면 먼저 C:\SQLFiles\ 폴더에 'StockData.txt'라는 텍스트 파일을 만듭니다. 이 파일에는 쉼표로 구분된 두 개의 데이터 열이 있어야 합니다. 예를 들어 다음과 같은 데이터를 사용합니다.

Alpine mountain bike,100

Brake set,22

Cushion,5

그런 다음 C:\SQLFiles\ 폴더에 'BulkloadFormatFile.xml'이라는 xml 서식 파일을 만듭니다. 다음과 같은 정보를 사용합니다.

<?xml version="1.0"?>

<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<RECORD>

<FIELD ID="1" xsi:type="CharTerm" TERMINATOR="," MAX_LENGTH="25"/>

<FIELD ID="2" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="5"/>

</RECORD>

<ROW>

<COLUMN SOURCE="1" NAME="Stock" xsi:type="SQLNVARCHAR"/>

<COLUMN SOURCE="2" NAME="Delta" xsi:type="SQLSMALLINT"/>

</ROW>

</BCPFORMAT>

USE AdventureWorks2008R2;
GO
CREATE TABLE dbo.Stock (StockName nvarchar(50) PRIMARY KEY, Qty int CHECK (Qty > 0));
GO
MERGE dbo.Stock AS s
USING OPENROWSET (
    BULK 'C:\SQLFiles\StockData.txt',
    FORMATFILE = 'C:\SQLFiles\BulkloadFormatFile.xml',
    ROWS_PER_BATCH = 15000,
    ORDER (Stock) UNIQUE) AS b
ON s.StockName = b.Stock
WHEN MATCHED AND (Qty + Delta = 0) THEN DELETE
WHEN MATCHED THEN UPDATE SET Qty += Delta
WHEN NOT MATCHED THEN INSERT VALUES (Stock, Delta);
GO


다음 기능을 사용하여 MERGE 문의 성능을 측정 및 진단할 수 있습니다.

  • sys.dm_exec_query_optimizer_info 동적 관리의 merge stmt 카운터를 사용하여 MERGE 문에 대한 쿼리 최적화 횟수를 반환할 수 있습니다.

  • sys.dm_exec_plan_attributes 동적 관리 함수의 merge_action_type 특성을 사용하여 MERGE 문의 결과로 사용되는 트리거 실행 계획의 유형을 반환할 수 있습니다.

  • SQL Trace를 사용하여 다른 DML(데이터 조작 언어) 문에 대해 사용하는 것과 동일한 방식으로 MERGE 문에 대한 문제 해결 데이터를 수집할 수 있습니다. 자세한 내용은 SQL Trace 소개를 참조하십시오.

이 정보가 도움이 되었습니까?  


'오라클' 카테고리의 다른 글

프로시져.INSERT 또는 UPDATE  (0) 2012.10.15
오라클 힌트 모음 (예제)  (0) 2012.08.31
오라클 procedure 정리  (0) 2012.08.30
오라클 FUNCTION() 생성 예제  (0) 2012.08.30
DB2 함수 정리.  (0) 2012.08.29
Posted by 사라링

오라클 procedure 정리

2012. 8. 30. 10:36

※ 스토어드 프로시져는 반드시 수정, 삭제전에 소스백업을 해놓고 수정, 삭제해야 한다.

 

PL/SQL (ProcedureLanguage/SQL) 정의

 

Oracle 에서 스토어드 프로시져를 개발할때 사용하는 언어(문법)입니다.

PL/SQL은 ANSI SQL 보다 확장된 SQL로써 좀더 다양한 처리를 구현할수 있습니다.

* PL/SQL과 스토어드 프로시져는 같은 의미로 해석함

 

스토어드 프로시져 사용목적

 

일반 SQL 실행

 

흐름 : 클라이언트에서 서버로 단일 쿼리를 날려 실행함

 

단점 : 여러개의 SQL를 실행시 실행할 SQL 갯수만큼 실행

 

스토어드 프로시져 SQL 실행

 

흐름 : 서버에 스토어드 프로시져를 먼저 생성후 클라이언트에서 호출하여 실행함

 

장점 : 여러개의 SQL을 실행시 하나의 스토어드 프로시져에 담아 컴파일하여 서버에 생성한후 한번만 호출하여 실행

 

※ 스토어드 프로시져 생성후 커밋처리를 해줘야 한다.

 

※ 스토어드 프로시져 생성시 정적쿼리에서 사용하는 테이블, 컬럼이 해당 DB에 존재하지 않으면 에러를 발생한다. 단 동적쿼리의 테이블과 컬럼은 체크하지 않는다.

 

※ 스토어드 프로시져 생성시 다른 스토어드 프로시져를 호출하는 명령이 있을때 해당 스토어드 프로시져가 현재 존재안하면 에러를 발생한다.

 

스토어드 프로시져 사용이점

 

1. 프로그램 의존성이 낮고 독립성이 높다.

 

PRO-C, SQC, 쉘스크립트에서 스토어드 프로시져 수정시 스토어드 프로시져만 컴파일하면 된다. PRO-C, SQC, 쉘스크립트 파일은 재컴파일을 안해도 된다.

 

오라클 스토어드 프로시저로 할수없는 SQL

 

DDL(CREATE TABLE, DROP TABLE, ALTER TABLE)

 

PL/SQL 사용의 장점?

 

 

변수를 선언하고 사용할수 있으며 조건문을 사용할수 있다.

예외처리도 가능하며 네트웍트랙픽도 감소시켜주며 프로그래개발을 모듈화할수 있다.

트랜잭션 로직으로 개발가능하다.

서버에 이미 저장되어있으므로 실행속도가 빠르다.

서버에 저장되어 있으므로 보안에 좋다.

 

PL/SQL 블록 구조

 

※ PL/SQL 블럭 내부에는 SQL명령문과 PL/SQL명령문이 포함되어있다.

 

DECLARE

 

--변수,상수 선언

 

BEGIN

 

--실행 가능 SQL문,PL/SQL문

 

EXCEPTION

 

--에러처리

 

END;

 

※ BEGIN과 END SECTION은 꼭 필수 부이다.

 

※ SP는 컴파일하기전에 사용된 컬럼과 테이블이 있는지 체크한후에 컴파일을

시작하며 존재하지 않는 컬럼,테이블이 있다면 에러를 발생한다.

 

PL/SQL 블록에서 사용못하는 SQL문

 

CREATE,GRANT

 

※ SELECT,UPDATE,INSERT,DELETE는 사용가능하다.

 

PL/SQL 에서 여러행을 리턴하는 방법

 

여러개의 리턴값을 넘길때 "var1 || '/' || var1" 와 같이 구분자를 넣어서 하나로 넘겨서 사용하면 됩니다.

사용예제

CREATE OR REPLACE FUNCTION FUN_EX

(

IN_VAR1 VARCHAR2,

IN_VAR2 VARCHAR2,

IN_VAR2 VARCHAR2) RETURN NUMBER IS

RTN_VAR VARCHAR2(100);

INTO1 VARCHAR2(10);

INTO2 VARCHAR2(10);

INTO3 VARCHAR2(10);

BEGIN

SELECT VAR1, VAR2, VAR3

INTO INTO1, INTO2, INTO3

FROM 테스트

WHERE 조건하나

AND 조건둘

AND.. .;

RTN_VAR := INTO1 || '/' || INTO2 || '/' || INTO3;

-- 구분자는 편의대로 정하시면 됩니다.

RETURN RTN_VAR;

EXCEPTION

WHEN NO_DATA_FOUND THEN

RETURN 0; -- check

WHEN OTHERS THEN

RETURN 0; -- check

END FUN_EX;

 

PL/SQL 데이타타입 종류

 

   v_hire      date;

 

    v_deptno    number(2) not null = 0;
    /* not null이 붙으면 꼭 초기화를 해야한다. */

 

    v_location  varchar2(13) := 'allanta';
    /* not null이 없으면 꼭 초기화를 하지 않아도 된다. */

    /* 가변길이 문자열 */

 

    v_name      char(4) := 'lee';

    /* 고정길이 문자열 */

 

    v_address   long;

    /* 32760 바이트를 저장할수는 문자열 */

 

    v_true      boolean;

    /* 진리값을 저장한다. */

 

    c_com       constant number :=1400;

    /* constant는 상이다. */

 

    v_age       emp.age%TYPE;

    v_age2      v_age%TYPE;
    /* %TYPE을 쓰는이유는 TABLE의 컬럼의 데이타형이 달라지거나 제어할 TABLE */
    /* 컬럼과 같게하기위해 매번 확인하야하는 번거로움을 없애기 위해 */

    /* 큰시스템에서는 프로시저형이 달라지면 다바꾸어야 하기때문에 테이블의 형을 참조

    /* 해서 사용하면 테이블구조가 바뀌어도 자동으로 바뀌게 좋다. 대신 제대로 형을 */

    /* 참조해야 한다.*/

    v_loc loc /* 구조화되지않은 큰데이타 저장 4기가바이트까지 저장 */

 

PL/SQL 블록 유형

 

Anonymouse 유형(매번 서버에 전송하여 컴파일하여 실행함)

 

[declare]

begin

--실행소스

[exception]

end;

 

Procedure 유형(초이 한번만 서버에 생성하여 컴파일하여 호출하여 실행함)

 

CREATE OR REPLACE Procedure name

is

begin

--실행소스

[exception]

end;

 

Function 유형(초이 한번만 서버에 생성하여 컴파일하여 호출하여 실행함)

 

CREATE OR REPLACE Function name

Return datatype

is

begin

--실행소스

[exception]

end;

 

Anonymouse PL/SQL 블록 유형

 

클라이언트에서 매번 PL/SQL블록을 만들어 서버에 전송하여 자동으로 컴파일되어 실행하는 방식으로 여러 SQL문을 하나의 PL/SQL블록으로 만들어 보내면 한번에 여러 SQL문실행이 가능하지만 매번 서버에서 컴파일되기때문에 PROCEDURE,FUNCTION유형보다 성능이 좋지 않다.

 

Anonymouse PL/SQL 사용예제

 

create table test
(
  a number,
  b date
);

 

select * from test;

 

/* select문에서 INTO절사용시 1개의 행(로우)만이 into절에 변수에 저장가능하다. */
Declare
  /* 2개의 선언 */
  a account.a_strday%TYPE;
  b account.a_in%TYPE;
begin
  /* a_strday,a_in의 값을 a,b에 넣어라 */
  select a_strday,a_in
  into a,b
  from account
  where a_type = '뮤직';
end;
/* select문에서 INTO절사용시 1개의 행(로우)만이 into절에 변수에 저장가능하다. */

 

 

/* 1개의 행의 컬럼값을 v_empno에 저장한후 test테이블에 대입한후 commit한다. */
Declare
  v_empno number;
  v_date  date := sysdate;
begin
  select 1
    into v_empno
  from dual;
  insert into test (a,b) values (v_empno,v_date);
  commit;
end;
/* 1개의 행의 컬럼값을 v_empno에 저장한후 test테이블에 대입한후 commit한다. */

 

 

/* PL/SQL UPDATE예제(UPDATE,DELETE는 다중행처리 가능) */
Declare
  v_sale number := 2000;
begin
  update test set a = v_sale;
  delete from test where a = v_sale;
  commit;
end;
/* PL/SQL UPDATE예제(UPDATE,DELETE는 다중행처리 가능) */

 

 

스토어드 프로시저 PL/SQL 블록 유형?

 

스토어드 프로시저란 어떤 업무를 수행 하기 위한 절차를 뜻하며 반복되는 코딩을

모듈화 하기 위하여 함수나 프로시져를 사용합니다.

 

보통 DB에서는 데이타를 조회하여 가져오고 그 데이타를 받는 언어쪽에서는 데이타를

가공하여 화면에 출력을 합니다. 하지만 DB에서 데이타조회와 가공까지 하면 좀더 빠르게

화면 출력이 되며 서버부하를 줄일수 있습니다.

 

ORACLE의 PROCEDURE을 이용하면 서버부하를 줄이며 좀더 빠른 화면출력이 되며 여러

쿼리들을 하나의 프로시저,함수로 만들어 한번에 실행시킬수 있습니다.

 

예를 들어 인터넷을 통해 극장표를 구매하는 프로시저로 표현 한다면

 

[극장표 구매 Procedure 시작 ]

1. 예매 사이트에 접속 한다.
2. 예매할 영화 선택 한다.
3. 예매 일자와 시간을 선택 한다.
4. 예매 매수를 선택 한다.
5. 위 과정이 모두 끝났으면 결재를 한다.

[극장표 구매 Procedure 종료 ]

 

위와 같이 어떤 프로세스 절차를 기술해 놓을것을 프러시저 라고 합니다.

 

Procedure에서 Procedure를 호출하는 방법

 

A프로시져에서 "프로시져명(변수, 변수2);" 명령으로 B프로시져를 호출할수 있다.

 

PROCEDURE and FUNCTION 의 차이점?

 

프로시저와 펀션 둘다 파라미터를 받고 리턴값을 지정할수있으나 가장 큰 차이점은

function은 반드시 리턴값을 하나만 가져야 하지만 procedure는 여러개의 리턴값을 가질수 있습니다.

 

생성된 PROCEDURE & FUNCTION 리스트보기

 

SELECT * FROM USER_OBJECTS WHERE OBJECT_TYPE='PROCEDURE';

SELECT * FROM USER_OBJECTS WHERE OBJECT_TYPE='FUNCTION';

 

PROCEDURE & FUNCTION 삭제하기

 

DROP FUNCTION lee2;

DROP PROCEDURE lee2;

 

※ 삭제시 아래 메세지가 출력되는 경우

ORA-04021: 객체 KMS.KM_GET_KNOWLEDGE_LIST_PAGE의 잠금 대기중 시간이

초과됐습니다.

library lock 이 발생하여 해당 procedure 를 사용중이거나, 머 library lock 이 발생하면

해당 package, procedure, function 에 대한 작업을 할수 없습니다.

lock 관련 체크 script 를 통해서 체크 해보세요.

 

생성된 Procedure & Function의 내용보기

 

select * from user_source;

select * from user_source where name='DATETOSTRDAY';

또는

SELECT * FROM ALL_SOURCE WHERE OWNER = '소유자' AND NAME = '프로시져명'

 

※ MSSQL, MySQL, DB2도 특정 테이블에 프로시져와 펑션의 내용이 들어있습니다.

 

PROCEDURE & FUNCTION 실행하기

 

EXECUTE lee;

--PROCEDURE 실행하기EXEC lee;

--PROCEDURE 실행하기 예제 select function_name(column) from table_name;

 

PROCEDURE & FUNCTION 기본 문법

 

create or replace procedure lee
--파라미터 선언부

is
--변수 선언부
begin
--실행부(쿼리적용)
end lee;

 

create procedure lee
--파라미터 선언부

is
--변수 선언부
begin
--실행부(쿼리적용)
end lee;

 

LOOP문  :LOOP와 END LOOP사이의 문장을 반복 수행하며 BREAK문으로 빠져나감

WHILE문 : 제어 조건이 TRUE가 아닐 때까지 문장을 반복수행

 

PROCEDURE 예제

 

※ 주의할점

1) END; 와 END 프로시저&함수명; 은 같다. 보통 안쓰는게 편합니다.

2) CREATE OR replace PROCEDURE LEE 와 CREATE PROCEDURE LEE의 차이는 전자는 같은 프로시저 이름으로 계속 생성해도 새롭게 내용이 갱신되고 후자는 같은 프로시저명이 있으면 에러를 내고 실행을 멈춥니다.

3)프로시저나 함수 생성시에 에러가 나면 sqlplus에서 show error을 쳐서 에러내용을 확인합니다.

 

숫자를 받은후 UPDATE쿼리를 합니다.

 

CREATE OR REPLACE PROCEDURE LEE1
(v_empno IN NUMBER) /* 정수형 파라미터를 v_empno변수로 받는다. */
IS
BEGIN
UPDATE emp SET sal = sal  * 1.1
WHERE empno = v_empno;/* query runtime */
COMMIT; /* update query commit */
END LEE1;
/
execute lee1(7369);

 

숫자를 받은후 UPDATE쿼리를 합니다.

 

CREATE OR REPLACE PROCEDURE LEE2
(v_empno in emp.sal%type)

/* v_empno변수에 파라미터로 받고 v_empno type은 emp테이블의 sal컬럼과 같은 타입이다. */
IS
BEGIN
UPDATE emp SET sal = sal  * 1.1
WHERE empno = v_empno;/* query runtime */
COMMIT; /* update query commit */
END LEE2;
/

execute lee1(7369);

 

list 테이블에서 사번을 입력받아 COMMISSION_PCT 값을 수정하시오.

COMMISSION_PCT 는 영업사원이 담당한 
주문(s_ord)  총금액(s_ord.total)으로 결정한다.
update_comm 라는  procedure 작성하시오.
a. 총금액이 100,000 미만이면 COMMISSION_PCT는 10
b. 총금액이 100,000 이상이고 1,000,000 미만이면 15
c. 총금액이 1,000,000 이상이면 20
d. NULL이면 0

 

create table list
(
id number,
money number,
comm number
);

 

create or replace procedure update_comm
(a_id in list.id%type)
is
v_total      list.money%type;
v_comm       list.comm%type;
begin
    select sum(money)
     into   v_total
    from   list
    where id = a_id;
    if   v_total < 100000 then
         v_comm := 10;
    elsif v_total < 1000000 then
         v_comm := 15;
    elsif v_total >= 1000000 then
         v_comm := 20;
    else
         v_comm := null;
    end if;
    dbms_output.put_line('사번      : '||to_char(a_id));
    dbms_output.put_line('TOTAL : '||to_char(v_total, '999,999,999'));
    dbms_output.put_line('커미션   : '||to_char(v_comm,'999.99'));
    update list
    set comm = v_comm
    where id = a_id;
    commit;
end;
/

execute update_comm(1);

 

FUNCTION 예제

 

사원번호를 입력받아 사원의 월급을 출력합니다.

 

CREATE OR REPLACE FUNCTION lee3
(id IN NUMBER)
return number
IS
value1 NUMBER;

BEGIN
select sal into value1 from emp where empno=id;
return(value1);
END;
/

select lee3(empno) from emp;

 

부서번호을 입력받아 부서명을 return 해주는 함수를 만들자.

함수명 : f_deptname
인자    : id(s_dept.id%type)
리턴값 : varchar2

사원정보에 대해서 
사번(id), 이름(last_name), 부서번호, 부서명을 조회하자.

 

create or replace function f_deptname
(a_id in dept.deptno%type)
return  varchar2
is
  v_dname      dept.dname%type;
begin
   select dname
     into v_dname
  from dept
 where  deptno= a_id;
 return(v_dname);
end;
/
select f_deptname(deptno) from dept;

 

S_EMP 테이블에서 사번을 입력받아 해당 사원의 급여에 따른 
세금을 구하시오. 
급여가 1000 미만이면 급여의 5%, 급여가 2000 미만이면 7%, 
급여가 3000 미만이면 9%,  그 이상은 12%로   세금을 정한다.

 

create or replace function f_tax

/*
정수형 파라미터 설정
(id in emp.empno%type)
*/
(id in number)
return  number

/* 변수선언 */
is
v_sal      NUMBER;
/* v_sal      s_emp.salary%type; */
v_tax      NUMBER;

/* 함수 실행문 */
begin
    select sal
     into   v_sal
    from emp
    where empno = id;

    if   v_sal < 1000 then
         v_tax := v_sal * 0.05;
    elsif v_sal < 2000 then
         v_tax := v_sal * 0.07;
    elsif v_sal < 3000 then
         v_tax := v_sal * 0.09;
    else
         v_tax := v_sal * 0.12;
    end if;
    return(v_tax);

end;
/
select f_tax(empno) from emp;

 

/*
함수명:숫자형식요일리턴함수
함수설명:날짜를 입력받아 요일을 숫자로 리턴하는 함수
함수작성자:이 준식
*/


create or replace FUNCTION DateToNumDay(DateValue IN date)/*받는 변수*/
return number/*리턴 데이타형*/
IS
ShowDay number;/*숫자변수 선언*/
BEGIN
/**********************************/
SELECT decode(to_char(DateValue,'D'),
              '2','1',
              '3','2',
              '4','3',
              '5','4',
              '6','5',
              '7','6',
              '1','7') "요일숫자" into ShowDay
from   dual;
/**********************************/
return(ShowDay);/*해당 변수를 리턴*/

end;

/

 

/*
함수명:문자형식요일리턴함수
함수설명:숫자요일을 입력받아 문자로 리턴하는 함수
함수작성자:이 준식
*/

 

create or replace FUNCTION NumdayToStrDay(NumValue IN number)/*받는 변수*/
return varchar2/*리턴 데이타형*/
IS
StrValue varchar2(10);/*문자변수 선언*/
BEGIN
/**********************************/
SELECT decode((NumValue),
              1,'월요일',
              2,'화요일',
              3,'수요일',
              4,'목요일',
              5,'금요일',
              6,'토요일',
              7,'일요일') "요일" into StrValue
from   dual;
/**********************************/
return(StrValue);/*해당 변수를 리턴*/

end;
/

 

/*
함수명:문자형식요일리턴함수
함수설명:날짜를 입력받아 요일을 문자로 리턴하는 함수
함수작성자:이 준식
*/

 

create or replace FUNCTION DateToStrDay(DateValue IN date)/*받는 변수*/
return varchar/*리턴 데이타형*/
IS
ShowDay varchar(10);/*숫자변수 선언*/
BEGIN
/**********************************/
SELECT decode(to_char(DateValue,'D'),
              '1','일요일',
              '2','월요일',
              '3','화요일',
              '4','수요일',
              '5','목요일',
              '6','금요일',
              '7','토요일') "요일" into ShowDay
from   dual;
/**********************************/
return(ShowDay);/*해당 변수를 리턴*/

end;

/

 

/*
함수명:숫자형식콤마문자리턴함수
함수설명:숫자를 입력받아 콤마처리를 문자로 리턴하는 함수
함수작성자:이 준식
*/

 

create or replace FUNCTION IntToComma(IntValue IN number)/*받는 변수*/
return varchar/*리턴 데이타형*/
IS
ShowDay varchar(20);/*문자변수 선언*/
BEGIN
/**********************************/

 

SELECT replace(to_char(IntValue,'999,999,999,999'),' ','') into ShowDay

from   dual;
/*SELECT trim(to_char(IntValue,'999,999,999,999')) into ShowDay*/

 

/**********************************/
return(ShowDay);/*해당 변수를 리턴*/
end;
/

 

/*
함수명:문자형식 숫자,문자,null 체크 출력
함수설명:문자형식을 숫자인지 문자와 숫자인지 null인지 알려준다.
함수작성자:이 준식
*/

 

create or replace function NumCheck(asString varchar2)
return varchar2
is
 nTemp number(1);
begin
 select sign(asString)
 into nTemp
 from dual;

 if nTemp is null then
  return 'null';
 end if;
 
 return 'number';
exception
 when others then
  return 'string';
end;
/

 

/*
함수명:출력컬럼명을 보내서 해당날짜에 그컬럼값을 출력한다.

함수작성자:이 준식
*/

 

create or replace function test_01(param1 IN date,param2 IN VARCHAR2)
 return varchar2
is
 ls_code varchar2(20);
BEGIN
 SELECT decode(param2,'a_type',a_type) INTO ls_code from ACCOUNT where A_DATE = param1;
 return ls_code;
/* 정상적으로 실행되었으나 조회갯수가 0개면 발생 */
exception when no_data_found then
 return '데이타가 없습니다.';
/* return null; */
END test_01;
/

 

select test_01(sysdate) from dual;
select test_01(to_date('2005-10-18','yyyy-mm-dd'),'a_type') from dual;

 

create or replace function test_01(param1 IN varchar2)
 return varchar2
is
 ls_code varchar2(20);
BEGIN
 SELECT A_TYPE INTO ls_code from ACCOUNT where A_DATE = to_date(param1,'yyyy-mm-dd');
 return ls_code;
/* 정상적으로 실행되었으나 조회갯수가 0개면 발생 */
exception when no_data_found then
 return '데이타가 없습니다.';
/* return null; */
END test_01;
/

 

select test_01(sysdate) from dual;
select test_01('2005-10-18') from dual;

 

프로시져는 SQL문에서 호출할수 없지만 함수는 SQL문에서 호출할수 있다.

 

PL/SQC 자동실행 방법

 

윈도우의 경우

보조프로그램 > 시스템도구 > 예약된 작업에서 .bat 파일을 만든후 등록함

 

유닉스의 경우

쉘스크립트 파일을 만든후 크론에 등록하거나 nohup으로 실행

 

오라클의 기능을 이용한 경우

dbms_job 패키지를 이용한다.

'오라클' 카테고리의 다른 글

오라클 힌트 모음 (예제)  (0) 2012.08.31
BYPASS_UJVC -> MERGE 문으로 변경 하자.  (0) 2012.08.31
오라클 FUNCTION() 생성 예제  (0) 2012.08.30
DB2 함수 정리.  (0) 2012.08.29
ORDERY BY 절 사용  (0) 2012.08.29
Posted by 사라링

 프로젝트 참여 과정중 예제로 오라클 프로시져를 만들 일이 생겨서 간단히 summery  해 두겠습니다 ^^

/* 예제 테이블 생성*/
create table exam1 (
yoil varchar2(1),
gyosi varchar2(2),
cnt varchar2(2),
gyo_name varchar2(50),
gang_dongsil varchar2(12),
judamdang varchar2(20),
gyo_code varchar2(10),
gangjwa_code varchar2(20))

/* 예제 데이터 집어 넣기 */
/*insert data*/
insert into exam1 values ('1', '13', '6' , '유통기관경영론' , '(059-610)', '' ,'251.563', '');
insert into exam1 values ('1', '14', '6' , '유통기관경영론' , '(059-610)', '' ,'251.563', '');
insert into exam1 values ('1', '15', '6' , '유통기관경영론' , '(059-610)', '' ,'251.563', '');
insert into exam1 values ('1', '16', '6' , '유통기관경영론' , '(059-610)', '' ,'251.563', '');
insert into exam1 values ('1', '17', '6' , '유통기관경영론' , '(059-610)', '' ,'251.563', '');
insert into exam1 values ('1', '18', '6' , '유통기관경영론' , '(059-610)', '' ,'251.563', '');
insert into exam1 values ('1', '23', '6' , '행정법일반이론' , '(017-105)', '' ,'270.721', '');
insert into exam1 values ('1', '24', '6' , '행정법일반이론' , '(017-105)', '' ,'270.721', '');
insert into exam1 values ('1', '25', '6' , '행정법일반이론' , '(017-105)', '' ,'270.721', '');
insert into exam1 values ('1', '26', '6' , '행정법일반이론' , '(017-105)', '' ,'270.721', '');
insert into exam1 values ('2', '16', '6' , '러시아예술과 문화' , '(003-204)', '' ,'100.124', '');
insert into exam1 values ('2', '17', '6' , '러시아예술과 문화' , '(003-204)', '' ,'100.124', '');
insert into exam1 values ('2', '18', '6' , '러시아예술과 문화' , '(003-204)', '' ,'100.124', '');
insert into exam1 values ('2', '19', '6' , '러시아예술과 문화' , '(003-204)', '' ,'100.124', '');
insert into exam1 values ('2', '20', '6' , '러시아예술과 문화' , '(003-204)', '' ,'100.124', '');
insert into exam1 values ('2', '21', '6' , '러시아예술과 문화' , '(003-204)', '' ,'100.124', '');

다음과 같이 예제 테이블과 예제 데이터를 만들었으면, select 를 해보겠습니다.
/* 일반적인 SELECT 문 */
select
    yoil, gyo_name, gang_dongsil, judamdang, gyo_code, gangjwa_code
from
    exam1

다음과 같은 결과 값이 나왔습니다.


그런데 문제는 요일에 따른 교시를 나타내고 싶습니다.

1 | 13, 14, 15, 16, 17 | 유통기관경영론 | (059-610) | .....

이렇게 데이터를 만들고 싶을때!



UDF : 사용자 FUNCTION 을 만듭니다. Procedure 라고도 부르는것 같군요

/*user function */
CREATE OR REPLACE FUNCTION GET_ALL_PROJECTp_gyo_code IN varchar) RETURN VARCHAR2
IS
RESULT_STR VARCHAR2 (200);
BEGIN
  SELECT SUBSTR(MAX( SYS_CONNECT_BY_PATH (gyosi,'|')),2) INTO RESULT_STR
  FROM (
    SELECT gyosi, ROWNUM rnum
    FROM EXAM1
    WHERE exam1.gyo_code = p_gyo_code
  )
  START WITH rnum = 1
  CONNECT BY PRIOR rnum = rnum -1; 
  RETURN RESULT_STR;
END GET_ALL_PROJECT;
/

GET_ALL_PROJECT : 함수 이름
p_gyo_code  :  p_gyo_code : 프로시져 안에서 쓰일 변수 
IN varchar : 파라미터  타입
RESULT_STR : 리턴값
UDF 생성후 쿼리를 다시 한번 날리겠습니다.
select
    yoil, gyo_name, gang_dongsil, judamdang, gyo_code, gangjwa_code, count(gyosi) as gyosi_cnt , GET_ALL_PROJECT(gyo_code)
from
    exam1
group by
    yoil, gyo_name, gang_dongsil, judamdang, gyo_code, gangjwa_code ;


다음과 같은 결과 화면을 얻을 수 있습니다 ^^



어려우면서도 쉬운것 같은 UDF 네요 - - 히힛-

'오라클' 카테고리의 다른 글

BYPASS_UJVC -> MERGE 문으로 변경 하자.  (0) 2012.08.31
오라클 procedure 정리  (0) 2012.08.30
DB2 함수 정리.  (0) 2012.08.29
ORDERY BY 절 사용  (0) 2012.08.29
최상위 코드와 그 최상위 코드를 대상으로 그룹 .  (0) 2012.08.24
Posted by 사라링

DB2 함수 정리.

2012. 8. 29. 17:44


기본정보보기
DESCRIBE TABLE table-name [show detail]
DESCRIBE SELECT * FROM tablename;

 

인덱스 정보보기 
DESCRIBE INDEXES FOR TABLE table-name [show detail]


등록 테이블 리스트 보기
LIST  TABLES  FOR  ALL ;

 

- LOCK 상태 확인
GET SNAPSHOT FOR LOCKS ON depsdb
  
유지되는 잠금현재 잠금대기중인 에이전트응용프로그램명
  
응용프로그램 상태총대기시간모드상태 등을 확인


SELECT * FROM staff FETCH FIRST 5 ROWS ONLY
라고 하면 하면 처음 5개의 row가 나옵니다.

 

SELECT bus_mkt_id, svc_mgmt_num, svc_cd, svc_num, cell_equip_modl_cd, line_num 
  FROM coispc.vcell_num 
 WHERE svc_mgmt_num = ? 
 ORDER BY eff_dt_tm desc FETCH FIRST 1 ROWS ONLY
  WITH UR


SELECT INTEGER(SUBSTR(CHAR(CURRENT DATE),1,1)||SUBSTR(CHAR(CURRENT DATE),3,2)||SUBSTR(CHAR(CURRENT DATE),6,2)||SUBSTR(CHAR(CURRENT DATE),9,2)),
       INTEGER(SUBSTR(CHAR(CURRENT TIMESTAMP),12, 2) || SUBSTR(CHAR(CURRENT TIMESTAMP),15,2) || SUBSTR(CHAR(CURRENT TIMESTAMP),18,2) || SUBSTR(CHAR(CURRENT TIMESTAMP),21,1))
FROM SYSIBM.SYSDUMMY1
WITH UR


CREATE FUNCTION month_between (p_start date, p_end date)
RETURNS SMALLINT
BEGIN atomic
      DECLARE v_year_diff  SMALLINT DEFAULT 0;
      DECLARE v_month_diff SMALLINT DEFAULT 0;
      DECLARE v_diff       SMALLINT DEFAULT 0;
             
      SET v_year_diff  = YEAR(p_start) - YEAR(p_end);
      SET v_month_diff = MONTH(p_start) - MONTH(p_end);
 
      IF v_year_diff != 0 THEN
         set v_diff = v_year_diff * 12;
      END if;
 
      SET v_diff = v_diff + v_month_diff;
 
      RETURN v_diff;
END@


@@@ Oracle
 Decode기능
ex1)
SELECT  rownumber,CASE WHEN  zip_code BETWEEN '100091' AND '100091' THEN '91'
                WHEN  zip_code BETWEEN '100092' AND '100092' THEN '92'
                WHEN  zip_code BETWEEN '100093' AND '100093' THEN '93'
                WHEN  zip_code BETWEEN '100094' AND '100094' THEN '94'
                WHEN  zip_code BETWEEN '100095' AND '100095' THEN '95'
             ELSE   '99'
          END
  FROM ( 
        SELECT zip_code,ROWNUMBER() OVER (ORDER BY zip_code) AS rownumber
          FROM zipcode
       ) AS t 
 WHERE ROWNUMBER  BETWEEN 20 AND 30

 

ex2)
SELECT  ROWNUMBER,CASE zip_code 
                  WHEN  '100091' THEN '91'
                  WHEN  '100092' THEN '92'
                  WHEN  '100093' THEN '93'
                  WHEN  '100094' THEN '94'
                  WHEN  '100095' THEN '95'
                  ELSE   '99'
                  END  
  FROM (                       
        SELECT  zip_code,ROWNUMBER() OVER (ORDER BY zip_code) AS rownumber
          FROM zipcode
       ) AS t 
 WHERE ROWNUMBER  BETWEEN 20 AND 30

 

 

@@@ INTEGER형으로 변환

ex)
SELECT INTEGER(zip_code)
  FROM zipcode
 FETCH FIRST 5 ROWS ONLY

 

 

@@@ DOUBLE형으로 변환

ex)
SELECT DOUBLE(zip_code)
  FROM zipcode
 FETCH FIRST 5 ROWS ONLY

 

 

@@@ SUBSTR

ex)
SELECT SUBSTR(zip_code,1,3)
  FROM zipcode
 FETCH FIRST 5 ROWS ONLY

 

 

@@@ CHAR

ex)
SELECT CHAR(doseo)
  FROM zipcode
 FETCH FIRST 5 ROWS ONLY

 

 

@@@ COALESCE - Oracle Nvl()기능 
컬럼 타입에 따라 인수를 결정한다. COALESCE(자형,문자형표시)  COALESCE(숫자형,숫자형표시)

ex)
SELECT COALESCE(doseo,'1')
  FROM zipcode
 FETCH FIRST 5 ROWS ONLY

 

 

@@@ ||
문자연결기능
SELECT COALESCE(doseo,'1') || zip_code
  FROM zipcode
 FETCH FIRST 5 ROWS ONLY

 

 

@@@ page기능
SELECT t.zip_code,page
FROM (
       SELECT zip_code,((ROWNUMBER() OVER() -1)/ 10+1) AS page
         FROM zipcode
     ) AS t
 WHERE t.page = 3
 FETCH FIRST 100 ROWS ONLY
  WITH UR

 

 

@@@ year 구하기
ex1)
SELECT  YEAR(CURRENT TIMESTAMP)
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

ex2)
SELECT  YEAR('2004-05-16')
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

ex3)
SELECT  YEAR(CURRENT DATE)
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ month 구하기

ex1)
SELECT  MONTH(CURRENT TIMESTAMP)
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

ex2)
SELECT  MONTH('2004-08-16')
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ day 구하기

ex1)
SELECT  DAY(CURRENT TIMESTAMP)
  FROM SYSIBM.SYSDUMMY1
  WITH UR
EX2)
SELECT  DAY('2004-08-16')
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ week 구하기
ex)
SELECT  WEEK('2004-05-16')
  FROM SYSIBM.SYSDUMMY1
  WITH UR

@@@ time 구하기

ex)
SELECT  CURRENT TIME
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ dayofyear 구하기(오늘이 365일중 몇번째 날짜)
ex)
SELECT  DAYOFYEAR(CURRENT DATE)
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ dayname 구하기(요일 이름)

ex)
SELECT  DAYNAME(CURRENT DATE)
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ CONCAT 문자연결함수

ex)
SELECT  CONCAT('111','22222 ')
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ MOD 나머지 함수

ex)
SELECT  MOD(11111,100)
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ value 함수 - COALESCE와 동일한 기능

ex)
SELECT  VALUE(CURRENT DATE,'2004-08-16')
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ abs 함수 절대값 함수

ex)
SELECT  ABS(-51234)
  FROM SYSIBM.SYSDUMMY1
  WITH UR

 

 

@@@ lcas 함수 대문자를 소문자로

ex)
SELECT  LCASE('ABCD')
  FROM SYSIBM.SYSDUMMY1
  WITH UR;

 

 

@@@ ucase 함수 소문자를 대문자로
ex)
SELECT  LCASE('abcd')
  FROM SYSIBM.SYSDUMMY1
  WITH UR;

 

 

@@@ multiply_alt 두 수를 곱한다.
ex)
SELECT MULTIPLY_ALT(3,20)
  FROM SYSIBM.SYSDUMMY1
  WITH UR;

 

 

@@@ round
ex)
SELECT  ROUND(873.726, 2), ROUND(873.726, 1), ROUND(873.726, 0), ROUND(873.726,-1),

        ROUND(873.726,-2), ROUND(873.726,-3), ROUND(873.726,-4)
  FROM SYSIBM.SYSDUMMY1
  WITH UR;

 

 

@@@ week_iso 함수
ex)
SELECT  WEEK_ISO(CURRENT DATE)     SELECT  WEEK_ISO('1997-12-28')
  FROM SYSIBM.SYSDUMMY1              FROM SYSIBM.SYSDUMMY1         
  WITH UR;                           WITH UR;                     

 

 

@@@ dayofweek_iso 해당주에서 몇일에 해당하는지
ex)
SELECT   DAYOFWEEK_ISO(CURRENT DATE)    SELECT   DAYOFWEEK_ISO('2004-08-16')
  FROM SYSIBM.SYSDUMMY1                   FROM SYSIBM.SYSDUMMY1               
  WITH UR;                                WITH UR;                           

 

SELECT  callback_dt,                                           
        callback_tm,                                          
        COUNT(seqno),                                         
        COUNT(custname),                                      
        telno_1||'-'|| telno_2||'-'|| telno_3  AS tel_number  
  FROM callback
 GROUP BY  callback_dt,callback_tm,telno_1||'-'|| telno_2||'-'|| telno_3
FETCH FIRST 5 ROWS ONLY;


SELECT  *  FROM 
(  SELECT  ROWNUMBER() OVER() AS rownum,statement_text
   FROM  explain_statement
) AS t
WHERE t.rownum = 2
FETCH  FIRST 100  ROWS  ONLY

 

 

@@@ outer join
SELECT CASE  WHEN a.relation = '1' THEN '본인'
             WHEN a.relation = '2' THEN '
배우자'  
             WHEN a.relation = '3' THEN '
자녀'   
             WHEN a.relation = '4' THEN '
부모'  
             WHEN a.relation = '5' THEN '
형제자매'  
             WHEN a.relation = '6' THEN '
기타'  
             ELSE '
기타
        END AS kwan,a.name,a.fsocial_no  AS  fsocial_no,  
 CASE SUBSTR(a.fsocial_no,7,1)  
      WHEN '1' THEN YEAR(CURRENT DATE - DATE('19'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '2' THEN YEAR(CURRENT DATE - DATE('19'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '3' THEN YEAR(CURRENT DATE - DATE('20'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '4' THEN YEAR(CURRENT DATE - DATE('20'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '5' THEN YEAR(CURRENT DATE - DATE('19'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '6' THEN YEAR(CURRENT DATE - DATE('19'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '7' THEN YEAR(CURRENT DATE - DATE('20'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '8' THEN YEAR(CURRENT DATE - DATE('20'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
      WHEN '9' THEN YEAR(CURRENT DATE - DATE('18'||SUBSTR(A.fsocial_no,1,2)||'-'||SUBSTR(A.fsocial_no,3,2)||'-'||'01'))  
  ELSE YEAR(CURRENT DATE - DATE('18'||SUBSTR(a.fsocial_no,1,2)||'-'||SUBSTR(a.fsocial_no,3,2)||'-'||'01'))
         END  AS  YEARS,
  VALUE(b.company_nm,'') AS COMPANY_NM,
  VALUE(b.dept,'') AS DEPT,
  VALUE(b.duty,'') AS DUTY,  
  VALUE(b.offi_tel_1,'') || VALUE(b.offi_tel_2,'') || VALUE(b.offi_tel_3,'') AS offi_tel,  
  CASE WHEN a.live_yn = '1' THEN '
동거
       ELSE '' 
  END AS home  
 FROM cust.family_info A LEFT OUTER JOIN euc20.customer b ON ( a.fsocial_no =  b.social_no )  
WHERE a.social_no = '6611211010815' 
ORDER BY  fsocial_no

Posted by 사라링

ORDERY BY 절 사용

2012. 8. 29. 11:27

1. 사용방법

 

ORDER BY [ASC|DESC]

--QUERY문의 맨뒤에 옵니다.

EX)

SELECT * FROM EMP ORDER BY JOB

-- JOB를 오름차순(어샌딩)으로 정렬하여 보여준다.

SELECT * FROM EMP ORDER BY JOB ASC

-- JOB를 오름차순(어샌딩)으로 정렬하여 보여준다.

SELECT * FROM EMP ORDER BY JOB DESC

-- JOB를 내림차순(디샌딩)으로 정렬하여 보여준다.

select empno,ename from emp order by empno,ename;

-- sal컬럼을 기준으로 오름차순으로 정렬하고 sal컬럼의 값이 같은 레코드는 다시

-- ename컬럼을 기준으로 오름차순으로 정렬하여 출력합니다.

 

※ 디폴트는 ASC 입니다.

 

※ 참고사항

오름차순:정순정렬:ASC

내림차순:역순정렬:DESC

 

2. 데이타형에 따른 정렬

 

문자열은 ASC면 A,B,C순으로 ASC코드값이 작은것부터이며

DESC면 C,B,A순으로 ASC코드값이 큰것부터나옵니다.

 

정수나 실수는 ASC면 전체수가 작은것부터이며

DESC면 전체수가 큰것부터나옵니다.

 

날짜는 ASC면 오래된 날짜부터 정렬되며

DESC면 최근의 날짜부터 정렬됩니다.

 

한글은 ASC면 가,나,다.... 순으로 정렬되며

DESC면 ....다,나,가 순으로 정렬된다.

 

NULL값은 연산이나 비교도 안됩니다. 하지만 정렬시에는 NULL값은 ASC면

무조건 맨뒤에 나오며 DESC면 무조건 앞에 나옵니다.

 

※ 무조건 맨뒤나 앞에 나올때의 널값은 순서가 입력순서는 순서대로입니다.

 

※ ASC일때 NULL 값을 맨앞에 하는 방법이 있습니다.

ex : order by name nulls first

ex : order by nvl(name,' ')

 

※ DESC일때 NULL 값을 맨뒤에 하는 방법이 있습니다.

ex : order by name nulls last

 

3. 특별한 사용법

 

※ ORDER BY는 ASC, DESC 키워드를 입력하지 않으면 자동으로 오름차순 정렬됩니다.

※ ORDER BY 뒤에 컬럼명을 , 간격으로 2개이상을 사용가능합니다.

 

ex : select * from table_name order by a,b;

* a를 오름차순으로 정렬한상태에서 a의 값이 중복인 레코드는 다시 b를 오름차순으로 정렬한다.

* a의 값이 중복값이 없을때는 b는 오름차순하지 않는다.

 

ORDER BY 뒤에 숫자가 나오면 현재 TABLE의 컬럼위치를 말합니다.

select * from emp order by 1 DESC;면 TABLE의 첫번째 컬럼으로 내림차순으로 정렬한다는 뜻입니다.

 

※ 0은 사용할수 없다.

 

ORDER BY 뒤에 앨리어스(별명)을 두어 정렬이 됩니다.

SELECT A AA,B FROM ORDER BY AA;

 

select name from goods order by 1;
-- 제대로된 query
-- 첫번째 출력컬럼으로 오름차순 정렬
select name from goods order by 0;
-- 잘못된 query
-- 0 이란 숫자는 order by사용할수 없습니다.

 

IN 연산자에 사용한 문자열 값들을 기준으로 원하는 순서로 출력하는 방법

 

SELECT * FROM TABLE_NAME WHERE ID IN('084', '081', '079', '077', '127')

ORDER BY DECODE(ID, '084', 1, '081', 2, '079', 3, '077', 4, '127', 5);

 

※ DECODE 함수로 원하는 값에 우선순위를 줄수 있습니다.

 

조회조건없는 쿼리 실행시 출력 정렬상태

 

SELECT IDX, NAME, AGE FROM TABLE_NAME; 이라고 할때 입력순서대로 출력되며

IDX가 PK라면 IDX를 기준으로 오름차순으로 정렬됩니다.

100% 입력된 자료 순서라고 장담할수 없습니다. 
별다른 실행계획이 없이 풀스켄 했다면 
rowid 순서로 조회가 됩니다. 
보통은 입력 순서대로 되지만 삭제작업이 빈번하게 일어나는 경우 나중에 입력된 자료가 먼저 나오기도 하는 것으로 알고 있습니다.. 

'오라클' 카테고리의 다른 글

오라클 FUNCTION() 생성 예제  (0) 2012.08.30
DB2 함수 정리.  (0) 2012.08.29
최상위 코드와 그 최상위 코드를 대상으로 그룹 .  (0) 2012.08.24
오라클 백업 및 복구(Export, Import)  (0) 2012.08.10
OUT Join  (0) 2012.08.08
Posted by 사라링

[감리 산출물 작업]


select A.COMM_CD,A.COMM_NM,A.UP_COMM_CD, B.COMM_NM,A.USE_YN

from COM_STD_MGT A INNER JOIN 

(

     SELECT COMM_CD,COMM_NM,UP_COMM_CD FROM COM_STD_MGT WHERE UP_COMM_CD='300'

) B ON (A.UP_COMM_CD = B.COMM_CD)

WHERE A.USE_YN ='Y'

ORDER BY UP_COMM_CD,COMM_CD;


                                                                  ▽



select   A.UP_COMM_CD AS 최상위코드,  B.COMM_NM AS 최상위코드네임 ,A.COMM_CD AS 하위코드,A.COMM_NM AS 하위코드네임,A.USE_YN AS 사용유무
from COM_STD_MGT A INNER JOIN 
(
     SELECT COMM_CD,COMM_NM,UP_COMM_CD FROM COM_STD_MGT WHERE UP_COMM_CD='200'   -- UP_COMM_CD 의 값에 최상위 코드를 입력 할것 
) B ON (A.UP_COMM_CD = B.COMM_CD)
WHERE A.USE_YN ='Y'
ORDER BY A.UP_COMM_CD,A.COMM_CD ;
  -- 검색후 엑셀로 추출 하여 필터 처리 하여 감리 산출물에 반영 할것 BY 김훈 

'오라클' 카테고리의 다른 글

DB2 함수 정리.  (0) 2012.08.29
ORDERY BY 절 사용  (0) 2012.08.29
오라클 백업 및 복구(Export, Import)  (0) 2012.08.10
OUT Join  (0) 2012.08.08
SYS_CONNECT_BY_PATH  (0) 2012.07.26
Posted by 사라링

1. export / import
가. 여러개의 테이블 중에서 특정 table만 백업/복구 하고자 할 때
나. 오라클의 버전, 플랫폼이 서로 다른 상황에서의 서버간 데이터 이동 시(migration)

2. export 방식
가. Conventional Path export : Evaluation Buffer를 사용하는 방식, DB Buffer cache에서 필요데이터를 Evaluation Buffer로 복사 후 데이터를 가공(text -> binary)하여 디스크에 파일로 저장함. export 작업 중에 발생하는 DDL, DML 등의 명령들은 백업파일에 반영되지 않는다.(백업 파일은 Evaluation Buffer을 이용하여 작업하기 때문)

나. Dircet Path export : DB Buffer Cache에서 데이터를 가공(text -> Binary)하여 디스크에 파일로 저장함, export 명령 이후에 백업대상이 되는 테이블스페이스나 테이블에 Lock이 발생하기 때문에 DDL, DML 작업은 실패 또는 보류 된다.

사용자 삽입 이미지사용자 삽입 이미지



3. export 옵션 및 사용예제
가. 옵션
- userid/passwd : export를 수행하는 계정/패스워드
- buffer : Evaluation Buffer크기 지정(용량이 클 수록 export 작업이 빨라진다)
- file : export 결과를 저장할 파일명
- full : 전체 DB를 export 할 것인가 지정
- owner : export 받을 사용자 이름지정
- tables : export 받을 테이블 이름 지정
- tablespaces : exprot 받을 테이블스페이스 이름지정
- parfile : export 옵션을 미리 지정한 파라미터 파일지정

나. 사용예제
exp system/oracle full=y file=/backup/export/test01.dmp

exp system/oracle full=y file=/backup/export/test02.dmp direct=y

exp system/oracle tables=emp \
file=('/backup/export/test03_1.dmp', '/backup/export/test03_2.dmp') filesize=10M

exp system/oracle tablespaces=(example, undotbs1) file=/backup/export/test04.dmp

exp system/oracle file=/backup/export/test05.dmp owner=(scott, hr)

exp system/oracle file=/backup/export/test06.dmp full=y buffer=1024000

vi par_full.dat
file=/backup/export/test07.dmp
full=y
dircet=y

exp system/oracle parfile=par_full.dat

exp scott/tiger query=\"where ename like \'F%\'\" tables=emp \
file=/backup/export/test07.dmp


4. import 옵션 및 사용예제
가. 옵션(export의 옵션과 유사하다)
- userid/passwd : import를 수행하는 계정/패스워드
- buffer : Evaluation Buffer크기 지정(용량이 클 수록 import 작업이 빨라진다)
- file : import 할 export 파일명 지정
- show : 데이터를 import 하지 않고 내용만 확인함
- ignore : import 작업 중 발생할 수 있는 에러를 무시하고 다음단계의 작업을 진행함
- fromuser : export 할 당시의 object의 소유자 지정
- touser : import 할 object의 새 소유자 지정
- tables : import 할 테이블 이름 지정
- parfile : import 옵션을 미리 지정한 파라미터 파일지정

나. 사용예정

imp system/oracle file=/backup/export/test01.dmp ignore=y full=y

imp system/oracle file=/backup/export/test02.dmp \
fromuser=scott touser=hr ignore=y

imp system/oracle file=/backup/export/test03.dmp full=y show=y log=test03.log


참고 : export/import 계정
import 할 때 사용하는 계정은 export 할 때 사용한 계정이어야 한다. 이 계정이 같지 않으면 import 수행 시 오류가 발생한다.만일 export 계정을 잊었다면 덤프파일을 vi 편집기로 열어 확인할 수 있다.(2번째 줄)
참고 : import 작업 중 에러발생 시
import 작업을 진행하던 도중 에러가 발생해 같은 작업을 반복하게 되면, import 대상이 되는 테이블(제약조건이 없는)에 데이터가 중복 저장될 수 있다. 그러므로 같은 작업을 반복시에는 import 대상이 되는 테이블의 내용을 지우고(drop 또는 truncate) 진행해야 한다.
참고 : SYS 계정으로 생성된 Object export
일반적으로 SYS계정에서 생성된 객체는 export 명령어로 백업할 수 없으므로 주의해야 한다.
(단, 경우에 따라서 system 계정으로 백업이 가능하기도 하다)

4. Import 대상 서버에서 필요한 사전 작업
가. Export 한 서버와 동일한 Tablespace 생성
나. 충분한 크기의 Temporary Tablespace 확보
다. Export 한 서버와 동일한 사용자 생성

'오라클' 카테고리의 다른 글

ORDERY BY 절 사용  (0) 2012.08.29
최상위 코드와 그 최상위 코드를 대상으로 그룹 .  (0) 2012.08.24
OUT Join  (0) 2012.08.08
SYS_CONNECT_BY_PATH  (0) 2012.07.26
오라클 구조 보기 sql 문 (desc)  (0) 2012.06.07
Posted by 사라링

OUT Join

2012. 8. 8. 19:50

◈ Out(외부) Join 

 - equijoin 문장들의 한가지 제약점은 그것들이 조인을 생성하려 하는 두 개의 테이블의 두 개 
    컬럼에서 공통된 값이 없다면 테이블로부터 테이터를 Return하지 않는 다는 것입니다. 

 - 정상적으로 조인 조건을 만족하지 못하는 행들을 보기위해 outer join을 사용합니다. 
    Outer join 연산자 "( + )"입니다. 

 - 조인시킬 값이 없는 조인측에 "( + )"를 위치 시킵니다

 - Outer join 연산자는 표현식의 한 편에만 올 수 있습니다. 


예제1) 일반 조인의 경우 

SQL> SELECT DISTINCT(a.deptno), b.deptno
         FROM emp a, dept b
         WHERE  a.deptno = b.deptno

DEPTNO     DEPTNO
---------- ----------
        10         10
        20         20
        30         30


예제2)out join을 했을 경우

SQL>  SELECT DISTINCT(a.deptno), b.deptno
          FROM emp a, dept b
          WHERE  a.deptno(+) = b.deptno

 DEPTNO     DEPTNO
 -------     ----------
     10         10
     20         20
     30         30
                 40

※ 다음의 쿼리를 한번 잘 보시기 바랍니다. 

SQL>  SELECT DISTINCT(a.deptno), b.deptno
          FROM emp a, dept b
          WHERE  a.deptno(+) = b.deptno
               AND a.ename LIKE '%';

    DEPTNO     DEPTNO
---------- ----------
        10         10
        20         20
        30         30

쿼리 결과를 잘 보면 out조인이 되지 않은 것을 알 수 있습니다.
위 쿼리를 out조인이 되기 위해서는 아래와 같이 고쳐야 합니다


SQL> SELECT DISTINCT(a.deptno), b.deptno
         FROM emp a, dept b
         WHERE  a.deptno(+) = b.deptno
              AND a.ename(+) LIKE '%'

    DEPTNO     DEPTNO
---------- ----------
        10         10
        20         20
        30         30
                    40

OUT조인 조건이 걸려있는 테이블에는 다른 조건절이 들어와도 
똑같이 OUT조인 연산자인 (+)를 해주어야 합니다.  



Oracle9i 부터는 ANSI/ISO SQL표준인 LEFT OUTER JOIN , RIGHT OUTER JOINFULL OUTER JOIN를 지원 합니다.


☞ LEFT OUTER JOIN 
 왼쪽 테이블에 조인시킬 컬럽의 값이 없는 경우 사용합니다. 
  
SQL>SELECT DISTINCT(e.deptno), d.deptno 
    FROM dept d LEFT OUTER JOIN emp e 
    ON d.deptno = e.deptno; 
  
  
☞ RIGHT OUTER JOIN 
 - 오른쪽에 테이블에 조인시킬 컬럽의 값이 없는 경우 사용합니다. 
  
SQL>SELECT DISTINCT(a.deptno), b.deptno 
    FROM emp a RIGHT OUTER JOIN dept b 
    ON a.deptno = b.deptno; 
  
  
☞ FULL OUTER JOIN 
양쪽 테이블에 다 outer join을 거는것을 TWO-WAY OUTER JOIN 또는 FULL OUTER JOIN이라 합니다. 
  
SQL>SELECT DISTINCT(a.deptno), b.deptno 
    FROM emp a FULL OUTER JOIN dept b 
    ON a.deptno = b.deptno; 
  
-- 위 세 문장의 결과는 아래와 같습니다. 
    DEPTNO     DEPTNO 
---------- ---------- 
        10         10 
        20         20 
        30         30 
                   40 
  
LEFT OUTER JOIN과 RIGHT OUTER JOIN의 테이블 순서를 바꾸어 가면서 테스트를 하시면 쉽게 이해를 하실 수 있습니다. 



지금까지 SQL의 조인을 어설프게 이해하고 사용하고 있었다 덕분에 오늘 삽질좀 했다. 그래서 관련 내용을 정리해본다. 


1. INNER JOIN
  - 두 테이블간의 조인 조건을 만족하는 ROW만 리턴함... (교집합 이라고 하기엔 좀 애매하지만 일단 그렇게 이해하는게 쉽다.)

 

2. OUTER JOIN
  - LEFT/RIGHT/FULL 형태의 OUTER JOIN 이 있음
  - LEFT OUTER JOIN의 경우 조인문 왼쪽에 있는 테이블의 모든 결과를 가져온 후 오른쪽 테이블의 데이터를 매칭하며, 매칭되는 데이터가 없는 경우 NULL 매칭
  - RIGHT OUTER JOIN은 LEFT 조인의 반대  - FULL OUTER JOIN은 일반적으로 사용할 일이 없으며, DB에 따라 지원하지 않음??? 간단히 설명하자면 두 테이블의 합집합이라고 이해하면 될 듯...


3. 주의 사항
  - 일반적으로 조인은 1:1 혹은 N:1 의 관계를 갖는 경우 유용한 것 같음... 1:N 관계에서 조인문을 사용하는 경우 기준이 되는 테이블의 데이터가 중복되는 결과를 리턴함. 따라서 1:N 관계에서 조인문을 통해 N에 해당하는 테이블의 컬럼을 이용해 제한조건을 사용하는 경우 distinct 혹은 group by 를 사용하여 1에 해당 하는 테이블의 데이터가 중복되지 않도록 해야 한다.  (에궁... 먼가 명확하지 않은 설명 ㅠ.ㅠ)
 

4. 예제 

CREATE TABLE tbl1 (id INT, name VARCHAR(8));
INSERT INTO tbl1 (id,name) VALUES (1,'aaa') ;
INSERT INTO tbl1 (id,name) VALUES (2,'bbb') ;
INSERT INTO tbl1 (id,name) VALUES (3,'ccc') ;
INSERT INTO tbl1 (id,name) VALUES (4,'ddd') ;
INSERT INTO tbl1 (id,name) VALUES (5,'eee') ;

CREATE TABLE tbl2 (id INT, car VARCHAR(8)) ;
INSERT INTO tbl2 (id,car) VALUES (2,'AVANTE') ;
INSERT INTO tbl2 (id,car) VALUES (3,'SONATA') ;
INSERT INTO tbl2 (id,car) VALUES (2, 'MINI');

-- Inner Join1
select a.id, a.name, b.car from tbl1 a inner join tbl2 b on a.id = b.id
-- Inner Join2 (위와 동일)
select a.id, a.name, b.car from tbl1 a, tbl2 b where a.id = b.id

<result>
2 bbb   AVANTE
3 ccc   SONATA

-- left outer join
select a.id, a.name, b.car from tbl1 a left outer join tbl2 b on a.id = b.id

<result>
1 aaa null
2 bbb AVANTE
3 ccc SONATA
4 ddd null
5 eee null

-- right outer join
select a.id, a.name, b.car from tbl1 a right outer join tbl2 b on a.id = b.id

<result>
2 bbb AVANTE
3 ccc SONATA

-- left outer join 을 이용해서 inner join과 동일한 결과 얻기
select a.id, a.name, b.car from tbl1 a left outer join tbl2 b on a.id = b.id where b.id is not null

<result>
2 bbb AVANTE
3 ccc SONATA


-- N:1 관계에서의 조인 예제 (Outer Join 의 경우도 비슷함)

INSERT INTO tbl2 (id,car) values (2, 'MINI');

select a.id, a.name, b.car from tbl1 a, tbl2 b where a.id = b.id

<result>
2 bbb   AVANTE
2 bbb   MINI
3 ccc   SONATA

select distinct a.id, a.name, b.car from tbl1 a, tbl2 b where a.id = b.id group by a.id

<result>
2 bbb AVANTE
3 ccc SONATA



'오라클' 카테고리의 다른 글

최상위 코드와 그 최상위 코드를 대상으로 그룹 .  (0) 2012.08.24
오라클 백업 및 복구(Export, Import)  (0) 2012.08.10
SYS_CONNECT_BY_PATH  (0) 2012.07.26
오라클 구조 보기 sql 문 (desc)  (0) 2012.06.07
오라클연습  (0) 2012.05.08
Posted by 사라링

SYS_CONNECT_BY_PATH

2012. 7. 26. 15:34

SYS_CONNECT_BY_PATH

문법

sys_connect_by_path::=
Description of sys_connect_by_path.gif follows

그림 설명

목적

SYS_CONNECT_BY_PATH함수는 계층적 쿼리에서 유의하다. 이 함수는 루트로 부터 node로 열의 값 Path를 반환환다. column 값은 CONNECT BY 조건에 의해 반환되는 각행을 char에 의해 분리된다.

column과 char의 데이터형은 CHAR,VARCHAR2,NCHAR,NVARCHAR2이다. 반환되는 문자열은 VARCHAR2형이고, column과 같은 문자 집합이다.

SYS_CONNECT_BY_PATH(column, char) 함수는 계층적 쿼리(계층구조)에서만 유효하며, column의 절대 경로를 char로 지정한 문자로 분리하여 반환한다.

예제

다음 예제는 Kochhar이름의 종업원으로 부터 Kochhar 모든 종업원에게 종업원 이름의 Path를 반환한다.

SELECT LPAD(' ', 2*level-1)||SYS_CONNECT_BY_PATH(last_name, '/') "Path"
FROM employees
START WITH last_name = 'Kochhar'
CONNECT BY PRIOR employee_id = manager_id;

Path
---------------------------------------------------------------
 /Kochhar
   /Kochhar/Greenberg
     /Kochhar/Greenberg/Faviet
     /Kochhar/Greenberg/Chen
     /Kochhar/Greenberg/Sciarra
     /Kochhar/Greenberg/Urman
     /Kochhar/Greenberg/Popp
   /Kochhar/Whalen
   /Kochhar/Mavris
   /Kochhar/Baer
   /Kochhar/Higgins
     /Kochhar/Higgins/Gietz
테이블 전치 : http://blogbbs1.media.daum.net/griffin/do/blognews/cafe/read?bbsId=CF01&articleId=13122&pageIndex=17&searchKey=&searchValue=
select * from hrm_bas_mgt;
select * from hrm_dept;
--1번
select * from hrm_bas_mgt where main_thsis is not null;
--2번
select emp_nm from hrm_bas_mgt where emp_nm like '%김%' union
select emp_nm from hrm_bas_mgt where emp_nm like '%주%';
--3번
select emp_nm as 성명, fn_get_crypt('D',RES_NO)as 주민번호,substr(fn_get_crypt('D',RES_NO),3,2),
case when to_number(substr(fn_get_crypt('D',RES_NO),3,2)) between 01 and 03 then '1분기'
        when to_number(substr(fn_get_crypt('D',RES_NO),3,2)) between 04 and 06 then '2분기'
        when to_number(substr(fn_get_crypt('D',RES_NO),3,2)) between 07 and 09 then '3분기'
        when to_number(substr(fn_get_crypt('D',RES_NO),3,2)) between 10 and 12 then '4분기'
else '알수 없음'
end  분기 from hrm_bas_mgt order by 3;
--4번
select emp_nm as 성명,  fn_get_crypt('D',RES_NO) as 주민등록번호 from hrm_bas_mgt where  to_number(substr(fn_get_crypt('D',RES_NO),3,2)) between 01 and 04;

-- 5번
select * from (select emp_nm as 성명,  fn_get_crypt('D',RES_NO) as 주민등록번호 ,
dense_rank() over (order by  (to_number(substr(fn_get_crypt('D',RES_NO),3,4))))as rownums
 from hrm_bas_mgt  ) where rownums between 20 and 40;
--6번
select B.dept_nm,count(A.dept_cd) from hrm_bas_mgt A 
                       LEFT OUTER JOIN hrm_dept B
                       ON A.DEPT_CD = B.DEPT_CD(+)
                       group by B.DEPT_nm
                       order by 2 desc;
                      
--7번

select A.emp_nm,
        A.emp_no,
        B.fmly_nm,
      row_number() OVER (PARTITION BY A.EMP_NO order by B.fmly_nm) RNUM
      from HRM_BAS_MGT A,HRM_FMLY B
     
      where A.EMP_NO = B.EMP_NO;
                   
         
          select emp_nm as 성명,
          substr(max(sys_connect_by_path(fmly_nm,',')),2)  as 가족성명
         from  (select A.emp_nm,
            A.emp_no,
            B.fmly_nm,
          row_number() OVER (PARTITION BY A.EMP_NO order by B.fmly_nm) RNUM
          from HRM_BAS_MGT A,HRM_FMLY B
          where A.EMP_NO = B.EMP_NO
          ) where emp_nm is not null
    start with RNUM =1
    connect by prior RNUM = RNUM -1
        and prior emp_no =emp_no
        group by emp_nm;
       
    select * from hrm_dept;
   
   
    select dept_nm as 부서명,
    substr(max(sys_connect_by_path(dept_cd,'.')),2  )as 모음 from
   (     
    select dept_nm,
       dept_cd,
      row_number() OVER (PARTITION BY dept_nm order by dept_cd ) RNUM
      from HRM_DEPT)
start with RNUM =1
connect by prior RNUM = RNUM -1
    and prior dept_nm =dept_nm
 group by dept_nm ;
     

1SQL능력평가

제한시간 30.

동점시 먼저 제출한 사람이 WINNER.

따로 표시가 없는 문제에 대한 정렬은 무조건 성명(EMP_NM) 오름차순 ASC.

문제를 풀고 SQL문을 확장자(.SQL) 파일로 저장 후 제출.

채점은 SQL문 실행 후 결과 확인.

 

<참조 테이블>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1. HRM_BAS_MGT 테이블에 주요논문(MAIN_THSIS) 컬럼을 이용하여 주요논문이 등록되어 있는(NULL이 아닌) 사원을

조회하는 SQL문을 작성 하시오.

<성명, 주요논문>

 

(실행화면)

 

SELECT *

FROM HRM_BAS_MGT

WHERE MAIN_THSIS IS NOT NULL;

 

 

2. HRM_BAS_MGT 테이블에 성명(EMP_NM) 컬럼을 이용하여 성명에 '' 또는 ''가 들어가는 사원을 같은 건이

중복되지 않게 조회하는 SQL문을 작성 하시오.

(, UNION 또는 UNION ALL을 이용하여 작성한다.) <성명>

 

(실행화면)

 

SELECT DISTINCT (EMP_NM)

FROM (SELECT EMP_NM

FROM HRM_BAS_MGT

WHERE EMP_NM LIKE '%%'

UNION ALL

SELECT EMP_NM

FROM HRM_BAS_MGT

WHERE EMP_NM LIKE '%%')

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. HRM_BAS_MGT 테이블에 암호화 된 주민번호(RES_NO) 컬럼을 이용하여 생일을 분기별로 구분하여 조회하는

SQL문을 작성하시오.

(1~31분기,4~62분기, 7~93분기, 10~124분기)

* 다음 함수를 이용하여 FN_GET_CRYPT('D',RES_NO) 복호화 한다.

<성명, 주민번호, 분기>

 

(실행화면)

SELECT EMP_NM AS 성 명

,FN_GET_CRYPT ('D', RES_NO) AS 주 민 번 호

,SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 2)

,CASE

WHEN SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 2) BETWEEN '01' AND '03' THEN '1분 기 '

WHEN SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 2) BETWEEN '04' AND '06' THEN '2분 기 '

WHEN SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 2) BETWEEN '07' AND '09' THEN '3분 기 '

WHEN SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 2) BETWEEN '10' AND '12' THEN '2분 기 '

END AS 분 기

FROM HRM_BAS_MGT

ORDER BY SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 2);

 

4. HRM_BAS_MGT 테이블에 암호화 된 주민번호(RES_NO) 컬럼을 이용하여 생일이 1,2,3,4월인 사원을

조회하는 SQL문을 작성 하시오.

* 다음 함수를 이용하여 FN_GET_CRYPT('D',RES_NO) 복호화 한다.

<성명, 주민번호>

(실행화면)

SELECT EMP_NM AS 성 명

,FN_GET_CRYPT ('D', RES_NO) AS 주 민 번 호

, (RANK () OVER (ORDER BY SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 4))) ROWNUMS

FROM HRM_BAS_MGT

WHERE SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 1

OR SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 2

OR SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 3

OR SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 4

 

 

 

5. 4번에서 조회한 사원들 중에서 생년월일이 빠른 직원 20번째부터 40번째 까지 조회하는 SQL문을 작성 하시오.

(나이가 많은 순으로 정렬)

<성명, 주민번호, 순번>

 

(실행화면)

SELECT *

FROM (SELECT EMP_NM AS 성 명

,FN_GET_CRYPT ('D', RES_NO) AS 주 민 번 호

, (RANK () OVER (ORDER BY SUBSTR (FN_GET_CRYPT ('D', RES_NO), 3, 4))) ROWNUMS

FROM HRM_BAS_MGT

WHERE SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 1

OR SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 2

OR SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 3

OR SUBSTR (FN_GET_CRYPT ('D', RES_NO), 4, 1) = 4)

WHERE ROWNUMS BETWEEN 20 AND 40

ORDER BY ROWNUMS

,주 민 번 호

 

6. HRM_BAS_MGT 테이블과 HRM_DEPT 테이블을 이용하여 부서(DEPT_NM)별로 그룹하여 부서별 인원수가 8명 이상인

부서만 조회하는 SQL문을 작성 하시오. (인원수가 많은 부서순으로 정렬)

<부서명, 인원수>

 

(실행화면)

 

SELECT *

FROM (SELECT B.DEPT_NM

,COUNT (A.DEPT_CD) AS CNT

FROM HRM_BAS_MGT A

,HRM_DEPT B

WHERE A.DEPT_CD = B.DEPT_CD(+)

GROUP BY B.DEPT_NM)

WHERE CNT >= 8

ORDER BY CNT DESC;

 

 

 

 

 

 

 

7. HRM_BAS_MGT 테이블과 HRM_FMLY 테이블을 이용하여 사원별로 가족들을 이름순으로 가로로 나열 하는 SQL문을

작성 하시오.

(, 가족이 없는 사원들은 '가족없음'으로 표시되게 하시오.)

<성명, 가족성명>

 

(실행화면)

SELECT EMP_NM AS 성 명

,SUBSTR (MAX (SYS_CONNECT_BY_PATH (FMLY_NM, ',')), 2) 가 족 성 명

FROM (SELECT A.EMP_NM

,A.EMP_NO

,B.FMLY_NM

,ROW_NUMBER () OVER (PARTITION BY A.EMP_NO ORDER BY B.FMLY_NM) RNUM

FROM HRM_BAS_MGT A

,HRM_FMLY B

WHERE A.EMP_NO = B.EMP_NO)

WHERE EMP_NM IS NOT NULL

START WITH RNUM = 1

CONNECT BY PRIOR RNUM = RNUM - 1

AND PRIOR EMP_NO = EMP_NO

GROUP BY EMP_NM

 

8. 7번에 작성된 결과를 VIEW로 생성하시오.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

9. <추가문제> 다음은 부서별(DEPT_NM) 사원(EMP_NM)들의 급여(PAY_AMT)를 조회하는 SQL문이다. 아래

SELECT문을 수정하여 부서별 급여의 합계를 구하는 SQL문을 작성하시오.

(정렬은 상관없음.)

 

WITH TEMP AS(

SELECT '기획조정실' DEPT_NM ,'이주임1' EMP_NM ,20000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '기획조정실' DEPT_NM ,'이주임2' EMP_NM ,30000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '기획조정실' DEPT_NM ,'이주임3' EMP_NM ,20000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '기획조정실' DEPT_NM ,'이주임4' EMP_NM ,15000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '공공사업부' DEPT_NM ,'황주임1' EMP_NM ,15000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '공공사업부' DEPT_NM ,'황주임2' EMP_NM ,26000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '공공사업부' DEPT_NM ,'황주임3' EMP_NM ,38000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '공공사업부' DEPT_NM ,'황주임4' EMP_NM ,40000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실' DEPT_NM ,'김주임1' EMP_NM ,56000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실' DEPT_NM ,'김주임2' EMP_NM ,46000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실' DEPT_NM ,'김주임3' EMP_NM ,38000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실' DEPT_NM ,'김주임4' EMP_NM ,60000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실2' DEPT_NM ,'우주임1' EMP_NM ,56000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실2' DEPT_NM ,'우주임2' EMP_NM ,46000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실2' DEPT_NM ,'우주임3' EMP_NM ,38000 PAY_AMT

FROM DUAL

UNION ALL

SELECT '인사총무실2' DEPT_NM ,'우주임4' EMP_NM ,60000 PAY_AMT

FROM DUAL

)

SELECT DEPT_NM

,EMP_NM

,PAY_AMT

FROM TEMP

 

 

(실행화면)

 

 

 

 

10. <추가문제> 9번 문제를 부서별 합계 금액이 큰 순서로 정렬하는 SQL문을 작성하시오.

 

 

(실행화면)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

수고하셨습니다.*^^*


'오라클' 카테고리의 다른 글

오라클 백업 및 복구(Export, Import)  (0) 2012.08.10
OUT Join  (0) 2012.08.08
오라클 구조 보기 sql 문 (desc)  (0) 2012.06.07
오라클연습  (0) 2012.05.08
sqlplus에서 셀렉트 update문 가져 오기.  (0) 2012.05.08
Posted by 사라링

BLOG main image
.. by 사라링

카테고리

사라링님의 노트 (301)
JSP (31)
J-Query (41)
JAVA (24)
VM-WARE (0)
디자인패턴 (1)
스크랩 (0)
스트러츠 (3)
안드로이드 (11)
오라클 (45)
우분투-오라클 (1)
이클립스메뉴얼 (6)
스프링3.0 (23)
자바스크립트 (10)
HTML5.0 (17)
정보처리기사 (1)
기타(컴퓨터 관련) (1)
문제점 해결 (3)
프로젝트 (2)
AJAX (4)
하이버네이트 (3)
트러스트폼 (11)
Jeus (2)
재무관리(회계) (5)
정규식 (5)
아이바티스 (8)
취미 (2)
소프트웨어 보안 관련모음 (0)
정보보안기사 (6)
C언어 베이직 및 프로그램 (3)
보안 관련 용어 정리 (2)
넥사크로 (6)
Total :
Today : Yesterday :