Oracle Schema名字和Object名字相同时带来的问题

本文详细解释了在Oracle数据库中,SQL和PL/SQL在解析对象名与Schema名时的不同机制,通过具体案例展示了这种机制可能导致的错误,并提供了解决方案。同时,讨论了在实际应用中遇到类似问题的解决方法,包括避免对象名与Schema名相同,以及在使用FGA功能时如何正确引用对象。

Table 名字和 Schema名字相同:


有schema和表名都为Arwen.
Schema Arwen里面有一个包PKG,包里有函数Plus,返回两数相加的结果
SELECT Arwen.PKG.Plus(1,2) FROM dual; --执行这条sql没出啥错,返回结果3.
但在一个pl/sql 块中就出错了
declare
result int;
begin
select Arwen.PKG.Plus(1,2) into result from dual;
dbms_output.put_line(result);
end;


如果把表Arwen Drop掉,则pl/sql块正确执行.(如果有函数或视图等其他对象的名字和schema相同也会出错)

关于这问题的解释

觉得有点奇怪就上网搜了下,然后在Oralce官方网站上看到有关pl/sql的名字解析方式的介绍,有这么一段话:
PL/SQL and SQL resolve qualified names differently.
For example, when resolving the table name HR.JOBS:
•PL/SQL searches first for packages, types, tables, and views named HR in the current schema, and then for objects named JOBS in the HR schema.
•SQL searches first for objects named JOBS in the HR schema, and then for packages, types, tables, and views named HR in the current schema.


按这解释貌似就可以理解上面的问题了.在sql的名字解析中,碰到带点号的这样的前缀先是把点号前面的当Schema解析,那么Arwen.PKG.Plus(1,2)这语句是先把Arwen当
Schema,然后PKG解析成Schema下的对象,在这里是包.但在PL/SQL中先把点后前面的当成当前schema下的对象,这样Arwen.PKG.Plus(1,2)中的Arwen先被解析成表Arwen,然后pkg解析成表中字段,由于没这样的字段就出错了


看起来Oracle文档上说的没错了,不过发现再弄个例子一试,还是有问题啊,文档里说HR.JOBS是个表,是表的话不太好举例,我就把JOBS改成个函数吧.示例如下
有Schema HR,HR中
有函数JOBS,(没有参数,返回字符串'jobs of schema').
有包HR,包中有函数JOBS,(没有参数,返回字符串'jobs of pkg').
如果按照文档里说的,SELECT HR.JOBS FROM dual;--应该返回的是jobs of schema.
而在pl/sql块中
declare
v_txt varchar2(100);
begin
SELECT HR.JOBS into v_txt FROM dual;
dbms_output.put_line(v_txt);--打印的应该是jobs of pkg
end;
但实际结果不管在sql中还是pl/sql中都是jobs of pkg.

难道Oracle官方文档里说的是坑爹的啊?


哎不管它坑不坑爹,平时尽量注意别把对象名和schema名搞成一样,不然到时出问题了还不容易知道哪出错了,
我其实也不是喜欢钻语法的牛角尖来研究这问题,只是在工作中确实碰到了这问题,犯晕了好久才找到这蛋痛的原因啊.
我碰到这问题是这样一种场景下,我是使用FGA这功能,创建了些审计策略来记录所有schema的DML操作.审计策略中有调用到一个包中的函数,调用时包名前加了schema做前缀.这个前缀是必须得加的.因为在其他schema中做DML操作触发审计策略调用那函数时没schema前缀会找不到的。结果由于那些审计策略所在的schema中有个表名和schema名字相同,结果悲剧就出现了.所有schema做DML操作时触发了审计策略,然后又调用那函数,但调用时出错.这意味着所有schema的DML操作都不能完成了,也意味着差不多整个数据库算是没法用了,想一想这么严重的影响就流汗了,如果要是生产环境中被我这样一整,我估计会被骂死了啊........

### 查询 Oracle 数据库中的 Schema 方法 在 Oracle 数据库中,Schema 是一组逻辑结构的集合,通常与特定用户关联。要查询某个用户的 Schema 或者整个数据库中的 Schema 信息,可以通过访问数据字典视图来实现。 以下是几种常见的查询方式: #### 1. 查询当前用户的对象列表 如果需要查看当前登录用户下的所有对象(包括表、索引、视图等),可以使用 `USER_OBJECTS` 视图[^2]。 ```sql SELECT OBJECT_NAME, OBJECT_TYPE, STATUS FROM USER_OBJECTS; ``` 此查询返回当前用户拥有的所有对象名称及其类型状态。 --- #### 2. 查询指定用户的 Schema 对象 如果需要查询其他用户的 Schema 中的对象,则可以使用 `ALL_OBJECTS` 或 `DBA_OBJECTS` 视图。 - **对于普通用户**:使用 `ALL_OBJECTS` 只能查看有权限访问的对象。 - **对于管理员角色**:使用 `DBA_OBJECTS` 可以查看数据库中所有的对象。 示例 SQL 如下: ```sql -- 查询指定用户名下的所有对象 SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, CREATED FROM ALL_OBJECTS WHERE OWNER = 'SCHEMA_OWNER' -- 替换为具体的模式名 ORDER BY OBJECT_TYPE, OBJECT_NAME; -- 如果具有 DBA 权限,可使用以下语句获取更全面的信息 SELECT OWNER, OBJECT_NAME, OBJECT_TYPE, STATUS FROM DBA_OBJECTS WHERE OWNER = 'SCHEMA_OWNER'; ``` --- #### 3. 获取 Schema 下的具体表信息 为了进一步了解某 Schema 下的表详情,可以结合 `ALL_TABLES` `USER_TAB_COLUMNS` 等视图进行查询。 ##### 查询 Schema 下的所有表 ```sql SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER = 'SCHEMA_OWNER'; ``` ##### 查询表的列定义 如果还需要知道这些表的列信息,可以扩展如下查询: ```sql SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, NULLABLE FROM ALL_TAB_COLUMNS WHERE OWNER = 'SCHEMA_OWNER' AND TABLE_NAME = 'TABLE_NAME'; -- 替换具体表名 ``` --- #### 4. 审计功能与性能调优辅助 当涉及复杂操作时,启用审计功能或自动跟踪可能有助于分析问题。例如,在执行某些 DDL/DML 操作前开启审计记录[^1],或者利用自动跟踪工具定位性能瓶颈[^3]。 启用会话级别的 SQL 跟踪命令如下: ```sql ALTER SESSION SET SQL_TRACE = TRUE; -- 执行目标 SQL 语句... ALTER SESSION SET SQL_TRACE = FALSE; TKPROF TRACE_FILE OUTPUT_FILE; ``` --- #### 5. 表空间管理关 除了 Schema 的元数据外,有时也需要关注其物理存储情况。比如计算表所占的空间大小以及释放未使用的空间[^4]: ```sql -- 计算表占用的空间 SELECT TABLE_NAME, ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS "SIZE(MB)" FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'CUSTOMERS'; -- 释放未使用的空间 ALTER TABLE CUSTOMERS DEALLOCATE UNUSED; ``` --- ### 总结 上述方法涵盖了从基础到高级的不同层次需求,无论是简单的对象浏览还是深入的性能诊断均有所涉猎。根据实际场景选择合适的查询手段即可满足大部分开发运维工作的要求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值