日期:2014-05-16  浏览次数:20448 次

关于oracle synonym 的总结整理

在用户codprov用户下,创建了两个同义词,一个是public的,一个是本用户下的,但是同义词的名称一样,codprov用户有查询cod用户下所有对象的权限。

create or replace public synonym TB_OFR_CUST_REP_DETAIL for COD.VW_OFR_CUST_REP_DETAIL;
create or replace synonym codprov.TB_OFR_CUST_REP_DETAIL for COD.TB_OFR_CUST_REP_DETAIL;

COD.VW_OFR_CUST_REP_DETAIL的内容如下:
CREATE OR REPLACE VIEW COD.VW_OFR_CUST_REP_DETAIL AS
SELECT rd.DISC_RULE_ID DISC_RULE_ID,
?????? rd.STAT_SECT_ID STAT_SECT_ID,
?????? rd.MONEY_ITEM MONEY_ITEM,
?????? rd.MONEY_CLAC_TYPE MONEY_CLAC_TYPE,
?????? rd.DISC_COUNT DISC_COUNT
? FROM MV_OFR_CUST_REP_PRI rp,
?????? MV_OFR_CUST_REP_DETAIL rd
?WHERE rp.DISC_RULE_ID = rd.DISC_RULE_ID
?? AND rp.MONEY_TYPE = '2'
UNION
SELECT rd.DISC_RULE_ID DISC_RULE_ID,
?????? 'A' || rd.DISC_RULE_ID || '_9999' STAT_SECT_ID,
?????? rd.MONEY_ITEM MONEY_ITEM,
?????? rd.MONEY_CLAC_TYPE MONEY_CLAC_TYPE,
?????? rd.DISC_COUNT DISC_COUNT
? FROM MV_OFR_CUST_REP_PRI rp,
?????? MV_OFR_CUST_REP_DETAIL rd
?WHERE rp.DISC_RULE_ID = rd.DISC_RULE_ID
?? AND rp.MONEY_TYPE = '1';
问题:
查询:select * from tb_ofr_cust_rep_detail;能得出如下结果:
DISC_RULE_ID STAT_SECT_ID MONEY_ITEM MONEY_CLAC_TYPE DISC_COUNT
1 A1_9999 1 1 .02
1 A1_9999 2 2 10
1 A1_9999 3 2 0
1 A1_9999 4 2 15
10016 A10016_9999 1 1 .02


查询:SELECT * FROM CODPROV.TB_OFR_CUST_REP_DETAIL;也得出如下结果:
DISC_RULE_ID STAT_SECT_ID MONEY_ITEM MONEY_CLAC_TYPE DISC_COUNT
1 A1_9999 1 1 .02
1 A1_9999 2 2 10
1 A1_9999 3 2 0
1 A1_9999 4 2 15
10016 A10016_9999 1 1 .02

可是查询:select * from cod.tb_ofr_cust_rep_detail;却报错ORA-00942:表和视图不存在,而查询同义词SELECT * FROM CODPROV.TB_OFR_CUST_REP_DETAIL时却没有报ORA-00980同义词转换不再有效的错误。是为什么?

经过分析,发现tb_ofr_cust_rep_detail在cod下确实不存在,因此查询:select * from cod.tb_ofr_cust_rep_detail报ORA-00942:表和视图不存在是必然的,而SELECT * FROM CODPROV.TB_OFR_CUST_REP_DETAIL时却没有报ORA-00980同义词转换不再有效的错误,那是因为这个用户下创建了一个 public的同义词,在codprov用户下创建私有的同义词:create or replace synonym codprov.TB_OFR_CUST_REP_DETAIL for COD.TB_OFR_CUST_REP_DETAIL时;映射的COD.TB_OFR_CUST_REP_DETAIL实际上是先前创建的public 同义词,而他们的名称正好一致,所有给人以错觉,以为他引用的还是cod.tb_ofr_cust_rep_detail的表。如果不创建这个 public同义词,那么查询SELECT * FROM CODPROV.TB_OFR_CUST_REP_DETAIL必定会报ORA-00980同义词转换不再有效的错误。或者说创建的PUBLIC同义词名 称如果和创建私有同义词说映射的对象的名称不一样时,那么查询私有同义词时也会报ORA-00980错误。??? --这个问题得到解释。

?

这里顺便说一下:

1.如果在某一个用户下,创建了一个PUBLIC同义词,如果查询不带用户名查询是不会报表或视图不存在的错误,如果带上用户名查询会则报ORA-00942表或视图错误,因为这个用户下确实没有这个对象。

2.如果再在这个用户下创建一个同名的对象,表、视图或者同义词,那么不管带不带用户名查询,他都会查询这个用户私有的对象,不会查询那个public的同义词,这一点特别要注意,如果在生产环境中,可能会造成很大的数据错误。

最后的总结是,一般情况下尽量避免创建public的同义词,这样会造成很多隐晦的问题,除非不得以才要建。哪个用户需要,就在哪个用户下创建本用户下的同义词,这样比较清晰。