只需從應用程序以另一個用戶身份登錄到Oracle數據庫,而不是架構所有者,並正確配置權限。
一個例子勝過千言萬語 - 用戶test
,架構test
:
CREATE TABLE TABLEa(
id int,
myColumn int
);
CREATE TRIGGER update_table_B_mycolumn
AFTER UPDATE OF myColumn ON tableA
FOR EACH ROW
BEGIN
UPDATE tableB
SET myColumn = :new.mycolumn
WHERE id = :new.id;
END;
/
CREATE TABLE TableB(
id int,
myColumn int
);
現在授予appriopriate特權用戶scott
:
GRANT ALL ON TableA to scott;
GRANT update (id) ON TableB to scott; -- update only ID, no myColumn
GRANT SELECT, INSERT ON TableB to scott;
注意UPDATE權限僅授予對於表A中的id
列!
用戶scott
對列沒有更新特權myColumn
現在讓我們登錄爲scott
和測試我們的解決方案:
insert into test.tablea values(1,5);
insert into test.tableb values(1,5);
commit;
現在scott
試圖更新mycolumn
在tableb
:
update test.tableb set mycolumn = 3 where id = 1;
QL Error: ORA-01031: insufficient privileges
01031. 00000 - "insufficient privileges"
*Cause: An attempt was made to perform a database operation without
the necessary privileges.
*Action: Ask your database administrator or designated security
administrator to grant you the necessary privileges
但scott
能夠在tablea
更新mycolumn
,並觸發(與模式所有者的權限解僱 - 用戶test
)更新的tableb.mycolumn
值:
update test.tablea set mycolumn = 3 where id = 1;
select * from test.tableb;
ID MYCOLUMN
---------- ----------
1 3
編輯 - 基於觸發器的解決方案
如果您必須使用觸發器,那麼在啓用/禁用觸發器的包中保留一個標誌。
請看下面的例子:
CREATE TABLE TABLEa(
id int,
myColumn int
);
CREATE TABLE TableB(
id int,
myColumn int
);
INSERT INTO tableA values(5,5);
INSERT INTO tableB values(5,5);
commit;
一種包裝
CREATE or replace PACKAGE table_b_trigger_switch
IS
PROCEDURE ENABLE_UPDATE_TRIGGER(sw BOOLEAN);
FUNCTION IS_UPDATE_ENABLED RETURN BOOLEAN;
END;
/
CREATE or replace PACKAGE BODY table_b_trigger_switch
IS
enable_flag BOOLEAN := FALSE;
PROCEDURE ENABLE_UPDATE_TRIGGER(sw BOOLEAN)
IS
BEGIN
enable_flag := sw;
END;
FUNCTION IS_UPDATE_ENABLED RETURN BOOLEAN
IS
BEGIN
RETURN enable_flag;
END;
END;
/
觸發器:
CREATE or replace TRIGGER prevent_update_tableB_mycolumn
BEFORE UPDATE OF myColumn ON tableB
FOR EACH ROW
BEGIN
IF NOT table_b_trigger_switch.IS_UPDATE_ENABLED THEN
raise_application_error(-20222, 'Updating of myColumn in TABLE_B is NOT ALLOWED');
END IF;
END;
/
CREATE or replace TRIGGER update_tableB_mycolumn
AFTER UPDATE OF mycolumn ON TableA FOR EACH ROW
BEGIN
table_b_trigger_switch.ENABLE_UPDATE_TRIGGER(TRUE);
UPDATE TABLEB b SET b.MYCOLUMN = :NEW.MYCOLUMN
WHERE b.id = :NEW.id;
table_b_trigger_switch.ENABLE_UPDATE_TRIGGER(FALSE);
EXCEPTION WHEN OTHERS THEN
table_b_trigger_switch.ENABLE_UPDATE_TRIGGER(FALSE);
raise;
END;
/
一個試驗:
select * from tableb;
ID MYCOLUMN
---------- ----------
5 5
UPDATE tableb SET myColumn = 3;
ORA-20222: Updating of myColumn in TABLE_B is NOT ALLOWED
ORA-06512: at "TEST.PREVENT_UPDATE_TABLEB_MYCOLUMN", line 4
UPDATE tablea SET myColumn = 3;
1 row updated.
select * from tableb;
ID MYCOLUMN
---------- ----------
5 3
感謝Mojimi。如果用戶試圖直接修改myColumn,他們會收到一個異常(或者至少是數據庫服務器拋出異常),那麼可以接受嗎? – alexgibbs
@alexgibbs是的,這將是可以接受的,我會測試你的答案和報告 – Mojimi