Как работать с PL / SQL-массивами или коллекциями в качестве параметров, а затем объединять их по индексу - PullRequest
1 голос
/ 19 июня 2019

Я пытаюсь создать действительно простую процедуру, которая создает учетную запись или несколько учетных записей.Чтобы добиться этого, я хотел, чтобы реализация Call, который будет сделан в этой Процедуре, была как можно более простой.Код, лежащий в основе процедуры, может быть сложным или простым, но это не совсем то, что меня волнует, поскольку я подхожу к этому в первую очередь с точки зрения пользователя, который будет выполнять вызов метода create_account ().

Простой вызов для создания учетной записи - Как вы можете видеть в приведенном мною коде, есть нулевые объявления ... Я не инициализирую ничего при выполнении вызова.Это важно для максимизации уровня простоты в отношении использования этой процедуры.

BEGIN    
  create_account(p_entity_id      => 550005
               , p_sub_id         => 100051
               , v_contacts_fname => sys.odcivarchar2list('dan','bob')
               , v_contacts_lname => sys.odcivarchar2list('anderson','bebop')
  );       
END;

В основном , я ищу самый простой маршрут, позволяющий пользователю простовведите в этот вызов простой список значений через запятую через массив, который затем будет проанализирован для выполнения вставки в таблицу счетов.

Проблема : так как я в настоящее времяпринимая в процедуру две коллекции, как связать записи по индексу?Индекс 1 из Коллекции 1 должен быть связан с Индексом 1 из Коллекции 2 и так далее.Каков наилучший подход для создания этого соединения в PL / SQL, содержащемся в процедуре create_account ()?

В идеале я бы хотел сделать что-то подобное, как это может быть сделано в C #, чтопросто создать объект LIST () без необходимости объявления этого объекта и просто отправить его в процедуру или какой-нибудь многостолбцовый массив, однако я не могу просто отправить тип RECORD напрямуюв процедуре, поэтому я подумал, что использование коллекций sys.odcivarchar2list, которые предоставляет Oracle, может работать.Этот подход позволяет мне создавать коллекции на основе моих базовых значений, разделенных запятыми, но они являются ТОЛЬКО коллекциями из одного столбца, поэтому я должен использовать две коллекции для каждого из двух параметров, которые мне здесь интересны.В конце концов я хотел бы увеличить параметры, чтобы включить account_type, phone_numbers и т. Д. ... но сначала мне нужно найти ЛУЧШИЙ способ связать эти коллекции на основе индекса.

См. Ниже работуЯ начал до сих пор.ПОЛНЫЙ Сценарий / Код - Очень простой, но он дает смысл.

/* This code will run on it's own.  Single PL/SQL Block. */
DECLARE

PROCEDURE create_account(p_entity_id NUMBER
                         , p_sub_id NUMBER
                         , v_contacts_fname sys.odcivarchar2list
                         , v_contacts_lname sys.odcivarchar2list
                         )
  IS

  BEGIN

    dbms_output.put_line('Entity_id: ' || p_entity_id || ' - Sub_id: ' || p_sub_id);

    FOR f IN (SELECT m.column_value fname FROM TABLE(v_contacts_fname) m)
    LOOP

      FOR l IN (SELECT m.column_value lname FROM TABLE(v_contacts_lname) m)
      LOOP
        dbms_output.put_line(l.lname ||', ' || f.fname);
      END LOOP;

    END LOOP;


END create_account;

BEGIN

  create_account(p_entity_id            => 550005
                     , p_sub_id         => 100051
                     , v_contacts_fname => sys.odcivarchar2list('dan','bob')
                     , v_contacts_lname => sys.odcivarchar2list('anderson','bebop')
      ) ;

END;

Вывод

/* I just thru a dbms_output() within both loops for display but of course this is NOT */
/*   how I want to tie together the entries of both collections to each other */
Entity_id: 550005 - Sub_id: 100051
anderson, dan 
bebop, dan
anderson, bob
bebop, bob

Правильный вывод курса будет:

anderson, dan
bebop, bob

1 Ответ

2 голосов
/ 19 июня 2019

Тип коллекции, которую вы используете, является varray, поэтому он индексируется;вы можете сделать:

FOR i IN 1..v_contacts_fname.COUNT
LOOP

  dbms_output.put_line(v_contacts_fname(i) ||', ' || v_contacts_lname(i));

END LOOP;

Адаптировать ваш пример кода:

DECLARE

PROCEDURE create_account(p_entity_id NUMBER
                         , p_sub_id NUMBER
                         , v_contacts_fname sys.odcivarchar2list
                         , v_contacts_lname sys.odcivarchar2list
                         )
  IS

  BEGIN

    dbms_output.put_line('Entity_id: ' || p_entity_id || ' - Sub_id: ' || p_sub_id);

    FOR i IN 1..v_contacts_fname.COUNT
    LOOP

      dbms_output.put_line(v_contacts_fname(i) ||', ' || v_contacts_lname(i));

    END LOOP;


END create_account;

BEGIN

  create_account(p_entity_id            => 550005
                     , p_sub_id         => 100051
                     , v_contacts_fname => sys.odcivarchar2list('dan','bob')
                     , v_contacts_lname => sys.odcivarchar2list('anderson','bebop')
      ) ;

END;
/

теперь получает

Entity_id: 550005 - Sub_id: 100051
dan, anderson
bob, bebop


PL/SQL procedure successfully completed.

Вы можете сделать очень простую проверку в начале, чтобы проверитьчто count из обоих массивов одинаковы - если нет, то, возможно, выдается исключение.

Если вы хотите передать один аргумент коллекции, тогда этот аргумент должен быть коллекцией типов записей или объектов,объявляется либо на уровне схемы, либо, возможно, в пакете, в зависимости от того, как вы хотите использовать содержимое (и, в некоторой степени, версию Oracle, которую вы используете).Похоже, вы не хотите этого делать.

...