2010-01-26 18 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; 

是什麼原因導致甲骨文總是拋出ORA-01031:權限不夠,即使只列1被改變。顯而易見的解決方案是更改客戶端應用程序,以便只使用更改的列發出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 2010-01-26 15:50:29

+0

@Juraj,你錯過了Quassnoi的觀點。他的觀點從表中選擇*(所有列)。觸發器只會更新實際更改的列(儘管每次只有一列,這是非常低效的,但是解決您的問題的唯一實用方法)。如果基礎表的*結構*發生更改,則只需更新代碼,而不是更改某些角色授予。 – 2010-01-27 00:20:38

+0

當然,如果用戶A對某一列沒有更新權限,但仍試圖改變它,他們仍然會得到ORA-01031 - 這是一件好事。 – 2010-01-27 00:21:57

1

我不知道該ODAC組件或庫,但是你不能沒有設置像一些屬性:update onlychanged fieldsall fields

即使沒有改變,這似乎浪費時間來包括所有列。我應該認爲大多數客戶端庫提供這個選項。

當然,如果你已經設置了sn TQuery-like組件的一些SQL屬性,你應該自己創建sql語句(也僅基於已更改的列)。