Можно ли использовать GRANT внутри триггера в Oracle 18c? - PullRequest
1 голос
/ 22 сентября 2019

Я пытаюсь создать триггер, который автоматически предоставляет выбор для всех новых таблиц для определенной схемы, всякий раз, когда создается новая таблица в этой схеме.

Фоном для этого является База данных исключений IBM InfoSphere Information Server.Этот инструмент создает новые таблицы для исключений, которые создаются в заданиях DataStage, и я хочу, чтобы группа разработчиков могла запрашивать эти таблицы, не давая им разрешения владельцу схемы.

Поэтому я хотел создатьтриггер как это:

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 не разрешен внутри триггера.Если это так, есть ли другой способ автоматически предоставлять пользователям право выбора для новых таблиц внутри определенной схемы?

1 Ответ

2 голосов
/ 22 сентября 2019

Полученная ошибка говорит о том, что вы не можете выполнить DDL (да, grant - это DDL) подобным образом - это нужно сделать как динамический SQL, используя execute immediate.

Однако этоне поможет в этом случае , потому что DDL неявно фиксирует , и вы не можете зафиксировать в триггере.

Теперь вы скажете, что можете создатьинициировать как автономная транзакция .Ну, да - вы можете, но это не поможет в этом случае , потому что таблица еще не создана (т.е. она еще не существует).


Вотобходной путь;посмотрим, поможет ли это.В нескольких словах:

  • создайте вспомогательную процедуру (чтобы упростить ее), которая фактически будет выполнять grant операцию
  • , позволяющую триггеру отправить задание который вызовет эту процедуру

Вот как: я подключен как Скотт и буду предоставлять привилегии пользователю Майку (поскольку у меня нет ваших пользователей):

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.

Подключитесь как Майк и проверьте, что он видит:

SQL> connect mike/lion
Connected.
SQL> select * from scott.test;

        ID
----------
       222

SQL>
...