问题
I have used MULTISET UNION
in order to load a collection into another collection of the same type however I am now working with Records and want to add a Record into a Collection of the same Type. For whatever reason I just can't figure out the appropriate syntax or simply the proper way to do this as MULTISET UNION appears to not play nice with Records in the way I'm used to working with Collections.
I've added a summary of how this code works at the end (supposed to work anyway).
Screenshot and Code Below
LINE 44: c_los_ms_tbl_ret := c_los_ms_tbl_ret MULTISET UNION los_ms_row;
DECLARE
TYPE t_los_ms_rec IS RECORD(
appt_id NUMBER DEFAULT NULL,
appt_name VARCHAR(300) DEFAULT NULL,
tot_units NUMBER DEFAULT 0,
new_rentals NUMBER DEFAULT 0,
term_rentals NUMBER DEFAULT 0,
avg_los_all NUMBER DEFAULT 0
);
TYPE t_los_ms_tbl IS TABLE OF t_los_ms_rec;
/* Two collections based on Table Type of Record t_los_ms_rec */
c_los_ms_tbl_ret t_los_ms_tbl := t_los_ms_tbl();
c_los_ms_tbl t_los_ms_tbl := t_los_ms_tbl();
FUNCTION los_func(p_appt_ids IN VARCHAR) RETURN t_los_ms_tbl
IS
los_ms_row t_los_ms_rec; /* Declare Row based on Record Type */
BEGIN
/* Outer loop: iterate through all user selected appartments. */
FOR los IN
(
SELECT 1001 AS appt_id, 45 AS tot_units, 10 AS new_rentals, 3 AS term_rentals, 'Building1' AS appt_name
FROM dual UNION ALL
SELECT 1002 AS appt_id, 37 AS tot_units, 6 AS new_rentals, 4 AS term_rentals, 'Building2' AS appt_name
FROM duaL
)
LOOP
/* Set Row Fields to the Data being returned by Outer Loop. Fake Table data from dual. */
los_ms_row.appt_name := los.appt_name;
los_ms_row.appt_id := los.appt_id;
los_ms_row.new_rentals := los.new_rentals;
los_ms_row.term_rentals := los.term_rentals;
los_ms_row.tot_units := los.tot_units;
los_ms_row.avg_los_all := 45; /* Made up Number */
/* Output Apartment Name for testing */
dbms_output.put_line('Apartment Name' || los_ms_row.appt_name);
/* Save Row Data into Collection */ /* HOW DO I POPULATE COLLECTION WITH A RECORD */
c_los_ms_tbl_ret := c_los_ms_tbl_ret MULTISET UNION los_ms_row;
END LOOP;
RETURN c_los_ms_tbl_ret; /* Return Populated Collection */
END los_func;
BEGIN
/* Call Function and Store Returned Collection into a collection of same type */
c_los_ms_tbl := los_func(p_appt_ids => '1001,1002');
FOR r IN c_los_ms_tbl.FIRST .. c_los_ms_tbl.LAST
LOOP
dbms_output.put_line(c_los_ms_tbl(r).avg_los_all);
END LOOP;
END;
Summary
- Record Type is Declared.
t_los_ms_rec
- Table Type Declared based on Record
t_los_ms_tbl
Two Collections Declared based on Table Type
c_los_ms_tbl_ret
andc_los_ms_tbl
In the BEGIN block of the Main script the Function
los_func()
that returns a Collection of type t_los_ms_tbl is called using the Apartment IDs as it's parameters.LINE 20:
Withinlos_func()
a Row is Declared namedlos_ms_row
of the Same Typet_los_ms_rec
. The fields of this Row are populated using Fake Data.- Next is to Populate the Collection one Row at a time. Can't figure this out.
- At this point when commenting out
LINE 44
where I attempt to populate the collection the Apartment names are successfully being sent to the dbms_output. This is where it breaks due to me not knowing how to get the Record which is successfully being populated with data into the Collectionc_los_ms_tbl_ret
.
Error report -
ORA-06550: line 44, column 32: PLS-00306: wrong number or types of arguments in call to 'MULTISET_UNION_ALL'
回答1:
MULTISET UNION
is used to create one nested table from two nested tables. You are trying to use MULTISET UNION
to join together a nested table and a single record.
There are two ways you can fix this:
Make a one-element table out of the single record:
c_los_ms_tbl_ret := c_los_ms_tbl_ret MULTISET UNION t_los_ms_tbl(los_ms_row);
Forgo the use of
MULTISET UNION
and just append the new record to the table:c_los_ms_tbl_ret.EXTEND(1); c_los_ms_tbl_ret(c_los_ms_tbl_ret.COUNT) := los_ms_row;
来源:https://stackoverflow.com/questions/55855857/oracle-how-to-add-a-record-to-a-collection-of-the-same-type-multiset-union