25일차 2023-04-11

2023. 4. 11. 20:03oracle

orcle

1. 트랜잭션 (일련의 작업)


- 일련의 작업 단위를 처리하기 위한 거를 트랜잭션

- 일련의 작업에서 하나의 작업이라도 실패한다면 모든 작업을 취소시킨다
(ROLLBACK 한다고 한다)

- 일련의 작업이 정상적으로 끝나면 COMMIT 한다

- 오라클의 트랜잭션 제어 명령어

    COMMIT:모든 미결정 데이타를 영구적으로 변경함으로써 
                 현재 TRANSATION을 종료
    ROLLBACK [TO SAVEPOINT name]:모든 미결정 데이터 변경을 원래대로 돌림으로써 
                                                    현재의 TRANSATION종료
    SAVEPOINT :TRANSATION내의 SAVEPOINT표시/ANSI 표준 SQL이 아님.

- 자동 COMMIT일 얼어나는 경우

1.DDL/DCL문장 완료시(DDL=>create,alter,drop,truncate,rename),DCL=>grant,revoke)
2.SQL*PLUS 정상 종료 시

- 자동 ROLLBACK이 일어나는 경우

1.SQL*PLUS 비정상 종료시 혹은 시스템 실패 시

※cmd에서 했지만 sql developer에서 안 보이는 이유 임시테이블에 저장되어 있어서 보이게 하려면 commit을 하면 됨.


- SAVEPOINT 예]

SQL> UPDATE emp SET depno=30 WHERE empno=7788;

SQL> SAVEPOINT point1

SQL> UPDATE emp SET job='MANAGER';
SQL>UPDATE emp SET SAL=500;

SQL> ROLLBACK  TO SAVEPOINT point1;
SQL> EXIT(정상종료라 부름 이걸 하면 자동 커밋)

 

변경 전
변경 후

 

 

 

 

2. 주요 내장 함수

 


2-1). 문자열 관련

-NVL(칼럼명, NULL인 경우 대체할 값) 
-NVL2(칼럼명, "대체값 1", "대체값 2") 


2-2). LOWER('문자열'):영문자를 소문자로 변환

SELECT LOWER('ORACLE') FROM DUAL +> oracle


2-3). UPPER('문자열'):영문자를 대문자로 변환

SELECT UPPER('oracle') FROM DUAL +> ORACLE


2-4). INITCAP('문자열'): 첫 영문자를 대문자로 변환

SELECT INITCAP('oracle') FROM DUAL +> Oracle



2-5). CONCAT('문자열', '문자열'):문자열 연결  또는 ||

SELECT CONCAT('ORACLE', 'JAVA') FROM DUAL +> ORACLEJAVA



2-6). LENGTH():문자열 길이

SELECT LENGTH('오라클') FROM DUAL; +>3

2-7). lengthb():문자열 길이를 바이트로(한글이 3바이트 차지)

SELECT LENGTHB('오라클') FROM DUAL; +>9

2-8). LPAD('문자열', 전체 자릿수, '채울 문자열'):좌측을 지정한 값으로 채운다

SELECT LPAD('HELLO',10, 'X') FROM DUAL+> XXXXXHELLO

혹은

SELECT LPAD('9',2, '0') FROM DUAL +>09


2-9). RPAD('문자열', 전체 자릿수, '채울 문자열'):우측을 지정한 값으로 채운다

SELECT LPAD('HELLO',10, 'X') FROM DUAL+> HELLOXXXXX

혹은

SELECT LPAD('9',2, '0') FROM DUAL +>90


2-10). INSTR('문자열', '찾을 문자열'): 찾은 문자열의 인덱스 반환.
                                인덱스는 1부터 시작

SELECT INSTR('ABCDEFG', 'DE') FROM DUAL +>4


(1) SELECT * FROM DEPT WHERE instr(LOWER(DNAME), 'e')!=0

(2) SELECT * FROM DEPT WHERE LOWER(DNAME) like '%e%'와 결과가
같으나 쿼리속도면에서 (1)이 훨씬 성능이 우수하다.

2-11). SUBSTR('문자열', 시작인덱스, 길이):문자열에서 시작인덱스부터 길이만큼 가져옴, 인덱스는 1부터 시작
                 
