只需从应用程序以另一个用户身份登录到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