Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
202,35 KB
Nội dung
the Oracle7 architecture allows you to embed many of your business rules directly into your database structure, using database triggers, constraints, and stored procedures In many cases, you will want to let the RDBMS trap and reject invalid database actions To this, you need a way to identify application-specific errors and return information about those error back to the client This kind of error communication is illustrated in Figure 8.2 Figure 8.2: Error communication from server to client I have called this type of exception "unnamed" and "programmer-defined." The programmer-defined aspect should be clear: because the error is application-specific, you cannot expect PL/SQL to have already defined it for you The reason this type of exception is also unnamed is that you cannot name or declare an exception within a server-based program or database trigger and have the client-side tool handle that named exception This identifier simply doesn't cross the great divide between client and server To get around this problem, Oracle provides a special procedure to allow communication of an unnamed, yet programmer-defined, server-side exception: RAISE_APPLICATION_ERROR (The use of this procedure and exception type is discussed in Section 8.7, "Client-Server Error Communication" later in this chapter.) The specification for this procedure is as follows: PROCEDURE RAISE_APPLICATION_ERROR (error_number_in IN NUMBER, error_msg_in IN VARCHAR2); where error_number_in is the error number you have assigned to this error The error_msg_in argument is the message that will be sent back with the error code to the client program Previous: 8.2 The Exception Section Oracle PL/SQL Programming, 2nd Edition Next: 8.4 Determining Exception-Handling Behavior Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark 8.2 The Exception Section Book Index 8.4 Determining ExceptionHandling Behavior The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 8.1 Why Exception Handling? Chapter Exception Handlers Next: 8.3 Types of Exceptions 8.2 The Exception Section A PL/SQL block (of which procedures, functions, and anonymous blocks are all instances) consists of up to four parts: the header, declaration section, execution section, and exception section, as shown in the following anonymous block: DECLARE declarations BEGIN executable statements [ EXCEPTION exception handlers ] END; When an exception is raised within the execution section of a PL/SQL block, control passes to the exception section PL/SQL then scans through the exception handlers to see if that exception is handled The syntax for an exception section follows: EXCEPTION WHEN exception_name [ OR exception_name ] THEN END; You can have multiple exception handlers in a single exception section The exception handlers are structured much like a conditional CASE statement, as shown below: The Exception Section An English-like Translation Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark EXCEPTION WHEN NO_DATA_FOUND THEN executable_statements1; If the NO_DATA_FOUND exception was raised, then execute the first set of statements WHEN payment_overdue THEN executable_statements2; If the payment is overdue, then execute the second set of statements WHEN OTHERS THEN executable_statements3; END; If any other exception is encountered, then execute the third set of statements An exception is handled if an exception that is named in a WHEN clause matches the exception that was raised Notice that the WHEN clause traps errors only by exception name, not by error codes If a match is found, then the executable statements associated with that exception are run If the exception that has been raised is not handled or does not match any of the named exceptions, the executable statements associated with the WHEN OTHERS clause if present will be run The WHEN OTHERS clause is optional; if it is not present, then any unhandled exception is immediately raised in the enclosing block, if any If the exception is not handled by any PL/SQL block, then the error number and message are presented directly to the user of the application The exception is, in other words, unhandled and it disrupts the execution of the application Previous: 8.1 Why Oracle PL/SQL Exception Handling? Programming, 2nd Edition 8.1 Why Exception Handling? Book Index Next: 8.3 Types of Exceptions 8.3 Types of Exceptions The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 7.7 Tips for PL/ SQL Loops Chapter Next: 8.2 The Exception Section Exception Handlers Contents: Why Exception Handling? The Exception Section Types of Exceptions Determining Exception-Handling Behavior Raising an Exception Handling Exceptions Client-Server Error Communication NO_DATA_FOUND: Multipurpose Exception Exception Handler as IF Statement RAISE Nothing but Exceptions In the PL/SQL language, errors of any kind are treated as exceptions situations that should not occur in your program An exception can be one of the following: ● ● ● An error generated by the system (such as "out of memory" or "duplicate value in index") An error caused by a user action A warning issued by the application to the user PL/SQL traps and responds to errors using an architecture of exception handlers The exceptionhandler mechanism allows you to cleanly separate your error processing code from your executable statements It also provides an event-driven model, as opposed to a linear code model, for processing errors In other words, no matter how a particular exception is raised, it is handled by the same exception handler in the exception section When an error occurs in PL/SQL, whether a system error or an application error, an exception is raised The processing in the current PL/SQL block's execution section halts and control is transferred to the separate exception section of your program, if one exists, to handle the exception You cannot return to that block after you finish handling the exception Instead, control is passed to the enclosing block, if any Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Figure 8.1 illustrates how control is transferred to the exception section when an exception is raised Figure 8.1: Exception handling architecture 8.1 Why Exception Handling? It is a sad fact of life that most programmers never take the time to properly bullet-proof their programs Instead, wishful thinking often reigns Most of us find it hard enough and more than enough work to simply write the code that implements the positive aspects of an application: maintaining customers, generating invoices, etc It is devilishly difficult from both a psychological standpoint and a resources perspective to focus on the negative side of our life: what happens when the user presses the wrong key? If the database is unavailable, what should I do? As a result, we write applications that often assume the best of all possible worlds, hoping that our programs are bug-free, that users will enter only the correct data in only the correct fashion, and that all systems (hardware and software) will always be a "go." Of course, harsh reality dictates that no matter how hard you try, there will always be one more bug in your application And your users will always find just the right sequence of keystrokes it takes to make a screen implode The situation is clear: either you spend the time up front to properly debug and bulletproof your programs, or you will fight an unending series of rear-guard battles, taking frantic calls from your users and putting out the fires You know what you should Fortunately, PL/SQL offers a powerful and flexible way to trap and handle errors in your programs It is entirely feasible within the PL/SQL language to build an application which fully protects the user and the database from errors Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark The exception handler model offers the following advantages: ● ● ● Event-driven handling of errors As we've mentioned, PL/SQL exception handling follows an event-driven rather than a linear code model No matter how a particular exception is raised, it is handled by the same exception handler in the exception section You not have to check repeatedly for a condition in your code, but instead can insert an exception for that condition once in the exception section and be certain that it will be handled throughout that block (and all of its enclosing blocks) Clean separation of error-processing code With the exception-handling model, whenever an exception is raised, program control transfers completely out of the normal execution sequence and into the exception section Instead of placing error-handling logic throughout different sections of your program, you can consolidate all of this logic into a single, separate section Furthermore, if you need to add new exceptions in your program (perhaps you overlooked a possible problem, or a new kind of system error has been identified), you not have to figure out where in your executable code to put the error-handling logic Simply add another exception handler at the bottom of the block Improved reliability of error handling It is quite difficult for errors to go undetected with the PL/SQL error-handling model If there is a handler, then that exception will be dealt with in the current block or in an enclosing block Even if there is no explicit handler for that error, normal code execution will still stop Your program cannot simply "work through" an error -unless you explicitly organize your code to allow this There is no avoiding the fact that if you want to trap errors in your PL/SQL programs you will have to write some additional code The exception handler architecture, however, minimizes the amount of code you will need to write, and offers the possibility of guarding against all problems that might arise in your application The following sections look at how you define, raise, and handle exceptions in PL/SQL Previous: 7.7 Tips for PL/ SQL Loops 7.7 Tips for PL/SQL Loops Oracle PL/SQL Programming, 2nd Edition Book Index Next: 8.2 The Exception Section 8.2 The Exception Section The Oracle Library Navigation Copyright (c) 2000 O'Reilly & Associates All rights reserved Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Previous: 7.6 Managing Loop Execution Chapter Loops Next: Exception Handlers 7.7 Tips for PL/SQL Loops Loops are very powerful and useful constructs, but they are among the most complicated control structures in PL/SQL The tips in this section will help you select the most efficient and easily maintained loops for your programs 7.7.1 Naming Loop Indexes How would you like to try to understand much less maintain code that looks like this? FOR i IN start_id end_id LOOP FOR j IN LOOP FOR k IN 24 LOOP build_schedule (i, j, k); END LOOP; END LOOP; END LOOP; It is hard to imagine that someone would write code based on such generic integer variable names (right out of Algebra 101), yet it happens all the time The habits we pick up in our earliest days of programming have an incredible half-life Unless you are constantly vigilant, you will find yourself writing the most abominable code In this case, the solution is simple: use variable names for the loop indexes that are meaningful and therefore self-documenting: FOR focus_account IN start_id end_id LOOP FOR day_in_week IN LOOP FOR month_in_biyear IN 24 LOOP build_schedule (focus_account, day_in_week, Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark month_in_biyear); END LOOP; END LOOP; END LOOP; Well, that cleared things up! Before I substituted the meaningless loop index names, I would wager that you were fairly sure the statement: FOR j IN meant that "j" stood for the seven days of the week And I bet further that you were equally confident that: FOR k IN 24 meant that "k" represented the hours in a day Now that I have provided descriptive names for those index variables, however, you discover that the innermost loop actually spanned two sets of twelve months (12 × = 24) Your deduction about "k", while reasonable, was wrong, but it would have been completely impossible to determine this without looking at the build_schedule code Given PL/SQL's ability to hide information within packages, this code might not even be available Software programmers should not have to make Sherlock Holmes-like deductions about the meaning of the start and end range values of the innermost FOR loops in order to understand their purpose Use names that self-document the purposes of variables and loops That way other people will understand your code and you will remember what your own code does when you review it three months later 7.7.2 The Proper Way to Say Goodbye No matter what kind of loop you are using, there is always only one entry point into the loop: the first executable statement following the LOOP keyword Your loops should also have just one way of leaving the loop The method of exit, furthermore, should be compatible with the type of loop you use The following tips will help you write well-structured and easily maintained loops 7.7.2.1 Premature FOR loop termination The syntax of the FOR loop states your intent explicitly and should only be a FOR loop if you know in advance how many times the loop needs to execute For example, the following loop is very clear: FOR month_count IN 12 LOOP analyze_month (month_count); Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark END LOOP; It states: "I am going to execute the analyze_month procedure 12 times, once for each month in the year." Straightforward and easy to understand Now take a look at the next numeric FOR loop: FOR year_count IN years_displayed LOOP IF year_count > 10 AND :store.status = 'CLOSED' THEN EXIT; END IF; analyze_month (month_count); END LOOP; In this case, the loop boundary states: "Run the loop for the number of years displayed in the form." Yet in the body of the loop, an IF statement allows a premature termination of the loop If the year count (the loop index) exceeds 10 and the current store status is CLOSED, then an EXIT statement is issued and the loop halts This approach is very unstructured and contradictory The loop boundary states one thing, but the loop body executes something very different You should always let a FOR loop (whether numeric or cursor) complete its stated number of iterations If you need to conditionally halt loop execution, you should choose either an infinite or a WHILE loop The above FOR loop could, for example, be easily recoded as follows: FOR year_count IN LEAST (years_displayed, 11) LOOP analyze_month (month_count); END LOOP; Similar guidelines apply to the infinite and WHILE loop, as I explore in the next sections 7.7.2.2 EXIT and EXIT WHEN statements Neither the FOR loop nor the WHILE loop should use the EXIT and EXIT WHEN statements You have already seen why this is so in FOR loops Consider the following WHILE loop: WHILE more_records LOOP NEXT_RECORD; EXIT WHEN :caller.name IS NULL; END LOOP; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark ... exceptions in PL/SQL Previous: 7.7 Tips for PL/ SQL Loops 7.7 Tips for PL/SQL Loops Oracle PL/SQL Programming, 2nd Edition Book Index Next: 8.2 The Exception Section 8.2 The Exception Section The Oracle. .. know what you should Fortunately, PL/SQL offers a powerful and flexible way to trap and handle errors in your programs It is entirely feasible within the PL/SQL language to build an application... Previous: 8.1 Why Oracle PL/SQL Exception Handling? Programming, 2nd Edition 8.1 Why Exception Handling? Book Index Next: 8.3 Types of Exceptions 8.3 Types of Exceptions The Oracle Library Navigation