본문 바로가기
DATABASE/ORACLE

[ORACLE] 총정리 (총계/소계, RANK, GROUP BY (ROLLUP)-HAVING, PARTITION BY, UNION, CASE, NVL, JOIN, SUBSTR, FUNCTION)

by sjs_2215 2019. 11. 10.
SQL 출처
https://cafe.naver.com/an02
school201712.sql

챕터번호 key points
1 OR, IN, REPLACE, TRIM, INNER JOIN
2 DECODE, CASE, 다중 CASE문(바보짓), SUBSTR, OUTER JOIN, NULL 허용 컬럼, DUAL, UNION ALL, NVL, NVL2, STRING 형태 숫자들의 정렬 방법,
3 날짜 조건 주는 방법 3가지, JOIN과 UNION, 날짜 BETWEEN 대신 부등호, SELECT문의 특정 컬럼 안보이게 하는 법, SELECT절에서 서브쿼리 vs. FROM절에서 서브쿼리, UNION과 UNION ALL
4 최근 N건의 데이터 뽑는 방법 2가지, RANK
5 GROUP BY, GROUP BY 칼럼 피하는 법, CASE에 SUM
6 GROUP BY ROLLUP, 총계, 소계, 총계/소계용 테이블 공백처리, CASE 활용
7 연습문제 (pass)
8 function
9, 9-1 집계함수, EXIT-IN
11 부등호 조인
12 IN, GROUP BY-HAVING, PARTITION BY, 중복인 대상 찾는 2가지 방법
추가) PK(논리 PK, 물리 PK), INDEX, TRIGGER, SEQUENCE, DB 설계 시 HISORY 남기기, FUNCTION, PROCEDURE, PACKAGE

기본 규칙(권장)


WHERE 1 = 1

한 줄씩 주석처리해서 유지보수 작업할 때 쿼리 문법 에러 안나기 때문에.

1=1 해놓고 다음줄 AND 부터 조건들 쓰기


들여쓰는 방법

select (space bar 세 번) 조건


컴마의 위치

한 줄씩 주석처리해서 유지보수 작업할 때 쿼리 문법 에러 안나기 때문에.

컴마를 앞에 위치


테이블의 구조 검색

DESC 테이블명;

현재 스키마의 모든 테이블 목록을 검색

SELECT * FROM TAB;



1번



AND와 OR를 같이 쓰는 것보다 IN 하나만 쓰는 게 더 효율적인 경우가 있다.

EX) 개발 직무의 ID가 2002, 2003인 사람을 구해라


방법 1) OR 쓰기

SELECT   ENO
           , ENAME
           , SEX
           , JOB
           , HDATE
FROM     EMP
WHERE   1 = 1
AND       JOB='개발'
AND       ENO='2002'
OR         ENO='2003';

방법 2) IN 쓰기

SELECT   ENO
           , ENAME
           , SEX
           , JOB
           , HDATE
FROM     EMP
WHERE   1 = 1
AND       JOB='개발'
AND       ENO IN ('2002' ,'2003');

=> 구해야하는 ID의 갯수가 1000개라면? 방법 1로 구한다면 답 없음.. 100줄 생길 것.

=> IN을 사용해 훨씬 간편하게 관리 OK.


INNER JOIN을 하는 경우는 여러가지가 있다.

  • INNER JOIN 테이블명 ON 조건

SELECT   * 
FROM     EMPLOYEES E
INNER JOIN DEPARTMENTS D ON D.DEPARTMENT_ID = E.DEPARTMENT_ID
WHERE   1 = 1
AND       SALARY <= 3000
;

-> 어떤 테이블들이 JOIN 되었는지 가독성 떨어짐.

-> JOIN 테이블이 많아지면 더 골치아픔.

AND절에 JOIN 조건 넣는 것 추천

  • AND 절에 하는 법

SELECT   * 
FROM     EMPLOYEES E
           , DEPARTMENTS D