SELECT SUBSTR('123456789',3,3) FROM DUAL;+>345


2-12). REPLACE('문자열', '바꿀 문자열', '바뀔 문자열'): 특정 문자열을 다른 문자열로 대체

SELECT REPLACE('HELLO WORLD', 'HELLO', 'JAVA') FROM DUAL +> JAVA WORLD


2-13). TO_CHAR():
TO_CHAR(숫자 혹은 날짜)
TO_CHAR(숫자 혹은 날짜, 숫자형식 포맷 문자열 혹은 날짜형식 포맷 문자열)

-숫자형을 문자형으로 변환

SELECT TO_CHAR(123) || TO_CHAR(456) FROM DUAL +>123456
혹은
SELECT 123 || 456 FROM DUAL


SELECT TO_CHAR(123, '0999') FROM DUAL +>0123--0은 숫자가 아니면 0
SELECT TO_CHAR(123, '9999') FROM DUAL +> 123--9는 숫자가 아니면 빈공백


SELECT TO_CHAR(1234, '$999,999.99') FROM DUAL +>$1,234.00
SELECT TO_CHAR(1234, '$999,999.00') FROM DUAL +>$1,234.00
SELECT TO_CHAR(1234, 'L999,999') FROM DUAL +> \1,234
SELECT TO_CHAR(1234, 'l999,999') FROM DUAL +> \1,234



※TO_CHAR(숫자, '숫자포맷문자열') 
  9는 값이 있으면 표시, 없으면 표시 안 함
  0은 값이 있으면 표시, 없으면 0으로 표시
                  단, 소수점은 9든 0이든 값이 없으면 모두 0으로 표시됨
                  또한 소수점은 실제값의 자릿수가 많으면 나머지는 짤림.
                  단, 정수인 경우는 실제값의 자리수가 많으면 값이 #으로 표시됨
  


2-14). 날짜형을 문자 형으로 변환

SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:MI:SS') FROM DUAL
※'yyyy"월"mm"년"dd"일" :한글로 연월일 표시 시 포맷형식에 ""로 한글을 감싼다.
예] SELECT TO_CHAR(SYSDATE, 'YYYY"년"MM"월"DD"일" HH"시"MI"분"SS"초"') FROM DUAL

2-15). 지정한 날짜의 특정 부분을 나타내는 문자열을 반환


SELECT TO_CHAR(TO_DATE('2012/10/1'), 'YYYY') FROM DUAL+>2012
SELECT TO_CHAR(TO_DATE('2012/10/1'), 'MM') FROM DUAL+>10

SELECT TO_CHAR(TO_DATE('2012/10/1'), 'HH') FROM DUAL+>12
SELECT TO_CHAR(SYSDATE, 'HH') FROM DUAL+>1~12시 형태의 시간 반환
                                        18 시인경우 06
오전 6시인 경우 06

SELECT TO_CHAR(SYSDATE, 'HH AM') FROM DUAL+> 06 오전 혹은 오후
SELECT TO_CHAR(SYSDATE,'HH PM') FROM DUAL+> 06 오전 혹은 오후

SELECT TO_CHAR(SYSDATE, 'AM HH') FROM DUAL+>  오전 혹은 오후 06
SELECT TO_CHAR(SYSDATE, 'PM HH') FROM DUAL+>  오전 혹은 오후 06

SELECT TO_CHAR(SYSDATE, 'HH24') FROM DUAL+>0~23시 형태의 시간 반환


SELECT TO_CHAR(SYSDATE, 'day') FROM DUAL+> 목요일
SELECT TO_CHAR(SYSDATE, 'dy') FROM DUAL+> 목

SELECT TO_CHAR(TO_DATE('2012/10/1'), 'DD') FROM DUAL+>01
SELECT TO_CHAR(TO_DATE('2012/10/1'), 'D') FROM DUAL+>2(요일 반환)
                                          1:일요일
  2:월
  3:화
  4:수
  5:목
  6:금
  7:토
SELECT TO_CHAR(TO_DATE('2013/1/1'), 'DDD') FROM DUAL+>001
                                          해당 연도 1월 1일부터
  몇일째인지 반환

