Oracle PL/SQL 트리거 튜토리얼: 복합 대신 [예]

PL/SQL의 트리거란 무엇입니까?

트리거 다음에 의해 실행되는 저장된 프로그램입니다. Oracle 테이블에서 insert, update, delete와 같은 DML 문이 실행되거나 일부 이벤트가 발생하면 엔진이 자동으로 실행됩니다. 트리거 발생 시 실행될 코드는 요구 사항에 따라 정의할 수 있습니다. 트리거가 실행되어야 하는 이벤트와 실행 타이밍을 선택할 수 있습니다. 트리거의 목적은 데이터베이스의 정보 무결성을 유지하는 것입니다.

트리거의 이점

트리거의 이점은 다음과 같습니다.

  • 일부 파생 열 값을 자동으로 생성
  • 참조 무결성 강화
  • 테이블 접근에 대한 이벤트 로깅 및 정보 저장
  • 감사
  • Sync테이블의 동시 복제
  • 보안 인증 부과
  • 잘못된 거래 방지

트리거 유형 Oracle

트리거는 다음 매개변수를 기준으로 분류할 수 있습니다.

  • 에 따른 분류 타이밍
  • BEFORE 트리거: 지정된 이벤트가 발생하기 전에 실행됩니다.
  • AFTER 트리거: 지정된 이벤트가 발생한 후에 실행됩니다.
  • INSTEAD OF Trigger: 특별한 유형입니다. 추가 주제에 대해 자세히 알아보게 됩니다. (DML에만 해당)
  • 에 따른 분류 수평
  • STATEMENT 수준 트리거: 지정된 이벤트 문에 대해 한 번 실행됩니다.
  • ROW 수준 트리거: 지정된 이벤트에서 영향을 받은 각 레코드에 대해 실행됩니다. (DML에만 해당)
  • 에 따른 분류 이벤트
  • DML 트리거: DML 이벤트가 지정되면 실행됩니다(INSERT/UPDATE/DELETE).
  • DDL 트리거: DDL 이벤트가 지정될 때 발생합니다(CREATE/ALTER).
  • DATABASE 트리거: 데이터베이스 이벤트가 지정되면 실행됩니다(LOGON/LOGOFF/STARTUP/SHUTDOWN).

따라서 각 트리거는 위 매개변수의 조합입니다.

트리거를 만드는 방법

다음은 트리거를 생성하는 구문입니다.

트리거 만들기

CREATE [ OR REPLACE ] TRIGGER <trigger_name> 

[BEFORE | AFTER | INSTEAD OF ]

[INSERT | UPDATE | DELETE......]

ON<name of underlying object>

[FOR EACH ROW] 

[WHEN<condition for trigger to get execute> ]

DECLARE
<Declaration part>
BEGIN
<Execution part> 
EXCEPTION
<Exception handling part> 
END;

구문 설명:

  • 위 구문은 트리거 생성에 존재하는 다양한 선택적 문을 보여줍니다.
  • BEFORE/AFTER는 이벤트 타이밍을 지정합니다.
  • 삽입/업데이트/로그온/만들기/등. 트리거가 실행되어야 하는 이벤트를 지정합니다.
  • ON 절은 위에서 언급한 이벤트가 유효한 개체를 지정합니다. 예를 들어 DML Trigger의 경우 DML 이벤트가 발생할 수 있는 테이블 이름이 됩니다.
  • "FOR EACH ROW" 명령은 ROW 레벨 트리거를 지정합니다.
  • WHEN 절은 트리거가 실행되어야 하는 추가 조건을 지정합니다.
  • 선언부분, 실행부분, 예외처리 부분은 나머지 부분과 동일합니다. PL/SQL 블록. 선언 부분과 예외 처리 부분은 선택 사항입니다.

:NEW 및 :OLD 절

행 수준 트리거에서는 관련된 각 행에 대해 트리거가 실행됩니다. 그리고 때로는 DML 문 전후의 값을 알아야 할 때도 있습니다.

