我收到了实现列级权限的请求,例如:
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无能为力。
答案 0 :(得分: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 :(得分:1)
我不知道ODAC组件或库,但你不能设置一些属性,如:update only
:changed fields
或all fields
?
即使没有更改,这似乎也浪费时间来包含所有列。我认为大多数客户端库都提供此选项。
当然,如果你设置了类似sn TQuery的组件的一些SQL属性,你应该自己创建sql语句(也只基于更改的列)。