Oracle EBS R12 - 查询同一个表在不同用户下的同义词(XLA_TRANSACTION_ENTITIES)时返回的结果不一样
2013-09-13 21:22
786 查看
Oracle EBS R12 - 查询同一个表在不同用户下的同义词(XLA_TRANSACTION_ENTITIES)时返回的结果不一样
在EBS R12系统中有张表"XLA"."XLA_TRANSACTION_ENTITIES",并且同时存在APPS和APPSREAD针对该表的同义词,
定义如下:
CREATE OR REPLACE SYNONYM "APPS"."XLA_TRANSACTION_ENTITIES" FOR "XLA"."XLA_TRANSACTION_ENTITIES";
CREATE OR REPLACE SYNONYM "APPSREAD"."XLA_TRANSACTION_ENTITIES" FOR "XLA"."XLA_TRANSACTION_ENTITIES";
但是针对同义词相同条件的查询返回的结果却不一样:
SQL> select count(*) from apps.XLA_TRANSACTION_ENTITIES where application_id=222;
COUNT(*)
----------
1
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222;
COUNT(*)
----------
112884
SQL>
看到这个问题首先想到就是用trace跟踪一下:
SQL> set autotrace traceonly explain
SQL> select count(*) from apps.XLA_TRANSACTION_ENTITIES where application_id=222;
Execution Plan
----------------------------------------------------------
Plan hash value: 2139858008
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 481 (2)| 00:00:06 | | |
| 1 | SORT AGGREGATE | | 1 | 8 | | | | |
| 2 | PARTITION LIST SINGLE| | 1 | 8 | 481 (2)| 00:00:06 | KEY | KEY |
|* 3 | TABLE ACCESS FULL | XLA_TRANSACTION_ENTITIES | 1 | 8 | 481 (2)| 00:00:06 | 2 | 2 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("SECURITY_ID_INT_1" IS NULL)
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222;
Execution Plan
----------------------------------------------------------
Plan hash value: 1648015674
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 331 (1)| 00:00:04 | | |
| 1 | SORT AGGREGATE | | 1 | 4 | | | | |
| 2 | PARTITION LIST SINGLE| | 112K| 438K| 331 (1)| 00:00:04 | KEY | KEY |
|* 3 | INDEX FULL SCAN | XLA_TRANSACTION_ENTITIES_U1 | 112K| 438K| 331 (1)| 00:00:04 | 2 | 2 |
----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("APPLICATION_ID"=222)
SQL>
trace告诉了我们真相,实际查询时二者的条件完全不一样:
apps使用的是: filter("SECURITY_ID_INT_1" IS NULL)和("APPLICATION_ID"=222),不过后者用来定位表的分区了
appsread使用的是:access("APPLICATION_ID"=222)
当我们把filter("SECURITY_ID_INT_1" IS NULL)加到appsread查询上时,得到了和apps相同的结果:
SQL> set autotrace on
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222 and ("SECURITY_ID_INT_1" IS NULL);
COUNT(*)
----------
1
Execution Plan
----------------------------------------------------------
Plan hash value: 2139858008
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 481 (2)| 00:00:06 | | |
| 1 | SORT AGGREGATE | | 1 | 8 | | | | |
| 2 | PARTITION LIST SINGLE| | 1 | 8 | 481 (2)| 00:00:06 | KEY | KEY |
|* 3 | TABLE ACCESS FULL | XLA_TRANSACTION_ENTITIES | 1 | 8 | 481 (2)| 00:00:06 | 2 | 2 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("SECURITY_ID_INT_1" IS NULL)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1661 consistent gets
0 physical reads
0 redo size
335 bytes sent via SQL*Net to client
350 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
为什么apps会多出一个我们没有指定的条件呢?这其实是Oracle VPD自动加上去的,
类似你要查询oe_order_headers的数据时要先调用fnd_global初始化ORG_ID,
有关VPD可以参考另一篇blog:
利用Oracle VPD(虚拟专用数据库)实现类似EBS R12里的多OU屏蔽 http://blog.csdn.net/t0nsha/article/details/7423638
知道了原因,我们试着给APPSREAD用户也增加APPS相似的policy,看看结果怎样:
SQL> BEGIN
2 DBMS_RLS.add_policy (object_schema => 'APPSREAD'
3 ,object_name => 'XLA_TRANSACTION_ENTITIES'
4 ,policy_name => 'APPSREAD_policy'
5 ,function_schema => 'APPS'
6 ,policy_function => 'XLA_SECURITY_POLICY_PKG.MO_POLICY'
7 ,statement_types => 'SELECT');
8 END;
9 /
PL/SQL procedure successfully completed.
SQL>
设置了和APPS相同的policy后,APPSREAD获得了和APPS用户相同的查询结果:
SQL> set autotrace on;
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222;
COUNT(*)
----------
1
Execution Plan
----------------------------------------------------------
Plan hash value: 2139858008
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 481 (2)| 00:00:06 | | |
| 1 | SORT AGGREGATE | | 1 | 8 | | | | |
| 2 | PARTITION LIST SINGLE| | 1 | 8 | 481 (2)| 00:00:06 | KEY | KEY |
|* 3 | TABLE ACCESS FULL | XLA_TRANSACTION_ENTITIES | 1 | 8 | 481 (2)| 00:00:06 | 2 | 2 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("SECURITY_ID_INT_1" IS NULL)
Statistics
----------------------------------------------------------
2 recursive calls
0 db block gets
1661 consistent gets
0 physical reads
0 redo size
335 bytes sent via SQL*Net to client
350 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
综上可以看出,如果DBMS_RLS.add_policy作用于同义词时,则只对在该过程的object_schema参数中指定的用户下的同义词有效。
最后删除policy,恢复环境:
SQL> exec DBMS_RLS.DROP_POLICY(object_schema=>'APPSREAD',object_name=>'XLA_TRANSACTION_ENTITIES',policy_name=>'APPSREAD_policy');
PL/SQL procedure successfully completed.
SQL>
REF:
1. Using Oracle Virtual Private Database to Control Data Access http://docs.oracle.com/cd/B28359_01/network.111/b28531/vpd.htm
在EBS R12系统中有张表"XLA"."XLA_TRANSACTION_ENTITIES",并且同时存在APPS和APPSREAD针对该表的同义词,
定义如下:
CREATE OR REPLACE SYNONYM "APPS"."XLA_TRANSACTION_ENTITIES" FOR "XLA"."XLA_TRANSACTION_ENTITIES";
CREATE OR REPLACE SYNONYM "APPSREAD"."XLA_TRANSACTION_ENTITIES" FOR "XLA"."XLA_TRANSACTION_ENTITIES";
但是针对同义词相同条件的查询返回的结果却不一样:
SQL> select count(*) from apps.XLA_TRANSACTION_ENTITIES where application_id=222;
COUNT(*)
----------
1
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222;
COUNT(*)
----------
112884
SQL>
看到这个问题首先想到就是用trace跟踪一下:
SQL> set autotrace traceonly explain
SQL> select count(*) from apps.XLA_TRANSACTION_ENTITIES where application_id=222;
Execution Plan
----------------------------------------------------------
Plan hash value: 2139858008
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 481 (2)| 00:00:06 | | |
| 1 | SORT AGGREGATE | | 1 | 8 | | | | |
| 2 | PARTITION LIST SINGLE| | 1 | 8 | 481 (2)| 00:00:06 | KEY | KEY |
|* 3 | TABLE ACCESS FULL | XLA_TRANSACTION_ENTITIES | 1 | 8 | 481 (2)| 00:00:06 | 2 | 2 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("SECURITY_ID_INT_1" IS NULL)
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222;
Execution Plan
----------------------------------------------------------
Plan hash value: 1648015674
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 331 (1)| 00:00:04 | | |
| 1 | SORT AGGREGATE | | 1 | 4 | | | | |
| 2 | PARTITION LIST SINGLE| | 112K| 438K| 331 (1)| 00:00:04 | KEY | KEY |
|* 3 | INDEX FULL SCAN | XLA_TRANSACTION_ENTITIES_U1 | 112K| 438K| 331 (1)| 00:00:04 | 2 | 2 |
----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("APPLICATION_ID"=222)
SQL>
trace告诉了我们真相,实际查询时二者的条件完全不一样:
apps使用的是: filter("SECURITY_ID_INT_1" IS NULL)和("APPLICATION_ID"=222),不过后者用来定位表的分区了
appsread使用的是:access("APPLICATION_ID"=222)
当我们把filter("SECURITY_ID_INT_1" IS NULL)加到appsread查询上时,得到了和apps相同的结果:
SQL> set autotrace on
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222 and ("SECURITY_ID_INT_1" IS NULL);
COUNT(*)
----------
1
Execution Plan
----------------------------------------------------------
Plan hash value: 2139858008
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 481 (2)| 00:00:06 | | |
| 1 | SORT AGGREGATE | | 1 | 8 | | | | |
| 2 | PARTITION LIST SINGLE| | 1 | 8 | 481 (2)| 00:00:06 | KEY | KEY |
|* 3 | TABLE ACCESS FULL | XLA_TRANSACTION_ENTITIES | 1 | 8 | 481 (2)| 00:00:06 | 2 | 2 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("SECURITY_ID_INT_1" IS NULL)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1661 consistent gets
0 physical reads
0 redo size
335 bytes sent via SQL*Net to client
350 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
为什么apps会多出一个我们没有指定的条件呢?这其实是Oracle VPD自动加上去的,
类似你要查询oe_order_headers的数据时要先调用fnd_global初始化ORG_ID,
有关VPD可以参考另一篇blog:
利用Oracle VPD(虚拟专用数据库)实现类似EBS R12里的多OU屏蔽 http://blog.csdn.net/t0nsha/article/details/7423638
SQL> SELECT object_owner,object_name,pf_owner,package,function,sel FROM dba_policies where object_name = 'XLA_TRANSACTION_ENTITIES'; OBJECT_OWNER OBJECT_NAME PF_OWNER PACKAGE FUNCTION SEL ------------------------------ ------------------------------ ------------------------------ ------------------------------ ------------------------------ --- APPS XLA_TRANSACTION_ENTITIES APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES APPS XLA_SECURITY_POLICY_PKG XLA_STANDARD_POLICY YES APPS XLA_TRANSACTION_ENTITIES APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES 7 rows selected. SQL>
知道了原因,我们试着给APPSREAD用户也增加APPS相似的policy,看看结果怎样:
SQL> BEGIN
2 DBMS_RLS.add_policy (object_schema => 'APPSREAD'
3 ,object_name => 'XLA_TRANSACTION_ENTITIES'
4 ,policy_name => 'APPSREAD_policy'
5 ,function_schema => 'APPS'
6 ,policy_function => 'XLA_SECURITY_POLICY_PKG.MO_POLICY'
7 ,statement_types => 'SELECT');
8 END;
9 /
PL/SQL procedure successfully completed.
SQL>
SQL> SELECT object_owner,object_name,policy_name,policy_group,pf_owner,package,function,sel FROM dba_policies where object_name = 'XLA_TRANSACTION_ENTITIES'; OBJECT_OWN OBJECT_NAME POLICY_NAME POLICY_GROUP PF_OW PACKAGE FUNCTION SEL ---------- ------------------------------ ------------------------------ --------------- ----- ------------------------------ ------------------------------ --- APPS XLA_TRANSACTION_ENTITIES PA_SECURITY_POLICY PA APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES DPP_SECURITY_POLICY DPP APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES OKL_SECURITY_POLICY OKL APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES XLA_SECURITY_POLICY XLA APPS XLA_SECURITY_POLICY_PKG XLA_STANDARD_POLICY YES APPS XLA_TRANSACTION_ENTITIES IGC_SECURITY_POLICY IGC APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES SQLAP_SECURITY_POLICY SQLAP APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPS XLA_TRANSACTION_ENTITIES AR_SECURITY_POLICY AR APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES APPSREAD XLA_TRANSACTION_ENTITIES APPSREAD_POLICY SYS_DEFAULT APPS XLA_SECURITY_POLICY_PKG MO_POLICY YES 8 rows selected. SQL>
设置了和APPS相同的policy后,APPSREAD获得了和APPS用户相同的查询结果:
SQL> set autotrace on;
SQL> select count(*) from appsread.XLA_TRANSACTION_ENTITIES where application_id=222;
COUNT(*)
----------
1
Execution Plan
----------------------------------------------------------
Plan hash value: 2139858008
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 8 | 481 (2)| 00:00:06 | | |
| 1 | SORT AGGREGATE | | 1 | 8 | | | | |
| 2 | PARTITION LIST SINGLE| | 1 | 8 | 481 (2)| 00:00:06 | KEY | KEY |
|* 3 | TABLE ACCESS FULL | XLA_TRANSACTION_ENTITIES | 1 | 8 | 481 (2)| 00:00:06 | 2 | 2 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("SECURITY_ID_INT_1" IS NULL)
Statistics
----------------------------------------------------------
2 recursive calls
0 db block gets
1661 consistent gets
0 physical reads
0 redo size
335 bytes sent via SQL*Net to client
350 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
综上可以看出,如果DBMS_RLS.add_policy作用于同义词时,则只对在该过程的object_schema参数中指定的用户下的同义词有效。
最后删除policy,恢复环境:
SQL> exec DBMS_RLS.DROP_POLICY(object_schema=>'APPSREAD',object_name=>'XLA_TRANSACTION_ENTITIES',policy_name=>'APPSREAD_policy');
PL/SQL procedure successfully completed.
SQL>
REF:
1. Using Oracle Virtual Private Database to Control Data Access http://docs.oracle.com/cd/B28359_01/network.111/b28531/vpd.htm
相关文章推荐
- Hibernate查询之SQL查询,查询结果用new新对象的方式接受,hql查询,通过SQL查询的结果返回到一个实体中,查询不同表中内容,并将查到的不同表中的内容放到List中
- Hibernate查询之SQL查询,查询结果用new新对象的方式接受,hql查询,通过SQL查询的结果返回到一个实体中,查询不同表中内容,并将查到的不同表中的内容放到List中
- Oracle EBS-SQL (SYS-1): sysadmin_用户职责查询.sql
- 三种方法实现从“一个(组)查询过程中返回两个表的查询结果”
- Oracle中查询同一个日期字段,格式不同的问题
- oracle 用lambda表达式查询和与原生态sql查询出来的结果不一样。
- 自己实现一个SQL解析引擎 功能:将用户输入的SQL语句序列转换为一个可执行的操作序列,并返回查询的结果集。 SQL的解析引擎包括查询编译与查询优化和查询的运行,主要包括3个步骤: 查询分析
- 和SQL内连接不同,SQL外连接返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行,下面就为您详细介绍SQL外连接,
- Linq to Sql 或linq to entities 与SQL查询结果不一致 返回重复结果问题
- Linq to Sql 或linq to entities 与SQL 查询结果不一致,返回重复结果问题解决方法
- python3 apistar 创建web api 根据前端用户输入返回数据库查询结果
- Oracle中不同用户下的表复制 或 将一个表中的数据复制到另一个表中
- 【oracle 分页问题】这两个查询结果竟然不一样,好神奇?
- oracle 动态拼接语句并返回查询结果集
- oracle赋予一个用户具有查询另一个用户所有表数据
- SQL一次性查询一个字段不同条件下的统计结果
- oracle中不同用户下的表复制 或 将一个表中的数据复制到另一个表中
- 制作一个银行卡用户登录页面,提交后连接数据库进行登录验证,根据验证结果跳转到不同页面
- Oracle EBS-SQL (SYS-19):sys-用户登陆纪录查询.sql
- Oracle一个用户查询另一个用户的表数据