2017-01-20 7 views
-1

Обновление FORALL обновляет только последнюю запись из коллекции и дает ошибку ORA-22160: элемент at index [1] не существует. У меня сценарий, я должен обновить миллион записей. Когда я выполняю приведенный ниже код, обновление происходит только для 100-й записи, оставшиеся 99 записей остаются такими же (я тестировал 100 записей). после выполнения он дает ORA-22160: элемент в индексе [1] не существует. Я использую oracle 9i database.need предложение для этой проблемы.Обновление FORALL обновляет только последнюю запись из коллекции и дает ошибку ORA-22160: элемент в индексе [1] не существует сообщение об ошибке

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; 

ответ

0

Это происходит потому, что вы используете r12_iflow коллекции в рамках коллекции r12_inv_id, где он не не доступен. FORALL заявление отличается от FOR LOOP. Несмотря на то, что они работают довольно с одинаковой логикой, но они различаются по объему использования переменных. Вы можете создать RECORD в вашем случае и выполнить обработку. Смотрите ниже, как вы можете это сделать. PS Не проверен.

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;