Chúng ta không thể tự nhiên thực thi DDL dưới bất kỳ hình thức PL / SQL nào. bao gồm cả các trình kích hoạt. Để làm điều đó, chúng ta cần sử dụng SQL động.
Kích hoạt có thêm một nếp nhăn:chúng được kích hoạt như một phần của giao dịch và chúng có một giới hạn cấm chúng tôi đưa ra một cam kết bên trong cơ thể của chúng. Trong Oracle, bất kỳ lệnh DDL nào cũng đưa ra hai cam kết, một trước và một sau khi câu lệnh DDL được thực thi. Vì vậy, để thực thi DDL trong một trình kích hoạt, chúng ta phải sử dụng autonomous_transaction pragma
, có nghĩa là DDL chạy trong một giao dịch lồng ghép, riêng biệt.
create or replace TRIGGER TestTrigger
BEFORE INSERT ON TestTable
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
declare
pragma autonomous_transaction;
BEGIN
execute immediate 'create role '|| :New.RoleName;
END;
Giao dịch tự động là một trong những cấu trúc dễ dàng để chúng tôi sử dụng sai và phá hoại các ứng dụng của chính chúng tôi. Trong tình huống của bạn, khó khăn là VAI TRÒ TẠO có thể thành công trong bong bóng giao dịch của nó trong khi INSERTT vào TestTable
thất bại; đó là ý nghĩa của "giao dịch tự trị". Vì vậy, bạn vẫn không được đảm bảo "tính nhất quán giữa bảng [của bạn] và một vai trò tiên tri".
Một giải pháp tốt hơn sẽ là gói cả hai câu lệnh vào một lệnh gọi thủ tục, thay vì cố gắng lừa DML làm điều gì đó mà nó không được phép làm.
create or replace procedure create_role
( p_role_name in user_roles.role%type
, p_desc in testtable.description%type )
is
pragma autonomous_transaction;
begin
insert into testtable
( id, creationdate, rolename, description)
values
( some_seq.nextval, sysdate, p_role_name, p_desc );
execute immediate 'create role '|| p_role_name;
end;