Почему последний элемент в ассоциативном массиве (индекс по таблице) не печатается? - PullRequest
1 голос
/ 12 апреля 2020

Это похоже на базовую c вещь, но я не могу понять. У меня есть кодовый блок PL SQL, как показано ниже. Он создает простой разреженный ассоциативный массив и хранит 5 элементов в индексах как -1,0,1,2,100.

Печать ARRAY.LAST дает 100, а ARRAY.COUNT дает 5. В мое время l oop правильно печатает все элементы. Но при l oop при переходе от ARRAY.FIRST к ARRAY.LAST печатаются только элементы последовательных подписок до 2, даже если ARRAY.LAST дает 100

DECLARE
    TYPE assoc_array IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
    table1 assoc_array;
    i BINARY_INTEGER;
BEGIN
    table1(-1) := 100;
    table1(0) := 101;
    table1(1) := 102;
    table1(2) := 103;
    table1(100) := 104;

    i := table1.FIRST;

    dbms_output.put_line(table1.FIRST);
    dbms_output.put_line(table1.LAST);
    dbms_output.put_line(table1.COUNT);

    i := table1.first;

    while (i is not null)
    loop
        dbms_output.put_line( table1(i) );
        i := table1.next(i);
    end loop;

    dbms_output.put_line( '***');

    for i IN table1.FIRST .. table1.LAST
    loop
        dbms_output.put_line(table1(i) );
    end loop;
END;

Вывод выглядит так:

-1
100
5
100
101
102
103
104
***
100
101
102
103

Ответы [ 2 ]

2 голосов
/ 12 апреля 2020

Добавьте этот фрагмент в свой блок, чтобы увидеть причину. ORA-01403:

  ...
EXCEPTION 
  WHEN no_data_found THEN
    dbms_output.put_line(sqlerrm);
END;

Ваш l oop не l oop из-за действующих индексов массива. Он возвращается с -1 .. 100, и когда вы пытаетесь получить доступ к table1(3), ну, вы не можете.

В качестве альтернативы, вы можете запустить это:

FOR i IN table1.FIRST .. table1.LAST LOOP
  IF table1.EXISTS(i) THEN 
    dbms_output.put_line(table1(i));
  END IF;
END LOOP;

Но это не очень хорошая идея потому что совершенно неэффективно, чтобы l oop через все целочисленные значения, которые вы уже знаете, не являются индексами вашего ассоциативного массива.

1 голос
/ 12 апреля 2020

ARRAY.FIRST - это наименьший индекс в вашем массиве, поэтому в вашем случае это будет -1. С другой стороны, ARRAY.LAST взял наибольшее индексное число (100).

Затем FOR l oop от наименьшего индекса к наибольшему с шагом 1. Но когда он достигает не существующий индекс вызовет исключение.

Так что просто добавьте один оператор IF внутри вашего l oop, чтобы проверить, существует ли элемент с определенным индексом.

IF array.EXISTS(i) THEN
  -- do something
 null;
END IF;
...