Why is APEX_COLLECTION.AddMember only adding the last index called of the outer loop, overwriting the previous indices?

huangapple go评论71阅读模式
英文:

Why is APEX_COLLECTION.AddMember only adding the last index called of the outer loop, overwriting the previous indices?

问题

我明白你的问题,但我不能提供直接的代码解决方案。这个问题可能涉及到代码逻辑和Oracle数据库的特定行为。你可能需要检查以下几个方面来解决这个问题:

  1. apex_collection的使用:确保在每次迭代时正确使用apex_collection,以便每个学校的数据都被添加而不是覆盖。

  2. 循环逻辑:检查循环逻辑,确保在处理每个学校数据时,apex_collection没有被清除或覆盖。

  3. 日志信息:你提到了日志信息,可以进一步分析日志以查看何时和为什么数据被覆盖。这可能有助于找到问题所在。

  4. Oracle版本:确保你使用的Oracle数据库版本没有已知的相关问题,有时候特定版本可能存在一些问题。

如果以上方法都没有解决问题,你可能需要在Oracle社区或论坛上寻求帮助,因为这可能需要更深入的分析和调试。

英文:

I have an procedure that I am calling on APEX. The procedure has two parameters. The status is 'Operational'. Here is sample data for the i_schoolList clob parameter. It splits the data into the l_schoolNames table type:

Harmony
Crestview
Evergreen
Brightside
Summit
Willowbrook
Riverside
Valleyview
Oakridge
Meadowlark

Below is my procedure:

Procedure POPULATE_SCHOOLS(i_status     In Varchar2,
                           i_schoolList In Clob) Is
  
  -- Declare a collection type to store the split values
  TYPE schoolNameList IS TABLE OF VARCHAR2(4000) INDEX BY PLS_INTEGER;

  -- Declare a variable to hold the split values
  l_schoolNames schoolNameList;
  l_count       Number;
  
  -- Declare variables for column values
  l_region       CLONE_FINAL.REGION%TYPE;
  l_schoolName     CLONE_FINAL.school_NAME%TYPE;
  l_sector       CLONE_FINAL.SECTOR%TYPE;

  --Declare variables for error logging
  l_errorNumber  Number;
  l_parameters   Varchar2(4000);
  l_errorMessage Varchar2(4000);
  l_procedure    Varchar2(400);
  l_owner        Varchar2(100);

  --Temporary variables
  l_proc_name  VARCHAR2(100);
  l_error_info VARCHAR2(4000);
  l_log_data   CLOB;
    
  Cursor schoolRows(schoolName In Varchar2)
  Is
    Select region, 
           school_name, 
           sector
    From   S_SCHOOLS
    Where  school_NAME = schoolName;
    
Begin
  -- Calculate the number of occurrences of the delimiter
  l_count := REGEXP_COUNT(i_schoolList, CHR(10)) + 1;

  -- Iterate over the occurrences and extract the substrings
  FOR ind IN 1..l_count LOOP
    l_schoolNames(ind) := REGEXP_SUBSTR(i_schoolList, '[^' || CHR(10) || ']+', 1, ind);
  END LOOP;

  IF apex_collection.collection_exists(p_collection_name => 'SCHOOLS') THEN
    apex_collection.delete_collection(p_collection_name => 'SCHOOLS');
  END IF;


  --Create collection
  apex_collection.create_or_truncate_collection(p_collection_name => 'SCHOOLS');

  --Check if status is operational only. If it is, select from CLONE_FINAL table
  If (i_status = 'Operational')
  Then
    l_errorMessage := 'i.Count=' || l_schoolNames.Count        || CHR(13) || CHR(13) ||
                      'SQLERRM:'                             || CHR(13) || SQLERRM                || CHR(13) || CHR(13) ||
                      'DBMS_UTILITY.FORMAT_ERROR_BACKTRACE:' || CHR(13) || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;
                        
    insert_log_entry(l_proc_name, l_parameters, l_errorMessage);
    
    --Loop through SCHOOLS to get data
    For schoolIndex In 1..l_schoolNames.Count
    Loop
    
      l_errorMessage := 'schoolIndex='         || schoolIndex         || CHR(13) || CHR(13) ||
                        'l_schoolNames.FIRST=' || l_schoolNames.FIRST || CHR(13) || CHR(13) ||
                        'l_schoolNames.LAST='  || l_schoolNames.LAST  || CHR(13) || CHR(13) ||
                        'l_schoolNames.COUNT=' || l_schoolNames.COUNT || CHR(13) || CHR(13) ||
                        'SQLERRM:'                                || CHR(13) || SQLERRM                || CHR(13) || CHR(13) ||
                        'DBMS_UTILITY.FORMAT_ERROR_BACKTRACE:'    || CHR(13) || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;

      DBMS_OUTPUT.PUT_LINE('schoolIndex=' || schoolIndex || ' l_schoolNames(schoolIndex)=' ||  l_schoolNames(schoolIndex));

      insert_log_entry(l_proc_name, l_parameters, l_errorMessage);

      For dataRec In schoolRows(schoolName => l_schoolNames(schoolIndex))
      Loop
          DBMS_OUTPUT.PUT_LINE('l_schoolNames.Count=' || l_schoolNames.Count || ' schoolIndex=' ||  schoolIndex);

          l_errorMessage := 'schoolIndex='                           || schoolIndex                         || CHR(13) || CHR(13) ||
                            'schoolRows(l_schoolNames(schoolIndex)='    || l_schoolNames(schoolIndex)            || CHR(13) || CHR(13) ||
                            'SQLERRM:'                             || CHR(13) || SQLERRM                || CHR(13) || CHR(13) ||
                            'DBMS_UTILITY.FORMAT_ERROR_BACKTRACE:' || CHR(13) || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;
                        
          insert_log_entry(l_proc_name, l_parameters, l_errorMessage);
          --Add the school to the apex collection to display on the Front end page 10922:5
          apex_collection.add_member(p_collection_name => 'SCHOOLS',
                                     p_c001            => dataRec.region,
                                     p_c002            => dataRec.school_name,
                                     p_c003            => dataRec.sector);
      End Loop;
    End Loop;
  End If;