※ '2012-10-1'도 날짜형식의 문자열로 인식하지만
  '2012년 10월 1일'은 오라클이 날짜형식의 문자열로 인식 못함.

 

 


2-16). TO_NUMBER():문자형을 숫자형으로 변환

SELECT TO_NUMBER('123') + TO_NUMBER('456') FROM DUAL +>579
혹은
SELECT '123' + '456' FROM DUAL



2-17). TRIM():양쪽 공백 제거

2-18). 날짜 관련

*ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH:MI:SS'
                *REGEDIT->HKEY_LOCAL_MACHINE->SOFTWARE->ORACLE->KEY~에
                          NLS_DATE_FORMAT ='YYYY-MM-DD'추가

*UNIX인 경우. bashrc 혹은. bash_profile에 export=NLS_DATE_FORMAT ='YYYY-MM-DD'추가

-SYSDATE:현재 날짜 가져오기

SELECT SYSDATE FROM DUAL +> YY/MM/DD


- + 혹은 - :날짜 더하기 빼기

SELECT SYSDATE + 1 FROM DUAL +>1일 더한 날 출력

SELECT SYSDATE  -1 FROM DUAL +>1일 뺀날 출력


2-19). TO_DATE():문자형을 날짜형으로 변환
yy:년도 2자리만
yyyy:년도 4자리
mm:01~12 형태의 월 
d: 요일 반환(일요일은 1, 월요일 2)
dd:1~31 형태의 일 표시
ddd:해당 연도의 1월 1일부터 현재까지의 일수

HH:1~12시 형태로 표시
HH12:1~12시 형태로 표시
HH24:0~23시
MI:0~59분
SS:0~59초

SELECT TO_DATE('2000/10/20') FROM DUAL;+>00/10/20
※문자열타입으로 저장된 날짜형식을 DATE타입으로 변환 후
  VARCHAR2   2017-12-19
  TO_CHAR(DATE타입, '날짜포맷형식')을 이용해 
  원하는 날짜 형태로 출력하고자 할 때

  단, 문자열타입의 날짜형식은 연월일형태여야 한다
  (시분초 포함 시 에러 즉 날짜형식으로 인식 안됨)
  만약 VARCHAR2(20)의 타입으로 2013-03-14 17:05;56로 저장되었다면
  select to_char(to_date(substr(postdate,1,10)), 'yyyy-mm-dd') postdate from board
  



2-20). MONTHS_BETWEEN(DATE타입, DATE타입):개월 수 구하기

SELECT MONTHS_BETWEEN(SYSDATE, TO_DATE('2012/01/01')) FROM DUAL+>2.48.....

-ADD_MONTHS(DATE타입, 숫자):개월 수 더하기

SELECT ADD_MONTHS(SYSDATE,2) FROM DUAL+>

2-21). 수학 관련

-ROUND() : 반올림

-FLOOR(): 소수자리 버림

-CEIL(): 올림

-MOD: 나머지

SELECT MOD(5,2) FROM DUAL+>1

-POWER(2,3):지수곱
-SQRT(10):제곱근 


2-22). -DECODE() 함수는  첫 번째 매개변수의 값에 따라 결과를 표시하는 함수
 (switch와 같다)

 DECODE(표현식, 값 1, 결괏값 1, 값 2, 결괏값 2,.. 값 N, 결괏값 N, 기본값)
       표현식이 값 1일 때 결괏값 1이 반환됨 값 2일 때는 결괏값 2
       표현식이 아무 값도 해당되지 않을 때 기본값 반환

 예]
 SELECT DECODE( 10/2 ,1, '값이 1',2, '값이 2',3, '값이 3', '그 외 값') FROM DUAL;

 select ename,
 decode(job, 'MANAGER', '매니저', 'SALESMAN', '영업맨', '기타') 
 FROM EMP



 DECODE()는 값 1 = 결괏값 1 즉 = 연산만 가능

2-23). ※CASE WHEN 절은 다양한 조건식 가능

 1] 다양한 조건을 줄 때(if ~else if ~else if else와 같다)
 CASE  WHEN  조건 1 THEN 결괏값 1 <=칼럼명이 없을 때 실수형 데이터일 때 사용
              WHEN  조건 2 THEN 결괏값 2
    ..................
      WHEN  조건 N THEN 결괏값 N
      ELSE  그 외 값
         END  [칼럼별칭]

 예]

