问题描述
如果您可以控制应用程序的连接方式(例如,连接池的初始化语句),则只需运行:
ALTER SESSION SET CURRENT_SCHEMA = PRODUCTS;
从那时起(在会话的生存期内),将在PRODUCTS
模式中搜索任何不合格的对象名称。
授予的所有补助金PRODUCTS_READONLY
将生效。该会话将在用于登录的原始用户的凭据(和安全限制)下运行。
如果您无法更改建立或初始化连接的方式,则登录触发器也应完成以下操作:
create or replace trigger logon_trg
after logon on database
begin
if (user = 'PRODUCTS_READONLY') then
execute immediate 'alter session set current_schema = products';
end if;
exception
when others then null; -- prevent a login failure due to an exception
end logon_trg;
/
请注意,捕获 任何 异常至关重要,因为否则执行的sql中潜在的错误将有效地使所有人退出数据库。因此,在投入生产之前请谨慎使用并进行良好的测试。
解决方法
我有一个架构和一个具有相同名称的用户:products
。为了进行开发,我想在Java应用程序中以只读模式使用它。因此,我为只读应用程序创建了一个新用户。
CREATE USER PRODUCTS_READONLY IDENTIFIED BY PRODUCTS_READONLY;
GRANT CREATE SESSION to PRODUCTS_READONLY;
BEGIN
FOR tab IN (SELECT table_name FROM all_tables WHERE owner = 'PRODUCTS') LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON PRODUCTS.'||tab.table_name||' TO PRODUCTS_READONLY';
END LOOP;
END;
运行应用程序时,我得到表不存在的错误。在互联网上寻找解决方案时,我遇到了SYNONYM
。因此,我为架构添加了同义词:
CREATE SYNONYM PRODUCTS_READONLY FOR PRODUCTS;
现在,我在java
应用程序中遇到此错误:
ERROR org.hibernate.util.JDBCExceptionReporter - ORA-17074 invalid name
pattern.: PRODUCTS_READONLY.PRODUCT_TYPE
我的方法有什么问题?
-更新-
似乎在10g中删除了为模式创建同义词的步骤(Oracle:是否可以为模式创建同义词?)。如果我为目标架构中的每个对象创建架构,那么每次将表添加到目标架构或对目标架构中的任何其他对象进行任何其他更改时,我都必须这样做吗?听起来很麻烦…
-更新2–
似乎有一个触发器with alter session
是一个可能的解决方案,但是只要用户只有SELECT
特权,它会使表变成只读吗?