是否可以在 Oracle 18c 的触发器中使用 GRANT?
Is it possible to use GRANT inside a trigger in Oracle 18c?
我尝试创建一个触发器,每当在此模式中创建新的 table 时,它会自动为特定模式的所有新 table 授予 select。
其背景是 IBM InfoSphere Information Server 的异常数据库。此工具为在 DataStage 作业中创建的异常创建新的 tables,我希望一组开发人员能够查询这些 tables 而无需向架构所有者授予他们权限。
所以我的想法是创建一个这样的触发器:
create or replace trigger set_permissions
after create on schema
DECLARE
obj_name VARCHAR2(30) := DICTIONARY_OBJ_NAME;
BEGIN
IF DICTIONARY_OBJ_TYPE = 'TABLE'
THEN
GRANT SELECT ON c##ESDB_USER.obj_name TO c##DATASTAGE_USER;
END IF;
END set_permissions;
但我在编译触发器后收到错误 "PLS-00103"。它说,"GRANT" 不是预期的,而是预期以下之一:
( begin case declare exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge json_exists json_value json_query json_object json_array
我觉得 GRANT 在触发器中是不允许的。如果是这样,是否有另一种方法可以自动授予用户 select 对特定模式内的新 table 的权限?
你得到的错误说你不能像那样执行 DDL(是的,grant
是一个 DDL)——它必须使用 execute immediate
作为动态 SQL 来完成.
但是,在这种情况下它无济于事,因为 DDL 隐式地提交,并且您不能在触发器内提交。
现在您会说您可以将触发器创建为自主事务。嗯,是的 - 你可以,但它不会帮助 在这种情况下 因为 table 尚未创建(即它尚不存在)。
这是一个解决方法;看看是否有帮助。简而言之:
- 创建一个辅助过程(使其更简单),它实际上将执行
grant
操作
- 让触发器提交一个 作业,它将调用该过程
方法如下:我以 Scott 的身份连接并将向用户 Mike 授予权限(因为我没有您的用户):
SQL> show user
USER is "SCOTT"
SQL>
SQL> -- Auxiliary procedure
SQL> create or replace procedure p_grant (par_str in varchar2) is
2 begin
3 execute immediate par_str;
4 end;
5 /
Procedure created.
SQL> -- Trigger
SQL> create or replace trigger set_permissions
2 after create on schema
3 declare
4 l_job number;
5 l_str varchar2(200);
6 obj_name varchar2(30) := dictionary_obj_name;
7 begin
8 if dictionary_obj_type = 'TABLE'
9 then
10 l_str := 'GRANT SELECT ON ' ||obj_name || ' TO mike';
11 dbms_job.submit
12 (l_job,
13 'begin p_grant(' || chr(39) || l_str || chr(39) ||'); end;',
14 sysdate
15 );
16 end if;
17 end set_permissions;
18 /
Trigger created.
SQL>
测试:
SQL> create table test (id number);
Table created.
SQL> insert into test values (222);
1 row created.
SQL> commit;
Commit complete.
以 Mike 身份连接并检查它看到的内容:
SQL> connect mike/lion
Connected.
SQL> select * from scott.test;
ID
----------
222
SQL>
我尝试创建一个触发器,每当在此模式中创建新的 table 时,它会自动为特定模式的所有新 table 授予 select。
其背景是 IBM InfoSphere Information Server 的异常数据库。此工具为在 DataStage 作业中创建的异常创建新的 tables,我希望一组开发人员能够查询这些 tables 而无需向架构所有者授予他们权限。
所以我的想法是创建一个这样的触发器:
create or replace trigger set_permissions
after create on schema
DECLARE
obj_name VARCHAR2(30) := DICTIONARY_OBJ_NAME;
BEGIN
IF DICTIONARY_OBJ_TYPE = 'TABLE'
THEN
GRANT SELECT ON c##ESDB_USER.obj_name TO c##DATASTAGE_USER;
END IF;
END set_permissions;
但我在编译触发器后收到错误 "PLS-00103"。它说,"GRANT" 不是预期的,而是预期以下之一:
( begin case declare exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge json_exists json_value json_query json_object json_array
我觉得 GRANT 在触发器中是不允许的。如果是这样,是否有另一种方法可以自动授予用户 select 对特定模式内的新 table 的权限?
你得到的错误说你不能像那样执行 DDL(是的,grant
是一个 DDL)——它必须使用 execute immediate
作为动态 SQL 来完成.
但是,在这种情况下它无济于事,因为 DDL 隐式地提交,并且您不能在触发器内提交。
现在您会说您可以将触发器创建为自主事务。嗯,是的 - 你可以,但它不会帮助 在这种情况下 因为 table 尚未创建(即它尚不存在)。
这是一个解决方法;看看是否有帮助。简而言之:
- 创建一个辅助过程(使其更简单),它实际上将执行
grant
操作 - 让触发器提交一个 作业,它将调用该过程
方法如下:我以 Scott 的身份连接并将向用户 Mike 授予权限(因为我没有您的用户):
SQL> show user
USER is "SCOTT"
SQL>
SQL> -- Auxiliary procedure
SQL> create or replace procedure p_grant (par_str in varchar2) is
2 begin
3 execute immediate par_str;
4 end;
5 /
Procedure created.
SQL> -- Trigger
SQL> create or replace trigger set_permissions
2 after create on schema
3 declare
4 l_job number;
5 l_str varchar2(200);
6 obj_name varchar2(30) := dictionary_obj_name;
7 begin
8 if dictionary_obj_type = 'TABLE'
9 then
10 l_str := 'GRANT SELECT ON ' ||obj_name || ' TO mike';
11 dbms_job.submit
12 (l_job,
13 'begin p_grant(' || chr(39) || l_str || chr(39) ||'); end;',
14 sysdate
15 );
16 end if;
17 end set_permissions;
18 /
Trigger created.
SQL>
测试:
SQL> create table test (id number);
Table created.
SQL> insert into test values (222);
1 row created.
SQL> commit;
Commit complete.
以 Mike 身份连接并检查它看到的内容:
SQL> connect mike/lion
Connected.
SQL> select * from scott.test;
ID
----------
222
SQL>