92
Copyright © 2015 Oracle and/or its affiliates. All rights reserved. | All About PL/SQL Collections 1 Steven Feuerstein Oracle Developer Advocate for PL/SQL Oracle CorporaDon Email: [email protected] TwiLer: @sfonplsql Blog: stevenfeuersteinonplsql.blogspot.com YouTube: PracDcally Perfect PL/SQL

All About PL/SQL Collections

Embed Size (px)

Citation preview

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.|

All About PL/SQL Collections

1

StevenFeuersteinOracleDeveloperAdvocateforPL/SQL

OracleCorporaDon

Email:[email protected]:@sfonplsql

Blog:stevenfeuersteinonplsql.blogspot.comYouTube:PracDcallyPerfectPL/SQL

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page2

ResourcesforOracleDatabaseDevelopers• OfficialhomeofPL/SQL-oracle.com/plsql•  SQL-PL/SQLdiscussionforumonOTNhLps://community.oracle.com/community/database/developer-tools/sql_and_pl_sql

•  PL/SQLandEBRblogbyBrynLlewellyn-hLps://blogs.oracle.com/plsql-and-ebr

• OracleLearningLibrary-oracle.com/oll• WeeklyPL/SQLandSQLquizzes,andmore-plsqlchallenge.oracle.com•  AskTom-asktom.oracle.com–'nuffsaid•  LiveSQL-livesql.oracle.com–scriptrepositoryand12/712cdatabase•  oracle-developer.net-greatcontentfromAdrianBillington•  oracle-base.com-greatcontentfromTimHall

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page3

Agenda•  IntroducDonandoverview•  DefiningandusingcollecDontypes•  UsingcollecDonmethods• WorkingwithassociaDvearrays• Workingwithnestedtables• Workingwithvarrays•  UsingcollecDonsinsideSQL•  BenefitsofNon-SequenDalIndexing•  UsingStringIndexeswithAssociaDveArrays• WorkingwithNestedCollecDons•  UsingMULTISETOperatorswithNestedTables•  BestPracDcesforCollecDons

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page4

PL/SQLCollec>ons•  AcollecDonisan"orderedgroupofelements,allofthesametype."(PL/SQLUserGuide)– Inshort,a"homogeneous"listof"stuff"

•  CollecDonsaresimilartosingle-dimensionalarraysinotherprogramminglanguages.– Withlotsofsubtledifferences,aswell.

•  CollecDonsalmostalwaysconsumeProcessGlobalAreamemory.

•  CollecDonsshouldbea"goto"datatypeforOracleDatabasedevelopers

1 Apple

22 Pear

100 Orange

10023 Apricot

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page5

System Global Area (SGA) of RDBMS Instance

PL/SQLinSharedMemory

SharedPool

LargePool

ReservedPool

show_empscalc_totals upd_salaries

Select * from emp

SharedSQL

Pre-parsedUpdate emp Set sal=...

Librarycache

Session1memory(PGA/UGA)

emp_rec emp%rowtype; tot_tab tottabtype;

Session2memory(PGA/UGA)

emp_rec emp%rowtype; tot_tab tottabtype; Session1 Session2

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page6

HowPL/SQLusestheSGA,PGAandUGA

• TheSGAcontainsinformaDonthatcanbesharedacrosssessionsconnectedtotheinstance.– InPL/SQL,thisislimitedtopackagestaDcconstants.

• TheUserGlobalAreacontainssession-specificdatathatpersistsacrossservercallboundaries– Package-leveldata

• TheProcessGlobalAreacontainssession-specificdatathatisreleasedwhenthecurrentservercallterminates:"local"data.

PACKAGE Pkg is   Nonstatic_Constant CONSTANT PLS_INTEGER := My_Sequence.Nextval;   Static_Constant    CONSTANT PLS_INTEGER := 42; END Pkg;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page7

Calcula>ngPGAandUGAConsump>on

• OraclekeepstrackofandshowsthePGAandUGAconsumpDonforasessioninthev_$sesstatdynamicview.

• Withthecorrectprivileges,PL/SQLdeveloperscananalysistheircode'smemoryusage.

show_pga_uga.sql grantv$.sql

plsql_memory.pkg plsql_memory_demo.sql

SELECT n.name, s.VALUE FROM sys.v_$sesstat s, sys.v_$statname n WHERE s.statistic# = n.statistic# AND s.sid = my_session.sid AND n.name IN ('session uga memory', 'session pga memory')

BEGIN plsql_memory.start_analysis; run_my_application; plsql_memory.show_memory_usage; END;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page8

Whyusecollec>ons?• Generally,tomanipulatelistsofinformaDoninmemory.

– Ofcourse,youcanuserelaDonaltables,too.– CollecDonmanipulaDonisgenerallymuchfasterthanusingSQLtomodifythecontentsoftables.

• CollecDonsenableotherkeyfeaturesofPL/SQL– BULKCOLLECTandFORALLusethemtoboostmulD-rowSQLperformance– ServeupcomplexdatasetsofinformaDontonon-PL/SQLhostenvironmentsusingtablefunc/ons.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page9

DifferentTypesofCollec>ons•  ThreetypesofcollecDons

– AssociaDvearray– Nestedtable– Varray(varyingarrays)

• AssociaDvearrayisaPL/SQL-onlydatatype.• NestedtablesandvarrayscanbeusedwithinPL/SQLblocksandalsofromwithinSQL.– Columntables– TablefuncDons

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page10

GlossaryofTerms•  Element

– A collection is made up of one or more elements, all of the same type. Also referred to as "row."

– Can be of almost any valid PL/SQL type.

•  Index value – The "location" in the collection in which an element is found. Also referred to as "row

number." – Usually an integer, can also be a string (associative arrays only)

•  Dense – Every index value between lowest and highest has a defined element.

•  Sparse – One or more elements between lowest and highest index values may be undefined

(gaps).

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page11

Definingcollec>ontypes• BeforeyoucanmanipulateacollecDonvariable,youneedacollecDontypeonwhichtodeclarethevariable.

• Oraclepre-definesseveralcollecDontypesinvarioussuppliedpackages.• DBMS_SQL

