Sie sind auf Seite 1von 9

Beginners Guide to the PL/SQL Language

Mark Kerzner NDC | Health Information Services

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

Paper #409 / Page 1

PL/SQL Block Structure


The PL/SQL block is the basic unit of all PL/SQL programs. The format of a block is the same, whether the PL/SQL code is implemented as a stored procedure, in a forms trigger or through SQL*Plus. PL/SQL code blocks can even be nested within other PL/SQL blocks. Well learn that this is a very effective way for trapping errors and controlling the flow of a process. More on that later. Every block has the following structure:
DECLARE Declaration section PL/SQL variables types cursors local subprograms BEGIN Executable section

SQL statements procedural logic EXCEPTION Error handling section

error handling statements END;

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).

Variables and Constants


Programming in PL/SQL requires both constants and variables. It is important to understand that all of the data types supported by Oracle, whether you are using SQL*Plus or Developer/2000 are supported by PL/SQL. These data types include: CHAR VARCHAR NUMBER DATE BOOLEAN CURSORS REF CURSORS TABLES - alphanumeric character data type - variable length characters - numerical data - date data - logical data - SQL select cursors - result set data - PL/SQL data tables

Paper #409 / Page 2

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;

IF and related Conditions


To process data within your PL/SQL programs will probably require some sort of conditional logic. The old standard IF-THEN-ELSE is available for use within PL/SQL. The syntax for the IF-THEN-ELSE statement is as follows:
IF boolean expression THEN processing statements; ELSIF boolean expression THEN processing statements; ELSE processing statements; END IF;

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]

An IF statement can also be used to break the loop.


IF condition THEN EXIT;

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.

Paper #409 / Page 4

SQL and Cursors


Much of the power of PL/SQL comes from the fact that it integrates so well with the Oracle tools. Even more important is the fact that it can perform SQL transactions within a procedural environment. That leads us to the discussion of how to manipulate data with SQL inside PL/SQL.

SQL within PL/SQL


There are a number of different SQL statements that can be included within a PL/SQL program. The ones that we will discuss are as follows: Data manipulation statements Transaction control

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).

CURSOR FOR LOOPS


Now that Ive taken the time to explain explicit cursors to you, Im going to show you a better code construct. The cursor for loop will simplify your life as a developer by reducing the lines of code you need to write and by making the code easier to understand. With the cursor for loop construct there is no need to declare the variables or a record to store the results of your SELECT statement. Gone too are the OPEN, FETCH and CLOSE cursor statements as well as the need to test the %NOTFOUND cursor attribute. Sounds too good to be true? Well its not. Take a look at the Explicit Cursor from our previous example re-written using a cursor for loop. (See Sample 2 at http://home.earthlink.net/~mkerzner/codesamples.html) With the cursor for loop, weve managed to reduce the amount of code from 19 lines to 14. The FOR sal_record IN sal_cursor LOOP statement does it all. A record with both an emp.emp_no and emp.salary type variable is declared on the fly and the column names are prefixed with the name of the record. The cursor is opened automatically, fetches are done into the record type variables, the loop stops when the %NOTFOUND attribute evaluates to true and the cursor is closed.

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)

Paper #409 / Page 6

Packages, Procedures and Functions


Stored procedures, packages and functions allow you to create program units that can be shared by many programs and users. These program types allow you to achieve a modular approach to your Oracle programs. Reuse of objects in the database makes your programs more manageable, simpler to maintain and also results in a more efficient use of memory. Oracles shared SQL pool reuses SQL that has been previously executed and still remains in memory, which allows for much quicker execution paths since Oracle remembers how the statement should be executed. Previously we have been discussing PL/SQL blocks, which are also known as anonymous blocks. The problem with anonymous blocks is that they are not stored in the database and therefore cannot be called by another program unit. These limitations make it very difficult to build a robust and efficient system. Instead of anonymity there are some constructs available within PL/SQL that provide you with the ability to name and store the programs in the database. Stored packages, procedures and functions are named blocks of PL/SQL code that can be called. They can be created with or without input and output parameters. They are stored in the database and privileges can be granted to make them available to other users. By nature, they are re-usable program units. If certain logic needs to be executed many times, a named package, procedure or function will allow a call to be made to a named PL/SQL block without ever having to write redundant lines of code.

Data and File I/O


When developing PL/SQL programs, it is often useful to be able to see what is happening inside of your program. In the absence of a good debugging tool, developers can use a system file or return messages to the terminal. It is often misleading when Oracle returns the message Procedure completed successfully. An error may have occurred during processing that was trapped by the EXCEPTION section. In this case, while the program will have completed successfully, it may not have done what was required.

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 ]

Reading and Writing Files


Starting with version 2.3 of PL/SQL, developers can use the UTL_FILE built-in package to efficiently read from and write to operating systems files. This is a very powerful mechanism that can be used while developing applications that have a requirement to interact with text files in read or write mode. In order to take advantage of the UTL_FILE built-in package, the DBA will need to setup a directory path parameter. A utl_file_dir parameter will be added to the INIT.ORA file, making the specified operating system directories accessible to the UTL_FILE package. A sample UNIX utl_file_dir parameter is as follows:
Paper #409 / Page 7

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;

location filename open_mode 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

Identifies the file, that is currently open.

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

Reading from a file


To read from an open file, the following command is use:
UTL_FILE.GET_LINE (file_handle IN OUT FILE_TYPE, buffer OUT VARCHAR2);

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.

Paper #409 / Page 8

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.

Paper #409 / Page 9

Das könnte Ihnen auch gefallen