1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Oracle PL/SQL Language Pocket Reference- P17 docx

50 496 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Thông tin cơ bản

Tiêu đề Database Trigger and Nested Blocks
Chuyên ngành Oracle PL/SQL
Định dạng
Số trang 50
Dung lượng 200,96 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

When you write this code you can enter a fully specified PL/SQL block declaration, execution, and exception sections, or you can enter only the executable section.. Figure 15.6: Anonymou

Trang 1

Database trigger Record or column of table The body of the trigger is coded in PL/

SQL While the trigger has a name, the PL/SQL code itself is unnamed, hence anonymous

Script SQL*Plus and SQL*DBA Ad hoc programs and batch processing

scripts written in SQL*Plus are always anonymous blocks (which may then call procedures or functions)

Embedded PL/SQL programs Pro* embedded languages Embed PL/SQL blocks to execute

statements inside the database server

Whenever you attach PL/SQL code to a trigger or field in a tool, that code forms an anonymous PL/SQL block When you write this code you can enter a fully specified PL/SQL block (declaration, execution, and exception sections), or you can enter only the executable section

15.3.4 Nested Blocks

PL/SQL allows you to nest or embed anonymous blocks within another PL/SQL block You can also nest anonymous blocks within anonymous blocks for more than one level, as shown in Figure 15.6

Figure 15.6: Anonymous blocks nested three levels deep

15.3.4.1 Nested block terminology

A PL/SQL block nested within another PL/SQL block may be called by any of the following: nested

Trang 2

block, enclosed block, child block or sub-block

A PL/SQL block that calls another PL/SQL block (anonymous or named) may be referred to as either the enclosing block or the parent block

15.3.4.2 Nested blocks provide scope

The general advantage of a nested block is that you create a scope for all the declared objects and executable statements in that block You can use this scope to improve your control over activity in your program For a discussion, see Section 15.3.5, "Scope and Visibility" later in this chapter

Consider the following procedure, in which the president and vice-president of the specified company request their salaries be cut in half if their current salaries are more than ten times the average salary

in the company It's the sort of incentive plan that would encourage executives to "share the wealth."

WHERE company_id = company_id_in

AND title = 'VICE-PRESIDENT';

IF v_sal > avgsal_in * 10

THEN

UPDATE employee SET salary := salary * 50

WHERE company_id = company_id_in

AND title = 'VICE-PRESIDENT';

WHERE company_id = company_id_in

AND title = 'PRESIDENT';

IF v_sal > avgsal_in * 10

THEN

Trang 3

UPDATE employee SET salary := salary * 50

WHERE company_id = company_id_in

AND title = `PRESIDENT';

UPDATE employee SET salary := salary * 50

WHERE company_id = &1

AND title = '&2'

AND salary > &3 * 10;

and then execute the SQL script in SQL*Plus using the START command:

SQL> start updemp 1100 VICE-PRESIDENT

SQL> start updemp 1100 PRESIDENT

The programmer who was assigned this task took several things into account:

● The executives might decide they will want to take such actions repeatedly in the coming years; better to package the steps into a reusable chunk of code like a procedure than simply execute a series of SELECT-UPDATEs in SQL*Plus

● Executives come and go frequently at the company There is no guarantee that there will be a person in the employee table with a title of `PRESIDENT' or `VICE-PRESIDENT' at any given time The first assumption argues for the encapsulation of these two SELECT-UPDATE steps into a procedure This second assumption results in the need for embedded PL/SQL blocks around each UPDATE statement Suppose that the procedure update_management did not make use of the embedded blocks The code would then look like this:

PROCEDURE update_management (company_id_in IN NUMBER, avgsal_in IN NUMBER)IS

BEGIN SELECT salary INTO v_sal FROM employee

Trang 4

WHERE company_id = company_id_in AND title = 'VICE-PRESIDENT';

IF v_sal > avgsal_in * 10 THEN

UPDATE employee SET salary := salary * 50 WHERE company_id = company_id_in

AND title = 'VICE-PRESIDENT';

ELSE DBMS_OUTPUT.PUT_LINE ('The VP is OK!');

UPDATE employee SET salary := salary * 50 WHERE company_id = company_id_in

AND title = 'PRESIDENT';

ELSE DBMS_OUTPUT.PUT_LINE ('The Prez is a pal!');

END IF;

END;

