Professional Documents
Culture Documents
2 Chuong2 PL SQL
2 Chuong2 PL SQL
Procedural Language/Structured
Query Language (PL/SQL)
Ưu điểm của PL/SQL
• Tích hợp chặt chẽ với SQL.
• Hiệu suất cao.
• Bảo mật chặt chẽ.
Phân quyền người được tác động lên khối lệnh
2
Các tính năng chính của PL/SQL
• Khối lệnh PL/SQL
• Biến và hằng số trong PL/SQL
• Cấu trúc điều khiển trong PL/SQL
• Quản lý lỗi trong PL/SQL
• Chương trình con PL/SQL (Subprogram)
• PL/SQL Packages
3
PL/SQL Block
DECLARE -- Declarative part (optional)
Declarations of local types, variables, & subprograms
4
Các tính năng chính của PL/SQL
• Khối lệnh PL/SQL
• Biến và hằng số trong PL/SQL
• Cấu trúc điều khiển trong PL/SQL
• Quản lý lỗi trong PL/SQL
• Chương trình con PL/SQL (Subprogram)
• PL/SQL Packages
5
Khai báo biến trong PL/SQL
• Biến trong PL/SQL có thể là bất kỳ kiểu dữ liệu nào được sử dụng trong SQL
(chẳng hạn char, date, number…) hoặc kiểu dữ liệu chỉ có ở PL/SQL (chẳng hạn
boolean, pls_integer).
DECLARE
part_number NUMBER(6); -- SQL data type
part_name VARCHAR2(20); -- SQL data type
in_stock BOOLEAN; -- PL/SQL-only data type
part_price NUMBER(6,2); -- SQL data type
part_description VARCHAR2(50); -- SQL data type
BEGIN
NULL;
END;
6
Gán giá trị cho biến
• Để gán giá trị cho biến ta có thể sử dụng các cách sau:
• Sử dụng toán tử gán :=
• Bằng cách selecting (hoặc fetching) dữ liệu.
• Bằng cách truyền cho nó như là một đối số OUT hoặc IN OUT trong chương
trình con (subprogram), rồi sau đó gán giá trị trong subprogram.
• Khai báo một hằng số giống như khai báo biến ngoại trừ việc phải
thêm từ khóa CONSTANT và ngay lập tức gán giá trị cho hằng số này.
• credit_limit CONSTANT NUMBER := 5000.00;
7
Các tính năng chính của PL/SQL
• Khối lệnh PL/SQL
• Biến và hằng số trong PL/SQL
• Cấu trúc điều khiển trong PL/SQL
• Quản lý lỗi trong PL/SQL
• Chương trình con PL/SQL (Subprogram)
• PL/SQL Packages
8
Cấu trúc điều khiển trong PL/SQL
• Quản lý điều kiện (Conditional Control)
• Quản lý lặp (Iterative Control)
• Quản lý tuần tự (Sequential Control)
9
Quản lý điều kiện (Conditional Control)
DECLARE
• sales NUMBER(8,2) := 20000;
bonus NUMBER(6,2);
emp_id NUMBER(6) := 120;
BEGIN
IF sales > 50000 THEN
bonus := 1500;
ELSIF sales > 35000 THEN
bonus := 500;
ELSE
bonus := 100;
END IF;
UPDATE employees SET salary = salary + bonus
WHERE employee_id = emp_id;
END;
10
Cấu trúc điều khiển trong PL/SQL
• Quản lý điều kiện (Conditional Control)
• Quản lý lặp (Iterative Control)
• Quản lý tuần tự (Sequential Control)
11
Quản lý lặp
Sử dụng FOR-LOOP Statement
• Trong một FOR loop, biến đếm có thể dùng để đọc nhưng không thể thay đổi, ví
dụ:
BEGIN
FOR i IN 1..3 LOOP
IF i < 3 THEN
DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
ELSE
i := 2; --ERROR Không thể thay đổi giá trị của i
END IF;
END LOOP;
END;
12
Cấu trúc điều khiển trong PL/SQL
• Quản lý điều kiện (Conditional Control)
• Quản lý lặp (Iterative Control)
• Quản lý tuần tự (Sequential Control)
13
Quản lý tuần tự
Sử dụng GOTO Statement
DECLARE
p VARCHAR2(30);
n PLS_INTEGER := 37;
BEGIN
FOR j in 2..ROUND(SQRT(n)) LOOP
IF n MOD j = 0 THEN
p := ' is not a prime number';
GOTO print_now;
END IF;
END LOOP;
p := ' is a prime number';
<<print_now>>
DBMS_OUTPUT.PUT_LINE(TO_CHAR(n) || p);
END;
14
Các tính năng chính của PL/SQL
• Khối lệnh PL/SQL
• Biến và hằng số trong PL/SQL
• Cấu trúc điều khiển trong PL/SQL
• Quản lý lỗi trong PL/SQL
• Chương trình con PL/SQL (Subprogram)
• PL/SQL Packages
15
Quản lý lỗi trong PL/SQL
Exception được định nghĩa sẵn
16
Quản lý lỗi trong PL/SQL
• DECLARE
stock_price NUMBER := 9.73;
net_earnings NUMBER := 0;
pe_ratio NUMBER;
BEGIN
-- Calculation might cause division-by-zero error.
pe_ratio := stock_price / net_earnings;
DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);
EXCEPTION -- exception handlers begin Only one of the WHEN blocks is executed.
WHEN ZERO_DIVIDE THEN -- handles 'division by zero' error
DBMS_OUTPUT.PUT_LINE('Company must have had zero earnings.');
pe_ratio := NULL;
WHEN OTHERS THEN -- handles all other errors
DBMS_OUTPUT.PUT_LINE('Some other kind of error occurred.');
pe_ratio := NULL;
END; -- exception handlers and block end here
17
Quản lý lỗi trong PL/SQL
• Ta có thể tránh exception bằng cách kiểm tra mẫu số trước
DECLARE
stock_price NUMBER := 9.73;
net_earnings NUMBER := 0;
pe_ratio NUMBER;
BEGIN
IF(net_earnings = 0) THEN
pe_ratio:=NULL;
ELSE net_earnings
pe_ratio:= stock_price / net_earnings;
END IF;
END;
18
Quản lý lỗi trong PL/SQL
DECLARE EMPLOYEE
id char(5) := 10009;
Name varchar2(50); empId empName address
add varchar2(10); 10001 John US
BEGIN
10002 Mary US
SELECT empName, address INTO name, add
FROM EMPLOYEE 10003 Micheal UK
WHERE empId=id 10004 Henry GER
Trong khối lệnh select phải gán biến, select without into -> lỗi do select không có mục đích
EXCEPTION
-- Catches all 'no data found' errors
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('No Data found for employee ' || id);
END;
19
Quản lý lỗi trong PL/SQL
• --Tự khai báo exception
DECLARE
out_of_stock EXCEPTION;
number_on_hand NUMBER := 0;
BEGIN
IF number_on_hand < 1 THEN
RAISE out_of_stock; -- raise an exception that you defined
………
……….
END IF;
EXCEPTION
-- handle the error
WHEN out_of_stock THEN
DBMS_OUTPUT.PUT_LINE('Encountered out-of-stock error.');
END;
20
Các tính năng chính của PL/SQL
• Khối lệnh PL/SQL
• Biến và hằng số trong PL/SQL
• Cấu trúc điều khiển trong PL/SQL
• Quản lý lỗi trong PL/SQL
• Chương trình con PL/SQL (Subprogram)
• PL/SQL Packages
21
Tổng quan về chương trình con
• Một chương trình con (PL/SQL subprogram) chính là một khối lệnh
PL/SQL được đặt tên và được gọi với một tập các đối số.
• Một chương trình con có thể là một thủ tục (procedure) hoặc là một
hàm (function).
• Thông thường, procedure được sử dụng để thực hiện một tác vụ nào
đó còn function được sử dụng để tính toán và trả về kết quả.
• Chương trình con có thể được tạo ở mức schema, trong một package,
hay trong một khối lệnh PL/SQL.
22
Chương trình con
trong một khối lệnh PL/SQL
DECLARE
in_string VARCHAR2(100) := 'Test string';
23
Chương trình con ở mức schema
(Standalone subprogram)
CREATE OR REPLACE PROCEDURE remove_emp (employee_id NUMBER) AS
tot_emps NUMBER;
BEGIN
DELETE FROM employees
WHERE employees.employee_id = employee_id;
--tot_emps := tot_emps - 1;
END;
CREATE OR REPLACE FUNCTION get_bal(acc_no IN NUMBER)
RETURN NUMBER IS
acc_bal NUMBER(11,2); --declare acc_bal
BEGIN
SELECT order_total INTO acc_bal
FROM orders
WHERE customer_id = acc_no;
DBMS_OUTPUT.PUT_LINE (TO_CHAR(acc_no));
RETURN(acc_bal);
24
END;
Các phần trong một chương trình con
PROCEDURE double (original IN VARCHAR2, new_string OUT VARCHAR2)
IS
-- Declarative part of procedure (optional) goes here
BEGIN
-- Executable part of procedure begins
new_string := original || ' + ' || original;
-- Executable part of procedure ends
25
Các phần trong một chương trình con
• Một thủ tục (procedure) và một hàm (function) có cùng cấu trúc, ngoại
trừ:
• Phần đầu của function phải chứa mệnh đề RETURN (return clause) xác định
kiểu dữ liệu trả về. Còn procedure không chứa mệnh đề RETURN này.
• Một function phải chứa ít nhất một câu lệnh RETURN (return statement) trong
phần thực thi. Trong procedure, câu lệnh RETURN không bắt buộc.
26
Chương trình con
Ví dụ
PROCEDURE raise_salary ( emp_id NUMBER, amount NUMBER)
IS
BEGIN
IF emp_id IS NULL THEN
RETURN; return statement
END IF;
UPDATE employees SET salary = salary + amount WHERE employee_id = emp_id;
END raise_salary;
28
Đối số trong chương trình con
sử dụng IN
• Đối số IN cho phép truyền giá trị tới chương trình con.
• Trong một chương trình con, đối số IN hoạt động giống như một hằng
số. Nó không được gán giá trị.
• Đối số IN có thể được khởi tạo một giá trị mặc định.
29
Đối số trong chương trình con
sử dụng IN
PROCEDURE debit_account (acct_id INTEGER, amount IN REAL) IS
service_charge REAL;
BEGIN
service_charge := amount + 100;
amount := amount + 5; error
...
END debit_account;
BEGIN
debit_account (100034, 20);
END;
30
Đối số trong chương trình con
sử dụng IN-truyền đối số mặc định
PROCEDURE Get_emp_names (Dept_num IN NUMBER DEFAULT 20) IS ...
31
Đối số trong chương trình con
sử dụng OUT
• Đối số OUT trả về giá trị tới môi trường gọi nó.
• Trong chương trình con, đối số OUT hoạt động như là một biến
(variable).
• Có thể thay đổi giá trị của nó và sử dụng giá trị này sau khi gán.
32
Đối số trong chương trình con
sử dụng OUT
CREATE PROCEDURE square (val IN NUMBER, resultval OUT NUMBER)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE (resultval );
resultval := val*val;
END;
SET SERVEROUTPUT ON
DECLARE
v_kq NUMBER := 200;
BEGIN
square (5, v_kq); --gọi chương trình con, đối số là OUT trả kết quả về
-- môi trường gọi nó thông qua biến v_kq
DBMS_OUTPUT.PUT_LINE (v_kq);
END;
33
Đối số trong chương trình con
sử dụng IN OUT
• Đối số IN OUT truyền giá trị khởi tạo tới chương trình con và trả về
một giá trị mới cho môi trường gọi nó.
• Đối số IN OUT phải là một biến, không được là hằng số hay một biểu
thức.
34
Đối số trong chương trình con
sử dụng IN OUT
CREATE PROCEDURE square (val IN OUT NUMBER) IS
BEGIN
val := val*val;
END;
SET SERVEROUTPUT ON
DECLARE
v_init NUMBER;
BEGIN
v_init := 5;
square (v_init);
DBMS_OUTPUT.PUT_LINE (v_init);
END;
35
Các tính năng chính của PL/SQL
• Khối lệnh PL/SQL
• Biến và hằng số trong PL/SQL
• Cấu trúc điều khiển trong PL/SQL
• Quản lý lỗi trong PL/SQL
• Chương trình con PL/SQL (Subprogram)
• PL/SQL Packages
36
PL/SQL Package là gì?
• Là một tập hợp các PL/SQL object được nhóm lại tạo thành một gói.
• Chúng có thể chứa:
• Procedures, functions
• Types, cursors, variables, constants
• Exceptions
37
Cấu trúc của Package
• Có 2 phần:
• Phần mô tả (specification):
• Khai báo các public item (procedure, function, variable...).
• Các chương trình khác có thể truy xuất đến chúng từ ngoài package.
• Phần thân (body)
• Hiện thực các public item. Đồng thời nó cũng có thể chứa các private item.
• Các đơn vị private này chỉ có thể truy xuất trong tầm vực của package.
38
Package specification và body
CREATE PACKAGE emp_actions AS
/* Declare externally visible types, cursor, exception. */
TYPE EmpRecTyp IS RECORD (emp_id INT, salary REAL);
invalid_salary EXCEPTION;
/* Declare externally callable subprograms. */
PROCEDURE raise_salary (emp_id INT, grade INT);
END emp_actions;
40
Ví dụ (Package Body)
CREATE OR REPLACE PACKAGE BODY empMgmt
IS
• PROCEDURE sal_raise (amount NUMBER, depNo NUMBER)
IS
BEGIN
update staff set salary=salary+amount where deptId =depNo;
END sal_raise;
---------------------------------------------
FUNCTION salDep_sum (depNo IN NUMBER)
RETURN NUMBER
IS
sal number;
BEGIN
select sum(salary) into sal from staff where deptId= depNo;
RETURN sal ;
END salDep_sum;
END empMgmt; 41
Gọi các phần tử trong package
• package elements (variables, procedures or functions) được truy cập
theo cú pháp sau:
package_name.element_name;
• Ví dụ: gọi hàm sal_raise trong package empMgmt
DECLARE
amt NUMBER := 500;
depId NUMBER :=101;
BEGIN
empMgmt.sal_raise (amt, depId);
END;
42
Xóa Package
• Để xóa toàn bộ package bao gồm specification và body sử dụng cú
pháp:
• DROP PACKAGE package_name
• Chỉ xóa package body sử dụng cú pháp: F
43
Ví dụ
• Tạo một package quản lý nhân viên bao gồm các thao tác: thêm nhân
viên, xóa nhân viên, tăng lương cho nhân viên
CREATE OR REPLACE PACKAGE Employee_management AS -- package specification
FUNCTION Hire_emp
(Name VARCHAR2, Job VARCHAR2, Mgr NUMBER,
Hiredate DATE, Sal NUMBER, Comm NUMBER, Deptno NUMBER)
RETURN NUMBER;
44
CREATE PACKAGE BODY Employee_management AS
FUNCTION Hire_emp (Name VARCHAR2, Job VARCHAR2, Mgr NUMBER, Hiredate DATE,
Sal NUMBER, Comm NUMBER, Deptno NUMBER) RETURN NUMBER IS
New_empno NUMBER(10);
BEGIN
SELECT Emp_sequence.NEXTVAL INTO New_empno FROM dual;
INSERT INTO Emp_tab VALUES (New_empno, Name, Job, Mgr, Hiredate, Sal, Comm, Deptno);
RETURN (New_empno);
END Hire_emp;
46
Tổng quan về trigger
• Trigger là một đơn vị chương trình lưu trữ trong database và thực thi
(fire) để đáp ứng một sự kiện nào đó.
• Sự kiện này được kết hợp với một table, view, schema, hoặc database,
và là một trong những sự kiện sau:
• Một câu lệnh DML (DELETE, INSERT, hoặc UPDATE).
• Một câu lệnh DDL (CREATE, ALTER, DROP)
• Một tác vụ trên database (SERVERERROR, LOGON, LOGOFF, STARTUP,
hoặc SHUTDOWN).
47
Sự khác biệt giữa trigger và constraint (ràng
buộc)
• Cả trigger và contraint đều ràng buộc dữ liệu đầu vào, nhưng chúng có
những điểm khác biệt đáng kể:
• Trigger chỉ áp dụng cho dữ liệu mới.
• Constraint có thể áp dụng cho dữ liệu mới hoặc cả dữ liệu cũ và dữ liệu mới
• Trigger có thể tuân theo những quy tắc phức tạp mà constraint không thể.
48
Simple DML trigger
• Simple DML trigger kích hoạt duy nhất ở một trong những thời điểm
sau:
• Trước khi câu lệnh thực thi
(BEFORE statement trigger hay statement-level BEFORE trigger)
• Sau khi câu lệnh thực thi
(AFTER statement trigger hay statement-level AFTER trigger)
• Trước mỗi dòng (row) mà câu lệnh tác động
(BEFORE each row trigger hay row-level BEFORE trigger).
• Sau mỗi dòng (row) mà câu lệnh tác động
(AFTER each row trigger hay row-level AFTER trigger).
49
Compound DML trigger
• Compound DML trigger có thể kích hoạt tại một thời điểm, một vài
thời điểm hoặc tất cả các thời điểm.
• Compound trigger giúp ích cách tiếp cận trong việc chia sẻ dữ liệu ở
các thời điểm khác nhau (timing point).
50
DML Trigger
• DML trigger được tạo trên table hoặc view và nó bắt các sự kiện
INSERT, DELETE, UPDATE.
• DML trigger có thể là trigger đơn (simple) hoặc trigger phức hợp
(compound).
51
Thứ tự kích hoạt trigger (DML trigger)
52
Thứ tự kích hoạt trigger (ví dụ)
Giả sử ta có 4 SIMPLE DML trigger được tạo trên table NHANVIEN (với phần thực thi là null)
BEFORE statement trigger
AFTER statement trigger
BEFORE each row trigger
AFTER each row trigger
Thực thi câu lệnh:
UPDATE nhanvien SET luong = luong + 10 WHERE diachi = ‘Q11’;
54
Tạo trigger
Ví dụ
•
CREATE TRIGGER Print_trigger_type _biu_s CREATE TRIGGER Print_trigger_type _aiu
BEFORE INSERT OR UPDATE ON emp AFTER INSERT OR UPDATE ON emp
BEGIN FOR EACH ROW
dbms_output.put_line('call before statement'); BEGIN
END; dbms_output.put_line('call after each row');
END;
55
Vị từ điều kiện trong trigger
Vị từ điều kiện TRUE nếu và chỉ nếu:
INSERTING Một câu lệnh INSERT kích hoạt trigger
UPDATING ('column') Một câu lệnh UPDATE tác động trên một
column cụ thể nào đó kích hoạt trigger.
56
Vị từ điều kiện trong trigger
Ví dụ
CREATE OR REPLACE TRIGGER t
BEFORE
INSERT OR
UPDATE OF salary, department_id OR
DELETE
ON employees
BEGIN
CASE
WHEN INSERTING THEN
DBMS_OUTPUT.PUT_LINE('Inserting');
WHEN UPDATING('salary') THEN
DBMS_OUTPUT.PUT_LINE('Updating salary');
WHEN UPDATING('department_id') THEN
DBMS_OUTPUT.PUT_LINE('Updating department ID');
WHEN DELETING THEN
DBMS_OUTPUT.PUT_LINE('Deleting');
END CASE;
END;
57
Old và New
• Khi row-trigger kích hoạt, có 2 dữ liệu ảo được tạo, gọi là new và old.
• new table_name%ROWTYPE;
• old table_name%ROWTYPE;
• Old và new có kiểu dữ liệu ROWTYPE từ table bị tác động. Sử
dụng dấu chấm (.) để tham chiếu đến column từ old và new.
Triggering Statement OLD.field Value NEW.field Value
NHANVIEN
MANV HOTEN DIACHI LUONG
:old.luong = 20
BEFORE each row
:new.luong = 30
1 NGUYEN VAN A Q11 20
30 thực thi Update set luong = :NEW.luong
2 NGUYEN VAN B Q8 50
60
Thực thi câu lệnh:
UPDATE nhanvien SET luong= luong + 10 WHERE diachi = ‘Q11’;
NHANVIEN
MANV HOTEN DIACHI LUONG
:old.luong = 20
BEFORE each row
• :new.luong = 30
sal_diff := :NEW.luong - :OLD.luong;
dbms_output.put('Old salary: ' || OLD. luong );
1 A Q11 20 dbms_output.put(' New salary: ' || :NEW. luong );
dbms_output.put_line(' Difference ' || sal_diff);
2 B Q8 50
:old.luong = 75
BEFORE each row
:new.luong = 85
sal_diff := :NEW.luong - :OLD.luong;
dbms_output.put('Old salary: ' || OLD. luong );
3 C Q11 75 dbms_output.put(' New salary: ' || :NEW. luong );
dbms_output.put_line(' Difference ' || sal_diff);
62
Thực thi câu lệnh:
UPDATE nhanvien SET luong = luong + 10 WHERE diachi = ‘Q11’;
2 B Q8 50
67
Aborting Triggers with Error
Ví dụ
• Viết trigger đảm bảo mỗi khi tăng lương của nhân viên thì lương mới không được
thấp hơn lương cũ.Nếu tồn tại một trường hợp nào đó mà lương mới thấp hơn
lương cũ thì báo lỗi.
CREATE OR REPLACE TRIGGER nhanvien_tangluong
BEFORE UPDATE OF luong ON nhanvien
FOR EACH ROW
BEGIN
IF (:NEW.luong < :OLD.luong) THEN
RAISE_APPLICATION_ERROR(-20000, 'luong moi khong duoc thap
hon luong cu');
END IF;
END;
68
Aborting Triggers with Error
Ví dụ
• Viết trigger đảm bảo tuổi vào làm của nhân viên không được nhỏ hơn
18
CREATE OR REPLACE TRIGGER PersonCheckAge
AFTER INSERT OR UPDATE OF Ngaysinh, ngayvl ON NHANVIEN
FOR EACH ROW
BEGIN
IF (extract(year from :NEW.ngayvl) - extract(year from :NEW.ngaysinh)<18)
THEN
RAISE_APPLICATION_ERROR(-20000, ‘Tuoi khong nho hon 18');
END IF;
END;
69
Ví dụ: trị giá hóa đơn bằng tổng tien (tiền)
của các CTHD thuộc hóa đơn đó
SOHD NGHD TRIGIA
HD01 25/12/2008 30000
HD02 12/05/2009 23000
HD03 12/05/2009 0
70
Ví dụ: trị giá hóa đơn bằng tổng tien (tiền)
của các CTHD thuộc hóa đơn đó
CREATE TRIGGER cthd_ins_ai
AFTER INSERT ON CTHD
FOR EACH ROW
BEGIN
UPDATE hoadon SET trigia = NVL(trigia, 0)+ :NEW.tien
WHERE sohd = :NEW.sohd;
END;
72
Ví dụ: trị giá hóa đơn bằng tổng tien (tiền)
của các CTHD thuộc hóa đơn đó (cách khác)
CREATE TRIGGER cthd_aiud_fer
AFTER INSERT OR DELETE OR UPDATE OF sohd, tien ON cthd
FOR EACH ROW
BEGIN
IF ( INSERTING OR UPDATING ) THEN
UPDATE hoadon SET trigia= NVL (trigia,0)+:NEW.tien
WHERE sohd = :NEW.sohd;
END IF;
73
Ví dụ: trị giá hóa đơn bằng tổng sl*gia của
các CTHD thuộc hóa đơn đó
SOHD NGHD TRIGIA
HD01 25/12/2008 30000
HD02 12/05/2009 23000
HD03 12/05/2009 0
74
Ví dụ: trị giá hóa đơn bằng tổng sl*gia của
các CTHD thuộc hóa đơn đó
CREATE TRIGGER cthd_ins_ai
AFTER INSERT ON CTHD
FOR EACH ROW
BEGIN
UPDATE hoadon SET trigia = trigia + :NEW.sl* :NEW.gia
WHERE sohd = :NEW.sohd;
END;
75
Ví dụ: trị giá hóa đơn bằng tổng sl*gia của
các CTHD thuộc hóa đơn đó
CREATE TRIGGER cthd_upd_au
AFTER UPDATE ON CTHD
FOR EACH ROW
BEGIN
UPDATE hoadon SET trigia = trigia + :NEW.sl* :NEW.gia
WHERE sohd = :NEW.sohd;
UPDATE hoadon SET trigia = trigia - :OLD.sl* :OLD.gia
WHERE sohd = :OLD.sohd;
END;
76
Table mutating
• Error xảy ra khi một row-level trigger truy cập đến cùng table (mà
trigger được định nghĩa trên đó) trong lúc thực thi. Table lúc này gọi là
mutating.
OPERATION TYPE MUTATING?
insert before/statement-level No
insert after/statement-level No
update before/statement-level No
update after/statement-level No
delete before/statement-level No
delete after/statement-level No
insert before/row-level Single row NO,Multi-row yes
insert after/row-level Yes
update before/row-level Yes
update after/row-level Yes
delete before/row-level Yes
delete after/row-level Yes
77
Table mutating
employee id firstname salary deptid
1 helen 100 fin
2 john 50 fin
78