– DynamicSQL-specifictypes– Generictypes(listofstrings,numbers,etc.).

• DBMS_OUTPUT– Listofstrings

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page12

Definingcollec>ontypes• DeclareallcollecDontypewithaTYPEstatement.• AssociaDvearraysuseISTABLEOFandtheINDEXBYclause.• NestedtablesuseISTABLEOF,withoutanyindexingclause.• VarraysuseISVARRAYOFsyntax.

TYPE coll_name IS TABLE OF element_type INDEX BY index_type;

TYPE coll_name IS TABLE OF element_type;

TYPE coll_name IS VARRAY (limit) OF element_type;

Associa>onarraytype

Nestedtabletype

Varraytype

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page13

ScopeforCollec>onTypes•  YoucandefinecollecDontypesin:

– Localblock–canbeusedonlyinthatblock– Package-availableforusebyanysessionwithexecuteauthorityonthatpackage– Schema–intheSQLlayer,possibleonlyfornestedtablesandvarrays

• Avoid"reinvenDng"collecDontypesinmanyplacesinyourcode.– Theyareexcellentcandidatesforsharedcodeelements.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page14

Localcollec>ontypes

•  TYPEstatementfoundindeclaraDonsecDonofblock(anonymous,nested,subprogram)

•  ItisdefinedandthendestroyedeachDmetheblockisexecuted.•  Youshouldavoidlocaltypes;itwilllikelyleadtoredundanciesinyourcode.

DECLARE TYPE strings_t IS TABLE OF VARCHAR2(100);

PROCEDURE my_procedure IS TYPE strings_t IS TABLE OF VARCHAR2(100);

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page15

Package-levelTypes

• WhendefinedinthepackagespecificaDon,itbecomesa"globally"availabletype.– AnysessionwithEXECUTEauthorityonthepackagecanusethetypetodeclarecollecDons.

•  Inthepackagebody,canonlybeusedbysubprogramsofthatpackage.•  ExcellentrepositoryforapplicaDon-specifictypes

PACKAGE my_types IS TYPE strings_t IS TABLE OF VARCHAR2(100);

colltypes.pks

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page16

Schema-levelTypes

• Definedintheschema,independentofanyPL/SQLprogramunit.• AnysessionwithEXECUTEauthorityontypecanuseittodeclarecollecDonvariables.– CollecDonsofthistypecanalsobedirectlyreferencedinsideSQLstatements.

• Canonlybeusedwithnestedtablesandvarrays.– AssociaDvearraysarePL/SQL-specific,cannotbedefinedattheschemalevel(SQLlayer).

CREATE OR REPLACE TYPE strings_t IS TABLE OF VARCHAR2(100)

GRANT EXECUTE ON strings_t TO PUBLIC

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page17

Declaringcollec>onvariables• OnceyouhavedefinedyourcollecDontype,youcandefineavariablebasedonthat.– ThesameasforanytypeofdatainPL/SQL

CREATE TYPE hire_dates_t IS TABLE OF DATE; CREATE PACKAGE my_types IS TYPE strings_t IS TABLE OF VARCHAR2(100); END my_types;

DECLARE l_names my_types.string_t; l_dates hire_dates_t; l_dates HR.hire_dates_t; l_strings DBMS_SQL.varchar2_table;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page18

Collec>onMethods•  ThetermmethodisusedtodescribeproceduresandfuncDonsthatdefinedinaclassorobjecttype.– YouinvokeamethodbyaLachingit,usingdotnotaDon,tothenameofthetype/classortoaninstanceoftheclass.

• CollecDonmethodsareproceduresandfuncDonsthatarea6achedtoacollecDonvariable.– FirstintroducDonofobject-orientedsyntaxinPL/SQL–waybackinOracle7.3.4!

method_vs_proc.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page19

Methodsthatretrieveinforma>on• COUNT:numberofelementscurrentlydefinedincollecDon.•  EXISTS:TRUEifthespecifiedindexvaluesisdefined.•  FIRST/LAST:lowest/highestindexvaluesofdefinedrows.• NEXT/PRIOR:definedindexvalueater/beforethespecifiedindexvalue.•  LIMIT:max.numberofelementsallowedinaVARRAY.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page20

TheCOUNTMethod• Returns0ifthecollecDonisempty.• Otherwisereturnsthenumberofdefinedindexvalues.•  Youcannotaskforacountofelementsbetweenarangeofindexvalues.Toobad...

BEGIN IF my_collection.COUNT > 0 THEN /* We have some data in the collection */ ... END IF;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page21

Checkingforelementexistence•  Ifyoutrytoreadanelementatanundefinedindexvalue,OracleraisestheNO_DATA_FOUNDexcepDon.– ApoordecisiononOracle'spart.

• UsetheEXISTSmethodtochecktoseeiftheindexvalueisdefined.

BEGIN IF my_collection.EXISTS (l_index) THEN DBMS_OUTPUT.PUT_LINE (my_collection (l_index)); END IF;

collection_exists.sql plsqlloops.sp

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page22

Naviga>ngThroughCollec>ons• OneofthemostcommonacDonsoncollecDonsisloopingthroughthecontents.

•  YoucanuseWHILE,simpleandFORloopstoperformthisnavigaDon.•  ThecharacterisDcsofyourcollecDonwilldeterminewhichsortoflooptouse.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page23

ChoosetheRightLoop•  FORloop

– Onlyusethisloopwhenyouwanttoiteratethrougheveryelementbetweenthelowandhighindexvalues.

– DonotusewithsparsecollecDons.• WHILEandsimpleloops

– BestfitforsparsecollecDonsandwhenyouwanttocondi/onallyexitfromyourloop.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page24

Naviga>onmethodsandFORloops• WithFORloops,youwilluse:

– COUNT–whenthefirstindexvalueinthecollecDonis1.– FIRSTandLASTwhenFIRSTmaynotbeone.

BEGIN FOR indx IN 1 .. my_collection.COUNT LOOP do_something_with (my_collection (indx)); END LOOP; END;

BEGIN FOR indx IN my_collection.FIRST .. my_collection.LAST LOOP

do_something_with (my_collection (indx)); END LOOP; END;