If there is a record in the employee table with the title of "VICE-PRESIDENT" (for the appropriate company_id) and if there is a record in the employee table with the title of "PRESIDENT," then this procedure works just fine But what if there is no record with a title of "VICE-PRESIDENT"? What

if the Vice-President did not want to take a 50% cut in pay and instead quit in disgust?

When the WHERE clause of an implict SELECT statement does not identify any records, PL/SQL raises the NO_DATA_FOUND exception (for more details on this phenomenon see Chapter 6,

Database Interaction and Cursors, and pay particular attention to the sections concerning implicit cursors) There is no exception handler section in this procedure As a result, when there is no Vice-President in sight, the procedure will immediately complete (well, abort, actually) and transfer

control to the calling block's exception section to see if the NO_DATA_FOUND exception is

handled there The SELECT-UPDATE for the President's salary is therefore not executed at all

NOTE: You don't actually need a BEGIN-END block around the second

SELECT-UPDATE This is the last statement, and if it fails nothing will be skipped It is good

practice, however, to include an exception statement for the procedure as a whole to

trap errors and handle them gracefully

Our programmer would hate to see an executive's wish go unfulfilled, so we need a mechanism to trap the failure of the first SELECT and allow PL/SQL procedure execution to continue on to the next SELECT-UPDATE The embedded anonymous block offers this protection By placing the first

Trang 5

SELECT within a BEGIN-END envelope, you can also define an exception section just for the

SELECT Then, when the SELECT fails, control is passed to the exception handler for that specific block, not to the exception handler for the procedure as a whole (see Figure 15.7) If you then code an exception to handle NO_DATA_FOUND which allows for continued processing, the next SELECT-UPDATE will be executed

Figure 15.7: An anonymous block "catches" the exception

15.3.4.3 Named modules offer scoping effect of nested block

You can also restructure the update_management procedure to avoid the problems addressed in the previous section, and also the redundancy in the code for that procedure The following version of update_management uses an explicit cursor to avoid the problem of the NO_DATA_FOUND

exception being raised It also encapsulates the repetitive logic into a local or nested procedure

Trang 6

FROM employee

WHERE company_id = company_id_in

AND title = title_in

AND salary > avgsal_in * 10;

PROCEDURE update_exec (title_in IN VARCHAR2)

IS

salrec salcur%ROWTYPE;

BEGIN

OPEN salcur (title_in);

FETCH salcur INTO salrec;

UPDATE employee SET salary := salary * decr_in

WHERE company_id = company_id_in

AND title = title_in;

concept of program (and therefore exception) scope remains the same Use the scoping and visibility rules to your advantage by isolating areas of code and cleaning up the program flow

15.3.5 Scope and Visibility

Two of the most important concepts related to a PL/SQL block are those of the scope and visibility of identifiers An identifier is the name of a PL/SQL object, which could be anything from a variable to

a program name In order to manipulate a PL/SQL identifier (assign a value to it, pass it as a

parameter, or call it in a module), you have to be able to reference that identifier in such a way that the code will compile

The scope of an identifier is the part of a program in which you can make a reference to the identifier and have that reference resolved by the compiler An identifier is visible in a program when it can be

referenced using an unqualified name

Trang 7

15.3.5.1 Qualified identifiers

A qualifier for an identifier can be a package name, module name (procedure or function), or loop label You qualify the name of an identifer with dot notation, the same way you would qualify a column name with the name of its table

The names of the following identifiers are qualified:

:GLOBAL.company_id

A global variable in Oracle Forms

std_types.dollar_amount

A subtype declared in a package

The scope of an identifier is generally the block in which that identifier is declared The following anonymous block declares and then references two local variables:

is precisely this anonymous block

I cannot make reference to either of those variables in a second anonymous block or in a procedure Any attempt to do so will result in a compile failure, because the reference to those variables cannot

be resolved

If an identifier is declared or defined outside of the current PL/SQL block, it is visible (can be

referenced without a qualifier) only under the following conditions:

● The identifier is the name of a standalone procedure or function on which you have

EXECUTE privilege You can then include a call to this module in your block

● The identifier is declared in a block which encloses the current block

15.3.5.2 Scope and nested blocks

Let's take a closer look at nested blocks and the impact on scope and visibility When you declare a

Trang 8

variable in a PL/SQL block, then that variable is local to that block, but is visible in or global to any blocks defined within the first, enclosing block For example, in the following anonymous block, the variable last_date can be referenced anywhere inside the block:

/* The enclosing or outer anonymous block */

DECLARE

last_date DATE;

BEGIN

last_date := LAST_DAY (SYSDATE);

/* The inner anonymous block */

Even though last_date is not defined in the inner block, it can still be referenced there without

qualification because the inner block is defined inside the outer block The last_date variable is therefore considered a global variable in the inner block

Figure 15.8 shows additional examples illustrating the concept of scope in PL/SQL blocks

Figure 15.8: Scope of identifiers in PL/SQL blocks

15.3.5.3 Qualifying identifier names with module names

When necessary, PL/SQL offers many ways to qualify an identifier so that a reference to the

Trang 9

identifier can be resolved Suppose I create a package called company_pkg and declare a variable named last_company_id in that package's specification, as follows:

IF new_company_id = company_pkg.last_company_id THEN

Because a variable declared in a package specification is global in your session, the last_company_id variable can be referenced in any program, but it is not visible unless it is qualified

I can also qualify the name of an identifier with the module in which it is defined:

variable name with the name of the procedure

PL/SQL goes to a lot of trouble and has established many rules for determining how to resolve such naming conflicts While it is good to be aware of such issues, you would be much better off never having to rely on these guidelines Use unique names for your identifiers in different blocks so that you can avoid naming conflicts altogether

15.3.5.4 Cursor scope

Trang 10

To use a cursor, you must declare it But you cannot refer to that cursor whether to OPEN, CLOSE,

or FETCH from it unless that cursor is accessible in your current PL/SQL block The scope of a cursor is that part of a PL/SQL program in which you can refer to the cursor

You can refer to a cursor in the code block in which it was declared and in all blocks defined within that declaring block You cannot refer to the cursor outside of the declaring block unless the cursor is declared in a package (see Chapter 16, Packages, for more information on global variables and

cursors) For example, if a cursor is declared in the get_employees procedure (see below) and within get_employees a second PL/SQL block is defined to calculate total compensation for each employee, the cursor and its attributes may still be referenced in that calculation block:

If, on the other hand, the cursor is declared within an inner block, then that cursor cannot be

referenced in an outer block In the next procedure, the outer block declares the variables that receive the data fetched from the cursor The inner block declares the cursor While the inner block can open the cursor without error, the FETCH statement is outside the scope of the cursor-declaring block and will therefore fail:

Trang 11

