Oracle PL/SQL ™ ® by Example FOURTH EDITION BENJAMIN ROSENZWEIG ELENA SILVESTROVA RAKHIMOV Upper Saddle River, NJ • Boston • Indianapolis • San Francisco • New York •Toronto • Montreal • London • Munich • Paris • Madrid • Cape Town • Sydney • Tokyo • Singapore • Mexico City
ContentsAcknowledgments xivAbout the Authors xvIntroduction xviiCHAPTER 1 PL/SQL Concepts 1LAB 1.1 PL/SQL in Client/Server Architecture 2 1.1.1 Use PL/SQL Anonymous Blocks 8 1.1.2 Understand How PL/SQL Gets Executed 10LAB 1.2 PL/SQL in SQL*Plus 12 1.2.1 Use Substitution Variables 16 1.2.2 Use the DBMS_OUTPUT.PUT_LINE Statement 17Chapter 1 Try It Yourself 19CHAPTER 2 General Programming Language Fundamentals 21LAB 2.1 PL/SQL Programming Fundamentals 22 2.1.1 Make Use of PL/SQL Language Components 23 2.1.2 Make Use of PL/SQL Variables 24 2.1.3 Handle PL/SQL Reserved Words 26 2.1.4 Make Use of Identifiers in PL/SQL 27 2.1.5 Make Use of Anchored Datatypes 28 2.1.6 Declare and Initialize Variables 31 2.1.7 Understand the Scope of a Block, Nested Blocks, and Labels 34Chapter 2 Try It Yourself 37CHAPTER 3 SQL in PL/SQL 39LAB 3.1 Making Use of DML in PL/SQL 40 3.1.1 Use the Select INTO Syntax for Variable Initialization 41 3.1.2 Use DML in a PL/SQL Block 42 3.1.3 Make Use of a Sequence in a PL/SQL Block 44LAB 3.2 Making Use of SAVEPOINT 45 3.2.1 Make Use of COMMIT, ROLLBACK, and SAVEPOINT in a PL/SQL Block 48Chapter 3 Try It Yourself 51
viii ContentsCHAPTER 4 Conditional Control: IF Statements 53LAB 4.1 IF Statements 54 4.1.1 Use the IF-THEN Statement 58 4.1.2 Use the IF-THEN-ELSE Statement 62LAB 4.2 ELSIF Statements 65 4.2.1 Use the ELSIF Statement 69LAB 4.3 Nested IF Statements 74 4.3.1 Use Nested IF Statements 76Chapter 4 Try It Yourself 80CHAPTER 5 Conditional Control: CASE Statements 81LAB 5.1 CASE Statements 82 5.1.1 Use the CASE Statement 89 5.1.2 Use the Searched CASE Statement 91LAB 5.2 CASE Expressions 96 5.2.1 Use the CASE Expression 100LAB 5.3 NULLIF and COALESCE Functions 103 5.3.1 The NULLIF Function 107 5.3.2 Use the COALESCE Function 109Chapter 5 Try It Yourself 112CHAPTER 6 Iterative Control: Part I 113LAB 6.1 Simple Loops 114 6.1.1 Use Simple Loops with EXIT Conditions 118 6.1.2 Use Simple Loops with EXIT WHEN Conditions 120LAB 6.2 WHILE Loops 124 6.2.1 Use WHILE Loops 128LAB 6.3 Numeric FOR Loops 132 6.3.1 Use Numeric FOR Loops with the IN Option 137 6.3.2 Use Numeric FOR Loops with the REVERSE Option 139Chapter 6 Try It Yourself 142CHAPTER 7 Iterative Control: Part II 143LAB 7.1 The CONTINUE Statement 144 7.1.1 Use the CONTINUE Statement 146 7.1.2 Use the CONTINUE WHEN Condition 152
Contents ixLAB 7.2 Nested Loops 154 7.2.1 Use Nested Loops 157Chapter 7 Try It Yourself 161CHAPTER 8 Error Handling and Built-in Exceptions 163LAB 8.1 Handling Errors 164 8.1.1 Understand the Importance of Error Handling 167LAB 8.2 Built-in Exceptions 169 8.2.1 Use Built-in Exceptions 174Chapter 8 Try It Yourself 178CHAPTER 9 Exceptions 179LAB 9.1 Exception Scope 180 9.1.1 Understand the Scope of an Exception 183LAB 9.2 User-Defined Exceptions 188 9.2.1 Use User-Defined Exceptions 193LAB 9.3 Exception Propagation 197 9.3.1 Understand How Exceptions Propagate 203 9.3.2 Reraise Exceptions 206Chapter 9 Try It Yourself 209CHAPTER 10 Exceptions: Advanced Concepts 211LAB 10.1 RAISE_APPLICATION_ERROR 212 10.1.1 Use RAISE_APPLICATION_ERROR 215LAB 10.2 EXCEPTION_INIT Pragma 217 10.2.1 USE the EXCEPTION_INIT Pragma 219LAB 10.3 SQLCODE and SQLERRM 222 10.3.1 Use SQLCODE and SQLERRM 225Chapter 10 Try It Yourself 227CHAPTER 11 Introduction to Cursors 229LAB 11.1 Cursor Manipulation 230 11.1.1 Make Use of Record Types 234 11.1.2 Process an Explicit Cursor 235 11.1.3 Make Use of Cursor Attributes 240 11.1.4 Put It All Together 242
x ContentsLAB 11.2 Using Cursor FOR Loops and Nested Cursors 246 11.2.1 Use a Cursor FOR Loop 247 11.2.2 Process Nested Cursors 247Chapter 11 Try It Yourself 252CHAPTER 12 Advanced Cursors 253LAB 12.1 Using Parameters with Cursors and Complex Nested Cursors 254 12.1.1 Use Parameters in a Cursor 255 12.1.2 Use Complex Nested Cursors 255LAB 12.2 FOR UPDATE and WHERE CURRENT Cursors 258 12.2.1 For UPDATE and WHERE CURRENT Cursors 258CHAPTER 13 Triggers 263LAB 13.1 What Triggers Are 264 13.1.1 Understand What a Trigger Is 272 13.1.2 Use BEFORE and AFTER Triggers 274LAB 13.2 Types of Triggers 277 13.2.1 Use Row and Statement Triggers 283 13.2.2 Use INSTEAD OF Triggers 285Chaper 13 Try It Yourself 290CHAPTER 14 Compound Triggers 291LAB 14.1 Mutating Table Issues 292 14.1.1 Understand Mutating Tables 296LAB 14.2 Compound Triggers 300 14.2.1 Understand Compound Triggers 306Chapter 14 Try It Yourself 313CHAPTER 15 Collections 315LAB 15.1 PL/SQL Tables 316 15.1.1 Use Associative Arrays 326 15.1.2 Use Nested Tables 330LAB 15.2 Varrays 334 15.2.1 Use Varrays 338LAB 15.3 Multilevel Collections 342 15.3.1 Use Multilevel Collections 344Chapter 15 Try It Yourself 348
Contents xiCHAPTER 16 Records 349LAB 16.1 Record Types 350 16.1.1 Use Table-Based and Cursor-Based Records 358 16.1.2 Use User-Defined Records 362LAB 16.2 Nested Records 367 16.2.1 Use Nested Records 369LAB 16.3 Collections of Records 373 16.3.1 Use Collections of Records 374Chapter 16 Try It Yourself 378CHAPTER 17 Native Dynamic SQL 379LAB 17.1 EXECUTE IMMEDIATE Statements 380 17.1.1 Use the EXECUTE IMMEDIATE Statement 387LAB 17.2 OPEN-FOR, FETCH, and CLOSE Statements 392 17.2.1 Use OPEN-FOR, FETCH, and CLOSE Statements 395Chapter 17 Try It Yourself 401CHAPTER 18 Bulk SQL 403LAB 18.1 The FORALL Statement 404 18.1.1 Use the FORALL Statement 413LAB 18.2 The BULK COLLECT Clause 422 18.2.1 Use the BULK COLLECT Statement 428Chapter 18 Try It Yourself 437CHAPTER 19 Procedures 439LAB 19.1 Creating Procedures 441 19.1.1 Create Procedures 441 19.1.2 Query the Data Dictionary for Information on Procedures 443LAB 19.2 Passing Parameters into and out of Procedures 444 19.2.1 Use IN and OUT Parameters with Procedures 445Chapter 19 Try It Yourself 447 Part 1 447 Part 2 447
xii ContentsCHAPTER 20 Functions 449LAB 20.1 Creating and Using Functions 450 20.1.1 Create Stored Functions 451 20.1.2 Make Use of Functions 452 20.1.3 Invoke Functions in SQL Statements 453 20.1.4 Write Complex Functions 454Chapter 20 Try It Yourself 455CHAPTER 21 Packages 457LAB 21.1 The Benefits of Using Packages 458 21.1.1 Create Package Specifications 460 21.1.2 Create Package Bodies 462 21.1.3 Call Stored Packages 464 21.1.4 Create Private Objects 465 21.1.5 Create Package Variables and Cursors 469LAB 21.2 Cursor Variables 471 21.2.1 Make Use of Cursor Variables 475LAB 21.3 Extending the Package 480 21.3.1 Extend the Package 480Chapter 21 Try It Yourself 493CHAPTER 22 Stored Code 495LAB 22.1 Gathering Information About Stored Code 496 22.1.1 Get Stored Code Information from the Data Dictionary 496 22.1.2 Enforce the Purity Level with the RESTRICT_REFERENCES Pragma 500 22.1.3 Overload Modules 506Chapter 22 Try It Yourself 512CHAPTER 23 Object Types in Oracle 513LAB 23.1 Object Types 514 23.1.1 Use Object Types 522 23.1.2 Use Object Types with Collections 526LAB 23.2 Object Type Methods 531 23.2.1 Use Object Type Methods 544Chapter 23 Try It Yourself 554
Contents xiiiCHAPTER 24 Oracle Supplied Packages 555LAB 24.1 Making Use of Oracle Supplied Packages to Profile PL/SQL, Access Files, and Schedule Jobs 556 24.1.1 Access Files with UTL_FILE 563 24.1.2 Schedule Jobs with DBMS_JOB 563 24.1.3 Submit Jobs 564LAB 24.2 Making Use of Oracle-Supplied Packages to Generate an Explain Plan and Create HTML Pages 568 24.2.1 Generate an Explain Plan with DBMS_XPLAN 572LAB 24.3 Creating Web Pages with the Oracle Web Toolkit 578 24.3.1 Create an HTML Page with the Oracle Web Toolkit 594APPENDIX A PL/SQL Formatting Guide 597APPENDIX B Student Database Schema 601APPENDIX C ANSI SQL Standards 607APPENDIX D Answers to the Try It Yourself Sections 613INDEX 7051) Visit www.informit.com/title/0137144229 to learn how to register this product and gainaccess to additional content.2) To register this product and gain access to bonus content, go to www.informit.com/register tosign in and enter the ISBN. After you register the product, a link to the additional content willbe listed on your Account page, under Registered Products.
ACKNOWLEDGMENTSBenjamin Rosenzweig: I would like to thank my coauthor, Elena Silvestrova Rakhimov, forbeing a wonderful and knowledgeable colleague to work with. I would also like to thankDouglas Scherer for giving me the opportunity to work on this book, as well as for providingconstant support and assistance through the entire writing process. I am indebted to the team atPrentice Hall, which includes Trina MacDonald, Songlin Qiu, Todd Taber, Shahdad Moradi, andOleg Voskoboynikov. Their contributions, suggestions, and edits helped improve our originalmanuscript and make the book what it is today. Finally, I would like to thank my many friendsand family, especially Edward Clarin and Edward Knopping, for helping me through the longprocess of putting the whole book together, which included many late nights and weekends.Elena Silvestrova Rakhimov: My contribution to this book reflects the help and advice of manypeople. I am particularly indebted to my coauthor, Benjamin Rosenzweig, for making this projecta rewarding and enjoyable experience. Special thanks to Trina MacDonald, Songlin Qiu, ToddTaber, and many others at Prentice Hall who diligently worked to bring this book to market.Thanks to Shahdad Moradi and Oleg Voskoboynikov for their valuable comments and sugges-tions. Most importantly, to my family, whose excitement, enthusiasm, inspiration, and supportencouraged me to work hard to the very end, and were exceeded only by their love.
ABOUT THE AUTHORSBenjamin Rosenzweig is a software development manager at Misys Treasury & Capital Markets,where he has worked since 2002. Prior to that he was a principal consultant for more than threeyears at Oracle Corporation in the Custom Development Department. His computer experienceranges from creating an electronic Tibetan–English dictionary in Kathmandu, Nepal, to supportingpresentation centers at Goldman Sachs and managing a trading system at TIAA-CREF Rosenzweig .has been an instructor at the Columbia University Computer Technology and Application programin New York City since 1998. In 2002 he was awarded the Outstanding Teaching Award from thechair and director of the CTA program. He holds a B.A. from Reed College and a certificate in data-base development and design from Columbia University. His previous books with Prentice Hall areOracle Forms Developer: The Complete Video Course (ISBN: 0-13-032124-9) and Oracle WebApplication Programming for PL/SQL Developers (ISBN: 0-13-047731-1).Elena Silvestrova Rakhimov has more than 15 years of experience in database developmentin a wide spectrum of enterprise and business environments, ranging from nonprofit organiza-tions to Wall Street. She currently works at Alea Software, where she serves as Senior Developerand Team Lead. Her determination to stay hands-on notwithstanding, Rakhimov has managedto excel in the academic arena, having taught relational database programming at ColumbiaUniversity’s highly esteemed Computer Technology and Applications program. She was educatedin database analysis and design at Columbia University and in applied mathematics at Baku StateUniversity in Azerbaijan. She currently resides in Vancouver, Canada.
INTRODUCTIONPL/SQL New Features in Oracle 11gOracle 11g has introduced a number of new features and improvements for PL/SQL. This intro-duction briefly describes features not covered in this book and points you to specific chaptersfor features that are within scope of this book. The list of features described here is also availablein the “What’s New in PL/SQL?” section of the PL/SQL Language Reference manual offered aspart of Oracle help available online.The new PL/SQL features and enhancements are as follows: . Enhancements to regular expression built-in SQL functions . SIMPLE_INTEGER, SIMPLE_FLOAT, and SIMPLE_DOUBLE datatypes . CONTINUE statement . Sequences in PL/SQL expressions . Dynamic SQL enhancements . Named and mixed notation in PL/SQL subprogram invocations . Cross-session PL/SQL function result cache . More control over triggers . Compound triggers . Database resident connection pool . Automatic subprogram inlining . PL/Scope . PL/SQL hierarchical profiler . PL/SQL native compiler generates native code directlyEnhancements to Regular Expression Built-In SQL FunctionsIn this release Oracle has introduced a new regular expression built-in function,REGEXP_COUNT. It returns the number of times a specified search pattern appears in asource string.
xviii IntroductionFOR EXAMPLESELECT REGEXP_COUNT (Oracle PL/SQL By Example Updated for Oracle 11g, ora, 1, i) FROM dual;REGEXP_COUNT(ORACLEPL/SQLBYEXAMPLEUPDATEDFORORACLE11G,ORA,1,I)-------------------------------------------------------------------- 2The REGEXP_COUNT function returns how many times the search pattern ora appears inthe source string Oracle PL/SQL... 1 indicates the position of the source string where thesearch begins, and i indicates case-insensitive matching.The existing regular expression built-in functions, REGEXP_INSTR and REGEXP_SUBSTR, havea new parameter called SUBEXPR. This parameter represents a subexpression in a search pattern.Essentially it is a portion of a search pattern enclosed in parentheses that restricts patternmatching, as illustrated in the following example.FOR EXAMPLESELECT REGEXP_INSTR (Oracle PL/SQL By Example Updated for Oracle 11g, ((ora)(cle)), 1, 2, 0, i) FROM dual;REGEXP_INSTR(ORACLEPL/SQLBYEXAMPLEUPDATEDFORORACLE11G,...)------------------------------------------------------------ 38The REGEXP_INSTR function returns the position of the first character in the source stringOracle PL/SQL… corresponding to the second occurrence of the first subexpression orain the seach pattern (ora)(cle). 1 indicates the position of the source string where the searchbegins, 2 indicates the occurrence of the subexpression in the source string, 0 indicates that theposition returned corresponds to the position of the first character where the match occurs, andi indicates case-insensitive matching and REGEXP_SUBSTR.SIMPLE_INTEGER, SIMPLE_FLOAT, and SIMPLE_DOUBLEDatatypesThese datatypes are predefined subtypes of the PLS_INTEGER, BINARY_FLOAT, andBINARY_DOUBLE, respectively. As such, they have the same range as their respective base types.In addition, these subtypes have NOT NULL constraints.
Introduction xixThese subtypes provide significant performance improvements over their respective base typeswhen the PLSQL_CODE_TYPE parameter is set to NATIVE. This is because arithmetic opera-tions for these subtypes are done directly in the hardware layer. Note that whenPLSQL_CODE_TYPE is set to INTERPRETED (the default value), the performance gains aresignificantly smaller. This is illustrated by the following example.FOR EXAMPLESET SERVEROUTPUT ONDECLARE v_pls_value1 PLS_INTEGER := 0; v_pls_value2 PLS_INTEGER := 1; v_simple_value1 SIMPLE_INTEGER := 0; v_simple_value2 SIMPLE_INTEGER := 1; -- Following are used for elapsed time calculation -- The time is calculated in 100th of a second v_start_time NUMBER; v_end_time NUMBER;BEGIN -- Perform calculations with PLS_INTEGER v_start_time := DBMS_UTILITY.GET_TIME; FOR i in 1..50000000 LOOP v_pls_value1 := v_pls_value1 + v_pls_value2; END LOOP; v_end_time := DBMS_UTILITY.GET_TIME; DBMS_OUTPUT.PUT_LINE (Elapsed time for PLS_INTEGER: || (v_end_time - v_start_time)); -- Perform the same calculations with SIMPLE_INTEGER v_start_time := DBMS_UTILITY.GET_TIME; FOR i in 1..50000000 LOOP v_simple_value1 := v_simple_value1 + v_simple_value2; END LOOP; v_end_time := DBMS_UTILITY.GET_TIME; DBMS_OUTPUT.PUT_LINE (Elapsed time for SIMPLE_INTEGER: || (v_end_time - v_start_time));END;
xx IntroductionThis script compares the performance of the PLS_INTEGER datatype with its subtypeSIMPLE_INTEGER via a numeric FOR loop. Note that for this run the PLSQL_CODE_TYPEparameter is set to its default value, INTERPRETED. Elapsed time for PLS_INTEGER: 147 Elapsed time for SIMPLE_INTEGER: 115 PL/SQL procedure successfully completed.CONTINUE StatementSimilar to the EXIT statement, the CONTINUE statement controls loop iteration. Whereas theEXIT statement causes a loop to terminate and passes control of the execution outside the loop,the CONTINUE statement causes a loop to terminate its current iteration and passes control tothe next iteration of the loop. The CONTINUE statement is covered in detail in Chapter 7,“Iterative Control—Part 2.”Sequences in PL/SQL ExpressionsPrior to Oracle 11g, the sequence pseudocolumns CURRVAL and NEXTVAL could be accessedin PL/SQL only through queries. Starting with Oracle 11g, these pseudocolumns can be accessedvia expressions. This change not only improves PL/SQL source code, it also improves runtimeperformance and scalability.FOR EXAMPLECREATE SEQUENCE test_seq START WITH 1 INCREMENT BY 1;Sequence created.SET SERVEROUTPUT ONDECLARE v_seq_value NUMBER;BEGIN v_seq_value := test_seq.NEXTVAL; DBMS_OUTPUT.PUT_LINE (v_seq_value: ||v_seq_value);END;This script causes an error when executed in Oracle 10g: v_seq_value := test_seq.NEXTVAL; * ERROR at line 4: ORA-06550: line 4, column 28: PLS-00357: Table,View Or Sequence reference TEST_SEQ.NEXTVAL not allowed in this context ORA-06550: line 4, column 4: PL/SQL: Statement ignored
Introduction xxiand it completes successfully when executed in Oracle 11g: v_seq_value: 1 PL/SQL procedure successfully completed.Consider another example that illustrates performance improvement when the PL/SQL expres-sion is used to manipulate sequences:FOR EXAMPLESET SERVEROUTPUT ONDECLARE v_seq_value NUMBER; -- Following are used for elapsed time calculation v_start_time NUMBER; v_end_time NUMBER;BEGIN -- Retrieve se