Exception
When Others
Then
  --Set error logging variables
  l_errorNumber  := 56032;

  l_parameters   := 'i_status='   || i_status   || CHR(13) ||
                    'i_schoolList=' || i_schoolList;

  l_errorMessage := 'Error getting schools for "Operational" status'                          || CHR(13) || CHR(13) ||
                    'SQLERRM:'                             || CHR(13) || SQLERRM                             || CHR(13) || CHR(13) ||
                    'DBMS_UTILITY.FORMAT_ERROR_BACKTRACE:' || CHR(13) || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;

  l_procedure    := 'POPULATE_SCHOOLS';

  l_owner        := 'USER';
          
  l_errorMessage := 'ERROR IN EXCEPTION'                          || CHR(13) || CHR(13) ||
                    'SQLERRM:'                             || CHR(13) || SQLERRM                || CHR(13) || CHR(13) ||
                    'DBMS_UTILITY.FORMAT_ERROR_BACKTRACE:' || CHR(13) || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE;
                        
  insert_log_entry(l_proc_name, l_parameters, l_errorMessage);
        --Log error in VODAERR table
        /*LOGGER.LOGERROR(ErrNum    => l_errorNumber, 
                        p_Param   => l_parameters,
                        p_ErrText => l_errorMessage,
                        p_PROC    => l_procedure,
                        p_OWNER   => l_owner);*/

End POPULATE_SCHOOLS;

I have checked the logs that I am logging in the code and can see that only the last index, in this case it is 10 in the example above, gets added to the apex collection. Suppose there are 3 or 4 rows returned in the second cursor, then it only adds the 3 or 4 rows in the last index of the first loop. It seems like it is overwriting the previous apex collection the whole time from the previous loop, because I can see that the index of the first loop gets incremented by looking at the logs. Does someone perhaps know why it is doing this and is this an oracle bug, because I tried using different kind of loops and nothing is working?

答案1

得分: 0

I can provide a translation of the code-related content without the code itself:

"没有您的代码和数据,很难确定出现了什么问题。我唯一能提供的建议是:通过添加调试语句来检查您的代码。您还可以使用add_member函数而不是procedure来查看发生了什么。以下是一个示例:

然后在调试模式下运行页面,检查触发了哪个处理过程,并查看日志。"

Please note that this translation is a direct representation of the code-related content without additional information or responses to translation-related questions.

英文:

Without having your code and data it's challenging to figure out what is going wrong. All I can advise is: instrument your code by adding debug statements. You could also use the add_member function instead of procedure to check what is happening. Here is an example:

DECLARE
  l_collection VARCHAR2(100) := 'EMP';
  l_seq NUMBER;
  l_rows NUMBER;
BEGIN
  APEX_COLLECTION.CREATE_OR_TRUNCATE_COLLECTION(p_collection_name => l_collection);
  apex_debug.info(
    p_message => 'KL Debug: before LOOP');

  FOR r IN (SELECT ename FROM emp)
  LOOP
    apex_debug.info(
        p_message => 'KL Debug: in LOOP ename: %0',
        p0        => r.ename);
    l_seq := APEX_COLLECTION.ADD_MEMBER (
              p_collection_name => l_collection,
              p_c001 => r.ename);
    apex_debug.info(
        p_message => 'KL Debug: in LOOP collection seq: %0',
        p0        => l_seq);
    SELECT count(*) 
      INTO  l_rows 
      FROM apex_collections 
      WHERE collection_name = l_collection; 
    apex_debug.info(
        p_message => 'KL Debug: in LOOP collection rowcount: %0',
        p0        => l_rows);
  END LOOP;
  apex_debug.info(
    p_message => 'KL Debug: after LOOP');
END;

Then run the page in debug, check the request for which the process is fired and go through the logs:

Why is APEX_COLLECTION.AddMember only adding the last index called of the outer loop, overwriting the previous indices?

答案2

得分: 0

希望你一切都好。

这个问题已经解决了。

这个问题的原因是在循环时不喜欢CHR(13)和CHR(10)。似乎如果你使用这两者进行拆分,它不会正确地拆分,而是如果你使用CHR(10),它会取最后一个索引,如果你使用CHR(13),它会取第一个索引。为了解决这个问题,我用管道符号“|”替换了CHR(10)和CHR(13),然后继续拆分它们。希望这样说得清楚。

英文:

Hope you are doing well.

This problem was fixed.

The problem with this one was that it did not like the CHR(13) and CHR(10) when doing the loop. It seems like if you split using those two, it does not split correctly and instead just takes the last index if you use CHR(10) and the first index if you use CHR(13). To resolve this issue, I replaced both CHR(10) and CHR(13) with a pipe "|" and then proceeded to split them. Hope this makes sense.

huangapple
  • 本文由 发表于 2023年5月25日 21:33:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332893.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定