plsqlloops.sp

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page25

Naviga>onmethods&WHILE/simpleloops• WithWHILEandsimpleloops,youwilluse

– FIRSTandNEXTtomovefromfirsttolast– LASTandPRIORtomovefromlasttofirst

rowind PLS_INTEGER := my_collection.FIRST; BEGIN LOOP

EXIT WHEN rowind IS NULL; rowind := my_collection.NEXT (rowind); END LOOP; END;

rowind PLS_INTEGER := my_collection.LAST; BEGIN LOOP EXIT WHEN rowind IS NULL; rowind := my_collection.PRIOR (rowind); END LOOP; END;

plsqlloops.sp

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page26

TheLIMITMethod• Onlythevarrayhasapre-definedupperlimitonthenumberofelementsthatcandefinedinit.– Well,theothercollecDonstypestheore/callyhaveanupperlimit,butyou'llneverreachit.

• UsetheLIMITmethodtodeterminewhatthatlimitis.

DECLARE TYPE max_of_five_t IS VARRAY (5) OF NUMBER; l_list max_of_five_t := max_of_five_t(); BEGIN DBMS_OUTPUT.put_line (l_list.LIMIT); END;

varray_limit.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page27

Methodsthatchangeacollec>on• DELETEdeletesoneormorerowsfromanassociaDvearrayornestedtable.

•  EXTENDaddsrowstotheendofanestedtableorvarray.•  TRIMremovesrowsfromavarrayornestedtable.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page28

TheDELETEMethod• YoucandeleteoneormorerowsfromanassociaDvearrayornestedtableusingDELETE.

• TrytoDELETEfromavarrayandyouwillsee"PLS-00306:wrongnumberortypesofargumentsincallto'DELETE'"

• Lowandhighindexvaluesdonothavetoexist.BEGIN -- Delete all rows myCollection.DELETE; -- Delete one (the last) row myCollection.DELETE (myCollection.LAST); -- Delete a range of rows myCollection.DELETE (1400, 17255); END;

delete.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page29

Makeroomfornewelementsw/EXTEND• UseEXTENDonlywithvarraysandnestedtables.•  TellOracletoaddNnumberofnewelementstotheendofthecollecDon.•  "Bulk"extendsfasterthanindividualextends.

– Ifyouknowyouwillneed10,000elements,dotheextendinasinglestep.

• OpDonal:specifythevalueofallnewelementsfromanexisDngelement.– DefaultvalueisNULL.

extend.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page30

Trimmingelementsfromendofcollec>on• UseTRIMonlywithvarraysandnestedtables.

– NottobeconfusedwiththeTRIMfuncDon!

•  YoucantrimoneormulDpleelements.– Defaultis1.– "ORA-06533:Subscriptbeyondcount"errorifyoutotrimmorethanisinthecollecDon.

•  TRIMistheonlywaytoremoveelementsfromavarray.– DELETEisnotsupported.

trim.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page31

Conclusions–Collec>onMethods• MethodsmakeitmucheasiertoworkwithcollecDons.•  YoucangetinformaDonaboutthecollecDonsandalsochangetheircontents.

• WhenyouusethenavigaDonmethods,makesureyouchoosetheappropriatetypeoflooptoiteratethroughtheelements.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page32

Associa>veArrays

•  AvariabledeclaredfromanassociaDvearraytype.•  Anunboundedsetofkey-valuepairs.•  Eachkeyisunique,andservesasthesubscriptoftheelementthatholdsthecorrespondingvalue.

•  YoucanaccesselementswithoutknowingtheirposiDonsinthearray,andwithouttraversingthearray.

1 Apple

22 Pear

100 Orange

10023 Apricot

DECLARE TYPE list_of_names_t IS TABLE OF employees.last_name%TYPE INDEX BY PLS_INTEGER;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page33

Associa>veArrayBackground•  ItwasthefirsttypeofcollecDonavailableinPL/SQL.•  FirstintroducedinOracle7asa"PL/SQLtable"(hence,theTABLEOFsyntax).

• RenamedinOracle8to"index-bytable"whennestedtablesandvarrayswereadded.

•  In9.2,renamedto"associaDvearray"withtheadventofstringindexing.• CanonlybeusedinaPL/SQLcontext.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page34

Characteris>csofAssocia>veArrays

• TABLEOFdatatypescanbealmostanyvalidPL/SQLtype(detailstofollow).

• INDEXBYtypecanbeintegerorstring.– ThismeansyoucanessenDallyindexbyanything!– ButindexvaluescanneverbeNULL.

• AssociaDvearrayscanbesparse.– Canpopulateelementsinnon-consecu/veindexvalues.– Easilyusedtoemulateprimarykeysanduniqueindexes.

DECLARE TYPE list_of_names_t IS TABLE OF employees.last_name%TYPE INDEX BY PLS_INTEGER;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page35

Simpleassocia>vearrayexampleDECLARE TYPE list_of_names_t IS TABLE OF VARCHAR2 (20) INDEX BY PLS_INTEGER; happyfamily list_of_names_t;

l_index_value PLS_INTEGER := 88; BEGIN happyfamily (1) := 'Eli'; happyfamily (-15070) := 'Steven'; happyfamily (3) := 'Chris'; happyfamily (l_index_value) := 'Veva';

l_index_value := happyfamily.FIRST; WHILE (l_index_value IS NOT NULL) LOOP DBMS_OUTPUT.put_line ( 'Value at index ' || l_index_value || ' = ' || happyfamily (l_index_value) ); l_index_value := happyfamily.NEXT (l_index_value);

END LOOP; END;

assoc_array_example.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page36

Associa>vearrayofrecordsexample•  Itisveryeasyto"emulate"arelaDonaltableinsideone'sPL/SQLcode.

– Oruseanyotherkindofrecordtype.

DECLARE TYPE employees_aat IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER; l_employees employees_aat; BEGIN FOR employee_rec IN (SELECT * FROM employees) LOOP l_employees (l_employees.COUNT + 1) := employee_rec; END LOOP; END;

collection_of_records.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page37