select ename,
CASE JOB WHEN 'MANAGER' THEN '매니저'<=case 칼럼명 when은 decode와 같음
 WHEN 'SALESMAN' THEN '영업맨'
 ELSE '기타'
END AS JOB, DEPTNO,
-- 범위를 조건으로 할 때는 CASE와 WHEN사이에 
    표현식 생략.(자바의 IF문)
CASE WHEN SAL >= 3000 THEN '고액 연봉자'
     WHEN SAL >= 2000 THEN '중간 연봉자'
     ELSE '하위 연봉자'
END SAL
FROM EMP


2] DECODE() 함수처럼 쓰려면(switch와 같다)
 --범위가 아닌 특정 값으로 분기할 때는 (자바의 SWITCH문)
     CASE와 WHEN 사이에 표현식 생략 불가

 CASE 표현식 WHEN  값 1 THEN 결괏값 1
                     WHEN  값 2 THEN 결괏값 2
    ..................
             WHEN  값 N THEN 결괏값 N
     ELSE  그 외 값
         END  [칼럼별칭]

 예]
 select ename,
CASE JOB WHEN 'MANAGER' THEN '매니저'
 WHEN 'SALESMAN' THEN '영업맨'
 ELSE '기타'
END AS JOB
FROM 

SELECT SAL,
       CASE FLOOR(SAL/1000) WHEN 3  THEN '고액연봉'
                            WHEN 4  THEN '고액연봉'
                            WHEN 5  THEN '고액연봉'
                            WHEN 2  THEN '중간연봉'
            ELSE  '저액연봉'
            END AS 직무,
       JOB
FROM emp ORDER BY sal;


    SELECT ENAME,
        CASE  
        WHEN MGR IS NULL
             THEN 'CEO'
        WHEN  EMPNO IN (SELECT E1.EMPNO   FROM EMP E1 JOIN EMP E2 ON E1.EMPNO=E2.MGR )
             THEN 'MANAGER'  
              
             
        WHEN  EMPNO NOT IN (SELECT E1.EMPNO   FROM EMP E1 JOIN EMP E2 ON E1.EMPNO=E2.MGR )
             THEN 'WORKER'  
              
             END
유형
FROM EMP

 

문제) hr 계정

 


3. CURSOR

- SEELCT 문장에 의해 여러 행이 RETURN 되는 경우 각 행에 접근하기 위한 것

CURSOR 선언]

CURSOR 커서명 IS
SELECT문장 ------------------DECLARE부에서 한다
(INTO절이 없는 SELECT문)

OPEN CURSOR]

-질의를 수행하라는 의미 즉 
  OPEN시에 CURSOR 선언 시의 SELECT문장이 실행되어
 결과 셋을 얻게 된다 CURSOR는 그 결과세의 첫 번째 행에
          바로 위에 위치하게 된다.

 OPEN 커서명'

FETCH ~ INTO ~]

-결과 셋에서 하나의 행을 읽어 들이는 작업,
 결과 셋에서 인출(FETCH) 후에
 CURSOR는 다음 행으로 이동

 FETCH  커서명 INTO {varaiable1 [, variable2,....]};


CURSOR 닫기]

-결과 셋의 자원을 반납. SELECT 문장이 다 처리된 후 CURSOR를 CLOSE

CLOSE 커서명;



CURSOR의 속성]
커서명%FOUND :가장 최근의 인출(FETCH)이 행을 RETURN 하면 TRUE 아니면 FALSE;
커서명%ROWCOUNT :지금까지 RETURN 된 행의 수

 

소스 예]

-----부서 번호를 입력받아 출력하는 예제

SET SERVEROUT ON

ACCEPT p_deptno PROMPT '부사번호를 입력하세요 : '

DECLARE

v_deptno emp.deptno%TYPE:=&p_deptno;
v_ename emp.ename%TYPE;
v_sal emp.sal%TYPE;

--커서 선언

CURSOR emp_cursor IS
SELECT ename, sal FROM emp WHERE deptno=v_deptno;


BEGIN

--커서 오픈

OPEN emp_cursor;

