我想做一些概念上简单的事情,但在现实中似乎要复杂得多.
基本上,每当为我们数据库中的几个用户创建一个新表时,我想授予一个角色的选择权限.基本上这个:
grant select on TABLENAME to READROLE;
到目前为止,我的触发器看起来像这样:
创建或替换触发器osmm_grant_on_creation
在OSMM.SCHEMA上创建之后
开始
Run Code Online (Sandbox Code Playgroud)//grant goes here结束
问题是,我无法弄清楚如何通过获取新创建的表的名称并通过触发器将其引用到授权来将两者连接在一起.有什么建议?谢谢.
Jus*_*ave 12
它可能比你想的更复杂.该GRANT语句是DDL,这意味着它发出隐式提交,这意味着您不能直接将其置于触发器中.您的触发器需要提交一个在提交的触发事务之后在单独的会话中运行的作业,该作业实际上将执行授权.这意味着你必须使用旧的DBMS_JOB包来安排工作,因为更现代的DBMS_SCHEDULER也隐式提交.
由于您不应该首先在Oracle中动态创建表,因此这种授权的适当位置在您首先创建表的运行脚本中.依靠触发器来执行诸如授予之类的操作往往会使构建正确的构建变得更加困难,因为在两个不同的环境中运行完全相同的脚本可能会因触发器的不同而生成两个不同的结果.
但是,如果你决定沿着这条路走下去,你可能会想要这样的东西
授予权限的过程
CREATE OR REPLACE PROCEDURE grant_select_to_readrole( p_table_name IN VARCHAR2 )
AS
BEGIN
EXECUTE IMMEDIATE 'grant select on ' || p_table_name || ' to readrole';
END;
Run Code Online (Sandbox Code Playgroud)
并且提交调用此过程的作业的触发器
CREATE OR REPLACE TRIGGER osmm_grant_on_creation
AFTER CREATE ON OSMM.SCHEMA
AS
l_jobno PLS_INTEGER;
BEGIN
dbms_job.submit( l_jobno,
'BEGIN grant_select_to_readrole( ''' || ora_dict_obj_name || ''' ); END;',
sysdate + interval '10' second );
END;
Run Code Online (Sandbox Code Playgroud)
如果您尝试在架构级触发器本身中发出DDL,则会出现错误
SQL> ed
Wrote file afiedt.buf
1 create or replace trigger after_create_on_scott
2 after create on schema
3 declare
4 begin
5 execute immediate 'grant select on scott.emp to hr';
6* end;
SQL> /
Trigger created.
SQL> create table foo( col1 number );
create table foo( col1 number )
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 1
ORA-30511: invalid DDL operation in system triggers
ORA-06512: at line 3
Run Code Online (Sandbox Code Playgroud)