/* This fetch will not be able to identify the cursor

sometimes ferreting out errors in the process

● Qualify the names of elements declared in the block to distinguish between references to elements with a different scope, but the same name

A PL/SQL label has this format:

<<identifer>>

where identifier is a valid PL/SQL identifier (up to 30 characters in length, starting with a letter; see

Section 2.2, "Identifiers" in Chapter 2 in Chapter 2, PL/SQL Language Fundamentals, for a complete list of rules)

Let's look at a couple of examples of applying block labels In the first example, I place a label in front of my block simply to give it a name and document its purpose:

Trang 12

Previous: 15.2 Review of

PL/SQL Block Structure

Oracle PL/SQL Programming, 2nd Edition

Next: 15.4 Procedures

15.2 Review of PL/SQL

Block Structure

The Oracle Library

Navigation

Copyright (c) 2000 O'Reilly & Associates All rights reserved

Trang 13

Previous: 15.3 The

Anonymous PL/SQL Block

Chapter 15Procedures and Functions

Next: 15.5 Functions

15.4 Procedures

A procedure is a module performing one or more actions Because a procedure is a standalone

executable statement in PL/SQL, a PL/SQL block could consist of nothing more than a single call to

a procedure Procedures are key building blocks of modular code, allowing you to both consolidate and reuse your program logic

The general format of a PL/SQL procedure is as follows:

PROCEDURE name [ ( parameter [, parameter ] ) ]

Trang 14

executable statements

The statements that the procedure executes when it is called You must have at least one executable statement after the BEGIN and before the END or EXCEPTION keywords

exception handler statements

The optional exception handlers for the procedure If you do not explicitly handle any

exceptions, then you can leave out the EXCEPTION keyword and simply terminate the execution section with the END keyword

Figure 15.9 shows the apply_discount procedure, which contains all four sections of the named PL/SQL block, as well as a parameter list

Figure 15.9: The apply_discount procedure

15.4.1 Calling a Procedure

A procedure is called as an executable PL/SQL statement In other words, a call to a procedure must

Trang 15

end with a semicolon (;) and be executed before and after other SQL or PL/SQL statements

The following executable statement runs the apply_discount procedure:

apply_discount( new_company_id, 0.15 ); 15% discount

If the procedure does not have any parameters, then you must call the procedure without any

● The procedure name

● The parameter list, if any

A programmer does not need to know about the inside of the procedure in order to be able to call it properly from another program

The header for the apply_discount procedure discussed above is:

The body of the procedure is the code required to implement the procedure It consists of the

declaration, execution, and exception sections of the function Everything after the IS keyword in the procedure makes up that procedure's body

Once again, the declaration and exception sections are optional If you have no exception handlers, you will leave off the EXCEPTION keyword and simply enter the END statement to terminate the procedure

If you do not have any declarations, the BEGIN statement simply follows immediately after the IS keyword (see the do_nothing procedure below for an example of this structure.)

You must supply at least one executable statement in a procedure Here is my candidate for the

Trang 16

procedure in PL/SQL with the smallest possible body:

15.4.4 The END Label

You can append the name of the procedure directly after the END keyword when you complete your procedure, as shown below:

PROCEDURE display_stores (region_in IN VARCHAR2) IS

Previous: 15.3 The

Anonymous PL/SQL Block

Oracle PL/SQL Programming, 2nd Edition

Next: 15.5 Functions

15.3 The Anonymous PL/

SQL Block

The Oracle Library

Navigation

Copyright (c) 2000 O'Reilly & Associates All rights reserved

Trang 17

Previous: 15.4 Procedures Chapter 15

Procedures and Functions

Next: 15.6 Parameters

15.5 Functions

A function is a module that returns a value Unlike a procedure, which is a standalone executable statement, a call to a function can only be part of an executable statement

Because a function returns a value, it can be said to have a datatype A function can be used in place

of an expression in a PL/SQL statement having the same datatype as the function

Appendix C, Built-In Packages, describes the built-in functions that PL/SQL provides to help you write your programs You can also write your own functions numeric functions, VARCHAR2 functions, and even functions that return a PL/SQL table or record The programmer-defined

function, a powerful addition to your toolchest, will aid greatly in making your code more flexible and easier to understand

Trang 18

The datatype of the value returned by the function This is required in the function header and

is explained in more detail in the next section

exception handler statements

The optional exception handlers for the function If you do not explicitly handle any

exceptions, then you can leave out the EXCEPTION keyword and simply terminate the

execution section with the END keyword

Figure 15.10 illustrates the PL/SQL function and its different sections Notice that the tot_sales

function does not have an exception section

Figure 15.10: The tot_sales function

Trang 19

15.5.2 The RETURN Datatype

The return_datatype is the datatype of the value returned by the function This datatype can be any datatype (and many complex structures) supported by PL/SQL, including scalars like these:

Trang 20

● PL/SQL record

● Object type (PL/SQL8)

● Large objects (LOBs) such as BFILEs and CLOBs (PL/SQL8)

The datatype of a function cannot be either of the following:

Named exception

Once you declare an exception, you can reference that exception only in a RAISE statement and in the exception handler itself

Cursor name

You cannot return a cursor from a function (Note that PL/SQL Release 2.2 and beyond

provides a REF CURSOR TYPE declaration that will allow you to return a cursor and even declare a parameter as a cursor.)

15.5.3 The END Label

You can append the name of the function directly after the END keyword when you complete your function, as shown below:

FUNCTION tot_sales (company_in IN INTEGER) RETURN NUMBER

15.5.4 Calling a Function

A function is called as part of an executable PL/SQL statement, wherever an expression can be used The following examples illustrate the different ways that the tot_sales function demonstrated in

Figure 15.10 might be called:

● Call tot_sales to assign a value to a local PL/SQL variable:

sales_for_1995 := tot_sales (1504, 'C');

● Use a call to tot_sales to set a default value for a variable:

Trang 21

DECLARE sales_for_1995 NUMBER DEFAULT tot_sales (1504, 'C');

BEGIN

● Use tot_sales directly in an expression:

IF tot_sales (275, 'O') > 10000THEN

15.5.4.1 Functions without parameters

If a function has no parameters, then the function call must be written without parentheses, as the line below illustrates:

IF tot_sales THEN

Notice that you cannot tell just by looking at the above line of code whether tot_sales is a function or

a variable You would, in fact, have to check the declaration section of your PL/SQL block if you really needed to know And that's the whole point A function returns a value, as does a variable The function just happens to execute some code to come up with that value, whereas a variable has that value as its very attribute, available for immediate return

15.5.5 Function Header

The portion of the function definition that comes before the IS keyword is called the function header The header provides all the information a programmer needs to call that function, namely:

● The function name

● The parameter list, if any

● The RETURN datatype

A programmer does not need to know about the inside of the function in order to be able to call it properly from another program

The header for the tot_sales function discussed above is:

Trang 22

NUMBER This means that the PL/SQL statement containing a call to tot_sales must be able to use a numeric value

15.5.6 Function Body

The body of the function is the code required to implement the function It consists of the declaration, execution, and exception sections of the function Everything after the IS keyword in the function makes up that function's body

Once again, the declaration and exception sections are optional If you have no exception handlers, you will simply leave off the EXCEPTION keyword and enter the END statement to terminate the function

If you do not have any declarations, the BEGIN statement simply follows immediately after the IS keyword (see the does_nothing function below for an example of this structure)

15.5.7 A Tiny Function

You must supply at least one executable statement in a function Here is my candidate for the

Boolean function with the smallest possible body in PL/SQL:

FUNCTION does_nothing RETURN BOOLEAN IS

15.5.8 The RETURN Statement

A function must have at least one RETURN statement in its execution section of statements It can have more than one RETURN, but only one of those statements is executed each time the function is called The RETURN statement that is executed by the function determines the value that is returned

by that function When a RETURN statement is processed, the function terminates immediately and returns control to the calling PL/SQL block

The RETURN clause in the header of the function is different from the RETURN statement in the execution section of the body of the function While the RETURN clause indicates the datatype of the return or result value of the function, the RETURN statement specifies the actual value that is

Trang 23

returned You have to specify the RETURN datatype in the header, but then also include at least one RETURN statement in the function

15.5.8.2 RETURN any valid expression

The RETURN statement can accept any expression for evaluation and return This expression can be composed of calls to other functions, complex calculations, and even data conversions All of the following usages of RETURN are valid:

RETURN 'buy me lunch';

RETURN POWER (max_salary, 5);

RETURN (100 - pct_of_total_salary (employee_id));

RETURN TO_DATE ('01' || earliest_month || initial_year,

'DDMMYY');

An expression in the RETURN statement is evaluated when the RETURN is executed When control

is passed back to the calling form, the result of the evaluated expression is passed along, too

Trang 24

FUNCTION company_type (type_code_in IN VARCHAR2)

ORA-6503: PL/SQL: Function returned without value

You can avoid this kind of problem (which you may never encounter in testing since you always pass

a sensible value to the function) by restructuring your use of the RETURN statement

15.5.8.4 RETURN as last executable statement

Generally, the best way to make sure that your function always returns a value is to make the last executable statement in the function your RETURN statement Declare a variable named

return_value, which clearly indicates that it will contain the return value for the function, write all the code to come up with that value, and then at the very end of the function RETURN the return_value:

FUNCTION do_it_all (parameter_list) RETURN NUMBER

The company_type function, for example, can be converted easily to this structure:

FUNCTION company_type (type_code_in IN VARCHAR2)

Trang 25

Notice that, because I provided the return_value variable with a default value of NULL, I didn't have

to code an ELSE clause in the IF statement to explicitly make that assignment (though doing so would probably make the code more readable) If the type_code_in does not match any of the values

in the IF statement, there is no problem because each IF and ELSIF no longer performs its own

RETURN Instead, they just assign a value and then leave the RETURNing to the little RETURN section at the end of the function

15.5.8.5 RETURN statement in a procedure

Believe it or not, RETURN statements can also be used in procedures The procedure version of the RETURN does not take an expression; it cannot, therefore, pass a value back to the calling program unit The RETURN simply halts execution of the procedure and returns control to the calling code

You do not (should not, in any case) see this usage of RETURN very often, and for good reason Use

of the RETURN in a procedure usually leads to very unstructured code that is hard to understand and maintain Avoid using both RETURN and GOTO to bypass proper control structures and process flow in your program units

Previous: 15.4 Procedures Oracle PL/SQL

Programming, 2nd Edition

Next: 15.6 Parameters

The Oracle Library

Navigation

Copyright (c) 2000 O'Reilly & Associates All rights reserved

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

TỪ KHÓA LIÊN QUAN