Tài liệu Teach Yourself PL/SQL in 21 Days- P4 pptx

50 392 0
Tài liệu Teach Yourself PL/SQL in 21 Days- P4 pptx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

D AY 5 W EEK 1 Implementing Loops and GOTO s by Tom Luers Day 4, “Using Functions, IF Statements, and Loops,” demonstrates ways to change the order of execution with PL/SQL. Today’s lesson covers several additional methods of changing the order of execution. Today’s material covers the following topics: •Statement labels • The GOTO statement • The WHILE loop • The simple LOOP • Emulating a REPEAT .UNTIL loop • Recursion 07 7982 ch05 11.8.00 11:23 AM Page 127 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Exploring Labels and the GOTO Statement The GOTO statement allows for unconditional branching to a statement label. You will first learn about statement labels, which are necessary to include before you can even use the GOTO statement. Statement Labels Statement labels are identifiers of a block of code that is similar to a function, but they are not actual PL/SQL statements. The GOTO statement can directly access these labels. In addition, these labels can be accessed by loops, which are covered in the section “The EXIT and EXIT WHEN Statements.” The format of a label is <<label_name>> Notice two things about the label: • The label is surrounded by double brackets ( << ). • The label must not have a semicolon after the label name. The label name does not contain a semicolon because it is not a PL/SQL statement, but rather an identifier of a block of PL/SQL code. 128 Day 5 Labels can’t take the place of required statements therefore you must have at least one statement after the label or an error results. If your intention is to execute the code after a label, you should re-evaluate your code decisions and choose an alternate method such as a function. Caution The GOTO Statement The GOTO statement enables you to immediately transfer control to another labeled PL/SQL block without the need for conditional checking. As soon as the GOTO statement is encountered, all control is transferred to the code following the matching label_name . This target label can appear anywhere in the same block of code. The Syntax for the GOTO Statement GOTO label_name; The label_name is the matching label_name that must be contained within the same PL/SQL block of code. S YNTAX 07 7982 ch05 11.8.00 11:23 AM Page 128 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Implementing Loops and GOTO s 129 5 Scoping Rules for the GOTO Statement The GOTO destination must be in the same block, at the same level as, or higher than the GOTO statement itself. This means that the label must be within the same scope as the GOTO statement itself. Conditions that cause Oracle to not compile the PL/SQL code include •Jumping into a subblock •Jumping into a loop •Jumping into an IF statement •Using GOTO to jump from one part of an IF statement to another •Jumping from an exception handler back to a current block of PL/SQL code You encounter the following error message if you do not follow the proper coding of GOTO statements and their labels: PLS-00375: illegal GOTO statement; this GOTO cannot branch to label If you want a more global approach, using stored functions is one appropriate method. Jumping into a Lower-Level Block You can’t jump from an outer block of PL/SQL code back to an inner block of PL/SQL code. Listing 5.1 is an example of an illegal GOTO call. The following listing, and the next few after it, is for illustration purposes only. Due to the errors they generate, you might not want to enter and exe- cute them. However, if you do enter and execute these listings, they will not destroy anything, and they might help you to troubleshoot errors in your code in the future because you can see what errors these listings generate. Caution L ISTING 5.1 Illegal GOTO Call to an Inner Block 1: DECLARE 2: v_Emergency_Warning VARCHAR2(50); 3: v_Status NUMBER = 0; 4: BEGIN 5: GOTO Emergency_Check; 6: BEGIN 7: <<Emergency_Check>> 8: IF v_Status = 1 THEN 9: DBMS_OUTPUT PUT_LINE(‘Emergency!’); 10: END IF; 11: END; 12: END; I NPUT 07 7982 ch05 11.8.00 11:23 AM Page 129 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. In Listing 5.1, you see the first block of PL/SQL code noted by a BEGIN state- ment. The block then calls the PL/SQL GOTO statement, which attempts to trans- fer control to the <<Emergency Check>> label. Because the label is within a separate block of PL/SQL code noted by another BEGIN statement, it is out of the required scope of the GOTO statement. If, instead of the keyword BEGIN ,an <<Emergency_Check>> label appeared within the first block, everything would compile and execute properly (barring errors in the logic of the code). Jumping into a Loop The scope of the loop is not complete until the entire range of the loop has completed. Therefore, attempting to jump into the middle of the loop is illegal. Listing 5.2 shows an attempt to make an illegal call into a FOR loop. 130 Day 5 A NALYSIS The following listing is another that serves illustration purposes only because it generates several errors. You might or might not want to enter and execute this listing, depending on whether you want to see what kinds of errors it generates. Caution L ISTING 5.2 Illegal GOTO Call to a Loop 1: BEGIN 2: GOTO insideloop; 3: FOR v_loopcounter IN 1 5 LOOP 4: <<insideloop> 5: DBMS_OUTPUT.PUT_LINE(‘Loop counter is ‘ || v_loopcounter); 6: END LOOP; 7: END; Error at Line 2 ORA-06550 Line 2 PLS-00201: Identifier ‘insideloop’ must be declared As you can see, although the loop and the GOTO statement are within the same block of PL/SQL code, Oracle does not know how to handle the jump inside the loop. The obvious question is “What is the value of the loop counter?” Because there is no answer, any attempt to implement this logic results in a compile error. I NPUT O UTPUT A NALYSIS 07 7982 ch05 11.8.00 11:23 AM Page 130 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Implementing Loops and GOTO s 131 5 Jumping into an IF Statement Another illegal attempt to use the GOTO statement is to jump inside an IF statement. Listing 5.3 provides an example of another illegal call. The following listing serves illustration purposes only because it generates several errors. You might or might not want to enter and execute this list- ing, depending on whether you want to see what kinds of errors it gener- ates. Caution L ISTING 5.3 Illegal GOTO Call Inside an IF Statement 1: DECLARE 2: v_Emergency_Warning VARCHAR2(50); 3: v_Status NUMBER = 0; 4: v_ReactorStatus VARCHAR2(10); 5: BEGIN 6: GOTO Emergency_Check; 7: IF v_ReactorStatus = ‘Very Hot’ THEN 8: <<Emergency_Check>> 9: DBMS_OUTPUT PUT_LINE(‘Emergency!’); 10: END IF; 11: END; From the GOTO call in Listing 5.3, if this block of PL/SQL code were allowed to actually execute, it would never check to see whether v_ReactorStatus = ‘Very Hot’ . There might not even be an emergency because v_ReactorStatus could have a value of ‘Cool’ . Because the value is never evaluated, the program always goes into cri- sis mode. Fortunately, this improper use of GOTO is not allowed! Jumping from One Part of an IF Statement to Another Although you can call a label from an IF statement, it is illegal for the jump to go from the IF clause to the THEN clause. Listing 5.4 is yet another example of a label not being within the same scope as the GOTO . I NPUT A NALYSIS 07 7982 ch05 11.8.00 11:23 AM Page 131 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. L ISTING 5.4 Illegal GOTO Call from One Clause of an IF Statement to Another Clause 1: DECLARE 2: v_Emergency_Warning VARCHAR2(50); 3: v_Status NUMBER = 0; 4: v_ReactorStatus VARCHAR2(10); 5: BEGIN 6: IF v_ReactorStatus = ‘Very Hot’ THEN 7: GOTO Emergency_Check; 8: ELSE 9: <<Emergency_Check>> 10: DBMS_OUTPUT PUT_LINE(‘Emergency!’); 11: END IF; 12: END; As Listing 5.4 suggests, the program jumps from an evaluation of the IF statement as true to executing code as if the entire statement were false. This is a definite misuse of the GOTO statement, and the code in this case probably does not require a GOTO statement. From Listing 5.5, it should be apparent that you can’t raise an error and then return to the original block of code where the error was generated from the exception handler. 132 Day 5 The following listing is another that serves illustration purposes only because it generates several errors. You might or might not want to enter and execute this listing, depending on whether you want to see what kinds of errors it generates. Caution I NPUT The following listing is another that serves illustration purposes only because it generates several errors. You might or might not want to enter and execute this listing, depending on whether you want to see what kinds of errors it generates. Caution L ISTING 5.5 Illegal GOTO Call from an Exception Handler 1: DECLARE 2: v_Emergency_Warning VARCHAR2(50); 3: v_Status NUMBER = 0; 4: v_ReactorStatus VARCHAR2(10); 5: BEGIN 6: <<Emergency_Check>> 7: PANIC(); 8: EXCEPTION I NPUT 07 7982 ch05 11.8.00 11:23 AM Page 132 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Implementing Loops and GOTO s 133 5 9: WHEN e_TOOHOT THEN 10: GOTO Emergency_Check; 11: END; An Example of the GOTO Statement in Action So far, you have seen conditions that exceed the scope of the GOTO statement. Now, how about an example of a legitimate block of PL/SQL code? See Listing 5.6 for a proper GOTO . L ISTING 5.6 Example of a Proper GOTO Statement 1: DECLARE 2: v_Status NUMBER := 1; 3: BEGIN 4: IF v_Status = 1 THEN 5: GOTO mybranch; 6: ELSE 7: v_Status := 1; 8: END IF; 9: <<mybranch>> 10: NULL; 11: END; In the GOTO example from Listing 5.6, the program checks the value of v_Status . If the value is equal to 1 ,then the program goes immediately to the block <<mybranch>> ; if the value is false ,the program changes the value of v_Status to equal 1 . Why Use the GOTO Statement? As in any procedural language, the use of GOTO statements is highly discouraged. As you saw from the listings earlier in the lesson, GOTO statements are easy to code improperly. In almost all cases, your code can and should be written to avoid the use of GOTO . There are several reasons not to use the GOTO statement: • It is easy to make logic errors when using GOTO . • It is easy to make coding errors even when you are trying to make the process work. I NPUT A NALYSIS 07 7982 ch05 11.8.00 11:23 AM Page 133 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. • If you use multiple GOTO statements, your code jumps all over the place out of sequence, which is known as spaghetti code. Using multiple GOTO s not only causes longer execution times, but also leads to confusion when you review your code and make changes. •Almost all cases in which you use the GOTO statement can be written with other Oracle constructs. Perhaps the only proper use of GOTO statements is to immediately stop all other execution of statements and branch to a section of code to handle an emergency situation. WHILE Loops The WHILE loop enables you to evaluate a condition before a sequence of statements is executed. In fact, if the condition is false, the code is never executed. This situation is different from the FOR loop where you must execute the loop at least once. The Syntax for the WHILE Loop The syntax of the WHILE loop is WHILE <condition is true> LOOP <statements> END LOOP; The WHILE loop requires the keywords LOOP and END LOOP to designate the statements to execute. 134 Day 5 , S YNTAX , WHILE loops are invaluable because the program does not have to ever exe- cute the code within the LOOP parameters. This is one fact I cannot stress enough! Note Examples of WHILE Loops All the WHILE loop examples are meant to be entered and executed so that you can get some experience coding WHILE loops. When you first sign on to the database, it is a good idea to create a login script—or else you can make a habit of typing and executing the statement SET SERVEROUTPUT ON . When you learn about the DBMS_OUTPUT package on Day 17, “Writing to Files and the Display,” using this statement allows you to see the actual output as the PL/SQL code executes to make PL/SQL easier to understand. Note 07 7982 ch05 11.8.00 11:23 AM Page 134 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Implementing Loops and GOTO s 135 5 You can enter the loops directly or use the EDIT command to save a file, which can be executed at any time. Listing 5.7 demonstrates how the conditions for a WHILE loop can cause the loop to never execute. L ISTING 5.7 Example of a WHILE Loop That Never Executes 1: DECLARE 2: v_Calc NUMBER := 0; 3: BEGIN 4: WHILE v_Calc >= 10 LOOP 5: v_Calc := v_Calc + 1; 6: DBMS_OUTPUT.PUT_LINE(‘The value of v_Calc is ‘ || v_Calc); 7: END LOOP; 8: END; 9: / In Listing 5.7, the condition is never evaluated to true. The condition v_Calc >= 10 from line 4 is never true because v_Calc is initialized at line 2 to a value of 0 , which is less, not greater, than 10 . When Listing 5.7 is executed, no output is sent to the screen. Listing 5.8 shows the corrected version of this WHILE loop. L ISTING 5.8 Corrected WHILE Loop That Executes 1: DECLARE 2: v_Calc NUMBER := 0; 3: BEGIN 4: WHILE v_Calc <= 10 LOOP 5: v_Calc := v_Calc + 1; 6: DBMS_OUTPUT.PUT_LINE(‘The value of v_Calc is ‘ || v_Calc); 7: END LOOP; 8: END; 9: / The value of v_Calc is 1 The value of v_Calc is 2 The value of v_Calc is 3 The value of v_Calc is 4 The value of v_Calc is 5 The value of v_Calc is 6 The value of v_Calc is 7 The value of v_Calc is 8 The value of v_Calc is 9 The value of v_Calc is 10 The value of v_Calc is 11 I NPUT A NALYSIS I NPUT O UTPUT 07 7982 ch05 11.8.00 11:23 AM Page 135 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. To make the WHILE loop execute, I simply changed the >= to <= in line 4. The loop executes at least once because v_Calc <= 10 . It is important to understand that the loop continues to execute until v_Calc > 10 . This is a potential source of logic error flaws if the intent was to enter the loop until v_Calc had a value of 10 and not 11 . 136 Day 5 A NALYSIS When debugging loops, in general it is a good idea to use Oracle’s DBMS_OUTPUT package to track the flow of the logic. It is a great help when testing all possible outcomes to make sure that the logic portion is working properly. A full discussion of this package occurs on Day 17. Tip Listing 5.9 illustrates how to step through a WHILE loop in increments other than one. L ISTING 5.9 Stepping Through a WHILE Loop 1: DECLARE 2: v_Radius NUMBER := 2; 3: BEGIN 4: WHILE v_Radius <=10 LOOP 5: DBMS_OUTPUT.PUT_LINE(‘The Area is ‘ || 6: 3.14 * v_Radius * v_Radius); 7: v_Radius := v_Radius + 2 ; — Calculates Area for Even Radius 8: END LOOP; 9: END; 10: / The Area is 12.56 The Area is 50.24 The Area is 113.04 The Area is 200.96 The Area is 314 On Day 4, you created a method to trick Oracle into stepping through a FOR loop. The WHILE loop gives you more flexibility in looping, whether you are stepping through a loop or even executing a loop. Listing 5.9 demonstrates stepping through the loop. This sequence increments v_Radius by a value of 2 from line 7 until it is equal to 10 from the condition specified in line 4. I NPUT O UTPUT A NALYSIS 07 7982 ch05 11.8.00 11:23 AM Page 136 Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... style of coding in Listings 5.22 and 5.23 INPUT LISTING 5 .21 A Confusing FOR Loop 1: BEGIN 2: FOR I = 1995 to 1997 3: LOOP 4: FOR J = 1 to 31 5: LOOP 6: FOR K = 1 to 12 7: LOOP 8: 9: END LOOP; 10: END LOOP; 11: END LOOP; 12: END; A programmer might take an initial look at the code in Listing 5 .21 and say “Huh?” A better approach is shown in Listing 5.22 INPUT LISTING 5.22 Making the FOR... nested loop or when nesting FOR loops to make the index counter more meaningful Proper spacing should include aligning the END LOOP with the LOOP statement and the usual indent of five spaces for statements within the loop Listing 5 .21 contains an example in which the spacing is proper, but the loop itself appears confusing because the code doesn’t follow these tips After Listing 5 .21, you will see the... TO_LABEL Converts a CHAR or VARCHAR2 string into a MLSLABEL TO_MULTI_BYTE Converts any single-byte string of characters into a multibyte string TO_NUMBER Converts a CHAR or VARCHAR2 string into a NUMBER value TO_SINGLE_BYTE Converts any multibyte string of characters into a single-byte string ID into its external 18-character string representation 6 160 Day 6 TABLE 6.5 Grouping Functions Function Name Function... Using Oracle’s Built -In Functions Function Name Function Description INSTRB Returns the location of a string within another string but returns the value in bytes for a single-byte character system LENGTH Returns the length of a character string, including pads Returns NULL if the value is NULL LENGTHB Returns the length of a character string in bytes, except that the return value is in bytes for single-byte... and modify it with label names, as shown in Listing 5.17 INPUT LISTING 5.17 Using Labels with Loops 1: BEGIN 2: 3: FOR v_outerloopcounter IN 1 2 LOOP 4: 5: FOR v_innerloopcounter IN 1 4 LOOP 6: DBMS_OUTPUT.PUT_LINE(‘Outer Loop counter is ‘ || 7: v_outerloopcounter || 8: ‘ Inner Loop counter is ‘ || v_innerloopcounter); 9: END LOOP innerloop; 10: END LOOP outerloop; 11: END;... Joins (concatenates) two strings together (It’s the same as using the || operator, which you might have noticed on Day 4 and Day 5, “Implementing Loops and GOTOs.”) INITCAP Returns a string in which the first letter in each word is capitalized and all remaining characters are converted to lowercase Does not affect any nonalphabetic characters INSTR Returns the location of a string within another string... value is a space, the program does nothing, as indicated by the NULL statement The placeholder in the string v_MYCOUNTER is then incremented by 1, and the loop continues to execute until it reaches the end of the string To see the function in action, type the procedure in Listing 5.11 and then execute it 5 138 Day 5 INPUT 1: 2: 3: 4: 5: 6: LISTING 5.11 Executing the WHILE Loop Function DECLARE v_MYTEXT... the looping continues Implementing Loops and GOTOs 139 You will find as a programmer that using the EXIT WHEN statement will save you time This statement requires less coding than the other looping statements One typical reason you use nested IF statements is for fine-tuning Oracle to speed up the process Tip Examples Using EXIT and EXIT WHEN In this lesson, you created a WHILE loop that incremented... TEST’; BEGIN DBMS_OUTPUT.PUT_LINE(‘Total count is ‘ || dontcountsp(v_MYTEXT)); END; / ANALYSIS The code in Listing 5.11 creates a variable called v_MYTEXT and assigns it a value of ‘THIS IS A TEST’ in line 2 It then outputs to the screen the total count of characters not including spaces in line 4 Note Both the SUBSTR() function and the LENGTH() function are covered on Day 6, “Using Oracle’s Built -In Functions.”... between Listing 4.15 in Day 4 and Listing 5.17 is the use of the label names outerloop and innerloop Otherwise, there is no difference in execution, output, and so on, but it is much easier to follow the logic Implementing Loops and GOTOs You can even change the order of execution of a loop by using the EXIT and EXIT statements, as shown in Listing 5.18 INPUT LISTING 5.18 143 WHEN Changing Labeled . within the same scope as the GOTO statement itself. Conditions that cause Oracle to not compile the PL/SQL code include •Jumping into a subblock •Jumping into. p_PASS_STRING called from the procedure. The return type in line 14 is simply a number telling you how many characters are actually contained in the string.

Ngày đăng: 15/12/2013, 05:15

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan