存储过程与匿名块 - 相同的数据,不同的结果

     2023-03-28     161

关键词:

【中文标题】存储过程与匿名块 - 相同的数据,不同的结果【英文标题】: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 */)
              )
   )**

【讨论】:

存储过程中的 MySQL select 语句返回的结果与 proc 外部不同

】存储过程中的MySQLselect语句返回的结果与proc外部不同【英文标题】:MySQLselectstatementinstoredprocreturnsdifferentresultsthanoutsideofproc【发布时间】:2016-02-2220:37:48【问题描述】:我无法弄清楚为什么在mysqlproc之外运行的完全相同的查询... 查看详情

数据库存储过程是啥

参考技术A问题一:sql数据库中的存储过程该怎么理解有什么用啊?存储过程是SQL语句和流程控制语句的预编译***,以一个名称存储并作为一个单元处理。存储过程存储在数据库内,可由应用程序调用执行,而且允许用户声明变... 查看详情

T-SQL 和存储过程使用相同的查询给出不同的结果

】T-SQL和存储过程使用相同的查询给出不同的结果【英文标题】:T-SQLandStoredProceduregivesdifferentresultswithsamequery【发布时间】:2018-04-0618:20:55【问题描述】:我是组的新手。有一个奇怪的问题。我的T-SQL查询返回69行,但存储过程中... 查看详情

oracle中的创建过程,函数,包(代码片段)

一、创建存储过程存储过程是在oracle中存取完成特定业务逻辑的代码块。存储过程是命名块,匿名块不存在数据库中,命名块会存储到数据库中,匿名块每次运行都需要提前编译,命名块一次存储,只会编译一次。命名块可以多... 查看详情

详解一条sql语句的执行过程(代码片段)

...直接运行在数据库上。同时,SQL语句与数据在数据库上的存储方式无关,只是不同的数据库对于同一条SQL语句的底层实现不同罢了,但结果相同。这有点类似于java中接口的作用,一个接口可以有不同的实现类,不同的实现类对... 查看详情

达梦数据库的存储过程

达梦数据库的存储过程数据库的存储过程是非常好的一个功能,有用过oracle存储过程的同学再来写达梦的存储过程就非常容易。说说存储过程的优点:1.让业务执行效率更高,因为语句在存储过程都是编译好的,执行速度更快。2... 查看详情

oracle创建存储过程(代码片段)

存储过程:  存储过程是在oracle中存取完成特定业务逻辑的代码块。存储过程是命名块。命名块会存储到数据库中。匿名块每次运行都需要提前编译。命名块一次存储,只会编译一次。命名块可以多次使用。  创建存储过程... 查看详情

从匿名块返回游标结果

...(需要像在Java中那样使用匿名块,并且无权访问创建的存储功能),以便将文字的使用删除到绑定变量:SELECTIL.LAT_NUM,IL.LNGTD_NUMFROMITEM_LOCATIONILWHEREIL.ITEM_ID 查看详情

怎么用oracleplsql匿名块调用存储过程

现在有一个存储过程producrecore_acct_compare(p_branchinvarchar2,p_formatinvarchar2,p_collate_dateinvarchar2,p_statusinvarchar2)isv_prior_datevarchar(8char);v_start_datevarchar(8char);v_invalidexception;BEGIN...具体过程...ENDcore_acct_compare;怎么用匿名块调用一下这个存储过... 查看详情

在plc编程中怎样使用fb模块

...调用FB块时,需要提供一个DB块做为此FB块的数据块,用于存储此FB块的一些过程数据,第一次运算的结果,能给下次运算使用。  所以,一般比较大的子程序,有很多的中间过程数据,比如PID等,就需要使用FB;一般的程序块... 查看详情

如何通过 JDBC 从 Db2 匿名块返回动态结果集?

...式似乎与MySQL、SQLServer中的工作方式相似,方法是从任何过程逻辑运行简单的SEL 查看详情

mysql数据库(31):存储过程procedure(代码片段)

存储过程procedurestoredprocedure完成特定功能的SQL语句集,存储在数据库中,经过第一次编译之后再次调用不需要编译(效率较高)1、存储过程与函数的区别1.1、相同点都是为了可重复地执行操作数据库的SQL语句集合都是一次编译... 查看详情

为啥调用 sp_who 的 sql 存储过程在通过 SqlCommand 调用时返回的结果与通过 SSMS 调用时返回的结果不同?

】为啥调用sp_who的sql存储过程在通过SqlCommand调用时返回的结果与通过SSMS调用时返回的结果不同?【英文标题】:Whydoesatsqlstoredproceedurethatcallssp_whoreturndifferentresultswhencalledthroughSqlCommnadthanitdoesthroughSSMS?为什么调用sp_who的sql存储过... 查看详情

存储过程非常慢,与具有相同结构的快速视图相比

】存储过程非常慢,与具有相同结构的快速视图相比【英文标题】:storedprocedureveryslow,versusfastviewwiththesameconstruction【发布时间】:2013-11-0615:48:28【问题描述】:我有一个针对特定参数运行非常缓慢的存储过程。存储过程返回一... 查看详情

视图和存储过程的不同结果

】视图和存储过程的不同结果【英文标题】:Differentresultinviewandstoredprocedure【发布时间】:2013-10-2506:46:45【问题描述】:我的表结构是这样的我正在为此表创建视图从dbo.tbPatientReport中选择输入表格中的数据是这样的如果我从sql... 查看详情

oracle存储过程连续执行结果不同

pl/sql里执行存储过程,f8执行后查看结果集,每次都累加.必须把窗口关闭重新测试.这是pl/sql本来就这样的吗,还是我存储过程写的不对??存储过程:http://hi.baidu.com/sordhmbreabivzq/item/a1626cca2873c3ce994aa05b存储过程是别人写的,我完全不懂,能... 查看详情

Pl/pgSQL 匿名代码块在 [42601] 错误上失败:查询没有结果数据的目的地

】Pl/pgSQL匿名代码块在[42601]错误上失败:查询没有结果数据的目的地【英文标题】:Pl/pgSQLanonymouscodeblockfailson[42601]ERROR:queryhasnodestinationforresultdata【发布时间】:2021-06-2011:38:39【问题描述】:假设我在应用程序启动时导入的sql脚... 查看详情

如何在存储过程中直接使用另一个存储过程返回的数据集

...环resultset封装你的数据 参考技术B首先你要知道“另一个存储过程”的结果集的所有列的类型。假设“另一个存储过程”的名字是sp1,没有参数,返回的结果集共3列,全部为int型,那么就在你说的“存储过程”里添加一个与结果... 查看详情