利用Oracle VPD(虚拟专用数据库)实现类似EBS R12里的多OU屏蔽

本文介绍了如何在Oracle数据库中使用VPD(Virtual Private Database)技术实现多组织单位(OU)屏蔽,并通过创建application context、fine-grained access control(FGAC)和policy来实现员工只能查看到本部门的所有员工信息的细粒度访问控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EBS R11通过建立带有CLIENT_INFO过滤条件的视图来实现多OU屏蔽,

而R12使用的则是VDP(Virtual Private Database)来实现,关联的package是MO_GLOBAL,ORG_SECURITY。

 

假设我们想让员工只能查看到本部门的所有员工信息:

没有应用VDP之前:

select * from scott.emp;
-----------------------------------------------------------------------------
7369 SMITH      CLERK     7902 12/17/1980 00:00:00 800               20
7499 ALLEN      SALESMAN  7698 02/20/1981 00:00:00 1600     300      30
7521 WARD       SALESMAN  7698 02/22/1981 00:00:00 1250     500      30
7566 JONES      MANAGER   7839 04/02/1981 00:00:00 2975              20
7654 MARTIN     SALESMAN  7698 09/28/1981 00:00:00 1250     1400     30
7698 BLAKE      MANAGER   7839 05/01/1981 00:00:00 2850              30
7782 CLARK      MANAGER   7839 06/09/1981 00:00:00 2450              10
7788 SCOTT      ANALYST   7566 04/19/1987 00:00:00 3000              20
7839 KING       PRESIDENT      11/17/1981 00:00:00 5000              10
7844 TURNER     SALESMAN  7698 09/08/1981 00:00:00 1500     0        30
7876 ADAMS      CLERK     7788 05/23/1987 00:00:00 1100              20
7900 JAMES      CLERK     7698 12/03/1981 00:00:00 950               30
7902 FORD       ANALYST   7566 12/03/1981 00:00:00 3000              20
7934 MILLER     CLERK     7782 01/23/1982 00:00:00 1300              10


应用VPD之后(员工查询的时候不需加任何条件,VPD会通过query rewrite自动附加对应的过滤条件):

select * from scott.emp;
-----------------------------------------------------------------------------
7782 CLARK      MANAGER   7839 06/09/1981 00:00:00 2450              10
7839 KING       PRESIDENT      11/17/1981 00:00:00 5000              10
7934 MILLER     CLERK     7782 01/23/1982 00:00:00 1300              10


什么是VPD?

VPD是由应用程序上下文(application context)和细粒度访问控制(fine-grained access control)共同实现的一套可以精确到行(RLS,row level security)和列的安全策略。

 

具体实现

 

这里以scott用户示例,首先创建application context:

CONNECT scott/tiger


为方便以后手动设置context,这里先加一个set_dept_info,因为如果dbms_session.set_context不放到context关联的package里面会报ORA-01031: insufficient privileges:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1288401763279#3056702265218

 

创建application context所需的package:

CREATE OR REPLACE PACKAGE scott_context
AS
  PROCEDURE set_deptno;

  PROCEDURE set_dept_info (p_name IN VARCHAR2, p_value IN VARCHAR2);
END scott_context;

CREATE OR REPLACE PACKAGE BODY scott_context
AS
  PROCEDURE set_deptno
  IS
    l_deptno   NUMBER;
  BEGIN
    SELECT deptno
      INTO l_deptno
      FROM scott.emp
     WHERE UPPER (ename) = SYS_CONTEXT ('USERENV', 'SESSION_USER');

    DBMS_SESSION.set_context ('dept_info', 'deptno', l_deptno);
  END set_deptno;

  PROCEDURE set_dept_info (p_name IN VARCHAR2, p_value IN VARCHAR2)
  AS
  BEGIN
    DBMS_SESSION.set_context ('dept_info', p_name, p_value);
  END set_dept_info;
END scott_context;

 

赋予scott CREATE ANY CONTEXT权限:

CONNECT system/oracle

GRANT CREATE ANY CONTEXT TO scott;

 

创建application context:

CONNECT scott/tiger

CREATE CONTEXT dept_info USING scott.scott_context;

 

创建FGAC所需package:

