How to work with PL/SQL Arrays or Collections as Parameters then JOIN them Together by Index

為{幸葍}努か 提交于 2019-12-11 05:18:19

问题


I am attempting to create a really simple procedure that creates an account or several accounts. In order to accomplish this I wanted the implementation of the Call that will be made to this Procedure to be as simple as possible. The Code behind the Procedure can be complex or simple but that's not entirely what I care about here as I'm approaching this first from the perspective of the User that will be making the Call to the create_account() Proc.

Simple Call to Create an Account - As you can see in the code I provided there are Zero Declarations... I'm not initializing anything when making the Call. This is important to maximize the level of simplicity regarding the usage of this Procedure.

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;

Basically, I'm looking for the easiest route to allow a user to just type into this call a simple list of comma separated values via an array which will then be parsed in order to perform an insert into an accounts table.

The issue: Since I'm currently taking into the Procedure two collections how do I tie together the entries by index..? Index 1 of Collection 1 should tie to Index 1 of Collection 2 and so on. What is the best approach to make this connection within the PL/SQL contained in the create_account() Procedure?

Ideally I would have loved to be able to do something similar as can be done in C# which would be to just New Up a LIST() Object without the requirement of Declaring that object and to just send that into the Procedure or some sort of multi column array however I'm unable to just send a RECORD Type directly into the Procedure which is why I thought that using the sys.odcivarchar2list collections Oracle provides could work. This approach does allow me to create collections based on my basic comma separated values but they are ONLY single column collections and so I must use Two collections for each of the two parameters I care about here. Eventually I will like to scale up the parameters to include account_type, phone_numbers etc... but I first need to discover the BEST way to tie these collections together based on the index.

See below the work I have begun so far. FULL Script/Code - Very basic but it gets the point across.

/* 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;

Output

/* 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

The correct Output of course would be:

anderson, dan
bebop, bob

回答1:


The collection type you are using is a varray, so it is indexed; you can do:

FOR i IN 1..v_contacts_fname.COUNT
LOOP

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

END LOOP;

Adapting your example code:

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;
/

now gets

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


PL/SQL procedure successfully completed.

You could do a very basic check at the start to verify that the count from both arrays is the same - if not then throw an exception perhaps.

If you want to pass a single collection argument then that argument would need to be a collection of record or object types, declared either at schema level or perhaps in a package, depending on how you want to use the contents (and, to some extent, the version of Oracle you are using). It sounds like you don't want to do that though.



来源:https://stackoverflow.com/questions/56675046/how-to-work-with-pl-sql-arrays-or-collections-as-parameters-then-join-them-toget

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!