DBMS_OUTPUT.PUT_LINE('         이름          연봉             ');
DBMS_OUTPUT.PUT_LINE('----------------------------------------');

LOOP
--FETCH 하기
FETCH emp_cursor INTO v_ename,v_sal;

EXIT WHEN  emp_cursor%FOUND;


DBMS_OUTPUT.PUT_LINE(RPAD(v_ename,12) || LPAD(TO_CHAR(v_sal, '$99,999,990.00'),16));
DBMS_OUTPUT.PUT_LINE('----------------------------------------');


END LOOP;

--커서 닫기

CLOSE emp_cursor;

END;
/
SET SERVEROUT OFF

4. SUBPROGRAM

- PL/SQL에는 (스토어드) 프로시저 와 함수라는 두 가지 유형의 SUBPROGRAM이 있다
- SELECT구문뿐만 아니라 기타 DML문 등을 이용하거나 
  혹은 프로그래밍적인 요소등을 사용하여 
  처리하기 복잡한 여러 가지 데이터베이스 작업등을 처리할 수 있도록 만들어진 
  데이터베이스 객체이다

 

4-1) Function

- 사용자가 PL/SQL구문을 사용하여 직접 오라클에서 제공하는 내장함수와 
  같은 기능을 정의한 것
- 함수는 IN 파라미터만 사용할 수 있으며,
  반드시 반환될 값의 데이터 타입을  
  RETURN문에 선언해야 하며 단일값만 반환된다.

-함수 구문

  CREATE [OR REPLACE] FUNCTION 함수명
  [(
  매개변수1 IN 자료형,    --IN 생략 가능
  매개변수2 IN 자료형     ---자료형 정의 시 자릿수 지정 안함 <=지정하면 에러
                   
  )]
RETURN 자료형-- 자리수 지정 안 함 <=지정하면 에러
  IS

  [변수 선언]

  BEGIN--<=함수 시작

  함수 내용

  RETURN(값);

  END;
   함수 예]


      - FUNCTION정의

      CREATE OR REPLACE FUNCTION GETSUM(A   NUMBER, B IN  NUMBER)
RETURN NUMBER
   IS
HAP NUMBER; --<=hap number(10);자릿수 여긴 설정가능
BEGIN

HAP:=0;

FOR i IN A .. B LOOP
HAP:=HAP+i;
END LOOP;


RETURN HAP;
END;
/

     -FUNCTION 호출

     방법 1)
SQL> SELECT GETSUM(1,100) FROM DUAL
    
     방법 2)
SQL> VAR  HAP CHAR(2);
SQL> EXCUTE :HAP := GETSUM(1,100);--<=함수를 실행하라 그리고 그걸 hap에 넣어라 
//excute는 실행권한을 가짐(함수나 프로시저를 실행할 때 사용)
SQL> PRINT HAP;

  함수 예]
  CREATE OR REPLACE FUNCTION GETGENDER(JUMIN VARCHAR2)
RETURN NCHAR
IS   ----함수란(;는 붙이면 안 됨)

RTVAL VARCHAR2(4);

BEGIN
IF TO_NUMBER(SUBSTR(TRIM(JUMIN),7,1)) = 1 THEN
RTVAL:='남자';
ELSE 
RTVAL:='여자';
END IF;

RETURN RTVAL;
END;
/

문제)

hrr계정에서 scott계정에서 만든 함수 to_asterisk사용하기 

 

 

 




4-2). 저장 프로시저([Stored] Procedure)


- 프로시저는 RETURN문이 없다  OUT 매개변수로 값을 RETURN 한다.
- 저장 프러시저(STORED PROCEDURE)의 장점
  (1) 매우 좋은 성능
  (2) 보안성을 높일 수 있음.
  (3) 다양한 처리가 가능
  (4) 네트워크의 부하를 줄일 수 있음.


-프로시저 구문

:RETURN 문이 없다.

CREATE [OR REPLACE] PROCEDURE 프로시저명
[(
매개변수 IN 자료형,//크기 지정 안 함
매개변수 OUT 자료형,//출력용
매개변수 IN OUT 자료형//입 출력용   EXEC시 숫자 전달 불가능, 역시 변수 전달
      
)]
IS
[변수선언]
BEGIN
........
END;

