且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

[20120901]关于同义词(Synonyms).txt

更新时间:2022-09-01 11:06:31

[20120901]关于同义词(Synonyms).txt

    我第1次知道同义词这个概念,是自己写代码,要访问别的schema的表,前面要加schema,问了当时开发人员才知道要建立同一词。
现在想想自己都觉得好笑!
    我还记得以前优化sql,因为以dba用户进入,要执行用户的sql语句,总是无法执行,我自己总是给语句补上schema,后来才知道
命令:ALTER SESSION SET current_schema = "XXX";
    知道同义词后,为了简便(我记得以前toad 7没有像现在的版本一样,可以在执行前,选择current_schema),我会建立对应表的
同义词。知道有一次我遇到一个问题,我看到的执行计划老是与实际执行的不符合,检查才发现原来程序中访问的表与我定义的同义词
对应的表不一致。从那以后,我很少为了优化,工作方便等原因,定义同义词。而且我自己一直很烦同义词。

1.测试环境:
SQL> select * from v$version ;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

create table t as select rownum id,'test' name from dual connect by level
create public synonym t_syn for t;

SQL> select status from dba_objects where object_name='T_SYN';
STATUS
-------
VALID

SQL> SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
OWNER      NAME       TYPE               REFERENCED_OWNER               REFERENCED REFERENCED_TYPE    REFERENCED DEPE
---------- ---------- ------------------ ------------------------------ ---------- ------------------ ---------- ----
PUBLIC     T_SYN      SYNONYM            SCOTT                          T        TABLE                         HARD

SQL> column db_link format a10
SQL> select * from DBA_synonyms where wner='PUBLIC' and SYNONYM_NAME='T_SYN';
OWNER      SYNONYM_NAME                   TABLE_OWNER                    TABLE_NAME DB_LINK
---------- ------------------------------ ------------------------------ ---------- ----------
PUBLIC     T_SYN                          SCOTT                          T

2,修改表名:

alter table T rename to zzz;
SQL> SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
OWNER      NAME       TYPE               REFERENCED_OWNER               REFERENCED REFERENCED_TYPE    REFERENCED DEPE
---------- ---------- ------------------ ------------------------------ ---------- ------------------ ---------- ----
PUBLIC     T_SYN      SYNONYM            SCOTT                          ZZZ        TABLE                         HARD

--REFERENCED='ZZZ'?

SQL> select status from dba_objects where object_name='T_SYN';
STATUS
-------
INVALID

SQL> select * from DBA_synonyms where wner='PUBLIC' and SYNONYM_NAME='T_SYN';
OWNER      SYNONYM_NAME                   TABLE_OWNER                    TABLE_NAME DB_LINK
---------- ------------------------------ ------------------------------ ---------- ----------
PUBLIC     T_SYN                          SCOTT                          T
--DBA_synonyms依旧指向的是表T。

SQL> select * from  t_syn;
select * from  t_syn
               *
ERROR at line 1:
ORA-00980: synonym translation is no longer valid

SQL> select status from dba_objects where object_name='T_SYN';
STATUS
-------
VALID

--??视乎修正回来了,但是执行,问题依旧。语句应该通过DBA_synonyms来定位,表T已经不存在了,自然访问错误!

SQL> select * from  t_syn;
select * from  t_syn
               *
ERROR at line 1:
ORA-00980: synonym translation is no longer valid

修改回来后一些正常!
alter table zzz rename to t;

3.删除表t:
SQL> drop table t;

SQL> select status from dba_objects where object_name='T_SYN';
STATUS
-------
INVALID

SQL> select * from DBA_synonyms where wner='PUBLIC' and SYNONYM_NAME='T_SYN';
OWNER      SYNONYM_NAME                   TABLE_OWNER                    TABLE_NAME DB_LINK
---------- ------------------------------ ------------------------------ ---------- ----------
PUBLIC     T_SYN                          SCOTT                          T
--依旧指向表T。

SQL> SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
OWNER      NAME       TYPE               REFERENCED_OWNER               REFERENCED REFERENCED_TYPE    REFERENCED DEPE
---------- ---------- ------------------ ------------------------------ ---------- ------------------ ---------- ----
PUBLIC     T_SYN      SYNONYM            SCOTT                          BIN$yJ2b7H TABLE                         HARD
                                                                        dJ1VbgQKjA
                                                                        KGRoDQ==$0

--DBA_DEPENDENCIES的REFERENCED指向了删除的对象。

SQL> select * from t_syn;
select * from t_syn
              *