WHERE   1 = 1
AND       E.DEPARTMENT_ID = D.DEPARTMENT_ID
AND       SALARY <= 3000
;

INNER JOIN 시 동일 테이블에 2개의 별명을 만들어야 하는 경우


조인할 테이블 a, b가 다음과 있고,

a(벤더 번호, 제조사 번호)

b(벤더 번호, 이름)

일때

a.벤더번호 = b1.벤더번호

a.제조사 번호 = b2. 벤더번호

조회(b1.이름, b2.이름) 이 필요할 때 쓰임


DATE 타입인데 CHAR 타입으로 변환하여 조건을 만족해야 하는 경우


아래와 같이 표현하고 싶을때!

SELECT   JOB_ID
           , END_DATE
           , TO_CHAR(END_DATE,'YYYYMMDD')||JOB_ID AS EXAMPLE
FROM    JOB_HISTORY
;

아래 실행하면 2019/01/01MANAGEMENT로 안나오고

20190101MANAGEMENT로 나온다는 점!


OUTER JOIN를 쉽게 이해하는 방법

두 테이블 중 모자라는 테이블 옆에 (+)를 해주자.

OUTER JOIN을 해야하는 경우

: NULL이 허용되는 칼람이 있을 경우, 꼭 OUTER JOIN을 해줘야 함!

OUTER JOIN 즉, (+) 표시를 안해주면 NULL이 있는 칼람들이 지워진 쿼리문이 보여짐

= 몇몇 데이터가 삭제된 결과 테이블이 나온다는 뜻....


날짜 형식을 지키자

TO_CHAR(칼람명, 'YYYY-MM-DD HH:MM:SS') 보다,

TO_CHAR(칼람명, 'YYYY-MM-DD HH24:MM:SS') 가 더 정확!


SELECT   ENO
           , ENAME
           , SEX
           , JOB
           , TO_CHAR(HDATE, 'YYYY-MM-DD HH24:MM:SS') AS HDATE
FROM     EMP;

차이점은 아래와 같음

형식 설명 HOW
HH, HH12 시간을 01~12시 형태로 TO_CHAR(SYSDATE, ‘HH’) → 04
HH24 시간을 01~23시 형태로 TO_CHAR(SYSDATE, ‘HH24’) → 16

출처: https://thebook.io/006696/part01/ch04/04/01/01/


REPLACE와 TRIM


별명 부가 시 주의사항

AS를 사용(or 생략)한다는 것은 누구나 다 아는 사실,,,

SELECT   ENAME
           , SEX
           , JOB
           , SAL
           , SAL*12 + COMM 연봉
FROM     EMP;

그러나 별명에 공백이 있거나 숫자가 있다면 이중 인용 부호를 사용하여 별명 부가해야 함

SELECT   ENAME
           , SEX
           , JOB
           , SAL
           , SAL*12 + COMM "1000연봉"
FROM     EMP;

NULL 연산을 위한 NVL 함수의 사용

  • NVL 함수

= NULL을 다른 값으로 치환해주는 단일 행 함수


SELECT   ENAME
           , SAL
           , COMM
           , SAL*12 + NVL(COMM,1) "연봉"
FROM     EMP;

-> COMM(=보너스 금액) 이 NULL이면 1로 치환한다.


연결 연산자 ||

SELECT   ENAME||'의 월급은 '||SAL||'이다'
FROM     EMP;



2번


//참고 url
case문 
http://www.gurubee.net/lecture/1028

  • 날짜 조건 주는 방법 3가지

7월 1일 전까지의 데이터를 구하는 쿼리문이라고 가정


방법 1) < end date + 1

방법 2) < end date + 0.99999

방법 3) < (end date+1)


기준 < TO_DATE('20170630', 'YYYYMMDD') + 1 

기준 < TO_DATE('2017-06-30','YYYY-MM-DD') + 0.99999