-실행
EXECUTE 프로시저명[(인수 1, 인수 2,..)]


※ 매개변수의 자료형 지정 시 해당 테이블의 칼럼과 같은
   자료형으로 지정하고 싶을 때 테이블명. 컬러명% TYPE
   이라고 지정한다

   예] 매개변수 IN 테이블명.컬럼명%TYPE




소스 예]

- 사원번호 와 연봉을 입력받아 연봉을 수정하고 수정된 행의 개수를 받아 오기
SET SERVEROUT ON
CREATE OR REPLACE PROCEDURE 
emp_sal_procedure(

p_empno [IN] emp.empno%TYPE,
p_sal IN emp.sal%TYPE,
count OUT NUMBER)

IS

BEGIN
UPDATE emp
SET sal =p_sal
WHERE empno =p_empno;

IF SQL%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE(TO_CHAR(p_empno) || '는 없는 사원번호입니다');
ELSE
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQL%ROWCOUNT) || '명의 자료가 수정되었습니다.');
count:=SQL%ROWCOUNT;
END IF;

COMMIT;  -- 커밋해야 실제 반영됨.

END;
/
SET SERVEROUT OFF


-프로시저 실행
SQL> VAR count NUMBER
SQL> EXECUTE emp_sal_procedure(10,1000,:count);
SQL> PRINT count

 


----회원일치여부 프로시저
CREATE OR REPLACE PROCEDURE SP_CHECK_MEMBER(IEMPNO IN EMP.EMPNO%TYPE,IENAME IN EMP.ENAME%TYPE,FLAG OUT NUMBER)
IS
CNT NUMBER:=0;
BEGIN
SELECT COUNT(*) INTO CNT 
FROM EMP
WHERE EMPNO = IEMPNO;

IF CNT = 0 THEN
FLAG:=0;   -- 아이디가 일치하지 않는 경우
ELSE
BEGIN
CNT:=0;
SELECT COUNT(*) INTO CNT
FROM EMP
WHERE EMPNO=IEMPNO AND ENAME=UPPER(IENAME);

IF CNT = 1 THEN
FLAG:=2; --아이디와 비밀번호가 일치하는 경우
ELSE
FLAG:=1;  --아이디는 일치하나 비밀번호가 일치하지 않은 경우
END IF;

END;
END IF;

END;
/

4-3). 트리거

  - 자동으로 실행되는 프로시저의 한 종류. 직접(exec) 실행불가
  - 하나의 테이블에 최대 3개까지 트리거 적용가능
    단, 트리거 많을수록 성능저하 초래 가능성 있다.
  - 트리거 몸체(PL/SQL블락) 안에는 COMMIT;ROLLBACK불가
 
  - :NEW(변경 후) ,:OLD(변경 전) 임시테이블은 행단 위 트리거에서만 사용가능
     트리거 몸체에서 :NEW 및 :OLD의 의미
 타깃 테이블에
 INSERT 실행 시 :OLD는 NULL이고 :NEW은 새로운 입력값이다
 UPDATE 실행시 :OLD는 업데이트 전의 값이고 :NEW은 새로운 변경 값이다
 DELETE 실행시 :OLD는 삭제 전의 값이고 :NEW은 NULL이다
 즉 :OLD는 DELETE 혹은 UPDATE 하기 전의 데이터(변경 전)이고 :NEW는 INSERT 혹은 UPDATE 하려는 데이터(변경 후)이다 
  
  
  - 트리거 종류
  
  1. 트리거몸체(DECLARE~ BEGIN END;절)의 실행 횟수에 따른 분류
  
     문장단위 트리거- 한 번만 실행
     행단 위 트리거   - 행단 위로 변경된 횟수만큼 실행됨 
    
  2. 타이밍에 따른 분류
      BEFORE트리거- 이벤트(I/D/U)발생전 트리거몸체 실행됨
                            예] 판매와 상품(재고) 관계, 보안
      AFTRE트리거  - 이벤트(I/D/U)발생후 트리거몸체 실행됨
                            예] 입고 와 상품(재고) 관계
      
  -트리거 생성
  
  CREATE TRIGGER 트리거명
  타이밍 [BEFORE|AFTER] 이벤트 [INSERT [OR] | UPDATE [OR] DELETE]
  ON 트리거를 걸 테이블명
  [FOR EACH ROW] --생략 시 문장단위 트리거
  [WHEN 트리거 조건]
  DECALRE
  변수 선언
  BEGIN
  
  END;
  /
  -트리거 삭제
  DROP TRIGGER 트리거명
  -특정 트리거 활성화/비활성화
  ALTER TRIGGER 트리거명 [ENABLE/DISABLE]
  - 테이블에 건 모든 트리거 활성화 비활성화
  ALTER TABLE 테이블명  ENABLE/DISABLE  ALL TRIGGERS 
  
  
  ※INSERTING /DELETING/UPDATING 키워드
     PL/SQL블락 안에서 사용하는 상수 
     예] INSERT이벤트가 발생하면 INSERTING 이 TRUE

  ※BEFORE트리거 걸 때 주로 사용하는 함수
    RAISE_APPLICATION_ERROR(에러번호, '에러메시지');
    에러번호는 -20000 ~-20999 사이의 임의의 숫자 지정

 

