All About PL/SQL Collections
-
Upload
steven-feuerstein -
Category
Technology
-
view
599 -
download
1
Transcript of All About PL/SQL Collections
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!).