Thông thường để lấy giá trị một SEQUENCE, chúng ta sẽ thường viết “SELECT SEQUENCE_NAME.NEXTVAL FROM DUAL”. Bởi vậy, chúng ta thường mắc phải lỗi rằng mọi phép gán giá trị trong PL/SQL được sử dụng như một hàm trong cơ sở dữ liệu yêu cầu một câu lệnh SELECT-FROM-DUAL. Nên bởi vậy chúng ta sẽ gặp vấn đề về hiệu năng ở đây.
Một lỗi cơ bản
Một mẫu thường dùng khi thiết kế các bảng cần phải lưu lại thông tin về người tạo, người thay đổi, thời gian tạo, thời gian thay đổi, và bởi vậy, rất nhiều cột ví dụ như:
- CREATED_BY
- CREATED_DATE
- MODIFIED_BY
- MODIFIED_DATE
được tạo ra, và chúng thường được dùng trigger để fill các giá trị vào như ví dụ dưới đây:
begin
if inserting then
:new.created_by := user;
:new.created_date := sysdate;
end if;
:new.modified_by := user;
:new.modified_date := sysdate;
end;
Nhưng đây là một sai lầm, khi chúng ta thực hiện một loạt các câu lệnh insert vào bảng như vậy, chúng ta sẽ thấy một điều đặc biệt xảy ra:
INSERT INTO T (ID,ENAME)
VALUES (:B1 ,:B2)
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 100000 7.20 7.83 132 1048 106235 100000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 100001 7.20 7.83 132 1048 106235 100000
SELECT USER
FROM SYS.DUAL
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 200000 0.84 0.93 0 0 0 0
Fetch 200000 0.15 0.29 0 0 0 200000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 400001 1.00 1.22 0 0 0 200000
Tham chiếu “USER” trong trigger được sử dụng bởi câu lệnh SELECT-FROM-DUAL. Vì vậy, có lẽ chúng ta đã gây ra lỗi vì đã hiểu sai hoạt động của câu lệnh gán trong PL/SQL như trên.
Có một cách dễ dàng để sửa vấn đề trên, thay vì tham cheiesu đến USER thì chúng ta sử dụng biến context
begin
if inserting then
:new.created_by := SYS_CONTEXT('USERENV', 'SESSION_USER');
:new.created_date := sysdate;
end if;
:new.modified_by := SYS_CONTEXT('USERENV', 'SESSION_USER');;
:new.modified_date := sysdate;
end;
Điều này không yêu cầu một lệnh SELECT-FROM-DUAL và mang lại hiệu suất đáng kể trong việc thực thi của trigger, đặc biệt khi trigger tác động trong bảng có tần suất giao dịch lớn.
Leave a Review