2010-01-26 1 views
4

я получил запрос для реализации права на уровне столбцов, например:привилегии на уровне столбцов против унаследованного приложения

GRANT UPDATE("column1") ON "TABLE" TO ROLE; 

Но я обнаружил, что клиентские приложения (в Delphi + ODAC) всегда выдает обновления SQL, как:

update TABLE set column1=:column1,column2=:column2,column3=:column3,...etc 
where id_c=:id_c; 

что заставляет Oracle всегда бросить ORA-01031: недостаточно привилегий, даже если только column1 был изменен. Очевидным решением является изменение клиентского приложения, так что он испускает обновления SQL только с измененными столбцами, но это выглядит довольно много кода.

Возможно ли более элегантное решение?

Редактирование: Я забыл упомянуть, что в моих источниках Delphi имеется значительное количество запросов вставки/обновления жесткого кодирования. ODAC не может помочь в этом случае.

ответ

3

Вы можете создать вид и INSTEAD OF UPDATE триггер на этой точке зрения:

CREATE VIEW myview ON mytable 
AS 
SELECT * 
FROM table 

CREATE TRIGGER trg_myview_iu 
INSTEAD OF UPDATE 
ON myview 
FOR EACH ROW 
BEGIN 
     UPDATE mytable 
     SET  column1 = :NEW.column1 
     WHERE id_c = :NEW.id_c; 
END; 

Если вы хотите обработать столбец только если его значение не изменилось, то вам придется написать несколько UPDATE заявления:

CREATE TRIGGER trg_myview_iu 
INSTEAD OF UPDATE 
ON myview 
FOR EACH ROW 
BEGIN 
     IF :NEW.column1 <> :OLD.column1 THEN -- add `NULL` processing options if necessary 
       UPDATE mytable 
       SET  column1 = :NEW.column1 
       WHERE id_c = :NEW.id_c; 
     END IF; 
     IF :NEW.column2 <> :OLD.column2 THEN 
       UPDATE mytable 
       SET  column2 = :NEW.column2 
       WHERE id_c = :NEW.id_c; 
     END IF; 
     … 
END; 

Это далеко не эффективный.

В Oracle выполняется UPDATE, даже если фактическое значение столбца не изменяется. Это означает, что строка блокируется, вызывает огонь и т.д.

+1

Спасибо! Но это не очень удобно. Что, если позже клиент решает, хочет ли он новую роль, которая будет включать, например, колонку2? А потом еще один? Должен ли я обновлять код каждый раз? – Juraj

+0

@ Юрай, вы пропустили точку в Квасной. Его представление выбирает * (все столбцы) из таблицы. Триггер обновляет только те столбцы, которые фактически изменились (хотя и один столбец за раз, что очень неэффективно, но единственный практический способ решить вашу проблему). Вам нужно обновить код только в том случае, если * структура * базовой таблицы изменится, а не если вы просто измените некоторые гранты. –

+0

Конечно, если пользователь A не имеет привилегий обновления в столбце, но все равно пытается его изменить, они все равно получат ORA-01031 - это хорошо. –

1

Я не знаю, о ODAC компонентов или библиотеке, но вы не можете не установить некоторые свойства, как: update only: changed fields или all fields?

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

Конечно, если вы установили некоторое свойство SQL компонента sn TQuery-alike, вы должны сами создать инструкцию sql (также на основе только измененных столбцов).