ValidTABLEOFdatatypes•  YoucancreateanassociaDvearrayofalmostanyPL/SQLorSQLdatatype.

– Allscalartypes,includingBoolean– CollecDonofobjecttypes– CollecDonofothercollecDons

•  TherearesomerestricDons:– CannothaveaTABLEOFcursorvariablesorexcepDons.

aa_table_of_invalid_types.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page38

ValidIndexValues• Noprac/callimittonumberofelementsyoucandefineinanassociaDvearray.

•  Integerindexvaluesrangefrom-2,147,483,647to2,147,483,647– ThisistheBINARY_INTEGERrange.– That'salmost4.3billionelements!

•  Stringindexvaluescanhaveanyvalue;youareonlyrestrictedbymaximumnumberofelementsallowedinacollecDon.– Whichyouwillneverreach.

aa_limits.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page39

MoredetailsonvalidINDEXBYtypes•  TheINDEXBYclausedefinestheindexingforthecollecDon.• YoucandefinetheindexdatatypeofyourassociaDvearraytypetobe:– BINARY_INTEGERandanysub-typederivedfromBINARY_INTEGER

– VARCHAR2(n),wherenisbetween1and32767– %TYPEagainstadatabasecolumnthatisconsistentwiththeaboverules

– ASUBTYPEagainstanyoftheabove.indexby_options.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page40

NestedTablesandVarrays• AddedinOracle8aspartoftheobjectmodel.•  TypescanbedefinedinPL/SQLoraschema-leveltype.•  Youmustini/alizebeforeusingthecollecDon.

– TherearesomeexcepDons,aswithBULKCOLLECT.

•  Youmustextendtomakeroomfornewelements.– TherearesomeexcepDons,aswithBULKCOLLECT.

• ColumnsinrelaDonaltablescanbeoftypenestedtableorvarray.– Oh,butthedenormalizaDon!

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page41

NestedTables

•  AnestedtableisatypeofcollecDon,which,accordingtoOracledocumentaDon,"modelsanunorderedsetofelements."– Itisa"mulDset":likearelaDonaltable,thereisnoinherentordertoitselements,andduplicatesareallowed/significant.

•  FromapracDcalstandpoint,youcanaccessnestedtableelementsthroughanintegerindex.

• MULTISEToperatorsallowset-leveloperaDonsonnestedtables.

1 Apple

2 Pear

3 Orange

4 Apricot

CREATE OR REPLACE TYPE list_of_names_t IS TABLE OF NUMBER;

5 Pear

Unordered set of elements

Integer index also available

nested_table_example.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page42

Varrays

• Avarray(shortfor"variablesizearray)isatypeofcollecDonthathasanupperboundonitsnumberofelements.

• Thisupperlimitissetwhenthetypeisdefined,butcanalsobeadjustedatrunDme.

• Alwaysdense,canonlytrimfromendofvarray.

• Otherthanthat,quitesimilartoanestedtable.

1 Apple

2 Pear

3 Orange

4 Apricot

CREATE OR REPLACE TYPE list_of_names_t IS VARRAY (5) OF NUMBER;

5 Pear

And no more elements can fit in

this varray.

varray_example.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page43

Ini>alizingNestedTablesandVarrays• Beforeyoucanuseanestedtable,itmustbeiniDalized.

– IniDalizethemexplicitlywithaconstructorfuncDon,samenameastype,providedbyOracle

– ProvidealistofvaluesoriniDalizeitasempty.

DECLARE TYPE numbers_t IS VARRAY (5) OF NUMBER; salaries numbers_t := numbers_t (100, 200, 300); BEGIN

DECLARE TYPE numbers_t IS TABLE OF NUMBER; salaries numbers_t; BEGIN salaries := numbers_t (100, 200, 300);

Initialize in execution

section

Initialize in declaration with

values

DECLARE TYPE numbers_t IS TABLE OF NUMBER; salaries numbers_t := numbers_t ();

Initialize empty in declaration

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page44

ValidTABLEOFandVARRAYdatatypes•  ForPL/SQL-definedtypes,youcancreatenestedtableofalmostanyPL/SQLorSQLdatatype.– Allscalartypes,includingBoolean;collecDonofobjecttypes;collecDonofothercollecDons

•  TherearesomerestricDons:– CannothaveaTABLEOForVARRAYOFcursorvariablesorexcepDons.

•  Schema-leveltypescanonlyuseSQLdatatypes.

nt_table_of_invalid_types.sql va_table_of_invalid_types.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page45

Collec>onasColumnType•  Ifthetypeisdefinedatschemalevel,itcanbeusedasacolumntype.

– MustalsoprovideaSTOREASclause.

•  Theorderofelementsinthecolumnisnotpreserved.• CanspecifystoragecharacterisDcsofcollecDon.•  SeeseparatelessonfordetailsonusingcollecDonsinSQL.

CREATE TABLE family ( surname VARCHAR2 (1000) , parent_names parent_names_t , children_names child_names_t ) NESTED TABLE children_names STORE AS parent_names_tbl [storage_clause] NESTED TABLE parent_names STORE AS children_names_tbl [storage_clause]

nested_table_example.sql varray_example.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page46

ChangingUpperLimitonVarray•  YouspecifyanupperlimitattheDmethevarraytypeisdefine.•  YoucanalsochangethislimitatrunDmewithanALTERTYPEcommand.

ALTER TYPE my_varray_t MODIFY LIMIT 100 INVALIDATE / BEGIN EXECUTE IMMEDIATE 'ALTER TYPE my_varray_t MODIFY LIMIT 100 CASCADE'; END; /

varray_change_limit.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page47

UsingCollec>onsInsideSQL• DefineyourcollecDontypeattheschemalevel&collecDonsdeclaredwiththattypecanbereferencedintheSQLlayer.– AsacolumninarelaDonaltable– ByselecDngfromthatcollecDoninaSELECTstatement(note:asof12.1,youcandothiswithassociaDvearraysindexedbyinteger).

• Oracleofferswaysto"translate"betweenacollecDonformatandarelaDonaltableformat.– TABLE:collecDon->relaDonaltable– MULTISET:relaDonaltable->collecDon

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page48

UsingtheTABLEOperator• UseTABLEtoworkwithdatainacollecDonasifitweredatainadatabasetable.– Oraclereferstothisas"un-nesDng".– EspeciallyusefulwhenyouwouldliketoapplySQLoperaDonstoaPL/SQLcollecDon(ie,onenotstoredinadatabasetable).

• YoudonotneedtoexplicitlyCASTthecollecDon.– OraclewillfigureoutthetypeautomaDcally.

collections_in_sql.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page49

Changingcollec>oncontentswithTABLE• YoucanuseTABLEtoquerythecontentsofacollecDoninsideSQL.

• YoucanalsochangethecontentsofanestedtablecolumnvaluewithTABLE.– Butvarrayshavetobechanged"enmasse"–thewhilevarrayisreplace;cannotmodifyindividualelements.UPDATE TABLE (SELECT children_names FROM family WHERE surname = 'Feuerstein') SET COLUMN_VALUE = 'Eli Silva' WHERE COLUMN_VALUE = 'Eli' /

nested_table_change.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page50

UsingtheMULTISETOperator• MULTISETistheinverseofTABLE,converDngasetoftable,view,query)intoaVARRAYornestedtable.– UseMULTISETtoemulateortransformrelaDonaljoinsintocollecDons,withpotenDalclient-serverperformanceimpact.DECLARE CURSOR bird_curs IS SELECT b.genus, b.species, CAST ( MULTISET (SELECT bh.country FROM bird_habitats bh WHERE bh.genus = b.genus

AND bh.species = b.species) AS country_tab_t) FROM birds b; bird_row bird_curs%ROWTYPE; BEGIN OPEN bird_curs; FETCH bird_curs into bird_row; END;

