【问题标题】:Check Values in sys_refcursor检查 sys_refcursor 中的值
【发布时间】:2013-06-17 12:10:21
【问题描述】:

我在函数中有以下代码

        CREATE OR REPLACE FUNCTION my_func (
        v_dt events.raised_date%TYPE
        )
        RETURN SYS_REFCURSOR
    IS    
            p_events    SYS_REFCURSOR;

        OPEN p_events FOR
                SELECT  event_id
                  FROM  events
                 WHERE  raised_date = v_dt;
RETURN p_events;
END;

我想检查p_events光标中是否存在100。如何在我的函数中执行此操作。

任何帮助都是非常值得赞赏的。

【问题讨论】:

  • 直接从事件中选择计数,而不是尝试检查您的光标(从事件中选择 count(1) 到 my_count ...)

标签: sql oracle plsql oracle10g sys-refcursor


【解决方案1】:

引用游标只是一个查询指针。它“里面”没有任何东西。因此,找出由 ref 游标标识的结果集是否包含特定记录(或确实包含任何记录)的唯一方法是获取游标并通读记录。

请记住,引用光标是一次性的。我们不能多次获取同一个游标。我们必须关闭并重新打开它。但这意味着我们冒着第二个获取的结果集与第一个不同的风险(除非我们更改事务的isolation level)。

所以结果是,只需编写消费过程来获取和使用 ref 游标,并确保它处理感兴趣记录的存在和不存在。

【讨论】:

    【解决方案2】:

    在函数内部检查它不是一个好主意。您错过了返回光标的原因。而是在函数之外进行。

    DECLARE
        l_rc SYS_REFCURSOR := my_func();
    
        TYPE events_ntt IS TABLE OF NUMBER;
        l_events  events_ntt;
    
        l_lookup  events_ntt := events_ntt(100);
        l_diff    events_ntt;
    BEGIN
        FETCH l_rc BULK COLLECT INTO l_events;
    
        l_diff := l_events MULTISET INTERSECT DISTINCT l_lookup;
    
        IF l_diff.COUNT > 0 THEN
            DBMS_OUTPUT.PUT_LINE('100 EXISTS');
        ELSE
            DBMS_OUTPUT.PUT_LINE('100 DOES NOT EXIST');
        END IF;
    END;
    

    使用游标变量(REF CURSOR)

    和游标一样,游标变量指向当前行 多行查询的结果集。游标变量更灵活 因为它与特定查询无关。你可以打开一个游标 用于返回正确列集的任何查询的变量。

    您将游标变量作为参数传递给本地并存储 子程序。在一个子程序中打开游标变量,并且 在不同的子程序中处理它,有助于集中数据 恢复。这种技术对于多语言也很有用 应用程序,其中 PL/SQL 子程序可能会将结果集返回到 用不同语言编写的子程序,例如 Java 或 Visual 基本。

    什么是光标变量(REF CURSOR)?

    游标变量就像指向结果集的指针。你在什么时候使用它们 您想在一个子程序中执行查询,并处理结果 在不同的子程序中(可能是用不同的子程序编写的) 语言)。游标变量的数据类型为 REF CURSOR,您可能 将它们非正式地称为 REF CURSOR。

    与显式游标不同,它始终引用相同的查询工作 area,一个游标变量可以引用不同的工作区。你不能 在需要游标的地方使用游标变量,反之亦然。

    来源:http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/sqloperations.htm#i7106

    (Oracle 数据库 PL/SQL 用户指南和参考)

    【讨论】:

    • 感谢您的详细解释,真的很有帮助。
    【解决方案3】:

    可以这样实现

    declare
      evt EVENTS%ROWTYPE;
      found_100 boolean := false;
    begin
      loop
        fetch p_events into evt;
        exit when p_events%NOTFOUND;
        if evt.event_id = 100 then
          found_100 := true;
          exit;
        end if;
      end loop;
    end;
    

    但是它的效率非常低,因为您可能要获取数百万条记录,而实际上只需要 1 次获取。

    【讨论】:

    • 我在函数中确实有我的 sql 查询的 where 条件,并且记录数将始终小于 10。
    • 我有一个问题,因为我试图查看 sys_refcursor 中的值,我如何引用 evt.event_id 这是一行表事件我问你的原因是在 sql 查询中,我将有一个计算值,例如max(log_event) - log_id 这是一个计算值。那我怎么能引用这个sys_refcursor呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    • 2021-01-26
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多