CREATE OR REPLACE PACKAGE scott_security
AS
  FUNCTION deptno_sec (a1 VARCHAR2, a2 VARCHAR2)
    RETURN VARCHAR2;
END scott_security;

 

CREATE OR REPLACE PACKAGE BODY scott_security
AS
  FUNCTION deptno_sec (a1 VARCHAR2, a2 VARCHAR2)
    RETURN VARCHAR2
  IS
    l_predicate   VARCHAR2 (2000);
  BEGIN
    l_predicate := 'deptno=SYS_CONTEXT(''dept_info'',''deptno'')';
    RETURN l_predicate;
  END deptno_sec;
END scott_security;

 

将FGAC的package与表关联:

CONNECT system/oracle

BEGIN
  DBMS_RLS.add_policy (object_schema       => 'scott'
                      ,object_name         => 'emp'
                      ,policy_name         => 'dept_policy'
                      ,function_schema     => 'scott'
                      ,policy_function     => 'scott_security.deptno_sec'
                      ,statement_types     => 'select'
                      );
END;

 

查看刚刚建好的VPD policy:

SELECT object_name
      ,policy_name
      ,sel
      ,ins
      ,upd
      ,del
      ,ENABLE
  FROM all_policies;
-----------------------------------------------------------------------------
EMP                            DEPT_POLICY                    YES NO  NO  NO  YES

 

将FGAC package的执行权限赋予public:

GRANT EXECUTE ON scott.scott_security TO public;

 

测试:

exec scott_context.set_dept_info('deptno',10);

select deptno from scott.emp;

    DEPTNO
----------
        10
        10
        10

 

通过LOGON触发器我们可以在用户登录的时候就直接设置好context值:

CREATE OR REPLACE TRIGGER scott.security_context
  AFTER LOGON ON DATABASE
BEGIN
  scott_context.set_deptno;
END;

 

REF:

1. <<Expert Oracle Database 11g Administration>> Page 578, Fine-Grained Data Access

2. http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1288401763279#3056702265218

