在创建同义词的时候都是明确指定一个对象。建好同义词后,我们可以通过使用同义词的名称来访问指定的对象。
但是在某种特定情况下,不同用户访问相同的同义词,他们访问到的最终对象也不同。
使用视图也存在相同的问题,下面以同义词为例进行说明。
环境:
数据库1 yangtk.yangtingkun 用户yangtk、scott
数据库2 rep.yangtingkun 用户yangtk、scott
两个数据库的用户yangtk的密码相同,用户scott的密码相同。
在站点yangtk.yangtingkun上建立了到rep.yangtingkun的PUBLIC数据库链,语法如下:
CREATE DATABASE LINK REP.YANGTINGKUN USING 'REP';
建立好环境后我们来看下面的语句:
SQL> conn scott/tiger@rep
已连接。
SQL> create table test (name varchar2(20));
表已创建。
SQL> insert into test values (user);
已创建 1 行。
SQL> select * from test;
NAME
--------------------
SCOTT
SQL> commit;
提交完成。
首先连接到REP库,用SCOTT帐户登陆,创建表TEST,并插入当前用户名SCOTT。
SQL> conn yangtk/yangtk@rep
已连接。
SQL> create table test (name varchar2(20));
表已创建。
SQL> insert into test values (user);
已创建 1 行。
SQL> select * from test;
NAME
--------------------
YANGTK
SQL> commit;
提交完成。
用YANGTK帐户登陆REP库,建立同名TEST表,插入当前用户名YANGTK。
SQL> conn scott/tiger@yangtk
已连接。
SQL> create synonym s_test for test@rep.yangtingkun;
同义词已创建。
SQL> select * from s_test;
NAME
--------------------
SCOTT
使用SCOTT用户登陆YANGTK库,建立REP数据库SCOTT帐户下TEST表的同义词S_TEST,然后访问该同义词,不出所料,查询得到的结果是SCOTT。
SQL> conn yangtk/yangtk@yangtk
已连接。
SQL> select * from scott.s_test;
NAME
--------------------
YANGTK
最后使用YANGTK用户登陆YANGTK库,访问SCOTT用户下的同义词S_TEST,但是结果发现,查询得到的结果是YANGTK,也就是说,访问了REP库上YANGTK方案下的TEST表。
这个问题是由于PUBLIC数据库链REP.YANGTINGKUN造成的。由于创建了不带CONNECT TO的数据库链,连接到远端站点使用当前连接用户名和密码。也就是说,YANGTK用户访问REP库使用的用户名是YANGTK,而SCOTT用户则使用SCOTT帐户访问REP库。
当SCOTT用户查询S_TEST时,查询语句扩展为select * from test@rep.yangtingkun,由于登陆用户是SCOTT,所以访问REP的SCOTT.TEST表。
而YANGTK用户访问SCOTT.S_TEST时,查询语句扩展为select * from test@rep.yangtingkun,由于登陆用户是YANGTK,所以访问REP的YANGTK.TEST表。
上面的这种情况会带来意想不到的错误,但是要想避免去很容易,在建立同义词的时候指定用户名就可以了。
SQL> conn scott/tiger@yangtk
已连接。
SQL> create or replace synonym s_test for scott.test@rep.yangtingkun;
同义词已创建。
SQL> select * from s_test;
NAME
--------------------
SCOTT
SQL> conn yangtk/yangtk@yangtk
已连接。
SQL> select * from scott.s_test;
NAME
--------------------
SCOTT