Một cách tiếp cận hơi khác là giữ cho các trình kích hoạt được bật nhưng giảm (nếu không phải là loại bỏ hoàn toàn) tác động của chúng, bằng cách thêm when
mệnh đề như:
create or replace trigger ...
...
for each row
when (sys_context('userenv', 'client_info') is null
or sys_context('userenv', 'client_info') != 'BATCH')
declare
...
begin
...
end;
/
Sau đó, trong quy trình của bạn, hãy thêm cuộc gọi tại bắt đầu như bước 'vô hiệu hóa trình kích hoạt' của bạn:
dbms_application_info.set_client_info('BATCH');
và xóa nó một lần nữa vào cuối, đề phòng trường hợp phiên vẫn còn hoạt động và được sử dụng lại (vì vậy bạn cũng có thể muốn thực hiện việc này trong một trình xử lý ngoại lệ):
dbms_application_info.set_client_info(null);
Bạn cũng có thể sử dụng mô-đun hoặc hành động hoặc kết hợp. Mặc dù cài đặt đó được áp dụng, trình kích hoạt sẽ vẫn được đánh giá nhưng sẽ không kích hoạt, vì vậy bất kỳ điều gì xảy ra bên trong sẽ bị bỏ qua - nội dung trình kích hoạt không chạy, vì tài liệu đặt nó.
Đây không phải là điều dễ hiểu vì không có gì thực sự ngăn cản những người dùng / ứng dụng khác thực hiện các cuộc gọi giống nhau, nhưng nếu bạn chọn một chuỗi mô tả hơn và / hoặc kết hợp các cài đặt, điều đó sẽ phải có chủ ý - và tôi nghĩ bạn chủ yếu lo lắng về tai nạn không phải là tác nhân xấu.
Kiểm tra tốc độ nhanh với một bộ kích hoạt vô nghĩa chỉ làm chậm mọi thứ một chút.
create table t42 (id number);
-- no trigger
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.050
create or replace trigger tr42 before insert on t42 for each row
declare
dt date;
begin
select sysdate into dt from dual;
end;
/
-- plain trigger
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.466
create or replace trigger tr42 before insert on t42 for each row
when (sys_context('userenv', 'client_info') is null
or sys_context('userenv', 'client_info') != 'BATCH')
declare
dt date;
begin
select sysdate into dt from dual;
end;
/
-- userenv trigger, not set
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.460
- userenv trigger, set to BATCH
exec dbms_application_info.set_client_info('BATCH');
insert into t42 (id) select level from dual connect by level <= 10000;
10,000 rows inserted.
Elapsed: 00:00:00.040
exec dbms_application_info.set_client_info(null);
Có một chút thay đổi so với việc thực hiện cuộc gọi từ xa, nhưng tôi đã chạy một vài lần và rõ ràng là chạy với trình kích hoạt đơn giản rất giống với chạy với trình kích hoạt bị ràng buộc mà không có bộ BATCH và cả hai đều chậm hơn nhiều so với chạy không có trình kích hoạt hoặc với trình kích hoạt bị ràng buộc với bộ BATCH. Trong thử nghiệm của tôi, có một thứ tự khác biệt về cường độ.