기준 < TO_DATE('20170701', 'YYYYMMDD')  

=> 1번 방법이 제일 정확함. 오차가 없는 방법


  • 날짜 BETWEEN 대신 부등호
date1 BETWEEN '2017-01-01' AND '2017-06-30' --between 쓴 방법


(date1 >= TO_DATE('20170101','YYYYMMDD') AND date2 < TO_DATE('20170630', 'YYYYMMDD') + 1  --부등호 쓴 방법

-> 부등호 쓰는 게 더 직관적이다!


  • SELECT문의 특정 컬럼 안보이게 하는 법

select절에서 a,b,c,d,e,f가 있다고 할 때, a,b만 보여지고 싶다면?

SELECT   a,b
FROM     (
           SELECT   a,b,c,d,e,f
           FROM     CGM_EQUIPMENT CE
           WHERE    1=1   
           )
         );

  • SELECT절에서 서브쿼리 / FROM절에서 서브쿼리

SELECT절 서브쿼리: RETURN 값이 1개여야 함. (rownum=1로 강제성 부여할 수도 있음 - 근데 함부로 하면 값 다르게 나옴.)

FROM절 서브쿼리: 다 가능. data 여러 건 상관 없음.

참고 링크:

http://blog.naver.com/PostView.nhn?blogId=pyj721aa&logNo=221466664622&categoryNo=0&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=postView


  • UNION과 UNION ALL

UNION: 교집합 중복되는 것들은 제거해주고 한 번만 나오게. 정렬도 해줌. 느림.

UNION ALL: 교집합을 이중으로 표시. 테이블에 있는 것 다. 정렬 안해줌. 순서대로 출력


-> 중복되는 게 없으면 union all 쓰는게 더 효율적


union, union all 그림으로 표시: https://uple.net/m/1689?category=19050




4번


DENSE (중복 있으면 그만큼 순위 공백이 생김)
DENSE_RANK (중복 있어도 순위 공백 없음)와
ROW_NUMBER (중복된 순위가 나오지 않음)


  • 데이터가 최근인 것 순으로 2건만 출력하는 방법 1) - ROW_NUMBER()
SELECT   A
FROM (
         SELECT   A
                , ROW_NUMBER() OVER (ORDER BY A DESC) AS RK
         FROM     테이블 MH
         WHERE    1 = 1
     )
WHERE    1 = 1
AND      RK <= 2
;

  • 데이터가 최근인 것 순으로 2건만 출력하는 방법 2) - DENSE_RANK()
SELECT   A
FROM (
         SELECT   A
                , DENSE_RANK() OVER (ORDER BY A DESC, B DESC) AS RK
         FROM     테이블 MH
         WHERE    1 = 1
     )
WHERE    1 = 1
AND      RK <= 2
;

  • 데이터가 최근인 것 순으로 2건만 출력하는 방법 3) - RANK()
SELECT   A
FROM (
         SELECT   A
                , RANK() OVER (ORDER BY A DESC) AS RK
         FROM     테이블 MH
         WHERE    1 = 1
     )
WHERE    1 = 1
AND      RK <= 2
;



5번


  • GROUP BY() 안에 칼럼들 다 때려 박는 방식 피하는 법

테이블 EX)

AAA 123 SE D1
AAA 123 SE D1
AAA 123 SE D9
AAA 123 SE D10

AAA가 같으면 123도 같고 SE도 같을 수 밖에 없는 구조. D의 사이즈만 달라지는 테이블 구조


이 테이블의 특성 덕분에 MAX(칼럼명)을 쓰는 걸로 발상의 전환해서, GROUP BY에 모든 컬럼을 죄다 때려 박지 않아도 됨


SELECT    AAA
        , MAX(123) --MAX 집계함수를 썼기에 에러 안 남 + GROUP BY()에 컬럼명 다 안써져도 됨
        , MAX(SE) 
        , COUNT(D9)