--트리거를 걸 테이블
CREATE TABLE  TRIGER_TBL(
    NO NUMBER PRIMARY KEY,
    MESSAGE NVARCHAR2(10)
);
--위 테이블에 행이 입력/수정/삭제되면 자동으로 아래 테이블에 어떤 이벤트(I/D/U)가 발생했는지 입력하자
CREATE TABLE TARGET_TBL(
    EVENT NVARCHAR2(10),
    POSTDATE DATE DEFAULT SYSDATE
);

create trigger mytrigger
after insert or update or delete
on TRIGER_TBL
for each row
declare
begin
    if inserting then
        insert into target_tbl values('insert',sysdate);
    elsif deleting then
        insert into target_tbl values('delete',sysdate);
    elsif updating then
        insert into target_tbl values('update',sysdate);
    end if;
end;
/
select * from triger_tbl;
select * from TARGET_TBL;

insert into triger_tbl values(1,'입력이밴트1');
insert into triger_tbl values(2,'입력이밴트2');
insert into triger_tbl values(3,'입력이밴트3');

update triger_tbl set message='inputevent' where no=1;
delete triger_tbl;

drop trigger mytrigger2;
create trigger mytrigger2
before insert 
on triger_tbl
for each row
declare
begin
    if to_char(sysdate,'dy')='수' or to_char(sysdate,'HH24')>=19 then
        raise_application_before(-20001,'화요일 혹은 19시 이후에는 입력불가');
    else
        insert into target_tbl values('입력성공',sysdate);
    end if;
end;
/

insert into triger_tbl values(4,'입력이밴트4');--[x]화요일 혹은 19시 이후에는 입력불가

--상품
CREATE TABLE PRODUCT(
    P_CODE CHAR(4) PRIMARY KEY,
    P_NAME NVARCHAR2(10) NOT NULL,
    P_PRICE NUMBER,
    P_QTY NUMBER DEFAULT 0);--재고수량
--입고
CREATE TABLE INP(
    I_NO NUMBER PRIMARY KEY,
    P_CODE CHAR(4) REFERENCES PRODUCT(P_CODE),
    I_DATE DATE DEFAULT SYSDATE,
    I_QTY NUMBER,
    I_PRICE NUMBER
);
--판매
CREATE TABLE SALES(
    S_NO NUMBER PRIMARY KEY,
    P_CODE CHAR(4) REFERENCES PRODUCT(P_CODE),--판매일련번호
    S_DATE DATE DEFAULT SYSDATE,
    S_QTY NUMBER,--판매수량
    S_PRICE NUMBER
);
SELECT * FROM PRODUCT;
UPDATE PRODUCT SET P_QTY=10 WHERE P_CODE='B001';
SELECT * FROM INP;
SELECT * FROM SALES;

INSERT INTO PRODUCT(P_CODE,P_NAME,P_PRICE) VALUES('B001','자바',2500);
INSERT INTO PRODUCT(P_CODE,P_NAME,P_PRICE) VALUES('B002','스프링',3000);
--입고테이블에 insert 트리거 걸자
--즉 입고되면 삼품테이블의 재고수량 자동증가
drop trigger ipgo_trigger;
create trigger ipgo_trigger
after insert 
on inp
for each row
declare
begin
    update product set p_qty=p_qty +:new.i_qty
    where P_CODE=:new.P_CODE;
