本文转载自微信公众号《DBA的杂念与杂念》,作者:潇湘隐士。转载本文请联系DBA杂念公众号。同义词的概念Oracle的同义词(synonyms)字面意思是别名,有点类似于视图的作用,是一种映射关系。可以节省大量的数据库空间,不同用户对同一张表的操作差别不大;扩展了数据库的使用范围,可以实现不同数据库用户之间的无缝交互;Oracle数据库提供了同义词管理功能。同义词是数据库对象的别名,常用来简化对象访问,提高对象访问的安全性。使用同义词时,Oracle数据库将其翻译成相应模式对象的名称。与视图类似,同义词不占用实际存储空间,只是在数据字典中保存同义词的定义。对于Oracle数据库中的大部分数据库对象,如表、视图、物化视图、序列、函数、存储过程、包、同义词等,数据库管理员可以根据实际情况为其定义同义词。同义词分类Oracle的同义词有两种,Oracle公共同义词和Oracle私有同义词。普通用户创建的同义词一般为私有同义词,公共同义词一般由DBA创建。普通用户如果要创建公共同义词,需要CREATEPUBLICSYNONYM的系统权限。1Oraclepublicsynonyms:属于一个特殊的用户组Public。顾名思义,数据库中的所有用户都可以使用公共同义词。常用的同义词往往用来标示一些常用的数据库对象,而这些对象往往需要大家参考。2Oracleprivatesynonym:对应于publicsynonym,为创建它的用户所有。当然,这个同义词的创建者可以通过授权来控制其他用户是否有权利使用自己的私有同义词。同义词的作用1在多用户协同开发中,可以屏蔽对象的名称及其所有者。如果没有同义词,则在操作其他用户的表时,必须使用用户名.对象名的形式。使用Oracle同义词后,可以隐藏用户名。当然,这里需要注意的是,publicsynonym只定义了一个数据库对象。公共别名,其他用户是否可以通过这个别名访问这个数据库对象取决于用户是否被授权。2为用户简化sql语句。上面的其实是SQL简化的一种体现。同时,如果你建的表名很长,你可以为这张表创建一个Oracle同义词,以简化SQL开发。3为分布式数据库中的远程对象提供位置透明性。4Oracle同义词在数据库链接中的作用数据库链接是一个命名对象,表示从一个数据库到另一个数据库的路径,通过它可以实现不同数据库之间的通信。使用“Oracle连接字符串”创建数据库链接数据库链接名称连接到由密码标识的用户名;通过对象名@数据库链接名访问对象。同义词在数据库链中的作用是提供位置透明性。同义词权限管理与同义词相关的权限包括CREATESYNONYM、CREATEANYSYNONYM和CREATEPUBLICSYNONYM权限。用户以自己的方式创建私有同义词。用户必须具有创建同义词许可,否则无法创建私有同义词。用sys账号给DM账号赋予CREATESYNONYM的权限SQL>GRANTCREATESYNONYMTODM;Grantsucceeded。然后创建私有同义词SQL>CREATESYNONYMTESTFORDM.TM_WGG_ATM_GTW_MON;Synonymcreated2。如果您需要在其他模式下创建同义词,您必须具有CREATEANYSYNONYM权限。看下面的例子,用户DM想在SCOTT模式下创建私有同义词SQL>CREATESYNONYMSCOTT.EMFORSOCTT.EMP;CREATESYNONYMSCOTT.EMFORSOCTT.EMPORA-01031:insufficientprivileges使用sys账号给DM账号CREATEANYSYNONYM权限SQL>GRANTCREATEANYSYNONYMTODM;授予成功。SQL>CREATESYNONYMSCOTT.EMFORSOCTT.EMP;Synonymcreated3。创建公共同义词需要CREATEPUBLICSYNONYM系统特权。创建同义词的语法如下:常用用法如下:SQL>GRANTCREATEANYSYNONYMTODM;Grantsucceeded.SQL>CREATESYNONYMSCOTT.EMFORSOCTT.EMP;Synonymcreated如果要为远程数据库上的表创建同义词,则需要创建一个先使用DatabaseLink(数据库连接)扩展访问,然后使用如下语句创建数据库同义词:createsynonymtable_namefortable_name@DB_Link;publicsynonym与用户的schema无关,但public表示并非所有用户都可以访问,必须获得授权后才能进行;私有同义词是模式视图同义词的对象--------------------------------------------------------------------PUBLICPUBLIC_TESTETLTESTETLSYSN_TESTETLTESTSQL>SELECT*FROMUSER_SYNONYMS使用同义词SELECT*FROMSYSN_TEST;使用同义词保证当数据库的位置或者对象的名称发生变化时,应用程序的代码保持稳定,只需要改变同义词;使用同义词而不指定schema时,先在用户自己的schema中查找,然后在publicsynonym中查找thesynonymoriginalobjectisdeleted,thesynonymwillnotbedeletedCompilethesynonymALTERSYNONYMTCOMPILE;--重新建立同义词原对象时,需要对原对象进行DDL操作后重新编译同义词,同义词的状态将变为INVALID;当再次引用同义词时,同义词会自动编译,无需人工干预,状态变为VALID,当然前提是原对象的名字没有改变SQL>SELECT*FROMT;IDNAME--------------------------------------------------------------------------SQL>SELECT*FROMTEST;IDNAME----------------------------------------------------------------------------SQL>ALTERTABLETESTADDSEXNUMBER(1);TablealteredSQL>SELECTOBJECT_NAME,STATUSFROMALL_OBJECTSWHEREOBJECT_NAME='T';OBJECT_NAMESTATUS---------------------------------------TINVALID问题集锦1.public同义词和私有同义词可以重名吗?如果是,访问同义词时,应该优先使用公共同义词还是私有同义词?是的,如果出现公共同义词和私有同义词同名的情况,在访问同义词时,应该访问私有同义词对象2.为什么HR用户不能访问OE用户创建的公共同义词?因为HR没有权限访问OE模式下的对象,如果OE用户授予HR用户SELECT对象等权限,那么HR用户就可以访问了。3.Canobjects,privatesynonyms,andpublicsynonymshavethesamename?WhatisthepriorityanalysisofsynonymsandtablesinORACLE?Underuserkerry,createatableTESTSQL>CREATETABLETESTASSELECT*FROMUSER_OBJECTSWHERE1=0;createPrivatesynonymTESTSQL>CREATESYNONYMTESTFORREF.REF_WGG_STUDENT;CREATESYNONYMTESTFORREF.REF_WGG_STUDENTORA-00955:nameisalreadyusedbyanexistingobjectNote:Theobject(table)andtheprivatesynonymcannothavethesamename,otherwiseORA-00955errorwillbereportedtocreatethepublicsynonymTEST,asshownbelow,thepublicsynonymSQL>canCREATEPUBLICSYNONYMTESTFORREF.REF_WGG_STUDENT;Synonymcreated访问TEST时,如下所示:它是表TEST的内容,而不是公共同义词的内容SQL>SELECT*FROMTEST;OBJECT_NAMESUBOBJECT_NAMEOBJECT_IDDATA_OBJECT_IDOBJECT_TYPECREATEDLAST_DDL_TIMETIMESTAMPSTATUSTEMPORARYGENERATEDSECONDARY删除表TEST后,此时数据库访问的是公共同义词SQL>DROPTABLETESTPURGE;TabledroppedSQL>SELECT*FROMTEST;IDNAME-------------------------------------------112SQL>Conclusion:Whenthereisanobjectwiththesamenameandapublicsynonym,thedatabasepreferentiallyselectstheobjectasthetarget,andwhenthereisaprivatesynonymandpublicsynonymwiththesamename,thedatabasepreferentiallyselectstheprivatesynonymasthetarget.