Oracle 이러한 값을 보유하기 위해 RECORD 수준 트리거에 두 개의 절을 제공했습니다. 이러한 절을 사용하여 트리거 본문 내부의 이전 값과 새 값을 참조할 수 있습니다.

  • :NEW – 트리거 실행 중에 기본 테이블/뷰의 열에 대한 새 값을 보유합니다.
  • :OLD – 트리거 실행 중 기본 테이블/뷰 열의 이전 값을 보유합니다.

이 절은 DML 이벤트를 기준으로 사용해야 합니다. 아래 표에서는 어떤 DML 문(INSERT/UPDATE/DELETE)에 어떤 절이 유효한지 지정합니다.

INSERT UPDATE 삭제
:새로운 유효한 유효한 유효하지 않은. 삭제 케이스에는 새로운 값이 없습니다.
:오래된 유효하지 않은. 삽입 케이스에 이전 값이 없습니다. 유효한 유효한

트리거 대신

"INSTEAD OF 트리거"는 특수 유형의 트리거입니다. DML 트리거에서만 사용됩니다. 복잡한 뷰에서 DML 이벤트가 발생할 때 사용됩니다.

3개의 기본 테이블에서 뷰가 생성되는 예를 생각해 보세요. 이 뷰에 대해 DML 이벤트가 발생하면 데이터가 3개의 다른 테이블에서 가져오기 때문에 유효하지 않게 됩니다. 따라서 이 INSTEAD OF 트리거가 사용됩니다. INSTEAD OF 트리거는 지정된 이벤트에 대한 뷰를 수정하는 대신 기본 테이블을 직접 수정하는 데 사용됩니다.

예제 1: 이 예제에서는 두 개의 기본 테이블에서 복잡한 뷰를 만들어 보겠습니다.

  • Table_1은 빈 테이블이고
  • Table_2는 부서 테이블입니다.

그런 다음 INSTEAD OF 트리거를 사용하여 이 복잡한 뷰에서 위치 세부 정보 문을 UPDATE하는 방법을 살펴보겠습니다. 또한 :NEW 및 :OLD가 트리거에서 어떻게 유용한지 살펴보겠습니다.

  • 1단계: 적절한 열을 사용하여 'emp' 및 'dept' 테이블 만들기
  • 2단계: 샘플 값으로 테이블 채우기
  • 3단계: 위에서 생성된 테이블에 대한 뷰 생성
  • 4단계: 대신 트리거 이전의 뷰 업데이트
  • 5단계: 대체 트리거 생성
  • 6단계: 트리거 대신 보기 업데이트

단계 1) 적절한 열을 사용하여 'emp' 및 'dept' 테이블 만들기

트리거 대신

CREATE TABLE emp(
emp_no NUMBER,
emp_name VARCHAR2(50),
salary NUMBER,
manager VARCHAR2(50),
dept_no NUMBER);
/

CREATE TABLE dept( 
Dept_no NUMBER, 
Dept_name VARCHAR2(50),
LOCATION VARCHAR2(50));
/

코드 설명

  • 코드 라인 1-7: 테이블 'emp' 생성.
  • 코드 라인 8-12: 테이블 'dept' 생성.

산출

테이블이 생성되었습니다.

단계 2) 이제 테이블을 만들었으므로 이 테이블을 위 테이블에 대한 샘플 값과 뷰 생성으로 채웁니다.

트리거 대신