FROM      테이블 MC
WHERE     1 = 1
GROUP BY  MC.AAA
;

  • SUM을 이용해 COUNT하기
        , COUNT(DECODE(X, 'R9',1,NULL))  AS X
        , SUM(CASE WHEN XX = 'D9' THEN 1 ELSE 0 END) AS XX --CASE에 SUM 쓰는 방법



6번


소계 총계 예시 테이블.

aaa 123 2
aaa 999 3
aaa SUB TOTAL 5
bbb 123 3
aaa SUB TOTAL 3
GRAND TOTAL 8

지금은 내장함수 ROLLUP() 이용하면 되는데,

옛날 같은 경우, 주어진 테이블 A를 FULL JOIN을 함. 3번을 함.

그럼

A

A

A

이렇게 있을텐데, 각각 역할을 다르게 해서 결과물 테이블을 만든거임.

첫번째 A는 원래대로 GROUP BY 해주고, 두 번째 A는 SUB TOTAL 만들어주고, 세 번째 A는 GRAND TOTAL 만들수 있게 해준거지.


//참고 url
총계 소계 표시 방법 http://blog.naver.com/PostView.nhn?blogId=acatholic&logNo=90148766925

하위 레벨 https://thebook.io/006696/part01/ch05/03/01/

GROUPING 칼람 개수별 하위 그룹 https://fly32.net/252

GROUPING_ID 10진수로 리턴 로직 https://m.blog.naver.com/PostView.nhn?blogId=minis24&logNo=80100555203&proxyReferer=http%3A%2F%2Fwww.google.com%2Furl%3Fsa%3Dt%26rct%3Dj%26q%3D%26esrc%3Ds%26source%3Dweb%26cd%3D2%26ved%3D2ahUKEwis2uvZ6MLlAhWPc3AKHbR3AeoQFjABegQIAhAB%26url%3Dhttp%253A%252F%252Fm.blog.naver.com%252Fminis24%252F80100555203%26usg%3DAOvVaw3Par0t42UZ01QmTQtRXTqE

그루비 http://www.gurubee.net/lecture/2679 소계 총계 각기 표시 

소계 총계 표시 여러 방법 http://blog.naver.com/PostView.nhn?blogId=acatholic&logNo=90148766925

  • ROLLUP - 총계/소계 표시할 때 쓰인다~

ROLLUP() 안에 들어가는 테이블 어떤 게 들어가는지 유의하기.


  • 총계/소계 표시를 위한 CASE문

https://softarchitecture.tistory.com/63 의 테이블 결과 스샷으로 예시

  1. 소계를 위해 신경써야 할 것:

조건) JOB이 NULL일 때


  1. 총계를 써줘야 하는 조건:

조건) DEPTNO가 NULL일 때

총계란의 JOB란도 NULL로 비워줘야 함.


소계/총계를 테이블에 표시 ex)

SELECT
  NVL(DEPTNO, '총계') AS DEPTNO

, CASE 
         WHEN DEPTNO IS NULL AND JOB IS NULL THEN NULL --총계란의 JOB 컬럼 빈칸만들기 위한 case문
              WHEN JOB IS NULL THEN '소계' --null이면 소계써주고
              ELSE JOB --아니면 원래값 출력
  END CNMV_STS_CD



8번


[function 생성 및 이용하는 법] 게시물 확인 ->




9번


//참고 url
EXIST와 NOT EXIST 예시. 둘 다 같게 어떻게? https://runtoyourdream.tistory.com/112

스택오버플로에서 9번 해결 방법 https://stackoverflow.com/questions/20893403/sql-select-query-excluding-certain-values


  • IN과 EXISTS

IN: () 안에 있는 특정값이나 서브쿼리의 결과값이 포함이 되는지만 체크

AND      (기본키1, 기본키2) NOT IN (SELECT 기본키1, 기본키2 FROM 테이블 WHERE 칼럼1 = '123')