collections_in_sql_multiset.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page51

Non-Sequen>alIndexing•  SomeDmesyousimplywanttoadditemstotheendofalist.

– Thismakessenseiftheorderinwhichitemswereaddedissignificant.

• Buthowdoyoufindaspecificelementinthelist?– WithsequenDalindexing,youhavetoscanthroughthecontentstofindamatch.

• AndwhatifyouwanttofindelementsinacollecDonusingmorethanone"index"?– CollecDonshavejustoneindex.Period.

string_tracker0.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page52

Takingadvantageofnon-sequen>alindexing• AssociaDvearrayscanbesparse.

– Certainly,anystring-indexedcollecDonisnotsequenDallyfilled.• ValidindexvaluesforanassociaDvearraycoveraverywiderangeofintegers.– Veryotenprimarykeysoftablesaresequence-generatedintegersthatfallwithinthisrange.

• CombinethesetwofeaturesandyouhaveapowerfulandrelaDvelysimplemechanismforemulaDngrelaDonaltablekeys.

collection_of_records.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page53

Emula>ngPrimaryKeyinCollec>on• Manytablesrelyonsequence-generatedintegervaluesfortheirprimarykeys.– Itispossiblethatthissequencevaluecouldexceed2**31-1,butitisrarelythecase.

• Primarykeysgenerallyarenot"densely"allocated.– Sequencesareallocatedingroups,rowsaredeleted.

•  Thesescenariosmeshperfectlywiththefeaturesofaninteger-indexedassociaDvearray.

emulate_primary_key1.sql emulate_primary_key2.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page54

"Mul>pleIndexes"onaCollec>on• MostrelaDonaltableshavemulDpleindexesdefinedinordertoopDmizequeryperformance(forvariousWHEREclauses).

• WhatifIneedtodothesamethinginacollecDon?•  YoucanonlyhaveasingleindexonanassociaDvearray(INDEXBY...).

– ButyoucouldcreateothercollecDonsthatserveasindexesintothe"original"collecDon.

emulate_indexes.sql genaa.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page55

Lotsofwaystoindexassocia>vearrays• PriortoOracle9iRelease2,youcouldonlyindexbyBINARY_INTEGER.

• YoucannowdefinetheindexonyourassociaDvearraytobe:– Anysub-typederivedfromBINARY_INTEGER– VARCHAR2(n),wherenisbetween1and32767– %TYPEagainstadatabasecolumnthatisconsistentwiththeaboverules– ASUBTYPEagainstanyoftheabove.

• Thismeansthatyoucannowindexonstringvalues!(andconcatenatedindexesand...)

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page56

ExamplesofNewTYPEVariants• AllofthefollowingarevalidTYPEdeclaraDonsinOracle9iRelease2andhigher– Youcannotuse%TYPEagainstanINTEGERcolumn,becauseINTEGERisnotasubtypeofBINARY_INTEGER.DECLARE TYPE array_t1 IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; TYPE array_t2 IS TABLE OF NUMBER INDEX BY PLS_INTEGER; TYPE array_t3 IS TABLE OF NUMBER INDEX BY POSITIVE; TYPE array_t4 IS TABLE OF NUMBER INDEX BY NATURAL; TYPE array_t5 IS TABLE OF NUMBER INDEX BY VARCHAR2(64); TYPE array_t6 IS TABLE OF NUMBER INDEX BY VARCHAR2(32767); TYPE array_t7 IS TABLE OF NUMBER INDEX BY

employee.last_name%TYPE; TYPE array_t8 IS TABLE OF NUMBER INDEX BY types_pkg.subtype_t;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page57

Workingwithstring-indexedcollec>ons• Thesyntaxforusingstringindexingisthesame.

– Andallthesamemethodsareavailable.• ButthetypeofdatareturnedbyFIRST,LAST,NEXTandPRIORmethodsisVARCHAR2.

• Thelongerthestringvalues,themoreDmeittakesOracleto"hash"orconvertthatstringtotheintegerthatisactuallyusedastheindexvalue.– RelaDvelysmallstrings,sayunder100characters,donotincurtoolargeapenalty.

assoc_array*.sql assoc_array_perf.tst

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page58

Anexampleofstringindexing• Igeneratetestcodeanddeclarevariables.SoIneedtomakesurethatIdonotdeclarethesamevariablemorethanonce.

•  Therearelotsofwaystodothis,butstring-indexedcollecDonsmakeitreallyeasy!

FOR indx IN 1 .. l_variables.COUNT LOOP If varname_already_used THEN -- DO NOTHING ELSE add_variable_declaration; mark_varname_as_used; END IF; END LOOP;

string_tracker0.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page59

StringTrackerwithoutstringindexing•  Twosubprogramsareneeded....

– string_in_use:returnsTRUEifthestringwaspreviouslyused.– mark_as_used:markthespecifiedstringasbeingused.

• Most"obvious"implementaDon:addeachstringtoalistofusedstrings.•  Thensearchthroughthelistforamatch.

string_tracker0.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page60

StringTrackerwithstringindexing• Ratherthanaddeachstringtoalistofusedstrings,whynotusethestringastheindex?

CREATE OR REPLACE PACKAGE BODY string_tracker IS TYPE used_aat IS TABLE OF BOOLEAN INDEX BY VARCHAR2(32767); g_names_used used_aat; FUNCTION string_in_use ( value_in IN VARCHAR2 ) RETURN BOOLEAN IS BEGIN RETURN g_names_used.EXISTS ( value_in ); END string_in_use; PROCEDURE mark_as_used (value_in IN VARCHAR2) IS BEGIN

g_names_used ( value_in ) := TRUE; END mark_as_used; END string_tracker;

string_tracker1.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page61

Conver>ngfromIntegertoStringIndexing•  SupposeIamemulaDngmyprimarykeyinacollecDonindexforabatchjob.– MuchbeLerperformance!– Butmyprimarykeyvaluesareapproaching2**31-1(themaximumallowedinancollecDon).

• MustIabandonthecollecDontechnique?• No!Youcanconverttoastringindex.

– NowtheonlylimitaDonisthenumberofelementsdefinedinthecollecDon.– Youaremuchmorelikelytorunoutofmemorybeforeyougetanywherenear2**31-1elements.

emulate_primary_key.sql int_to_string_indexing.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page62

Mul>level(a.k.a.,Nested)Collec>ons• AmulDlevelcollecDontypeisatypewhoseelementis,directlyorindirectly,anothercollecDon.

• UsagesformulDlevelcollecDons:– ModelnormalizeddatastructuresinPL/SQLcollecDons– EmulatemulDdimensionalarrays.

•  ThesyntaxforworkingwithmulDlevelcollecDonscanbehardtoparse(inyourhead).

multilevel_collections.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page63

StringTrackerVersion2•  Iintroducedthestring_trackerpackagein"WorkingwithString-IndexedCollecDons."– Keepstrackofthenamesofvariablesalreadygeneratedintestcode.– Thatworkedfineforasinglelist.WhatifIneedtokeeptrackofmulDplelists,andlistswithinlists?

•  Let'sextendthefirstversiontosupportmulDplelistsbyusingastring-indexed,mulD-levelcollecDon.Alistoflists....

string_tracker1.* string_tracker2.* string_tracker3*.*

List1:1-10000 List2:10001-20000 List2:20001-30000Thehardway:segmenDngonebigcollecDon

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page64

Emulatemul>dimensionalarrays• CollecDonsarealwayssingledimensioned.• ButacollecDonofcollecDonsis"kindalike"atwo-dimensionalarray.

– Youcanextrapolatefromthere.

CREATE OR REPLACE PACKAGE multdim IS TYPE dim1_t IS TABLE OF VARCHAR2 (32767) INDEX BY PLS_INTEGER; TYPE dim2_t IS TABLE OF dim1_t INDEX BY PLS_INTEGER; TYPE dim3_t IS TABLE OF dim2_t INDEX BY PLS_INTEGER;

multdim*.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page65

Complexexample:four-levelsofnes>ng•  ThemostcomplicatedstructureIeverbuiltwasafour-levelnestedcollecDonstructure.

•  IusedittobuildauDlitytoanalyzepackagesforpotenDallyambiguousoverloading.

•  ThenextseveralslidesexploretheimplementaDon.– Itistoocomplextofullyexplaininthislesson.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page66

Mul>levelcollec>onsasakindofnormalizeddatabasedesign•  IhavefoundthatcomingupwiththerightmodelofmulDlevelcollecDonsisverysimilartonormalizingdatainrelaDonaltables.– Avoidredundancy– AccuratelyreflectrelaDonships– SimplyresulDngapplicaDoncode

•  Let'stakealookatanexampleofsuchaprocess.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page67

Theproblemofambiguousoverloading• Oddlyandsadly,itispossibletocompileoverloadingswhicharenotusable.– Youseeanobviousexamplebelow,buttherearemanymoresubtlecircumstances,usuallyinvolvingdefaultedparameters.

• SoIwillbuildauDlitytoidenDfysuchambiguousoverloadings.ButhowcanIdothis?

BEGIN salespkg.calc_total ('ABC'); END;

PACKAGE salespkg IS PROCEDURE calc_total ( dept_in IN VARCHAR2); PROCEDURE calc_total ( dept_in IN CHAR); END salespkg;

? ambig_overloading.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page68

ALL_ARGUMENTStotherescue!• Parsingistoocomplicatedforme,buttheALL_ARGUMENTSdatadicDonaryviewcontainsinformaDonaboutalltheargumentsofalltheproceduresandfuncDonstowhichIhaveaccess.– ThatsoundspreLygood!

• Asusual,Oracleoffersusawholelotofpleasure,mixedwithaliLlebitofpain.– TheorganizaDonofdatainALL_ARGUMENTSisabitbizarre,plusitisincomplete,necessitaDngtheusealsoofDBMS_DESCRIBE.DESCRIBE_COLUMNS. all_arguments.tst

all_arguments.sql allargs.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page69

FirstInclina>on:SameOld,SameOld• Allrightthen,IwillgraballtheinformaDonfromALL_ARGUMENTSanddumpitintoacollecDonbasedonthatview!Veryeasy...

CREATE OR REPLACE PROCEDURE get_all_arguments ( package_in IN VARCHAR2) IS TYPE all_arguments_tt IS TABLE OF all_arguments%ROWTYPE INDEX BY BINARY_INTEGER;

l_arguments all_arguments_tt; BEGIN FOR rec IN ( SELECT * FROM all_arguments WHERE owner = USER AND package_name = package_in) LOOP l_arguments (SQL%ROWCOUNT) := rec; END LOOP; END;

