存储过程与匿名块 - 相同的数据,不同的结果
Posted
技术标签:
【中文标题】存储过程与匿名块 - 相同的数据,不同的结果【英文标题】:stored procedure vs anonymous block - same data, different results 【发布时间】:2016-12-05 12:22:49 【问题描述】:当我使用匿名块和存储过程运行相同的代码时,我无法理解我得到的不同结果。他们都从数据字典中获取了一些细节,但看起来存储过程无法提取完整数据:
CREATE OR REPLACE PROCEDURE testing IS
lv_schema VARCHAR2(10) := 'some_schema';
total NUMBER;
CURSOR tab_cur IS
SELECT table_name
, column_name
FROM all_tab_columns
WHERE OWNER = lv_schema;
in_record tab_cur%ROWTYPE;
BEGIN
total := 0;
OPEN tab_cur;
LOOP
FETCH tab_cur INTO in_record;
EXIT WHEN tab_cur%NOTFOUND;
total := total + 1;
END LOOP;
CLOSE tab_cur;
dbms_output.put_line(total);
END testing;
对于我自己的架构,它给了我正确的结果(小架构,找到 13 个结果)。对于我们的一个较小的应用程序,它给出了不完整的结果(50,而不是预期的 83),而对于另一个(大)它列出了 0,而不是 5181)。
我已经驳回了这是因为特权的想法(当我直接使用 SELECT 查询数据字典时,我可以正确查看所有结果),并认为它可能与大小有关(当结果太多时光标失败,不知道),但是当我在匿名块中运行相同的代码时,我得到了所有正确的结果:
DECLARE
lv_schema VARCHAR2(10) := 'some_schema';
total NUMBER;
CURSOR tab_cur IS
SELECT table_name
, column_name
FROM all_tab_columns
WHERE OWNER = lv_schema;
in_record tab_cur%ROWTYPE;
BEGIN
total := 0;
OPEN tab_cur;
LOOP
FETCH tab_cur INTO in_record;
EXIT WHEN tab_cur%NOTFOUND;
total := total + 1;
END LOOP;
CLOSE tab_cur;
dbms_output.put_line(total);
END;
这里唯一的变化是“DECLARE”而不是“CREATE OR REPLACE FUNCTION testing IS”以及从 END 行中删除函数名称...任何人都可以指出我的一些解释吗?
谢谢!
【问题讨论】:
光标失败?如何?你有错误吗? 不,不,没有错误,很抱歉造成误解。这两段代码执行时都没有任何明显的错误,它们只是给出不同的结果。游标无法检索大量数据(我错误地描述为“失败”)的想法正在抓住稻草,我知道...... all_tab_columns 显示的列表取决于授予用户的权限。检查一下,如果它不起作用,请告诉我。 角色将在匿名块中处于活动状态,但在定义者权限过程中不处于活动状态,因此all_*
视图中的差异是可以预料的。
绅士们,我认为威廉·罗伯逊有一点 - 我读了一点(docs.oracle.com/cd/E25054_01/network.1111/e16543/…;搜索“角色如何在 PL/SQL 块中工作”)我尝试使用 DBA_TAB_COLUMNS,asn A Techtown 建议,但是对这两个数据字典表的访问权是从角色授予的,所以即使我似乎对这一切发生的原因有了答案,我仍在寻找一些补救策略。感谢所有参与者!
【参考方案1】:
William Robinson's comment 指出了一个解决方案。
这是来自 Oracle 文档中 Configuring Privilege and Role Authorization 的相关引用:
在具有定义者权限的命名块中使用的角色
在任何命名的 PL/SQL 块(存储过程、 以定义者的权限执行的函数或触发器。
我对使用的数据字典表 (all_tab_columns
) 的访问权限是通过角色授予的。这就是为什么当我在存储过程中运行查询时没有考虑到它。这里的解决方案是创建一个过程,并在创建过程时使用AUTHID CURRENT_USER
子句强制它使用调用者权限而不是定义者权限(这是默认设置)。
【讨论】:
更多的是您对表本身的访问,而不是对 all_tab_columns 视图的访问。假设 HR 将EMPLOYEES
的选择权限授予角色 HR_READONLY
,SCOTT 拥有该权限。 all_
视图将角色考虑在内,因此 SCOTT 在命令行或匿名块中查询时将看到 EMPLOYEES
列在 all_tables
等中,但不是从定义者权限过程内部,其中仅直接授予权限数。【参考方案2】:
您是否尝试过使用 DBA_TAB_COLUMNS。我认为它与权限有关。
下面是 ALL_TAB_COLUMNS 中的附加子句,DBA_TAB_COLUMNS 中没有。
and (o.owner# = userenv('SCHEMAID')
or
o.obj# in ( select obj#
from sys.objauth$
where grantee# in ( select kzsrorol
from x$kzsro
)
)
or /* user has system privileges */
exists (select null from v$enabledprivs
where priv_number in (-45 /* LOCK ANY TABLE */,
-47 /* SELECT ANY TABLE */,
-397/* READ ANY TABLE */,
-48 /* INSERT ANY TABLE */,
-49 /* UPDATE ANY TABLE */,
-50 /* DELETE ANY TABLE */)
)
)**
【讨论】:
以上是关于存储过程与匿名块 - 相同的数据,不同的结果的主要内容,如果未能解决你的问题,请参考以下文章