前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >同名的同义词和视图解惑

同名的同义词和视图解惑

作者头像
bisal
发布2020-12-16 18:07:45
1K0
发布2020-12-16 18:07:45
举报
文章被收录于专栏:bisal的个人杂货铺

昨天的文章《v$和v_$的一些玄机》,有朋友提出了一些异议,如下相同名称的两个对象v

文章提到了,

"(1) 假设xbisal,他的基表是xbisal,create view vbisal as select * from xbisal;(3) 创建视图v_bisal,他是基于vbisal视图创建的,create view v_bisal as select * from vbisal;(4)创建公共同义词v$bisal,他表示的是v_$bisal视图,create public synonym v$bisal for v_$bisal;" ;"

准确地说,以上操作的目的,通过v_视图将v视图和普通用户隔离,这种机制适合系统动态性能视图的场景,不是普通用户自定义的视图场景,为什么这么说?

针对系统动态性能视图,数据库启动时,Oracle动态创建了x$表,在此基础之上,创建gv$和v$视图,Oracle创建了gv_$和v_$视图,然后创建了gv$和v$的公共同义词,而真正的v$视图访问的限制是通过软件机制实现的,不是数据库权限控制的。因此,用户访问的v$对象,不是视图,而是指向v_$视图的同义词,而v_$视图才是基于真正的v$视图(基于x$创建的)创建的。这才能达到通过v_$视图将v$视图和普通用户隔离。

P.S.

gv是Global v,除了一些例外,每个v视图都有个对应的gv视图,他是为了满足RAC环境的需要,gv返回所有实例的信息,每个v视图是基于gv视图,只是增加了inst_id列作为where条件,限定在当前实例的信息,例如vsession基于gv

gv$session定义(未显示完整),

针对普通用户自定义的视图,我们稍微改造下最开始的SQL,

1. x$bisal表包含id和a字段。

1. vbisal视图是基于xbisal表,包含id和a字段。

2. v_bisal视图是基于vbisal视图,但是只含max(id)字段。

3. v$bisal的公共同义词是基于v_$bisal视图,只含max(id)字段。

代码语言:javascript
复制
SQL> create table x$bisal (id number, a varchar2(1));
Table created.


SQL> create view v$bisal as select * from x$bisal;
View created.


SQL> create view v_$bisal as select max(id) x from v$bisal;     
View created.


SQL> create public synonym v$bisal for v_$bisal;
Synonym created.


SQL> select object_name, object_type from dba_objects where object_name in ('V$BISAL','X$BISAL','V_$BISAL');
OBJECT_NAME     OBJECT_TYPE
--------------- -------------------
V$BISAL         SYNONYM
V$BISAL         VIEW
V_$BISAL        VIEW
X$BISAL         TABLE

vbisal这个名称,既是视图的名称,又是公共同义词的名称。问题来了,执行检索vbisal,访问的是视图还是公共同义词?

公共同义词v$bisal指向的是含一个字段的视图v_$bisal,视图v$bisal是含两个字段的。我们执行的“desc v$bisal”,返回两个字段,所以可确认他访问的是视图v$bisal,说明在进行数据访问的时候,先访问的是视图,其优先级要高于公共同义词,

代码语言:javascript
复制
SQL> desc v$bisal
 Name          Null?    Type
 ------------- -------- ----------------------------
 ID                     NUMBER
 A                      VARCHAR2(1)

如下是我们创建的顺序,

xbisal(表) -> vbisal(视图) -> v

但实际执行v$bisal得到的是v$bisal(视图),不是v$bisal(同义词),因此,针对普通用户自定义的视图,不能通过v_$视图将v$视图和普通用户隔离。

P.S.

eygle的书中介绍了Oracle对于对象名的解析顺序,

(1) Oracle首先查看在发出命令的用户模式中是否存在表或视图。

(2) 如果表或视图不存在,Oracle会看私有同义词是否存在。

(3) 如果私有同义词存在,将使用这个同义词所引用的对象。

(4) 如果私有同义词不存在,看同名的公共同义词是否存在。

(5) 如果公共同义词存在,将使用这个同义词所引用的对象。

(6) 如果公共同义词不存在,返回信息"ORA-00942 table or view does not exit"。

朋友提出第二个问题,为什么能创建出两个相同名称的对象v$bisal

我们知道,同义词分为public和private,public同义词属于PUBLIC组,每个用户都可以访问,private同义词属于对象所有者,只有其显式授权后其他用户才可访问。

在创建同义词vbisal时指定了public关键字,视图vbisal是当前用户,因此这两个对象其实还是属于不同空间的,不存在同名问题,

代码语言:javascript
复制
SQL> create view v$bisal as select * from x$bisal;
View created.


SQL> create public synonym v$bisal for v_$bisal;
Synonym created.

再测试几个例子,不能创建两个同名的公共同义词,

代码语言:javascript
复制
SQL> create public synonym a for dba_tables;
Synonym created.


SQL> create public synonym a for dba_tables;
create public synonym a for dba_tables
                      *
ERROR at line 1:
ORA-00955: name is already used by an existing object

不能创建两个同名的私有同义词,

代码语言:javascript
复制
SQL> create synonym a for dba_tables;
Synonym created.


SQL> create synonym a for user_tables;
create synonym a for user_tables
               *
ERROR at line 1:
ORA-00955: name is already used by an existing object

但是可创建同名的公共同义词和私有同义词,

代码语言:javascript
复制
SQL> create public synonym a for dba_tables;
Synonym created.


SQL> create synonym a for dba_tables;
Synonym created.


SQL> select object_name, object_type from dba_objects where object_name in ('A');
OBJECT_NAME     OBJECT_TYPE
--------------- -----------------------
A               SYNONYM
A               SYNONYM

但是当前用户下,不能再创建同名对象,无论是视图、序列、还是表,

代码语言:javascript
复制
SQL> create table a(id number);
create table a(id number)
             *
ERROR at line 1:
ORA-00955: name is already used by an existing object


SQL> create sequence a;
create sequence a
                *
ERROR at line 1:
ORA-00955: name is already used by an existing object


SQL> create view a as select * from user_tables;
create view a as select * from user_tables
                               *
ERROR at line 1:
ORA-00955: name is already used by an existing object
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/12/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档