Load it up!

Emulate the view.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page70

Thenwhat?Writelotsofcodetointerpretthecontents...• Whichprogramsareoverloaded?Wheredoesoneoverloadingendandanotherstart?

l_last_program all_arguments.object_name%TYPE; l_is_new_program BOOLEAN := FALSE; l_last_overload PLS_INTEGER := -1; BEGIN FOR indx IN l_arguments.FIRST ..

l_arguments.LAST LOOP IF l_arguments (indx).object_name != l_last_program OR l_last_program IS NULL THEN

l_last_program := l_arguments (indx).object_name; l_is_new_program := TRUE; do_new_program_stuff; END IF;

...

IF l_arguments (indx).overload != l_last_overload OR l_last_overload = -1 THEN IF l_is_new_program

THEN do_first_overloading_stuff; ELSE do_new_overloading_stuff; END IF; END IF;

END LOOP; END;

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page71

Discovery:thereisahierarchywithintheALL_ARGUMENTSdata!

•  Eachprogramhaszeroormoreoverloadings,eachoverloadinghasNarguments,andeachargumentcanhavemulDple"breakouts"(myterm-appliestonon-scalarparameters,suchasrecordsorobjecttypes).

RUN_TEST

SHOW_RESULTS

RESET_FLAGS

Program name

Overloading 1

Overloading 2

Overloading

Argument 1

Argument 2

Argument 3

Argument 4

Argument 5

Argument Breakout 1

Breakout 1

Breakout 2

Breakout 3

Breakout

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page72

WhatifIreflectthishierarchyinamul>levelcollec>on?

• HavetobuildfromtheboLomup:

TYPE breakouts_t IS TABLE OF all_arguments%ROWTYPE INDEX BY PLS_INTEGER; TYPE arguments_t IS TABLE OF breakouts_t INDEX BY PLS_INTEGER; TYPE overloadings_t IS TABLE OF arguments_t INDEX BY PLS_INTEGER; TYPE programs_t IS TABLE OF overloadings_t INDEX BY all_arguments.object_name%type;

1. Set of rows from ALL_ARGUMENTS

String-based index

2. All the "breakout" info for a single argument 3. All the argument info for a single overloading 4. All the overloadings for a distinct program name

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page73

ThenIcanpopulateitveryeasily• Assigningasinglerecordtothe"lowest"levelalsodefineseachoftheupperlevels.

• NoDcetheautomaDc"SELECTDISTINCT"onnamethatresults!FOR rec IN (SELECT * FROM all_arguments) LOOP l_arguments (NVL (l_arguments.LAST, 0) + 1) := rec;   l_programs (rec.object_name) (NVL (rec.overload, 0)) (rec.position) (rec.data_level) := rec; END LOOP;

I can still do the typical sequential

load.

But I will now also add the multi-level

load in single assignment

show_all_arguments.sp show_all_arguments.tst

cc_smartargs.pkb/load_arguments

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page74

AndthenIcan"query"thecontentswithaminimumofcode

l_programs ('TOP_SALES') (2).EXISTS (0)

Is the TOP_SALES program overloaded?

l_programs ('TOP_SALES') (2)(0)(0).datatype

l_programs ('TOP_SALES').COUNT > 1

Is the 2nd overloading of TOP_SALES a

function?

What is the datatype of the RETURN

clause of the 2nd overloading of TOP_SALES? And, of course, I know the beginning and end points of

each program, overloading, and argument. I just use the FIRST and LAST methods on those collections!

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page75

Conclusions–NestedCollec>ons• ThenestedcollecDonisapowerful,butpotenDallyverycomplicated,featureofPL/SQL.

• Usedcorrectly,itcanhidecomplexityintheunderlyingdatastructure,andgreatlysimplifyyouralgorithms.

• Ifyoufindyourselfsaying"Itshouldn'tbethishard,"takealookathowyouareusingyourcollecDons(orSQL).– PerhapsmulDlevelcollecDonscancometotherescue!

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page76

Manipula>ngNestedTablesasMul>sets• Nestedtablesare,fromatheoreDcalstandpoint,"mulDsets."

– Thereisnoinherentordertotheelements.– Duplicatesareallowedandaresignificant.– RelaDonaltablesaremulDsetsaswell.

•  Ifasethasnoorder,thenithasnoindex,soitmustbemanipulatedasaset.

•  InOracleDatabase10g,OracleaddedMULTISETsetoperatorstomanipulatethecontentsofnestedtables(only).– UseinbothPL/SQLblocksandSQLstatements.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page77

Set-OrientedFeaturesforNestedTables• Determineif...

– twonestedtablesareequal/unequal– anestedtablehasduplicates,andremoveduplicates– onenestedtablecontainsanother– anelementisamemberofanestedtable

• PerformsetoperaDons.– Joincontentsoftwonestedtables:MULTISETUNION.– ReturncommonelementsoftwonestedtableswithMULTISETINTERSECT.– TakeawaytheelementsofonenestedtablefromanotherwithMULTISETEXCEPT(oddly,notMINUS).

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page78

Checkforequalityandinequality• Youcanuse=and<>tocomparethecontentsoftwonestedtables.– Butwatchout!NULLshavetheusualdisrupDveimpact.

• ThisisanenormousadvantageoverwriDngaprogramtocomparethecontentsoftwocollecDons.

DECLARE TYPE clientele IS TABLE OF VARCHAR2 (64); group1 clientele := clientele ('Customer 1', 'Customer 2'); group2 clientele := clientele ('Customer 1', 'Customer 3'); group3 clientele := clientele ('Customer 3', 'Customer 1'); BEGIN IF group1 = group2 THEN DBMS_OUTPUT.put_line ('Group 1 = Group 2');

ELSE DBMS_OUTPUT.put_line ('Group 1 != Group 2'); END IF; END;

10g_compare.sql 10g_compare_nulls.sql 10g_compare_old.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page79Copyright2000-2008StevenFeuerstein-Page79