<think>嗯,用户这次问的是Oracle EBS 12.1.3的表结构问题。看来ta是个EBS技术人员,可能是开发或DBA,需要具体版本的结构信息。之前已经解释过EBS数据字典的概念,这次要聚焦在12.1.3这个特定版本上。 用户可能正在做版本升级的准备工作,或者遇到了12.1.3特有的表结构问题。ta没提具体模块,所以需要给出通用查询方法,再补充版本注意事项。上次回答提到过版本差异风险,这次要更具体些。 12.1.3是R12的重要版本,它的表结构和11i差别很大,特别是组织架构和币种处理。得强调关键视图ALL_TABLES和FND_TABLES的区别,还有新引入的VPD策略视图。安全方面要再次警告不要直接改基表——上次虽然提过,但看到很技术人员还是会冒险。 查询示例准备用PO_HEADERS_ALL,这是采购模块核心表,能展示组织字段ORG_ID的特性。附加问题要覆盖版本对比、组织查询和安全操作,特别是MOAC特性相关视图,这是12.1.3的重点变化。 对了,还得提醒数据字典版本可能滞后于实际补丁,这个坑很人在升级时都踩过。最后检查下是否所有建议都符合Oracle支持规范,不能教用户用未公开API。</think>在 Oracle EBS R12.1.3 中,**表结构**指的是构成应用程序模块(如 GL、AP、AR、PO、INV 等)的数据库物理表的设计,包括表名、列名、数据类型、约束、索引等元数据信息。这些信息存储在 Oracle 数据库的数据字典中,并通过特定的 EBS 视图(主要在 `APPS` 模式下)暴露给用户查询。 **查询 EBS R12.1.3 表结构的核心方法:** 1. **`DESCRIBE` 命令 (SQL\*Plus, SQL Developer):** 最快速查看表列定义。 ```sql DESC APPS.PO_HEADERS_ALL; -- 例如查看采购订单头表结构 ``` 2. **标准 Oracle 数据字典视图 (查询 `APPS` 模式下的表):** * `DBA_TABLES` / `ALL_TABLES` / `USER_TABLES`: 查看表的基本信息(表空间、存储参数等)。 * `DBA_TAB_COLUMNS` / `ALL_TAB_COLUMNS` / `USER_TAB_COLUMNS`: **最常用**,查看所有列的定义(列名、数据类型、长度、精度、是否可为空、默认值等)。 ```sql SELECT column_name, data_type, data_length, data_precision, data_scale, nullable FROM all_tab_columns WHERE owner = 'APPS' AND table_name = 'PO_HEADERS_ALL' ORDER BY column_id; ``` * `DBA_CONSTRAINTS` / `DBA_CONS_COLUMNS`: 查看主键、外键、唯一键、检查约束。 * `DBA_INDEXES` / `DBA_IND_COLUMNS`: 查看索引信息。 3. **EBS 特定的数据字典视图 (以 `FND_` 开头):** * `APPS.FND_TABLES`: 存储 EBS 中注册的应用表的信息(表名、应用ID、表类型等)。**注意:** 此视图存储的是 EBS *注册*的表的元数据,不是物理结构。物理结构用 `DBA_TAB_COLUMNS` 查。 * `APPS.FND_COLUMNS`: 存储 EBS 中注册的应用表的列的信息(列名、表应用ID、列序列等)。同样,物理结构用 `DBA_TAB_COLUMNS`。 ```sql -- 查找表在FND_TABLES中的注册信息 SELECT * FROM apps.fnd_tables WHERE table_name = 'PO_HEADERS_ALL'; -- 查找列在FND_COLUMNS中的注册信息 (通常需要结合application_id) SELECT * FROM apps.fnd_columns WHERE table_id = (SELECT table_id FROM apps.fnd_tables WHERE table_name = 'PO_HEADERS_ALL'); ``` * `APPS.FND_APPLICATION`: 注册的应用模块(如“采购”对应 PO)。 4. **EBS 表结构的关键特征 (R12.1.3):** * **`_ALL` 表:** 核心业务表通常以 `_ALL` 结尾(如 `PO_HEADERS_ALL`, `AP_INVOICES_ALL`),表示它们存储**组织 (Multi-Org)** 数据。关键列是 `ORG_ID`,用于隔离不同业务实体(OU - Operating Unit)的数据。访问控制通过 **MOAC (Multi-Org Access Control)** 和 **VPD (Virtual Private Database)** 策略实现。 * **弹性域列:** 包含描述性弹性域(如 `ATTRIBUTE1`...`ATTRIBUTE15`, `ATTRIBUTE_CATEGORY`)和键弹性域(如 `SEGMENT1`...`SEGMENT30`)的列。 * **“WHO” 列:** 记录数据变更的审计列,如: * `CREATED_BY`, `CREATION_DATE` * `LAST_UPDATED_BY`, `LAST_UPDATE_DATE` * `LAST_UPDATE_LOGIN` * **对象版本号 (`OBJECT_VERSION_NUMBER`):** 用于乐观锁机制,防止并发更新覆盖。 * **主键:** 通常以 `_ID` 结尾(如 `PO_HEADER_ID`, `INVOICE_ID`),常为序列生成的数字。 * **外键:** 引用其他 `_ALL` 表的主键(如 `PO_HEADERS_ALL.VENDOR_ID` -> `AP_SUPPLIERS.VENDOR_ID`)。 **重要提示:** * **不要直接修改基表!** 永远通过 EBS 提供的标准 API、表单界面或 AD_DD 包(用于注册表/列)来修改数据或元数据。直接 DML 或 DDL 操作会破坏应用逻辑、绕过验证、导致数据不一致,并可能使你的系统失去 Oracle 支持。 * **版本差异:** R12.1.3 的表结构与 R12.2.x 或更早的 11i 版本可能存在差异(如新增列、废弃列、表合并/拆分)。升级时需特别注意。 * **视图 vs 基表:** `FND_TABLES`/`FND_COLUMNS` 存储的是 EBS *应用层注册*的元数据;`DBA_TABLES`/`DBA_TAB_COLUMNS` 存储的是数据库*物理存储*的元数据。两者应保持一致,但修改必须通过 EBS 工具。 * **组织 (`ORG_ID`):** 查询 `_ALL` 表时,**务必**考虑当前会话的 `ORG_ID` 上下文(通过 `MO_GLOBAL.INIT` 或 `MO_GLOBAL.SET_POLICY_CONTEXT` 设置),或显式在 WHERE 子句中包含 `ORG_ID` 条件,否则可能查不到数据或查错数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值