【问题标题】:Oracle package - Create a cursor using temp tableOracle 包 - 使用临时表创建游标
【发布时间】:2019-10-29 12:28:11
【问题描述】:

我正在尝试解决与包中的存储过程有关的问题并且需要一些指导。

在 SP 内部的某个时刻,一条记录或一组记录被插入到临时表中。我说可能是一组记录,因为插入发生在循环内。当循环退出时,使用从此临时表中的选择设置游标并删除临时表的内容。

这不意味着光标现在将向调用它的应用程序返回空数据集吗?

这是代码;输入是一个或多个项目ID(我修剪了不必要的代码):

PROCEDURE USPGETOUTCOMEBYITEMCOI
(
IPSITEMIDS                VARCHAR2,
OPDQUERIEDON              OUT TIMESTAMP,
OPIERRORCODE              OUT NUMBER,
CUR_OUT                   OUT GETDATACURSOR
)
IS
LVIERRORCODE            NUMBER(38):=0;
LVSQUERY                VARCHAR2(4000):='';
V_NEWITEM VARCHAR2(38);
V_NEWITEM2 VARCHAR2(4000);
V_TEMPITEMID VARCHAR2(38);
V_NEWITEMSLIST VARCHAR2(4000) := REPLACE(IPSITEMIDS, '''', '');
V_ORIGINDATE     TIMESTAMP;

CURSOR cur IS
SELECT  REGEXP_SUBSTR(V_NEWITEMSLIST, '[^,]+', 1, LEVEL) V_NEWITEM2 FROM DUAL CONNECT BY instr(V_NEWITEMSLIST, ',',1, LEVEL -1) > 0;

BEGIN
-- Loop thorugh each ITEM ID and determine outcome, add ITEM ID and OUTCOME to temp table
FOR rec IN cur LOOP   
    V_NEWITEM := rec.V_NEWITEM2;
    ....
    INSERT INTO TEMPOUTCOME
    (
      ITEMID,
      OUTCOME,
      ORIGINDATE
    )
    VALUES
    (
        V_TEMPITEMID,
        V_OUTCOME,
        V_ORIGINDATE
    );
    COMMIT;
    ....
END LOOP;
LVSQUERY:='SELECT ITEMID, OUTCOME, ORIGINDATE FROM TEMPOUTCOME WHERE ITEMID IN (' || IPSITEMIDS || ')';

OPEN CUR_OUT FOR LVSQUERY;

OPDQUERIEDON:= SYSTIMESTAMP;

-- Delete from temp table all item IDs used in this session
DELETE FROM TEMPOUTCOME WHERE ITEMID IN (select REGEXP_SUBSTR(IPSITEMIDS, '\''(.*?)\''(?:\,)?', 1, LEVEL, NULL, 1) FROM dual CONNECT BY LEVEL <= REGEXP_COUNT(IPSITEMIDS, '''(?: +)?(\,)(?: +)?''', 1) + 1);        

【问题讨论】:

    标签: stored-procedures cursor oracle12c


    【解决方案1】:
    CREATE GLOBAL TEMPORARY TABLE today_sales(order_id NUMBER)
    ON COMMIT delete ROWS
    
    set serveroutput on
    declare
        cursor cur_temp is select
                               *
                           from
                               today_sales;
    
    begin
        insert into today_sales values ( 1 );
    
        commit;
        for i in cur_temp loop
            dbms_output.put_line('There is data');
        end loop;
    end;
    

    所以我执行了上面的两个代码,它没有打印任何东西。这意味着只要你commit,数据将被删除,cursor 将返回 0 条记录。

    如果你通过removing/commenting commit 执行上述相同的代码(plsql 代码),这将打印数据,这意味着游标正在返回记录。

    所以回答你的问题:是的,一旦你提交,光标就会返回空数据集。

    【讨论】:

    • 谢谢。这与我在示例代码中包含的内容相同吗? GLOBAL TEMPORARY 是否与常规表相同?我的临时表称为 temp 但它是一个常规数据库表。我只是不想在其中保留大量数据,一旦返回光标,这些数据就会变得无用。
    • Global Temporary 和普通表不同。您可以使用this 进行更多探索。如果您不想深入,可以在执行过程中的操作后发出truncate。这样对于不知道temporary table 的其他人来说会更容易理解,因为它将使用常规表和truncate
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 2016-04-02
    • 2015-12-12
    • 2019-12-07
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多