Nestedtableduplicates–detec>onandremoval• UsetheSEToperatortoworkwithdisDnctvalues,anddetermineifyouhaveasetofdisDnctvalues.

DECLARE keep_it_simple strings_nt := strings_nt (); BEGIN keep_it_simple := SET (favorites_pkg.my_favorites);

favorites_pkg.show_favorites ('FULL SET', favorites_pkg.my_favorites); p.l (favorites_pkg.my_favorites IS A SET, 'My favorites distinct?'); p.l (favorites_pkg.my_favorites IS NOT A SET, 'My favorites NOT distinct?'); favorites_pkg.show_favorites ( 'DISTINCT SET', keep_it_simple);

p.l (keep_it_simple IS A SET, 'Keep_it_simple distinct?'); p.l (keep_it_simple IS NOT A SET, 'Keep_it_simple NOT distinct?');

END;

authors.pkg 10g_set.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page80

Determineifvalueisinnestedtable• UsetheMEMBEROFsyntaxtodetermineifavalueisinthenestedtable.– MuchsimplerthanscanningthecontentsofacollecDon.– PerformsanequalitycheckfortheenDreelement;youcannotcompareindividualfieldsofrecords,andsoon.

• TheimplementaDoninSQLitselfisquiteslow.• PerformanceinPL/SQLisfast.

in_clause.* 10g_member_of.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page81

Doesonenestedtablecontainsanother?•  TheSUBMULTISETOFoperatordeterminesifalltheelementsofonenestedtableareinanother.

DECLARE TYPE nested_typ IS TABLE OF NUMBER; nt1 nested_typ := nested_typ (1, 2); nt2 nested_typ := nested_typ (3, 2, 1); BEGIN IF nt1 SUBMULTISET OF nt2 THEN ... END IF; END;

authors.pkg 10g_submultiset.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page82

UNIONtwonestedtablestogether• UseUNIONtojointogetherthecontentsoftwonestedtables.• DuplicatesarepreservedunlessyouincludetheDISTINCTmodifier.– ThisistheoppositeofSQLUNIONandUNIONALL.

• TheresulDngcollecDoniseitheremptyorsequenDallyfilledfromindexvalue1.– YoudonotneedtoiniDalizeorextendfirst.

authors.pkg 10g_union.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page83

Intersecttwonestedtablestogether• UseINTERSECTtofindthecommonelementsoftwonestedtables.• DuplicatesarepreservedunlessyouincludetheDISTINCTmodifier.

– AndtheALLmodifieristhedefault.

•  TheresulDngcollecDoniseitheremptyorsequenDallyfilledfromindexvalue1.– YoudonotneedtoiniDalizeorextendfirst.

10g_intersect.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page84

Takeawaytheelementsofonenestedtablefromanother• UseEXCEPT(notMINUS!)totakeallelementsinonenestedtableoutofanother.

• DuplicatesarepreservedunlessyouincludetheDISTINCTmodifier.– AndtheALLmodifieristhedefault.

•  TheresulDngcollecDoniseitheremptyorsequenDallyfilledfromindexvalue1.– YoudonotneedtoiniDalizeorextendfirst.

10g_except.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page85

Conclusions–MULTISEToperators• WhenyouneedtomanipulatethecontentsofacollecDonasaset,useanestedtable.

• TheMULTISEToperatorsofferapowerful,simplewaytoavoidwriDnglotsofcode.

• TheSET,SUBMULTISETandMEMBERoperatorsalsocancomeinveryhandy.

• WatchoutforresultswhenyournestedtablemaycontainNULLelements.

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page86

Collec>onBestPrac>ces• WatchthePGAmemory.• HidetheimplementaDondetails.• Usesubtypestoself-documentelementandindexbytypes.• ChoosingthebesttypeofcollecDon

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page87

WatchPGAmemoryconsump>on• MemoryforcollecDonsisallocatedfromthePGA(ProcessGlobalArea).– ThereisaPGAforeachsessionconnectedtotheinstance.

• LargecollecDonsconstructedbyprogramsrunbymanysimultaneously-connecteduserscancausememoryerrors.

• Usetheplsq_memorypackagetoanalyzetheamountofmemoryused.– OratleastmakesureyourDBAknowsyouaremakingextensiveuseofcollecDons.

plsql_memory*.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page88

Hidetheimplementa>ondetails.• CollecDons,especiallymulD-levelcollecDons,areverycomplexstructures.

• HidethewayyoutosetandgetelementsinacollecDonbehindanAPI.– Proceduretoset,funcDontoget.– Whenyouhavechangetheimplement,youchangeinoneplace(singlepointofdefiniDon).

multdim.sql cc_smartargs.sql

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page89

Usesubtypestoself-documentdatatypes•  YoushouldavoidusingbasedatatypesinboththeTABLEOFandINDEXBYclauses.– Especiallywhenworkingwithstring-indexedassociaDvearrays.

• UseSUBTYPEstoprovideapplicaDon-specificnamesthatself-documentbothcontentsandintenDon.– Constantscanalsocomeinhandy.

string_tracker3.*

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page90

Choosingthebesttypeofcollec>on• UseassociaDvearrayswhenyouneedto...

– WorkwithinPL/SQLcodeonly– SparselyfillandmanipulatethecollecDon– TakeadvantageofnegaDveindexvaluesorstringindexing

• Usenestedtableswhenyouneedto...– AccessthecollecDoninsideSQL– WantorneedtoperformhighlevelsetoperaDons(MULTISET)

• Usevarrayswhenyouneedto...– IfyouneedtospecifyamaximumsizetoyourcollecDon– OpDmizeperformanceofstoringcollecDonascolumn

Copyright©2015Oracleand/oritsaffiliates.Allrightsreserved.| Page91

Collec>ons:Don'tstartcodingwithoutthem.• Itisimpossibletowriteefficient,highqualityPL/SQLcode,takingfulladvantageofnewfeatures,unlessyouusecollecDons.– FromarrayprocessingtotablefuncDons,collecDonsarerequired.

• LearncollecDonsthoroughlyandapplythemthroughoutyourbackendcode.– Yourcodewillgetfasterandinmanycasesmuchsimplerthanitmighthavebeen(thoughnotalways!).

92