Beruflich Dokumente
Kultur Dokumente
Introduction
Regardless of whether you are building a system to batch process data or youre building an online system with forms and reports, you will want to perform some task programmatically, and for that purpose youll need to know PL/SQL. This paper will attempt to introduce you to the many uses of PL/SQL and how to put all the pieces together. PL/SQL stands for Procedural Language SQL. It is the procedural language extension Oracle has created to be used with all Oracle products. With PL/SQL, you can create program blocks that include variables, loops, conditional programming, error handling and external calls to other packages, procedures and functions that have been created with PL/SQL. It provides users with a means to perform SQL data manipulation within a program. PL/SQL provides users with a robust environment that can be used to create simple and complex applications in order to manipulate an Oracle database and control user applications. PL/SQL programs are created, compiled, stored and run directly from the database. This is extremely advantageous in the client/server environment and in the thin client Web browser environment that is becoming a large part of our daily lives.
Topics to be covered
The many features and syntax of the PL/SQL program is a subject that is well documented. This paper and supporting presentation are intended for a beginner level audience. As a result, advanced topics are out of the scope of this paper. The purpose of this paper is to provide a quick overview of PL/SQL. At the end of this paper you should have acquired the tools necessary to be able to create small and relatively simple PL/SQL programs, and maybe even a stored procedure or function. The only previous knowledge that is assumed in this paper is that the reader has an understanding of SQL. This paper will touch on the following subjects: PL/SQL Block Syntax Declaration of Variables and Constants Conditional Constructs Loops Cursors Procedures, Packages and Functions I/O Methods
The Declaration and Exception sections are optional. The only section that must exist is the execution section noted by a BEGIN statement. A PL/SQL program unit can be written without the use of variables and without implementing any logic to handle Oracle server or user-defined errors. For every BEGIN that exists in your PL/SQL code, there must be a matching END. Blocks can also contain headers, found before the declaration section. The header is only used with subprograms. A header block contains the type of block (procedure, function, package), its name (salary_review) and optionally any I/O arguments (emp_no IN NUMBER, success OUT BOOLEAN).
In order to use a variable within a PL/SQL block, it must be declared within the declaration section. The format for the declaration is as follows: Identifier[CONSTANT] datatype [NOT NULL] [:= | DEFAULT expression]; A variable or constant is given an identifier within the declaration section, preferably one that describes the data that it will hold. For an identifier to contain a constant value, the word constant must follow the declaration of the identifier. The datatype is declared and as an option, it can be defined as NOT NULL. A variable can also be initialized with a value using either := or DEFAULT followed by the value. A constant must be initialized in the declaration section and cannot be changed throughout the entire PL/SQL block. In contrast, a variable can be assigned and re-assigned a value at anytime. Some examples of variables and constants follow:
v_sex CHAR(1); v_date DATE NOT NULL := SYSDATE; c_interest_rate CONSTANT NUMBER(5,3) DEFAULT 11.325;
Variable types can also be declared dynamically. If a variable will be base on a column in a table, the variable can be declared with a pseudo link between the column and the variable. If the structure of the column ever changes, the variable will automatically be changed the next time the program unit is used. A variable can also be declared with a datatype based on another variable. An example of a dynamic declaration based on a column can be found below, followed by a declaration of a variable based on another variable:
l_item_id inventory.item_id%TYPE; l_unit_price NUMBER(7,2); l_order_total l_unit_price%TYPE;
The only mandatory part of the IF statement is the IF, THEN and END IF. The ESLIF and ELSE are optional. It is important to note that your boolean expression needs to resolve into a true or false decision. The following are a few valid examples of boolean expressions:
salary > 1000 hire_date > sysdate first_name IS NULL
If these conditions resolve to a true answer, then the processing statements that immediately follow the expression will be run. Once the processing is finished, the processing continues with the first line after the END IF
Paper #409 / Page 3
statement. If the first statement did not evaluate to true, ESLIF conditions will be evaluated in order. If neither the original IF statement or the ELSIF statements evaluate to TRUE, if an ELSE clause is contained in the expression, the statements that follow the ELSE will be processed. In the absence of an ELSE statement, none of the processing in the IF group will be carried out and the PL/SQL program will continue after the END IF statement.
Loops
In addition to the standard IF-THEN-ELSE conditional processing, PL/SQL provides looping facilities that allow users to step through data and perform iterative processing of information. Loops are often used to process the multiple rows of data in a result set of a cursor. More on this in just a moment. Lets first examine some of the different types of loops. There are a number of different types of loops that are available for use in PL/SQL, they are as follows:
Simple Loop:
LOOP processing statements; END LOOP;
Since there is no condition that will stop this loop from continuing, this loop will execute indefinitely. To stop the processing and leave the loop, an EXIT statement will need to be added inside the loop. The following is the syntax for the EXIT statement:
EXIT [WHEN condition]
While Loop:
WHILE condition LOOP processing statements; END LOOP;
The condition in the WHILE expression will be evaluated before each iteration of the loop. When the condition evaluates to FALSE, the loop terminates and processing will continue on the line immediately following the END LOOP statement.
For Loop:
FOR loop_counter IN [REVERSE] low_value .. high_value LOOP processing statements; END LOOP;
The FOR loop is used when we are able to predict the number of iterations that are required within the loop. The low and high values do not need to be hardcode. Depending on some logic in your code, variables can be set in the procedure for the purpose of controlling the low and high values dynamically.
Data manipulation statements are items such as SELECT, INSERT, UPDATE and DELETE. These are the expressions that control the methods used to access and alter you data within your database. Transaction control statement examples are COMMIT and ROLLBACK. These statements are commonly used within PL/SQL programs, since PL/SQL on its own cannot post data to the database.
Cursors
A PL/SQL cursor differs greatly from that small annoying line that is flashing on my screen while I type this paper? An ORACLE cursor is the memory area that is allocated to a SQL statement. The cursor is a pointer to the memory area that the SQL statement holds in memory. There are two types of cursors in PL/SQL, EXPLICIT and IMPLICIT. The way that each is handled is unique to the cursor type. An IMPLICIT cursor occurs when a SQL statement is placed in the body of a PL/SQL block. It requires an INTO expression when a SELECT is used and it must return one and only one row. If no rows or more than one row are returned by the select statement, you will need to handle the NO_DATA_FOUND or TOO_MANY_ROWS exceptions that PL/SQL will raise. More on this later in this paper. An example of an IMPLICIT cursor would be as follows:
DECLARE ln_salary emp.salary%TYPE; BEGIN SELECT salary INTO FROM WHERE END; ln_salary emp emp_name = ARLENE;
In the example above, we are selecting data from the EMP table and placing it into a local variable in the PL/SQL block. The local variable ln_salary has been declared dynamically as being of the SALARY column type from the EMP table. The local variable will be evaluated at runtime and a change to the database schema will not affect our program. When your PL/SQL program will require a SELECT statement that is expected to return more than one result, you must make use of an EXPLICIT cursor. Having a LOOP around the cursor execution will enable you to process each retrieved row one at a time. These cursors are declared in the declaration section of the PL/SQL block and do not include any INTO expressions like the implicit cursors do. To utilize an explicit cursor in PL/SQL,
Paper #409 / Page 5
there are four steps that you must follow. The steps are as follows: (1) Declare the cursor, (2) Open the cursor, (3) Fetch the results of the cursor INTO local variables and (4) Close the cursor. EXPLICIT cursors can be used for simple SELECT statements. While they may require more lines of code than usual, they use memory more efficiently. An EXPLICIT cursor example can be found in the package of sample code available for downloading from http://home.earthlink.net/~mkerzner/codesamples.html (see Sample 1).
ERROR HANDLING
When an error occurs in the execution of a program, processing will immediately drop down to the EXCEPTION section of the current block. If the exact error is handled with a WHEN condition THEN statement, the error will be handled gracefully and the processing will continue at the first line immediately following the END statement of the current block. If the error was not handled in the local block, the next outermost blocks EXCEPTION section is implemented. The program will continue to look for an exception handler in all of the outer blocks that contain the block where the error occurred. If no suitable exception handler statement is found, the PL/SQL procedure will abort. Nesting blocks and using inner and outer EXCEPTION sections will make your code more robust. By rule of thumb, I will always build a BEGIN EXCEPTION END block around each and every implicit SELECT statement, UPDATE, INSERT or DELETE. If the DML statement fails, the exception section, properly coded of course, will handle the error and the processing can continue with the next block after the exception section. An error does not always mean that you want to abort your processing, it could very simply mean that you need to follow another path of logic. In addition to the many Oracle -defined and user-defined errors that you can place in your exception section, use of a WHEN OTHERS THEN exception will allow you to trap any undeclared errors. Using Oracle supplied functions SQLCODE and SQLERRM, you can always interrogate the error and determine the error-code and error-message respectively. Using an earlier example of a simple select statement, I have illustrated how an EXCEPTION section can be added to trap Oracle errors. (Sample 3 at http://home.earthlink.net/~mkerzner/codesamples.html)
DBMS OUTPUT
In order to get receive feedback from your programs via your terminal, you can use the DBMS_OUTPUT built-in package supplied as part of your database. The following line of code will produce a message in your terminal. The message can include text, a date, a value from a variable, error codes, error messages or any combination.
DBMS_OUTPUT.PUT_LINE (The salary for employee ||sal_record.emp_name|| has been increased.);
In order to see these types of messages in your terminal during a SQL*Plus session, the following parameter set statement needs to be made:
SQL> SET SERVEROUTPUT ON [SIZE number ]
utl_file_dir = /usr/home/kerz/
The following is a description of the different procedures within the UTL_FILE package and their specifications.
Opening a file
Files can be opened for either reading or writing but not both.
UTL_FILE.FOPEN (location IN VARCHAR2, filename IN VARCHAR2, open_mode IN VARCHAR2) RETURN file_type;
The directory containing the file The name of the file to open Method to open the file (r: read file, w: write file or a: append to file) File handle, may be used by subsequent function calls.
Closing a file
Files should be closed after work has been completed
UTL_FILE.FCLOSE (file_handle IN OUT FILE_TYPE);
file_handle
Writing to a file
To write to an open file, the following command is used:
UTL_FILE.PUT_LINE (file_handle IN OUT FILE_TYPE, buffer IN VARCHAR2);
file_handle buffer
Identifies the file, that is currently open The contents that are to written to the file
file_handle buffer
Identifies the file, that is currently open The contents that are read from the file
The comprehensive sample procedure (sample #4) utilizes the UTL_FILE I/O capabilities. The sample can be found at http://home.earthlink.net/~mkerzner/codesamples.html.
Conclusion
PL/SQL is a powerful and robust product that allows users of the Oracle database to create complex and efficient programs. It is to the developers advantage to master PL/SQL. This paper only scratched the surface and hopefully wets your appetite for the many of uses of PL/SQL and the multitude of publications on this topic. The endless potential for procedural processing and data manipulation by PL/SQL make this tool a must learn for the developers arsenal.