EXISTS: ()안의 서브쿼리로 부터 해당 컬럼의 값이 존재 유무만 체크

FROM     테이블2 LA
~
~
AND      NOT EXISTS (
                     SELECT   기본키1 --이부분은 아무거나 써도됨. 이 서브쿼리문 전체의 유무만 파악하는게 NOT EXISTS이기 때문. 굳이 컬럼값일 필요 X
                     FROM     테이블 LR 
                     WHERE    1 =1 
                     AND      칼럼1 = '123' 
                     AND      LA.기본키1 = LR.기본키1 
                     AND      LA.기본키2 = LR.기본키2
                    )
;

=> 이 2가지 결과는 동일.


그러나, EXISTS가 훨씬 빠름

이유는??

-IN을 이용하게 되면 서브쿼리 전체를 먼저 스캔하고 tableA의 모든 레코드에 대해 IN에서 추출된 데이터와 비교하게 되므로 서브쿼리의 추출되는 레코드가 많다면 성능이 저하됩니다.

-EXISTS와 조인을 이용하는 방법은 비교해서 참 또는 거짓만 리턴하므로 서브쿼리의 추출되는 데이터가 많다면 훨씬 좋은 성능을 보이게 됩니다.


http://ojc.asia/bbs/board.php?bo_table=LecOrccleTun&wr_id=116




12번

//참고 url
PARTITIONI BY 아이디어(중복체크용도) https://hmjkor.tistory.com/9

분석 함수 그루비 http://www.gurubee.net/lecture/2671

  • 중복인 대상 찾는 2가지 방법
  1. group by - having 이용
SELECT 칼럼1 
FROM 테이블명
GROUP BY 칼럼1
HAVING COUNT(*)>1
;

중복이 아닌 대상 찾기

SELECT 칼럼1 
FROM 테이블명
GROUP BY 칼럼1
HAVING COUNT(*)=1
;

  1. row_number() over(partition by ~ order by ~) 이용
SELECT   칼럼1
FROM     (
           SELECT   칼럼1
                  , ROW_NUMBER() OVER(PARTITION BY 칼럼1 ORDER BY 칼럼2) CNT
           FROM     테이블명
         )
WHERE    1 = 1
AND      CNT > 1
GROUP BY 칼럼1
;

  • group by - having

having 절: gouping된 것에 있어, 집계함수로 조건을 줄 수 있다.

틀린 예 1)

SELECT 칼럼명1 FROM 테이블명
GROUP BY 칼럼명1
HAVING 칼럼명2 = 3;

'ORA-00979: GROUP BY 표현식이 아닙니다.' -> 에러 뜸!


틀린 예 2)

SELECT 칼럼명1 FROM 테이블명
GROUP BY 칼럼명1
HAVING COUNT(칼럼명2);

'ORA-00920: 관계 연산자가 부적합합니다' -> 에러 뜸!


맞는 예)

SELECT 칼럼명1 FROM 테이블명
GROUP BY 칼럼명1
HAVING COUNT(칼럼명2) > 1;

  • (칼럼 여러개) IN (칼럼 여러개)

: 이 여러개 컬럼들의 조건들에 맞는 것들을 다 검사

ex)

쌍으로 IN 연산자에 부합해야할 때가 있을 수 있음 - 이때 유용

SELECT   *
FROM     A
WHERE   (A.1, A.2, A.3) IN ( 
            SELECT B.1, B.2, B.3 
            FROM    B
            WHERE  ....
          );
출처: https://derveljunit.tistory.com/174 [IT를 보고, 듣고, 사색하고]



11번


//참고 url
부등호 조인 https://tedock.tistory.com/156

  • 누계 계산법 2가지
  1. 부등호 조인 이용

= 한 테이블을 FROM절에 두 번 가져오기 -> 한 테이블은 SUM용, 한 테이블은 원본용 으로 -> 조인!

