【问题标题】:SELECT records only once within a stored procedure and operate on selected records在存储过程中只选择一次记录并对选定的记录进行操作
【发布时间】:2020-10-19 14:59:20
【问题描述】:

我选择了两次相同的记录集,一次返回 IN REF_CURSOR,然后选择相同的记录来构建一个 CSV,这样我就可以更新 IN 子句中的所有记录...。我可以如何将我的过程更改为 SELECT only一次而不是两次选择相同的记录

      PROCEDURE LOADBATCH(
      inBUCKET_SIZE IN NUMBER,
      OUTCURSOR OUT REF_CURSOR )
  AS
    V_HANDLE      VARCHAR2(2000);
    V_LOCK_RESULT INTEGER;
    IDs           VARCHAR2(2000);
  BEGIN
    BEGIN
      V_HANDLE      := GET_LOCK_HANDLE('BATCH');              
      V_LOCK_RESULT := DBMS_LOCK.REQUEST(V_HANDLE, TIMEOUT => 1); 
      DBMS_OUTPUT.PUT_LINE(V_LOCK_RESULT);
      IF V_LOCK_RESULT <> 1 THEN
        OPEN OUTCURSOR FOR SELECT BATCH_ID,INSTRUCTION_ID,INSTRUCTION_DUMP,BATCH_MSG_TYPE,BATCH_AMOUNT,BATCH_CURRENCY,RECIEVED_DATETIME,MODIFIED_DATETIME,SETTLEMENT_DATE,BATCH_STATUS,FROM_MMBID,BATCH_DATE,MODIFICATION_DATETIME,PARENTBATCH_ID,INSTR_REASON FROM
        ( SELECT DISTINCT BI.*,
          BM.*,
          BM.AMOUNT          AS BATCH_AMOUNT,
          BM.CURRENCY        AS BATCH_CURRENCY,
          BI.PARENT_BATCH_ID AS PARENTBATCH_ID,
          BI.REASON          AS INSTR_REASON
        FROM ACT.BATCH_INSTRUCTIONS BI
        INNER JOIN ACT.BATCH_MESSAGES BM
        ON BI.BATCH_ID  =BM.ID
        WHERE (BI.STAGE = 'NEW'
        OR (BI.STAGE    = 'PICKED'
        AND (SYSDATE    > (BI.LAST_PICKED_AT + interval '65' second))))
        AND (BM.STAGE  <> 'COMPLETED')
        ORDER BY LAST_PICKED_AT ASC
        ) WHERE ROWNUM <=inBUCKET_SIZE ;
        
        SELECT listagg(INSTRUCTION_ID, ',') WITHIN GROUP (
        ORDER BY INSTRUCTION_ID) AS concatenation
        INTO IDs
        FROM
          (SELECT DISTINCT *
          FROM ACT.BATCH_INSTRUCTIONS BI
          INNER JOIN ACT.BATCH_MESSAGES BM
          ON BI.BATCH_ID  =BM.ID
          WHERE (BI.STAGE = 'NEW'
          OR (BI.STAGE    = 'PICKED'
          AND (SYSDATE    > (BI.LAST_PICKED_AT + interval '65' second)))
          )
          AND (BM.STAGE  <> 'COMPLETED')
          ORDER BY LAST_PICKED_AT ASC
          )
        WHERE ROWNUM <=inBUCKET_SIZE ;
        DBMS_OUTPUT.PUT_LINE('IDs are:');
        DBMS_OUTPUT.PUT_LINE(IDs);
        IF( IDs IS NOT NULL) THEN
          UPDATE ACT.BATCH_INSTRUCTIONS
          SET LAST_PICKED_AT    =sysdate,
            STAGE               = 'PICKED'
          WHERE INSTRUCTION_ID IN
            (SELECT INSTRUCTION_ID
            FROM ACT.BATCH_INSTRUCTIONS
            WHERE INSTRUCTION_ID IN
              (SELECT regexp_substr(IDs,'[^,]+', 1, level)
              FROM dual
                CONNECT BY regexp_substr(IDs, '[^,]+', 1, LEVEL) IS NOT NULL
              )
            );
          COMMIT;
        END IF;
      END IF;
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
      NULL;
    END;
    --                        DBMS_OUTPUT.PUT_LINE('releasing lock:');
    V_LOCK_RESULT := DBMS_LOCK.RELEASE(V_HANDLE);
  END LOADBATCH;

【问题讨论】:

  • 请以文本形式发布您的表定义 (ddl) 和示例数据 - 无图像,或者最好是 fiddle,以及该数据的预期结果。还有你期望的数据量。目前还不确定,但可以对 ID 进行批量收集,然后对查询和引用游标使用 TABLE 函数,而不是重复相同的子查询。

标签: oracle select stored-procedures code-duplication


【解决方案1】:

单选无法使用,因为“select into”不接受动态 SQL 也不接受游标。

【讨论】:

  • 那么这种情况如何实现
猜你喜欢
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多