2012-02-13 2 views
1

Я хочу сделать что-то концептуально простое, но в действительности оно намного сложнее.Как создать триггер Oracle, предоставляющий разрешения

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

grant select on TABLENAME to READROLE;

Пока мой триггер выглядит примерно так:

CREATE OR REPLACE TRIGGER osmm_grant_on_creation

ПОСЛЕ СОЗДАТЬ НА OSMM.SCHEMA

BEGIN

//grant goes here 

END

Проблема в том, что я не могу понять, как соединить их вместе, получив имя вновь созданной таблицы и ссылаться на него через триггер к гранту. Любые предложения? Благодарю.

+3

Любые предложения? Конечно: не делай этого. Разрешенные разрешения являются частью нашей конфигурации базы данных. Таким образом, они должны быть написаны сценариями и храниться в репозитории управления версиями вместе с DDL для создания таблицы. – APC

+0

@ APC - Почему я не хочу этого делать?Я не администратор базы данных и ограниченные знания Oracle, поэтому я боюсь, что ваш ответ не имеет смысла. Есть ли другой способ автоматически предоставлять права выбора для роли для новой таблицы? Потому что делать это вручную - это тяжелая работа, которую мы бы хотели избежать. Триггеры казались очевидным решением, но если есть «лучший» способ, я открыт для него. –

+0

Триггеры - это единственный способ автоматически предоставлять разрешения на объекты по требованию, и это непросто (как показывает ответ Джастина). Это сложно, потому что необычно требовать предоставления одинаковых разрешений для всех таблиц в схеме кому-то другому (роли или пользователю). Чаще всего предоставляется множество привилегий для подмножества таблиц, часто для разных учетных записей. Это сложная логика, чтобы включить триггер. Более общий подход (кроме кодировки cut'n'paste) заключается в использовании метаданных для генерации скриптов. – APC

ответ

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; 

И триггер, который отправляет на работу, которая требует эта процедура

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; 

Если вы должны были попытаться выпустить 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 
+1

+1 за то, что сказал «не делай этого», а затем -1, чтобы показать им, что нужно справляться с проблемами. – APC

+1

@ APC - Я, к сожалению, сделал что-то подобное, чтобы иметь дело с упакованным приложением, которое периодически создавало новые таблицы, и в этом случае триггер был разумным обходным решением (учитывая, что замена системы была не стартером). Но его следует признать массивным взломом. –

+0

Согласно информации, которую я нашел, некоторые DDL разрешены в триггерах уровня схемы (что неясно). – Allan

0

вам probabply нужно сделать что-то вроде:

CREATE OR REPLACE TRIGGER osmm_grant_on_creation 

AFTER CREATE ON OSMM.SCHEMA 
DECLARE 
new_obj_name varchar2(30); 
BEGIN 
SELECT ora_dict_obj_name 
INTO new_obj_name 
FROM dual 
WHERE ora_dict_obj_type = 'TABLE'; 

execute immediate 'grant select on ' || new_obj_name || ' to READROLE'; 
END 

, но я не могу проверить, работает ли он

+0

Как написано, я считаю, что это вызовет ошибку, если созданный объект - это нечто иное, чем таблица, так как он попытается выполнить 'grant select on to READROLE'. – Allan

Смежные вопросы