SELECT   GR.테이블1
       , MAX(GR.환율칼럼) 당월_환율
       , SUM(GR2.환율칼럼) 누계_환율
FROM     테이블1 GR
       , 테이블1 GR2
WHERE    1 = 1
AND      GR.기본키 >= GR2.기본키         --부등호 조인
AND      GR.기본키2 = GR2.기본키2         --다른 조인 조건
AND      GR2.기본키3 = 'USD'         --다른 조인 조건
AND      GR.기본키3 = GR2.기본키3         --다른 조인 조건
GROUP BY GR.기본키         --부등호 조인한 기본키로 GROUP BY, ORDER BY
ORDER BY GR.기본키         --부등호 조인한 기본키로 GROUP BY, ORDER BY
;

  1. SUM() OVER (ORDER BY ~) 이용법
SELECT   기본키
       , GR.환율칼럼 당월_환율
       , SUM(GR.환율칼럼) OVER (ORDER BY GR.기본키) 누계_환율
FROM     테이블1 GR
WHERE    1 = 1
AND      GR.기본키3 = 'USD'
;



  • 논리 pk, 물리 pk

논리 pk: (프로그램상으로) 중복이 들어올 수 없는 값

물리 pk: 눈에 보이는 pk. ex) sequence들

-보통 논리,물리 pk를 같이 씀




  • history를 남길 수 있게 db를 설계하자

: 데이터 삭제의 경우, 실제로 삭제하는 것보다, delete_flg 칼럼을 만드는 것

null값 방지를 위해 default로 delte_flg='n'를 해주고 삭제여부를 이 컬럼에 표시하는 것


ex) (출처: https://12bme.tistory.com/246)

이름 역할 의미
_FL FLAG 플래그값이다. 종종 삭제하지 않은 테이블에서 삭제플래그를 많이 사용한다. 값은 0/1이나 Y/N을 많이 사용한다.

장점: CUD시 추적관리에 좋다. 그러나 데이터 양이 많이 발생하는 곳에는 x


  • sequence를 적극 활용하자

각 칼럽의 개수를 MAX(+1)로 관리한다면?

-> 동시작업시 PK 중복 에러날 수 있음.


Sol) Oracle에서는 (테이블 속성이 아닌) 별도의 sequence 객체를 생성해서 이용할 수 있다.

MySQL 에서는 컬럼에 auto_increment 속성을 지정

출처: https://offbyone.tistory.com/239 [쉬고 싶은 개발자]

insert 작업 시 이 sequence를 무조건 거치기에, 동시성에 있어서 문제 될 일 x




  • DB OBJECT의 종류

DB OBJECT 설명
테이블 데이터를 담고 있는 객체
인덱스 테이블에 있는 데이터를 빠르게 찾기 위한 객체.
> 칼럼들의 순차적인 의미를 부여. (ex. 전화번호부, 사전)
하나 이상의 테이블을 연결해 마치 테이블인 것처럼 사용하는 객체
트리거 시점 기준. before/after 2가지로 나눠서 스크립트를 짤 수 있게 도와줌. (ex. CUD라면 6가지)
존재 이유: 중복을 피하기 위해
패키지 용도에 맞게 함수나 프로시저를 하나로 묶어 놓은 객체. 관리의 포인트를 둠. (ex. 모듈별/성격별로 나눌 수 있음)
함수 특정 연산을 하고 값을 반환하는 객체.
return 값이 1개. -> 쿼리에서 사용할 수 있음.
프로시저 CUD 성격의 일련의 과정을 복합적으로 가지고 있는 객체.
함수와 비슷하지만 값을 반환하지는 않는 객체. return 값이 여러 개일 수 있다.
장점: 복잡한 흐름을 잘 명시. 빠르다.
시퀀스 일련번호 채번을 할 때 사용되는 객체

https://thebook.io/006696/part01/ch02/01/01/


  • procedure와 function