BEGIN
INSERT INTO DEPT VALUES(10,‘HR’,‘USA’);
INSERT INTO DEPT VALUES(20,'SALES','UK’);
INSERT INTO DEPT VALUES(30,‘FINANCIAL',‘JAPAN'); 
COMMIT;
END;
/

BEGIN
INSERT INTO EMP VALUES(1000,'XXX5,15000,'AAA',30);
INSERT INTO EMP VALUES(1001,‘YYY5,18000,‘AAA’,20) ;
INSERT INTO EMP VALUES(1002,‘ZZZ5,20000,‘AAA',10); 
COMMIT;
END;
/

코드 설명

  • 코드 라인 13-19: 'dept' 테이블에 데이터를 삽입합니다.
  • 코드 라인 20-26: 'emp' 테이블에 데이터를 삽입합니다.

산출

PL/SQL 프로시저 완료

단계 3) 위에서 생성된 테이블에 대한 뷰를 생성합니다.

트리거 대신

CREATE VIEW guru99_emp_view(
Employee_name:dept_name,location) AS
SELECT emp.emp_name,dept.dept_name,dept.location
FROM emp,dept
WHERE emp.dept_no=dept.dept_no;
/
SELECT * FROM guru99_emp_view;

코드 설명

  • 코드 라인 27-32: 'guru99_emp_view' 뷰 생성.
  • 코드 라인 33: guru99_emp_view를 쿼리하는 중입니다.

산출

뷰가 생성되었습니다.

EMPLOYEE_NAME DEPT_NAME 주소
Zzz HR 한국
YYY 매상 UK
트리플 엑스 금융 일본

단계 4) 트리거 대신 보기 전의 업데이트입니다.

트리거 대신

BEGIN
UPDATE guru99_emp_view SET location='FRANCE' WHERE employee_name=:'XXX’;
COMMIT;
END;
/

코드 설명

  • 코드 라인 34-38: 'XXX'의 위치를 ​​'FRANCE'로 업데이트하세요. 예외가 발생했습니다. DML 문 복잡한 뷰에서는 허용되지 않습니다.

산출

ORA-01779: 키 보존되지 않은 테이블에 매핑하는 열을 수정할 수 없습니다

ORA-06512: 라인 2에

단계 5)이전 단계에서 뷰를 업데이트하는 동안 오류 발생을 방지하기 위해 이 단계에서는 "트리거 대신"을 사용하겠습니다.

트리거 대신

CREATE TRIGGER guru99_view_modify_trg
INSTEAD OF UPDATE
ON guru99_emp_view
FOR EACH ROW
BEGIN
UPDATE dept
SET location=:new.location
WHERE dept_name=:old.dept_name;
END;
/

코드 설명

  • 코드 라인 39: ROW 수준의 'guru99_emp_view' 뷰에서 'UPDATE' 이벤트에 대한 INSTEAD OF 트리거를 생성합니다. 여기에는 기본 테이블 'dept'의 위치를 ​​업데이트하는 업데이트 문이 포함되어 있습니다.
  • 코드 라인 44: 업데이트 문은 ':NEW' 및 ':OLD'를 사용하여 업데이트 전후의 열 값을 찾습니다.

산출

트리거가 생성되었습니다.

단계 6) 트리거 대신 뷰 업데이트. 이제 "트리거 대신"이 이 복잡한 뷰의 업데이트 작업을 처리하기 때문에 오류가 발생하지 않습니다. 그리고 코드가 실행되면 직원 XXX의 위치가 "일본"에서 "프랑스"로 업데이트됩니다.

트리거 대신

BEGIN
UPDATE guru99_emp_view SET location='FRANCE' WHERE employee_name='XXX'; 
COMMIT;
END;
/
SELECT * FROM guru99_emp_view;

코드 설명 :

  • 코드 라인 49-53: 'XXX'의 위치를 ​​'FRANCE'로 업데이트했습니다. 'INSTEAD OF' 트리거가 뷰의 실제 업데이트 문을 중지하고 기본 테이블 업데이트를 수행했기 때문에 성공한 것입니다.
  • 코드 라인 55: 업데이트된 기록을 확인하는 중입니다.

출력:

PL/SQL 프로시저가 성공적으로 완료되었습니다.

EMPLOYEE_NAME DEPT_NAME 주소
Zzz HR 한국
YYY 매상 UK
트리플 엑스 금융 프랑스

복합 트리거

