2010-01-26 17 views
4

j'ai eu une demande pour mettre en œuvre des privilèges au niveau de la colonne, par exemple:privilèges au niveau des colonnes par rapport aux applications héritées

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

Mais je trouve que les applications clientes (en Delphi + ODAC) émet toujours des mises à jour SQL comme:

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

ce qui provoque Oracle à toujours lancer ORA-01031: privilèges insuffisants, même si ce ne colonne1 a été changé. La solution évidente est de changer l'application cliente pour qu'elle n'émette des mises à jour SQL qu'avec des colonnes modifiées, mais cela ressemble à beaucoup de code.

Y a-t-il une solution plus élégante possible? Editer: J'ai oublié de mentionner qu'il y a un nombre considérable de requêtes d'insertion/mise à jour codées en dur dans mes sources Delphi. L'ODAC ne peut pas aider dans ce cas.

Répondre

3

Vous pouvez créer une vue et un déclencheur INSTEAD OF UPDATE sur ce point de vue:

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; 

Si vous voulez traiter une colonne que si sa valeur n'a pas changé, alors vous devrez écrire plusieurs déclarations 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; 

Ceci est loin d'être efficace, cependant. En Oracle, le UPDATE s'exécute même si la valeur réelle de la colonne ne change pas. Cela signifie que la ligne est verrouillée, déclenche le feu etc.

+1

Merci! Mais ce n'est pas bien entretenu. Que se passe-t-il si le client décide plus tard qu'il veut un nouveau rôle qui inclura column2, par exemple? Et puis un autre? Devrai-je mettre à jour le code à chaque fois? – Juraj

+0

@Juraj, vous avez manqué le point de Quassnoi. Sa vue sélectionne * (toutes les colonnes) de la table. Le déclencheur ne met à jour que les colonnes qui ont réellement changé (bien qu'une colonne à la fois, ce qui est très inefficace, mais le seul moyen pratique de résoudre votre problème). Vous avez seulement besoin de mettre à jour le code si la * structure * de la table sous-jacente change, pas si vous changez juste des attributions de rôle. –

+0

Bien sûr, si l'utilisateur A n'a pas de privilège de mise à jour sur une colonne, mais qu'il essaie de le changer de toute façon, il aura toujours l'ORA-01031 - ce qui est une bonne chose. –

1

Je ne connais pas les composants ODAC ou la bibliothèque, mais ne pouvez-vous pas définir certaines propriétés comme: update only: changed fields ou all fields?

Cela semble une perte de temps pour inclure toutes les colonnes, même si elles ne sont pas modifiées. Je devrais penser que la plupart des bibliothèques clientes offrent cette option.

Bien sûr, si vous avez défini une propriété SQL du composant sn TQuery-alike, vous devez créer l'instruction sql vous-même (en vous basant uniquement sur les colonnes modifiées).