프로시져 :
업무를 맡기는 목적 (CRUD 업무 로직)
로직을 기술 하여 해당 업무 처리를 위임시켜 사용 할 수 있도록 하는 용도로 많이 사용됨


프로시저 형식

CREATE OR REPLACE PROCEDURE 프로시저명 ( 파라미터1 데이터타입 [ IN | OUT | INOUT ] , ~)

IS [AS]

변수 선언부..;

BEGIN

프로시저 본문 처리..;

EXCEPTION

예외처리..;

END;

출처: https://arrkaize86.tistory.com/entry/오라클-프로시저PROCEDURE [송군함대]

함수 :
로직을 도와주는 목적
자주 쓰는 로직을 모듈화 시켜 현재 하는 업무를 서포트 해주는 목적으로 많이 사용됨

사실 프로시져나 펑션은 둘다 결과값도 리턴되고 ( 프로시져는 out 파라메터로 ) 하지만
펑션(function)은 조회를 제외한 나머지 데이타 조작은 구현하기 사용하기 힘듭니다.
하지만 프로시져는 강력하게 데이타조작 처리가 가능하기 때문에 데이타를 배치 처리에 많이 사용 됩니다.
소위 말하는 사정업무라고 할까요.

https://okky.kr/article/212226


  • 트리거

= 테이블에 대한 이벤트를 자동으로 실행 해 주는 것이다. 즉, 자동으로 실행되는 PL/SQL 문이라고 보면 된다.

예를 들면 A,B,C 라는 테이블에 공통으로 사원번호가 있다 . A테이블의 사원번호가 지워지면 B,C테이블의 회원번호도 자동으로 지워지게하거나 Update , insert 등을 할 수 있다.


-트리거의 종류

1. SQL문의 실행시기에 따른 분류

: before 트리거-SQL 문장이 실행되기 전 트리거가 먼저 실행됨

: after 트리거-SQL 문장이 실행된 다음 트리거가 먼저 실행됨


  1. SQL문에 의해 영향 받는 각 row에 따른 분류

: row 트리거-SQL 문장의 각 row에 대해 한번 씩 실행

: statemnet 트리거-SQL 문장에 대해 한번만 실행

(DEFAULT TRIGGER)


트리거 형식

CREATE or REPLACE TRIGGER trigger_name

BEFORE or AFTER [INSERT,DELETE,UPDATE] ON table_name

[Referencing OLD AS {변경전 값을 참조하는 변수명} NEW AS {변경후 값을 참조하는 변수명}]

[ FOR EACH ROW ]

DECLARE

-- 변수선언

BEGIN

-- 트리거 코드(PL/SQL 코드)

EXCEPTION

WHEN

--익셉션

END;

트리거 예시

CREATE OR REPLACE TRIGGER trigger_name
BEFORE UPDATE
ON table_name 
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
BEGIN

INSERT INTO TABLE_MOD
(aa,bb,cc)
   VALUES
(:OLD.aa,:OLD.bb,:OLD.cc);

https://thatisgood.tistory.com/entry/oracle-Trigger오라클-트리거




  • 집계함수에는 무조건 1개 이상의 ROW가 발생한다. (데이터가 없어도!)
SELECT   MAX(ACCT_XCH_RT_YRMON)
FROM     GL_MON_XCH_RT GR
WHERE    1 = 1
AND      GR.CURR_CD = '월루'
;

결과: 1 rows

-> 코딩 시 유용하게 사용 가능-무조건 결과값이 있기에. nodatafound 같은 에러 발생 x

-> procedure, function에서도 loop 돌 때 한 줄이라도 결과값 나오게 할 때도 쓰임. nullpointerror 나오기도 하기 때문


  • SELECT절은 데이터 없으면 값이 아예 안나옴
SELECT   ACCT_XCH_RT_YRMON
FROM     GL_MON_XCH_RT GR
WHERE    1 = 1
AND      GR.CURR_CD = '월루야호'
;

결과: 0 rows


Comments