2017-01-20 3 views
-1

La mise à jour FORALL met à jour uniquement le dernier enregistrement de la collection et donne l'erreur ORA-22160: element at l'index [1] n'existe pas. J'ai un scénario où je dois mettre à jour des millions d'enregistrements. Quand j'exécute le code ci-dessous, la mise à jour ne se produit que pour le 100ème enregistrement restant 99 enregistrements restent les mêmes (j'ai testé avec 100 enregistrements). après l'exécution, il donne ORA-22160: l'élément à l'index [1] n'existe pas. J'utilise oracle 9i database.need suggestion pour ce problème.FORALL update met à jour uniquement le dernier enregistrement de la collection et donne l'erreur ORA-22160: l'élément à l'index [1] n'existe pas message d'erreur

Declare 
CURSOR tk_iflow_cur 
    IS 
    SELECT DISTINCT top.rule_id, 
     top.rule_item_id, 
     msib.segment2 
    FROM iflow_rules top, 
     iflow_active_rules msib 
    WHERE top.rule_id = msib.rule_item_id 
    AND msib.organization_id = 5039 and rownum<=100 
    ORDER BY top.ora_inv_item_id; -- cursor fetches 100 row 
    ---Variable declaration 
TYPE l_iflow_id 
IS 
    TABLE OF VARCHAR2(200) INDEX BY BINARY_INTEGER; 
TYPE l_iflow_org 
IS 
    TABLE OF NUMBER INDEX BY BINARY_INTEGER; 
TYPE l_iflow_inv_id 
IS 
    TABLE OF NUMBER INDEX BY BINARY_INTEGER; 
TYPE l_r12_inv_id 
IS 
    TABLE OF NUMBER; 
TYPE l_r12_item_key 
IS 
    TABLE OF VARCHAR2(200) INDEX BY BINARY_INTEGER; 
TYPE l_r12_iflow 
IS 
    TABLE OF VARCHAR2(200) INDEX BY BINARY_INTEGER; 
TYPE l_omar_item_id 
IS 
    TABLE OF NUMBER INDEX BY BINARY_INTEGER; 
TYPE l_omar_seg2 
IS 
    TABLE OF VARCHAR2(200) INDEX BY BINARY_INTEGER; 
    tk_iflow_id l_iflow_id; 
    tk_iflow_org l_iflow_org; 
    tk_iflow_inv_id l_iflow_inv_id; 
    t_omar_item_id l_omar_item_id; 
    t_omar_seg2 l_omar_seg2; 
    r12_inv_id l_r12_inv_id:=l_r12_inv_id(); 
    r12_item_key l_r12_item_key; 
    r12_iflow l_r12_iflow; 
    user_excep EXCEPTION; 
    v_err_count NUMBER; 
    PRAGMA EXCEPTION_INIT (user_excep, -24381); 
    r12_item_id2 VARCHAR2(200); 


BEGIN -- 
    tk_iflow_id.DELETE; 
    tk_iflow_inv_id.DELETE; 
    OPEN tk_iflow_cur; 
    LOOP --Cursor Loop 
    tk_iflow_id.DELETE; 
    tk_iflow_inv_id.DELETE; 
    t_omar_seg2.DELETE; 
    FETCH tk_iflow_cur BULK COLLECT INTO tk_iflow_id, tk_iflow_inv_id, t_omar_seg2; ---100 records assigned to variables 
    FOR i IN 1..tk_iflow_id.COUNT -- to store the cursor value 
    LOOP       --for Loop 
     BEGIN 
     --Comment : passing the cursor value to derive new records from different instance for updating the records 
     SELECT DISTINCT segment1, 
      inventory_item_id, 
      item_type 
     INTO r12_iflow(i), 
      r12_item_id2, 
      r12_item_key(i) 
     FROM [email protected]_db_link 
     WHERE segment1   =tk_iflow_id(i) 
     AND NVL(SEGMENT2,'NULL') = NVL(t_omar_seg2(i),'NULL') 
     AND organization_id  =5063; 
     EXCEPTION 
     WHEN OTHERS THEN 
     r12_inv_id(i) := 0; 
     r12_item_key(i) := 0; 
     END; 
     r12_inv_id :=l_r12_inv_id(); 
     r12_inv_id.EXTEND (i); 
     r12_inv_id (i) := r12_item_id2; 

    END LOOP; --end for loop 
    BEGIN 
     FORALL i IN r12_inv_id.FIRST..r12_inv_id.LAST SAVE EXCEPTIONS -- for all the derived records i'm updating the target table.100 records i'm updating 
     UPDATE iflow_active_rules 
     SET ora_org_id  =5063, 
     ora_inv_item_id =r12_inv_id(i) 
     WHERE iflow_id  =r12_iflow(i) 
     AND ora_inv_item_id = tk_iflow_inv_id(i); 
    EXCEPTION 
    WHEN user_excep THEN 
     v_err_count := SQL%BULK_EXCEPTIONS.COUNT; 
     FOR i  IN 1 .. v_err_count 
     LOOP 
     DBMS_OUTPUT.put_line ('Error: ' || i || ' Array Index: ' || SQL%BULK_EXCEPTIONS (i).ERROR_INDEX || ' Message: ' || SQLERRM (SQL%BULK_EXCEPTIONS (i).ERROR_CODE)); 
     END LOOP; 
    END; 
    BEGIN 
     FORALL i IN r12_inv_id.FIRST .. r12_inv_id.LAST SAVE EXCEPTIONS 
     UPDATE iflow_rules --- updating openup system iflow cost details 
     SET ora_org_id  =5063, 
     ora_inv_item_id =r12_inv_id(i) 
     WHERE iflow_id  =r12_iflow(i) 
     AND ora_inv_item_id = tk_iflow_inv_id(i) ; 
    EXCEPTION 
    WHEN user_excep THEN 
     v_err_count := SQL%BULK_EXCEPTIONS.COUNT; 
     FOR i  IN 1 .. v_err_count 
     LOOP 
     DBMS_OUTPUT.put_line ('Error: ' || i || ' Array Index: ' || SQL%BULK_EXCEPTIONS (i).ERROR_INDEX || ' Message: ' || SQLERRM (SQL%BULK_EXCEPTIONS (i).ERROR_CODE)); 
     END LOOP; 
    END; 
    EXIT 
    WHEN tk_iflow_id.COUNT=0; 
    COMMIT; 
    END LOOP; --End Cursor Loop 
    CLOSE tk_iflow_cur; 
END; 

Répondre

0

Cela se produit parce que vous utilisez collection r12_iflow dans le cadre de la collecte r12_inv_id où il ne sont pas accessibles. FORALL déclaration est différent le FOR LOOP. Même s'ils fonctionnent assez bien sur la même logique mais ils diffèrent sur la portée de l'utilisation des variables. Vous pouvez créer un RECORD dans votre boîtier et effectuer le traitement. Voir ci-dessous comment vous pouvez le faire. PS Non testé.

DECLARE 
    CURSOR tk_iflow_cur 
    IS 
     SELECT DISTINCT top.rule_id, top.rule_item_id, msib.segment2 
      FROM iflow_rules top, iflow_active_rules msib 
     WHERE  top.rule_id = msib.rule_item_id 
       AND msib.organization_id = 5039 
       AND ROWNUM <= 100 
     ORDER BY top.ora_inv_item_id;     -- cursor fetches 100 row 


    Type var_cur is table of tk_iflow_cur%rowtype index by pls_integer;  
    l_cur var_cur; 

    --Record of your variables. 
    TYPE var_rec is RECORD 
    (
     l_r12_iflow VARCHAR2 (200), 
     l_r12_inv_id number, 
     l_r12_item_key VARCHAR2 (200) 

    ); 

    TYPE rec is table of var_rec index by pls_integer; 

    --Variable declared to hold the result of your cursor. 
    l_rec rec; 

    user_excep  EXCEPTION; 
    v_err_count  NUMBER; 
    PRAGMA EXCEPTION_INIT (user_excep, -24381); 
    r12_item_id2  VARCHAR2 (200); 
BEGIN                   
    OPEN tk_iflow_cur; 

    LOOP               --Cursor Loop  

     FETCH tk_iflow_cur BULK COLLECT INTO l_cur LIMIT 100; ---100 records assigned to variables   

     FOR i IN 1 .. l_cur.COUNT    -- to store the cursor value 
     LOOP               --for Loop 
     BEGIN 
      --Comment : passing the cursor value to derive new records from different instance for updating the records 
      SELECT DISTINCT segment1, inventory_item_id, item_type 
       INTO l_rec(i).l_r12_iflow ,l_rec(i).l_r12_inv_id ,l_rec(i).l_r12_item_key 
       FROM [email protected]_db_link 
      WHERE segment1 = l_cur(i).rule_id 
       AND NVL (SEGMENT2, 'NULL') = NVL (l_cur(i).segment2 , 'NULL') 
       AND organization_id = 5063; 
     EXCEPTION 
      WHEN OTHERS 
      THEN 
       l_rec(i).l_r12_iflow := 0; 
       l_rec(i).l_r12_inv_id:= 0; 
       l_rec(i).l_r12_item_key := ''; 
     END; 

     END LOOP;             --end for loop 

     BEGIN 
     FORALL i IN 1 .. l_rec.COUNT SAVE EXCEPTIONS -- for all the derived records i'm updating the target table.100 records i'm updating 
      UPDATE iflow_active_rules 
       SET ora_org_id = 5063, 
        ora_inv_item_id = l_rec(i).l_r12_inv_id 
      WHERE  iflow_id = l_rec(i).l_r12_iflow 
       AND ora_inv_item_id = l_rec(i).l_r12_inv_id; 

     EXCEPTION 
     WHEN user_excep 
     THEN 
      v_err_count := SQL%BULK_EXCEPTIONS.COUNT; 

      FOR i IN 1 .. v_err_count 
      LOOP 
       DBMS_OUTPUT.put_line (
        'Error: ' 
        || i 
        || ' Array Index: ' 
        || SQL%BULK_EXCEPTIONS (i).ERROR_INDEX 
        || ' Message: ' 
        || SQLERRM (SQL%BULK_EXCEPTIONS (i).ERROR_CODE)); 
      END LOOP; 
     END; 

     BEGIN 
     FORALL i IN 1..l_rec.COUNT SAVE EXCEPTIONS 
      UPDATE iflow_rules --- updating openup system iflow cost details 
       SET ora_org_id = 5063, 
        ora_inv_item_id = l_rec(i).l_r12_inv_id 
      WHERE  iflow_id = l_rec(i).l_r12_iflow 
      AND ora_inv_item_id = l_rec(i).l_r12_inv_id; 

     EXCEPTION 
     WHEN user_excep 
     THEN 
      v_err_count := SQL%BULK_EXCEPTIONS.COUNT; 

      FOR i IN 1 .. v_err_count 
      LOOP 
       DBMS_OUTPUT.put_line (
        'Error: ' 
        || i 
        || ' Array Index: ' 
        || SQL%BULK_EXCEPTIONS (i).ERROR_INDEX 
        || ' Message: ' 
        || SQLERRM (SQL%BULK_EXCEPTIONS (i).ERROR_CODE)); 
      END LOOP; 
     END; 

     EXIT WHEN tk_iflow_cur%NOTFOUND; 
    END LOOP;             --End Cursor Loop 

    COMMIT; 
    CLOSE tk_iflow_cur; 

END;