Oracle同义词(Synonym)是数据库对象的别名,不存储数据,仅作为快捷方式使用。
它分为私有(仅创建者可用)和公有(所有用户可用)两种类型。
主要作用是简化对象引用(避免写完整schema前缀)和实现逻辑隔离(底层表迁移时无需修改代码)。
使用时需注意:权限基于原始对象而非同义词本身,若对原对象无权限,即使有同义词也会报错。
可通过数据字典查看同义词信息,但要避免链式同义词等复杂用法。
简言之,同义词就像"不干胶标签",简化访问但依赖原对象权限。
Oracle 中的同义词(Synonym)
Oracle 中的同义词(Synonym),理解起来其实特别简单。结合你之前遇到的“查 Owner 报权限不足”的问题,我们用大白话 + 生活类比来彻底搞懂它。
1. 一句话核心定义
同义词就是数据库对象的“外号”或“快捷方式”。
它不占物理存储空间(不存数据),只是数据字典里的一条映射记录。它的作用就是给一张表、视图、序列、存储过程等起一个别名。
2. 生活类比(秒懂)
假设你们公司总部在北京,全称叫“北京三体科技有限公司”。
-
真实物理名(Schema.Object):
BEIJING.THREEBODY_TECH(又长又得带归属地)。 -
你要给上海分公司写快递单,每次写全称太累。
-
于是你在上海快递系统里设了一个快捷词,只要输入“三体上海办”,快递员就知道要送到北京总部去。
这个“三体上海办”就是同义词。
3. 两种类型(必考重点)
| 类型 | 英文 | 特点 | 谁来管 |
|---|---|---|---|
| 私有同义词 | Private Synonym | 只有创建者自己能用(或授权给别人)。 | 普通用户(在自己Schema下) |
| 公有同义词 | Public Synonym | 所有人都能直接用(不需要加Schema前缀)。 | 必须由 DBA 或拥有 CREATE PUBLIC SYNONYM 权限的人创建。 |
4. 为什么我们常用同义词?(解决你之前的痛点)
结合你之前问的 “当前用户查Owner报错”,同义词主要用来解决两大痛点:
痛点一:屏蔽复杂的 Schema 前缀(偷懒必备)
没有同义词时,跨用户查询必须写前缀:SELECT * FROM DWHRPT.DWS_ZC_HETQDXX_SS_D;
建了同义词后:
sql
-- DBA 或 DWHRPT 用户执行:
CREATE PUBLIC SYNONYM HETQD FOR DWHRPT.DWS_ZC_HETQDXX_SS_D;
-- 你(普通用户)直接查,无需知道 DWHRPT:
SELECT * FROM HETQD; -- 爽!
痛点二:隐藏物理位置,实现“逻辑隔离”
这是生产环境最牛的地方。如果表 DWS_ZC_HETQDXX_SS_D 因为数据量太大,要迁移到另一个用户 HIS_DATA 下(历史库)。
-
没有同义词:你所有写死的 SQL 全都要改成
HIS_DATA.DWS_ZC...(改代码风险极大)。 -
有同义词:DBA 只需把同义词
HETQD的指向从DWHRPT改为HIS_DATA。你的 SQL 一行都不用改!
5. 核心陷阱:权限是给“本体”的,不是给“外号”的
这是你最需要记住的一句话:
同义词本身没有权限!你操作同义词时,Oracle 检查的是你对“本体(Base Object)”的权限。
-
如果你对
DWHRPT.DWS_ZC_HETQDXX_SS_D没有SELECT权限,那么即使你有了同义词HETQD,执行SELECT * FROM HETQD照样报错ORA-01031: insufficient privileges。 -
解决方法:表的拥有者(
DWHRPT)必须先把SELECT权限授权给你,同义词才能生效。
6. 如何查看当前用户有哪些同义词?
sql
-- 查看你自己创建的同义词
SELECT * FROM USER_SYNONYMS;
-- 查看你能访问到的所有同义词(包括公有的)
SELECT * FROM ALL_SYNONYMS WHERE TABLE_OWNER = 'DWHRPT';
7. 实战避坑清单
-
同义词指向的对象可以不存在:创建时不会报错,但执行时如果本体不存在,会报
ORA-00942: table or view does not exist。 -
公共同义词冲突:如果 DBA 创建了公共同义词
EMP,而你自己也建了一张表叫EMP,那么SELECT * FROM EMP优先查你自己的表(私有对象优先级高于公共同义词)。 -
链式同义词(不建议):同义词指向视图,视图里又引用了同义词。虽然 Oracle 支持(最多 32 层),但维护起来极其混乱,生产环境尽量避开。
总结一句话
同义词就是给数据库对象贴的一张“不干胶标签”。贴了它,你就不用记冗长的“用户名.对象名”,且当底层表位置变动时,只需撕下标签贴到新位置,你的代码毫发无伤。但前提是,你必须拥有访问那个“真身”的权限。
:数据库对象的别名(代表一张表、视图、序列、存储过程等),不存储数据,仅作为快捷方式使用&spm=1001.2101.3001.5002&articleId=163912884&d=1&t=3&u=079945ef284e41c1a5afcbefcc74ba4a)
612

被折叠的 条评论
为什么被折叠?