end;
/
-- 입고 테이블에 입력하자
INSERT INTO inp(i_no,P_CODE,i_qty,i_price) values(1,'B001',10,2000);
INSERT INTO inp(i_no,P_CODE,i_qty,i_price) values(2,'B001',15,1800);

--입고테이블에 update트리거를 걸자
--즉 입고량이 수정되면 상품 테이블의 재고수량 자동으로 수정
--입고 테이블 입고 수량 수정
update inp set i_qty = 1 where i_no=1;

CREATE TRIGGER IPGO_TRIGGER3
BEFORE INSERT
ON SALES
FOR EACH ROW
DECLARE
    qty NUMBER;--상품의 재고수량 저장
BEGIN
   --재고수량 파악
   SELECT P_QTY INTO QTY FROM PRODUCT WHERE P_CODE = :NEW.P_CODE;
   --재고수량과 판매수량비교
   IF qty < :NEW.s_qty THEN
    RAISE_APPLICATION_ERROR(-20002,'재고가 없어요. 수량이 ' || QTY || '밖에 남자 않았어요');
    ELSE
        --PRODUCT테이블의 재고 수량 수정을 판매수량만큼 뺀다
        update product SET P_QTY = P_QTY - :NEW.S_QTY WHERE P_CODE =:NEW.P_CODE;
    END IF;
END;
/
INSERT INTO SALES(S_NO,P_CODE,S_QTY,S_PRICE) VALUES(1,'B001',9,10000);

 

 

5. 백업과 복원

:백업 및 복원 실행 파일 위치 : [오라클설치된 디렉토리]\product\10.2.0\db_1\BIN
         백업:EXP.EXE
         복원:IMP.EXE

-백업(Export) :데이타와 구조를 바이너리 파일로 저장


dos>exp userid=아이디/비밀번호@전역데이타베이스명 file=저장경로

예]

:system계정으로 전체 백업

dos>exp userid=system/비밀번호@전역데이타베이스명 full=y file=c:\dump.dmp

:system 계정으로 scott 계정에 있는 DB백업

dos>exp userid=system/비밀번호@전역데이타베이스명 owner=scott file=c:\dump.dmp

:scott계정으로 자신의 모든 데이타 백업

dos>exp userid=scott/비밀번호@전역데이타베이스명 file=c:\dump.dmp


:scott계정으로 emp테이블만 백업

dos>exp userid=scott/비밀번호@전역데이타베이스명 file=c:\dump.dmp tables=emp
*여러개 테이블을 동시에 받으려면 tables=(테이블1,테이블2,...)

*백업 파일의 확장자는 보통 .dmp 혹은 .dat .bak으로 한다 한다.

-복원(Import)

imp 아이디/비밀번호@전역데이타베이스명 file=백업경로


예]

:system계정으로 전체 복원


dos>imp system/비밀번호@전역데이타베이스명 file=c:\dump.dmp


:system 계정으로 scott 계정에 있는 DB복원

dos>imp system/비밀번호@전역데이타베이스명 fromuser=scott touser=scott file=c:\dump.dmp

:scott계정으로 자신의 모든 데이타 복원

dos>imp scott/비밀번호@전역데이타베이스명 file=c:\dump.dmp


:복원하고자하는 DB에 같은 이름의 Object가 있을때,오류를 무시하고 건너 띄고 싶을때 ignore 옵션사용

dos>imp 아이디/비밀번호@전역데이타베이스명 file=c:\dump.dmp ignore=y

:system계정으로 들어가 scott에서 Export한 데이터를 scott2에게 Import

dos>imp system/비밀번호@전역데이타베이스명 fromuser=scott touser=scott2 file=c:\dump.dmp

 

 

 

 

 

 

 

 

 

 

 

'oracle' 카테고리의 다른 글

24일차 2023-04-10  (0) 2023.04.10
23일차 2023-04-07  (0) 2023.04.07
22일차 2023-04-06  (0) 2023.04.06
21일차 2023-04-05  (0) 2023.04.05