복합 트리거는 단일 트리거 본체의 XNUMX개 타이밍 지점 각각에 대한 작업을 지정할 수 있는 트리거입니다. 지원하는 네 가지 타이밍 지점은 다음과 같습니다.

  • 진술 전 – 수준
  • 행 앞 - 수준
  • 행 이후 – 수준
  • AFTER STATEMENT – 레벨

이는 서로 다른 타이밍에 대한 작업을 동일한 트리거로 결합하는 기능을 제공합니다.

복합 트리거

CREATE [ OR REPLACE ] TRIGGER <trigger_name> 
FOR
[INSERT | UPDATE | DELET.......]
ON <name of underlying object>
<Declarative part>‭	‬
BEFORE STATEMENT IS
BEGIN
<Execution part>;
END BEFORE STATEMENT;

BEFORE EACH ROW IS
BEGIN
<Execution part>;
END EACH ROW;

AFTER EACH ROW IS
BEGIN
<Execution part>;
END AFTER EACH ROW;

AFTER STATEMENT IS
BEGIN
<Execution part>;
END AFTER STATEMENT;
END;

구문 설명:

  • 위 구문은 'COMPOUND' 트리거 생성을 보여줍니다.
  • 선언 섹션은 트리거 본문의 모든 실행 블록에 공통됩니다.
  • 이 4개의 타이밍 블록은 어떤 순서로든 있을 수 있습니다. 이 4개의 타이밍 블록을 모두 보유하는 것이 필수는 아닙니다. 필요한 타이밍에 대해서만 COMPOUND 트리거를 생성할 수 있습니다.

예제 1: 이 예에서는 급여 열을 기본값 5000으로 자동 채우는 트리거를 생성하겠습니다.

복합 트리거

CREATE TRIGGER emp_trig 
FOR INSERT 
ON emp
COMPOUND TRIGGER 
BEFORE EACH ROW IS 
BEGIN
:new.salary:=5000;
END BEFORE EACH ROW;
END emp_trig;
/
BEGIN
INSERT INTO EMP VALUES(1004,‘CCC’,15000,‘AAA’,30); 
COMMIT;
END;
/
SELECT * FROM emp WHERE emp_no=1004;

코드 설명 :

  • 코드 라인 2-10: 복합 트리거 생성. 급여를 기본값 5000으로 채우기 위해 BEFORE ROW 수준의 타이밍에 대해 생성됩니다. 이렇게 하면 레코드를 테이블에 삽입하기 전에 급여가 기본값 '5000'으로 변경됩니다.
  • 코드 라인 11-14: 'emp' 테이블에 레코드를 삽입합니다.
  • 코드 라인 16: 삽입된 레코드를 확인하는 중입니다.

출력:

트리거가 생성되었습니다.

PL/SQL 프로시저가 성공적으로 완료되었습니다.

EMP_NAME EMP_NO 봉급 MANAGER DEPT_NO
CCC 1004 5000 AAA 30

트리거 활성화 및 비활성화

트리거를 활성화하거나 비활성화할 수 있습니다. 트리거를 활성화하거나 비활성화하려면 트리거를 비활성화하거나 활성화하는 트리거에 대해 ALTER(DDL) 문을 제공해야 합니다.

다음은 트리거를 활성화/비활성화하는 구문입니다.

ALTER TRIGGER <trigger_name> [ENABLE|DISABLE];
ALTER TABLE <table_name> [ENABLE|DISABLE] ALL TRIGGERS;

구문 설명:

  • 첫 번째 구문은 단일 트리거를 활성화/비활성화하는 방법을 보여줍니다.
  • 두 번째 문은 특정 테이블의 모든 트리거를 활성화/비활성화하는 방법을 보여줍니다.

제품 개요

이 장에서는 PL/SQL 트리거와 그 장점에 대해 배웠습니다. 또한 다양한 분류에 대해 알아보고 INSTEAD OF 트리거와 COMPOUND 트리거에 대해 논의했습니다.