Использовать пользовательский тип для создания массива в памяти — PLS-00306 неправильное количество аргументов

#oracle #plsql #oracle12c

#Oracle #plsql #oracle12c

Вопрос:

Я пытаюсь создать в памяти массив всех таблиц, содержащих пространственные метаданные и пространственный индекс.

* Я столкнулся с ошибкой,

PLS-00306 неправильное количество аргументов

в приведенном ниже коде в строке:**

 v_idx_info_arr(v_array_counter) := 
                 idx_info_arr('THE_TABLE','THE_OWNER','THE_INDEX_NAME');
  

Почему это неправильное количество аргументов, когда тип «index_info» имеет 3 поля типа varchar2 (100)?

Я планирую изменить код с этого ^ на idx_info_arr(rec.index_name, rec.table_owner, rec.table_name); , но для тестирования я оставил его только с жестко закодированными строками.

Я также не уверен в том, как пользовательские типы и массивы работают здесь, в PL / SQL, потому что я собирал их вместе из документации и вопросов о переполнении стека. Любые исправления в этих объявлениях и использовании приветствуются.

 DECLARE
    TYPE index_info IS RECORD(
        table_name varchar2(100),
        table_owner varchar2(100),
        index_name varchar2(100)
    );

    CURSOR all_geom_tables IS
    SELECT gt.owner, gt.table_name, gt.column_name, gt.srid
        FROM all_sdo_geom_metadata gt
        WHERE SRID = 8311            
        ORDER BY TABLE_NAME;

    type idx_info_arr is table of index_info;
    array v_idx_info_arr := idx_info_arr();
    v_array_counter integer := 0;

    v_table_geom sdo_geometry;
    v_spt_index varchar2(100);
    v_view_count integer;
    v_index_count integer;
BEGIN 
-- Start Loop Through all tables in database
    FOR db_table IN all_geom_tables LOOP  
        -- Loop through all tables which have a spatial index
        FOR rec IN (select table_name, table_owner, index_name 
   from ALL_SDO_INDEX_INFO WHERE 
 TABLE_OWNER = db_table.owner
    AND TABLE_NAME = db_table.table_name) LOOP                    
            DBMS_OUTPUT.PUT_LINE('Index name is: ' || rec.index_name);                    
            -- record the index here
      v_idx_info_arr(v_array_counter) := idx_info_arr('THE_TABLE','THE_OWNER','THE_INDEX_NAME');            
            v_idx_info_arr.extend();
            v_array_counter := v_array_counter   1;
        END LOOP;
    END LOOP;
END;
  

Ответ №1:

Для версий ниже Oracle 18c вы не можете назначить все элементы записи сразу. Они должны назначаться индивидуально. Кроме того, v_idx_info_arr.extend требуется перед циклом, так как даже после инициализации без указания элементов коллекция все равно будет иметь нулевой размер.

Код для версий до Oracle 12.2

 DECLARE
     TYPE index_info IS RECORD ( table_name        VARCHAR2(100),
     table_owner       VARCHAR2(100),
     index_name        VARCHAR2(100) );
     TYPE idx_info_arr IS
          TABLE OF index_info;
     v_idx_info_arr    idx_info_arr := idx_info_arr ();
     v_array_counter   INTEGER := 1;

BEGIN
     v_idx_info_arr.extend;
     FOR i IN 1..10 LOOP
          v_idx_info_arr(v_array_counter).table_name := 'THE_TABLE';
          v_idx_info_arr(v_array_counter).table_owner := 'THE_OWNER';
          v_idx_info_arr(v_array_counter).index_name := 'THE_INDEX_NAME';
          v_idx_info_arr.extend ();
          v_array_counter := v_array_counter   1;
     END LOOP;
END;
/
  

Oracle 18c представила квалифицированные выражения, которые позволяют вам это делать.

 v_idx_info_arr(v_array_counter)  := 
                  index_info('THE_TABLE','THE_OWNER','THE_INDEX_NAME');
  

ДЕМОНСТРАЦИЯ для 18c

Комментарии:

1. Спасибо Kaushik, это решило мою проблему и сделало мой код намного лучше