ERROR at line 1:
ORA-00980: synonym translation is no longer valid

SQL> SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
no rows selected
--如果执行查询select * from t_syn;再查询SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
--结果没有行返回。看来有后台进程做清理工作。

4.建立一张新表T,里面的字段与原来不同。并且做一个跟踪看看。

SQL> create table t as select * from emp;

SQL> select object_id,data_object_id,status from dba_objects where object_name='T_SYN';
 OBJECT_ID DATA_OBJECT_ID STATUS
---------- -------------- -------
    106164                INVALID

SQL> select * from DBA_synonyms where wner='PUBLIC' and SYNONYM_NAME='T_SYN';
OWNER      SYNONYM_NAME                   TABLE_OWNER                    TABLE_NAME DB_LINK
---------- ------------------------------ ------------------------------ ---------- ----------
PUBLIC     T_SYN                          SCOTT                          T

SQL> SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
no rows selected

SQL> alter session set events '10046 trace name context forever, level 12'
SQL> select * from t_syn where rownum
     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ------------------- ---------- ---------- ----------
      8000 ZWS        CLERK           7782 2001-01-23 00:00:00       1700                    60
--执行成功!
SQL> alter session set events '10046 trace name context forever, level 12'

SQL> SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
OWNER      NAME       TYPE               REFERENCED REFERENCED REFERENCED_TYPE    DEPE
---------- ---------- ------------------ ---------- ---------- ------------------ ----
PUBLIC     T_SYN      SYNONYM            SCOTT      T          TABLE              HARD

--从跟踪文件发现:
SQL ID: 1xb9vhvwp9g2s
Plan Hash: 0
ALTER PUBLIC SYNONYM "T_SYN" COMPILE

insert into dependency$(d_obj#,d_timestamp,order#,p_obj#,p_timestamp,
  property, d_attrs)
values
 (:1,:2,:3,:4,:5,:6, :7)

5.定义环路问题:

SQL> drop public synonym t_syn;
Synonym dropped.

SQL>  create public synonym t_syn for t_syn;
Synonym created.
--按照道理,这样建立不应该成功。
--我自己曾经遇到的问题是在expdp在备份文件时要产生一个SYS_EXPORT_TABLE_01文件,如果在toad里面没有刷新,实际上备份
--完成后会删除,如果建立同义词是对应的表已经删除就会出现以上情况。以后expdp就会出错。
ORA-39001: invalid argument value
ORA-01775: looping chain of synonyms

SQL> SELECT * FROM DBA_DEPENDENCIES WHERE name = 'T_SYN'  and wner='PUBLIC';
OWNER      NAME       TYPE               REFERENCED REFERENCED REFERENCED_TYPE    DEPE
---------- ---------- ------------------ ---------- ---------- ------------------ ----
PUBLIC     T_SYN      SYNONYM            PUBLIC     T_SYN      SYNONYM            HARD

SQL> select object_id,data_object_id,status from dba_objects where object_name='T_SYN';
 OBJECT_ID DATA_OBJECT_ID STATUS
---------- -------------- -------
    106164                VALID

SQL> select * from DBA_synonyms where wner='PUBLIC' and SYNONYM_NAME='T_SYN';
OWNER      SYNONYM_NA TABLE_OWNE TABLE_NAME
---------- ---------- ---------- ----------
PUBLIC     T_SYN      SCOTT      T_SYN

SQL> select * from t_syn;
select * from t_syn
              *
ERROR at line 1:
ORA-01775: looping chain of synonyms
--出现环路!

还有比较特殊的情况像这样
CREATE SYNONYM s1 for s2;
CREATE SYNONYM s2 for s3;
CREATE SYNONYM s3 for s1;

--可以通过如下脚本查询:
--参考http://tamimdba.wordpress.com/2011/03/12/ora-01775-looping-chain-of-synonyms/

SELECT     owner, synonym_name, CONNECT_BY_ISCYCLE CYCLE
      FROM dba_synonyms
     WHERE CONNECT_BY_ISCYCLE > 0
CONNECT BY NOCYCLE PRIOR table_name = synonym_name AND PRIOR table_owner = owner
UNION
SELECT 'PUBLIC', synonym_name, 1
  FROM dba_synonyms
 WHERE wner = 'PUBLIC' AND table_name = synonym_name AND (table_name, table_owner) NOT IN (SELECT object_name, owner
                                                                                              FROM dba_objects
                                                                                             WHERE object_type != 'SYNONYM')