Top Banner
sBasic Structure of PL/SQL PL/SQL stands for Procedural Language/SQL. PL/SQL extends SQL by adding constructs found in procedural languages, resulting in a structural language that is more powerful than SQL. The basic unit in PL/SQL is a block. All PL/SQL programs are made up of blocks, which can be nested within each other. Typically, each block performs a logical action in he program. A block has the following structure: DECLARE
90

PLSQL Tutorial

Dec 03, 2014

Download

Documents

sumanth_0678
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: PLSQL Tutorial

sBasic Structure of PL/SQL

PL/SQL stands for Procedural Language/SQL. PL/SQL extends

SQL by adding constructs found in procedural languages,

resulting in a structural language that is more powerful than

SQL. The basic unit in PL/SQL is a block. All PL/SQL programs

are made up of blocks, which can be nested within each other.

Typically, each block performs a logical action in he program. A

block has the following structure:

DECLARE

/* Declarative section: variables, types, and local

subprograms. */

Page 2: PLSQL Tutorial

BEGIN

/* Executable section: procedural and SQL statements go

here. */

/* This is the only section of the block that is required. */

EXCEPTION

/* Exception handling section: error handling statements go

here. */

END;

Only the executable section is required. The other sections are

optional. The only SQL statements allowed in a PL/SQL

program are SELECT, INSERT, UPDATE, DELETE and several

other data manipulation statements plus some transaction

Page 3: PLSQL Tutorial

control. However, the SELECT statement has a special form in

which a single tuple is placed in variables; more on this later.

Data definition statements like CREATE, DROP, or ALTER are not

allowed. The executable section also contains constructs such

as assignments, branches, loops, procedure calls, and triggers,

which are all described below (except triggers). PL/SQL is not

case sensitive. C style comments (/* ... */) may be used.

To execute a PL/SQL program, we must follow the program

text itself by

* A line with a single dot ("."), and then

* A line with run;

As with Oracle SQL programs, we can invoke a PL/SQL program

Page 4: PLSQL Tutorial

either by typing in sqlplus.

Variables and Types

Information is transmitted between a PL/SQL program and the

database through variables. Every variable has a specific type

associated with it. That type can be

* One of the types used by SQL for database columns

* A generic type used in PL/SQL such as NUMBER

* Declared to be the same as the type of some database

column

The most commonly used generic type is NUMBER. Variables of

type NUMBER can hold either an integer or a real number. The

most commonly used character string type is VARCHAR(n),

Page 5: PLSQL Tutorial

where n is the maximum length of the string in bytes. This

length is required, and there is no default. For example, we

might declare:

DECLARE

price NUMBER;

myBeer VARCHAR(20);

Note that PL/SQL allows BOOLEAN variables, even though

Oracle does not support BOOLEAN as a type for database

columns.

Types in PL/SQL can be tricky. In many cases, a PL/SQL

variable will be used to manipulate data stored in a existing

Page 6: PLSQL Tutorial

relation. In this case, it is essential that the variable have the

same type as the relation column. If there is any type

mismatch, variable assignments and comparisons may not

work the way you expect. To be safe, instead of hard coding

the type of a variable, you should use the %TYPE operator. For

example:

DECLARE

myBeer Beers.name%TYPE;

gives PL/SQL variable myBeer whatever type was declared for

the name column in relation Beers.

A variable may also have a type that is a record with several

fields. The simplest way to declare such a variable is to use

Page 7: PLSQL Tutorial

%ROWTYPE on a relation name. The result is a record type in

which the fields have the same names and types as the

attributes of the relation. For instance:

DECLARE

beerTuple Beers%ROWTYPE;

makes variable beerTuple be a record with fields name and

manufacture, assuming that the relation has the schema

Beers(name, manufacture).

The initial value of any variable, regardless of its type, is NULL.

We can assign values to variables, using the ":=" operator. The

assignment can occur either immediately after the type of the

Page 8: PLSQL Tutorial

variable is declared, or anywhere in the executable portion of

the program. An example:

DECLARE

a NUMBER := 3;

BEGIN

a := a + 1;

END;

run;

This program has no effect when run, because there are no

changes to the database.

Simple Programs in PL/SQL

The simplest form of program has some declarations followed

Page 9: PLSQL Tutorial

by an executable section consisting of one or more of the SQL

statements with which we are familiar. The major nuance is

that the form of the SELECT statement is different from its SQL

form. After the SELECT clause, we must have an INTO clause

listing variables, one for each attribute in the SELECT clause,

into which the components of the retrieved tuple must be

placed.

Notice we said "tuple" rather than "tuples", since the SELECT

statement in PL/SQL only works if the result of the query

contains a single tuple. The situation is essentially the same as

that of the "single-row select" discussed in Section 7.1.5 of the

Page 10: PLSQL Tutorial

text, in connection with embedded SQL. If the query returns

more than one tuple, you need to use a cursor. Here is an

example:

CREATE TABLE T1(

e INTEGER,

f INTEGER

);

DELETE FROM T1;

INSERT INTO T1 VALUES(1, 3);

INSERT INTO T1 VALUES(2, 4);

/* Above is plain SQL; below is the PL/SQL program. */

Page 11: PLSQL Tutorial

DECLARE

a NUMBER;

b NUMBER;

BEGIN

SELECT e,f INTO a,b FROM T1 WHERE e>1;

INSERT INTO T1 VALUES(b,a);

END;

run;

Fortuitously, there is only one tuple of T1 that has first

component greater than 1, namely (2,4). The INSERT

statement thus inserts (4,2) into T1.

Page 12: PLSQL Tutorial

Control Flow in PL/SQL

PL/SQL allows you to branch and create loops in a fairly

familiar way.

An IF statement looks like:

IF <condition> THEN <statement_list> ELSE <statement_list>

END IF;

The ELSE part is optional. If you want a multiway branch, use:

IF <condition_1> THEN ...

ELSIF <condition_2> THEN ...

... ...

ELSIF <condition_n> THEN ...

ELSE ...

Page 13: PLSQL Tutorial

END IF;

The following is an example, slightly modified from the

previous one, where now we only do the insertion if the second

component is 1. If not, we first add 10 to each component and

then insert:

DECLARE

a NUMBER;

b NUMBER;

BEGIN

SELECT e,f INTO a,b FROM T1 WHERE e>1;

IF b=1 THEN

Page 14: PLSQL Tutorial

INSERT INTO T1 VALUES(b,a);

ELSE

INSERT INTO T1 VALUES(b+10,a+10);

END IF;

END;

run;

Loops are created with the following:

LOOP

<loop_body> /* A list of statements. */

END LOOP;

At least one of the statements in <loop_body> should be an

EXIT statement of the form

Page 15: PLSQL Tutorial

EXIT WHEN <condition>;

The loop breaks if <condition> is true. For example, here is a

way to insert each of the pairs (1, 1) through (100, 100) into T1

of the above two examples:

DECLARE

i NUMBER := 1;

BEGIN

LOOP

INSERT INTO T1 VALUES(i,i);

i := i+1;

EXIT WHEN i>100;

Page 16: PLSQL Tutorial

END LOOP;

END;

.run;

Some other useful loop-forming statements are:

* EXIT by itself is an unconditional loop break. Use it inside a

conditional if you like.

* A WHILE loop can be formed with

· WHILE <condition> LOOP

· <loop_body>

END LOOP;

* A simple FOR loop can be formed with:

· FOR <var> IN <start>..<finish> LOOP

Page 17: PLSQL Tutorial

· <loop_body>

·

END LOOP;

Here, <var> can be any variable; it is local to the for-loop and

need not be declared. Also, <start> and <finish> are

constants.

Cursors

A cursor is a variable that runs through the tuples of some

relation. This relation can be a stored table, or it can be the

answer to some query. By fetching into the cursor each tuple

of the relation, we can write a program to read and process the

value of each such tuple. If the relation is stored, we can also

Page 18: PLSQL Tutorial

update or delete the tuple at the current cursor position.

The example below illustrates a cursor loop. It uses our

example relation T1(e,f) whose tuples are pairs of integers.

The program will delete every tuple whose first component is

less than the second, and insert the reverse tuple into T1.

1) DECLARE

/* Output variables to hold the result of the query: */

2) a T1.e%TYPE;

3) b T1.f%TYPE;

/* Cursor declaration: */

4) CURSOR T1Cursor IS

Page 19: PLSQL Tutorial

5) SELECT e, f

6) FROM T1

7) WHERE e < f

8) FOR UPDATE;

9) BEGIN

10) OPEN T1Cursor;

11) LOOP

/* Retrieve each row of the result of the above query

into PL/SQL variables: */

12) FETCH T1Cursor INTO a, b;

/* If there are no more rows to fetch, exit the loop: */

13) EXIT WHEN T1Cursor%NOTFOUND;

Page 20: PLSQL Tutorial

/* Delete the current tuple: */

14) DELETE FROM T1 WHERE CURRENT OF T1Cursor;

/* Insert the reverse tuple: */

15) INSERT INTO T1 VALUES(b, a);

16) END LOOP;

/* Free cursor used by the query. */

17) CLOSE T1Cursor;

18) END;

19) .

20) run;

Here are explanations for the various lines of this program:

Page 21: PLSQL Tutorial

* Line (1) introduces the declaration section.

* Lines (2) and (3) declare variables a and b to have types

equal to the types of attributes e and f of the relation T1.

Although we know these types are INTEGER, we wisely make

sure that whatever types they may have are copied to the

PL/SQL variables (compare with the previous example, where

we were less careful and declared the corresponding variables

to be of type NUMBER).

* Lines (4) through (8) define the cursor T1Cursor. It ranges

over a relation defined by the SELECT-FROM-WHERE query.

That query selects those tuples of T1 whose first component is

less than the second component. Line (8) declares the cursor

FOR UPDATE since we will modify T1 using this cursor later on

Page 22: PLSQL Tutorial

Line (14). In general, FOR UPDATE is unnecessary if the cursor

will not be used for modification.

* Line (9) begins the executable section of the program.

* Line (10) opens the cursor, an essential step.

* Lines (11) through (16) are a PL/SQL loop. Notice that such a

loop is bracketed by LOOP and END LOOP. Within the loop we

find:

o On Line (12), a fetch through the cursor into the local

variables. In general, the FETCH statement must provide

variables for each component of the tuple retrieved. Since the

query of Lines (5) through (7) produces pairs, we have

correctly provided two variables, and we know they are of the

correct type.

o On Line (13), a test for the loop-breaking condition. Its

Page 23: PLSQL Tutorial

meaning should be clear: %NOTFOUND after the name of a

cursor is true exactly when a fetch through that cursor has

failed to find any more tuples.

o On Line (14), a SQL DELETE statement that deletes the

current tuple using the special WHERE condition CURRENT OF

T1Cursor.

o On Line (15), a SQL INSERT statement that inserts the

reverse tuple into T1.

* Line (17) closes the cursor.

* Line (18) ends the PL/SQL program.

* Lines (19) and (20) cause the program to execute.

Procedures

PL/SQL procedures behave very much like procedures in other

programming language. Here is an example of a PL/SQL

Page 24: PLSQL Tutorial

procedure addtuple1 that, given an integer i, inserts the tuple

(i, 'xxx') into the following example relation:

CREATE TABLE T2 (

a INTEGER,

b CHAR(10)

);

CREATE PROCEDURE addtuple1(i IN NUMBER) AS

BEGIN

INSERT INTO T2 VALUES(i, 'xxx');

END addtuple1;

Page 25: PLSQL Tutorial

run;

A procedure is introduced by the keywords CREATE PROCEDURE

followed by the procedure name and its parameters. An option

is to follow CREATE by OR REPLACE. The advantage of doing so

is that should you have already made the definition, you will

not get an error. On the other hand, should the previous

definition be a different procedure of the same name, you will

not be warned, and the old procedure will be lost.

There can be any number of parameters, each followed by a

mode and a type. The possible modes are IN (read-only), OUT

(write-only), and INOUT (read and write). Note: Unlike the type

specifier in a PL/SQL variable declaration, the type specifier in

Page 26: PLSQL Tutorial

a parameter declaration must be unconstrained. For example,

CHAR(10) and VARCHAR(20) are illegal; CHAR or VARCHAR

should be used instead. The actual length of a parameter

depends on the corresponding argument that is passed in

when the procedure is invoked.

Following the arguments is the keyword AS (IS is a synonym).

Then comes the body, which is essentially a PL/SQL block. We

have repeated the name of the procedure after the END, but

this is optional. However, the DECLARE section should not start

with the keyword DECLARE. Rather, following AS we have:

... AS

Page 27: PLSQL Tutorial

<local_var_declarations>

BEGIN

<procedure_body>

END;

.

run;

The run at the end runs the statement that creates the

procedure; it does not execute the procedure. To execute the

procedure, use another PL/SQL statement, in which the

procedure is invoked as an executable statement. For

example:

BEGIN addtuple1(99); END;

Page 28: PLSQL Tutorial

.

run;

The following procedure also inserts a tuple into T2, but it takes

both components as arguments:

CREATE PROCEDURE addtuple2(

x T2.a%TYPE,

y T2.b%TYPE)

AS

BEGIN

INSERT INTO T2(a, b)

VALUES(x, y);

Page 29: PLSQL Tutorial

END addtuple2;

.

run;

Now, to add a tuple (10, 'abc') to T2:

BEGIN

addtuple2(10, 'abc');

END;

.

run;

The following illustrates the use of an OUT parameter:

CREATE TABLE T3 (

a INTEGER,

Page 30: PLSQL Tutorial

b INTEGER

);

CREATE PROCEDURE addtuple3(a NUMBER, b OUT NUMBER)

AS

BEGIN

b := 4;

INSERT INTO T3 VALUES(a, b);

END;

.

run;

Page 31: PLSQL Tutorial

DECLARE

v NUMBER;

BEGIN

addtuple3(10, v);

END;

run;

Note that assigning values to parameters declared as OUT or

INOUT causes the corresponding input arguments to be

written. Because of this, the input argument for an OUT or

INOUT parameter should be something with an "lvalue", such

as a variable like v in the example above. A constant or a

literal argument should not be passed in for an OUT/INOUT

Page 32: PLSQL Tutorial

parameter.

We can also write functions instead of procedures. In a

function declaration, we follow the parameter list by RETURN

and the type of the return value:

CREATE FUNCTION <func_name>(<param_list>) RETURN

<return_type> AS ...

In the body of the function definition, "RETURN <expression>;"

exits from the function and returns the value of <expression>.

To find out what procedures and functions you have created,

use the following SQL query:

select object_type, object_name

Page 33: PLSQL Tutorial

from user_objects

where object_type = 'PROCEDURE'

or object_type = 'FUNCTION';

To drop a stored procedure/function:

drop procedure <procedure_name>;

drop function <function_name>;

Discovering Errors

PL/SQL does not always tell you about compilation errors.

Instead, it gives you a cryptic message such as "procedure

created with compilation errors". If you don't see what is

wrong immediately, try issuing the command

show errors procedure <procedure_name>;

Page 34: PLSQL Tutorial

Alternatively, you can type, SHO ERR (short for SHOW ERRORS)

to see the most recent compilation error.

Printing Variables

Sometimes we might want to print the value of a PL/SQL local

variable. A ``quick-and-dirty'' way is to store it as the sole

tuple of some relation and after the PL/SQL statement print

the relation with a SELECT statement. A more couth way is to

define a bind variable, which is the only kind that may be

printed with a print command. Bind variables are the kind that

must be prefixed with a colon in PL/SQL statements.

The steps are as follows:

Page 35: PLSQL Tutorial

1. We declare a bind variable as follows:

VARIABLE <name> <type>

where the type can be only one of three things: NUMBER,

CHAR, or CHAR(n).

2. We may then assign to the variable in a following PL/SQL

statement, but we must prefix it with a colon.

3. Finally, we can execute a statement

PRINT :<name>;

outside the PL/SQL statement

Here is a trivial example, which prints the value 1.

VARIABLE x NUMBER

BEGIN

Page 36: PLSQL Tutorial

:x := 1;

END;

.

run;

PRINT :x;

Looking for more information of PL SQL tutorials:

1. PLSQL Tutorial

2. PL/SQL Tutorial

What is SQL?

The Structured Query Language is used in manipulating data stored in Relational Database Management Systems (RDBMS). SQL provides commands through which data can be extracted, sorted, updated, deleted and inserted. SQL has the full support of ANSI (American National Standards Institute), which has laid down certain rules for the language.SQL can be used with any RDBMS such as MySQL, mSQL, PostgresSQL, Oracle, Microsoft SQL Server, Access, Sybase, Ingres etc. All the important and common sql statements are supported by these RDBMS, however, each has its own set of proprietary statements and extensions.

Page 37: PLSQL Tutorial

SQL Data Manipulation Language (DM): SQL (Structured Query Language) is a syntax for executing queries. But the SQL Data Manipulation Language (DM): SQL (Structured Query Language) is a syntax for executing queries. But the SQL language also includes a syntax to update, insert, and delete records.  

  Joins and Keys Sometimes we have to select data from two tables to make our result complete. We have to perform a join. Tables in a database can be related to each other with keys. A primary key is a column with a unique value for each row. The purpose is to bind data together, across tables, without repeating all of the data in every table. In the "Employees" table below, the "Employee_ID" column is the primary key, meaning that no two rows can have the same Employee_ID. The Employee_ID distinguishes two persons even if they have the same name. When you look at the example tables below, notice that: 

The "Employee_ID" column is the primary key of the "Employees" table The "Prod_ID" column is the primary key of the "Orders" table The "Employee_ID" column in the "Orders" table is used to refer to the persons in the

"Employees" table without using their names

Employees:

Employee_ID Name

01 Hansen, Ola

02 Svendson, Tove

03 Svendson, Stephen

04 Pettersen, Kari

Orders:

Prod_ID Product Employee_ID

234 Printer 01

657 Table 03

865 Chair 03

Referring to Two Tables

We can select data from two tables by referring to two tables, like this: Example Who has ordered a product, and what did they order?

SELECT Employees.Name, Orders.Product

FROM Employees, Orders

WHERE Employees.Employee_ID=Orders.Employee_ID

Result

Name Product

Hansen, Ola Printer

Svendson, Stephen Table

Svendson, Stephen Chair

Example Who ordered a printer?

SELECT Employees.Name

FROM Employees, Orders

WHERE Employees.Employee_ID=Orders.Employee_ID

AND Orders.Product='Printer'

Result

Name

Page 38: PLSQL Tutorial

Hansen, Ola

Using Joins OR we can select data from two tables with the JOIN keyword, like this: Example INNER JOIN Syntax

SELECT field1, field2, field3

FROM first_table

INNER JOIN second_table

ON first_table.keyfield = second_table.foreign_keyfield

Who has ordered a product, and what did they order?

SELECT Employees.Name, Orders.Product

FROM Employees

INNER JOIN Orders

ON Employees.Employee_ID=Orders.Employee_ID

The INNER JOIN returns all rows from both tables where there is a match. If there are rows in Employees that do not have matches in Orders, those rows will not be listed. Result

Name Product

Hansen, Ola Printer

Svendson, Stephen Table

Svendson, Stephen Chair

Example LEFT JOIN Syntax

SELECT field1, field2, field3

FROM first_table

LEFT JOIN second_table

ON first_table.keyfield = second_table.foreign_keyfield

List all employees, and their orders - if any.

SELECT Employees.Name, Orders.Product

FROM Employees

LEFT JOIN Orders

ON Employees.Employee_ID=Orders.Employee_ID

The LEFT JOIN returns all the rows from the first table (Employees), even if there are no matches in the second table (Orders). If there are rows in Employees that do not have matches in Orders, those rows also will be listed. Result

Name Product

Hansen, Ola Printer

Svendson, Tove  

Svendson, Stephen Table

Svendson, Stephen Chair

Pettersen, Kari  

Example RIGHT JOIN

Page 39: PLSQL Tutorial

Syntax

SELECT field1, field2, field3

FROM first_table

RIGHT JOIN second_table

ON first_table.keyfield = second_table.foreign_keyfield

List all orders, and who has ordered - if any.

SELECT Employees.Name, Orders.Product

FROM Employees

RIGHT JOIN Orders

ON Employees.Employee_ID=Orders.Employee_ID

The RIGHT JOIN returns all the rows from the second table (Orders), even if there are no matches in the first table (Employees). If there had been any rows in Orders that did not have matches in Employees, those rows also would have been listed. Result

Name Product

Hansen, Ola Printer

Svendson, Stephen Table

Svendson, Stephen Chair

Example Who ordered a printer?

SELECT Employees.Name

FROM Employees

INNER JOIN Orders

ON Employees.Employee_ID=Orders.Employee_ID

WHERE Orders.Product = 'Printer'

Result

Name

Hansen, Ola

 Create a Database

CREATE DATABASE database_name

Create a Table

CREATE TABLE Person 

(

LastName varchar,

FirstName varchar,

Address varchar,

Page 40: PLSQL Tutorial

Age int

)

The data type specifies what type of data the column can hold. The table below contains the most common data types in SQL:

Data Type Description

integer(size)int(size)smallint(size)tinyint(size)

Hold integers only. The maximum number of digits are specified in parenthesis.

decimal(size,d)numeric(size,d)

Hold numbers with fractions. The maximum number of digits are specified in "size". The maximum number of digits to the right of the decimal is specified in "d".

char(size) Holds a fixed length string (can contain letters, numbers, and special characters). The fixed size is specified in parenthesis.

varchar(size) Holds a variable length string (can contain letters, numbers, and special characters). The maximum size is specified in parenthesis.

date(yyyymmdd) Holds a date

Create Index Indices are created in an existing table to locate rows more quickly and efficiently. It is possible to create an index on one or more columns of a table, and each index is given a name. The users cannot see the indexes, they are just used to speed up queries. 

Note: Updating a table containing indexes takes more time than updating a table without, this is because the indexes also need an update. So, it is a good idea to create indexes only on columns that are often used for a search.

A Unique Index Creates a unique index on a table. A unique index means that two rows cannot have the same index value.

CREATE UNIQUE INDEX index_name

ON table_name (column_name)

The "column_name" specifies the column you want indexed. A Simple Index Creates a simple index on a table. When the UNIQUE keyword is omitted, duplicate values are allowed.

CREATE INDEX index_name

ON table_name (column_name)

The "column_name" specifies the column you want indexed. Example This example creates a simple index, named "PersonIndex", on the LastName field of the Person table:

CREATE INDEX PersonIndex

ON Person (LastName)

If you want to index the values in a column in descending order, you can add the reserved word DESC after the column name:

CREATE INDEX PersonIndex

ON Person (LastName DESC)

If you want to index more than one column you can list the column names within the parentheses, separated by commas:

CREATE INDEX PersonIndex

ON Person (LastName, FirstName)

Drop Index You can delete an existing index in a table with the DROP statement.

DROP INDEX table_name.index_name

Delete a Database or Table To delete a database:

Page 41: PLSQL Tutorial

DROP DATABASE database_name

To delete a table (the table structure, attributes, and indexes will also be deleted):

DROP TABLE table_name

Alter Table The ALTER TABLE statement is used to add or drop columns in an existing table.

ALTER TABLE table_name

ADD column_name datatype

ALTER TABLE table_name

DROP COLUMN column_name   Note: Some database systems don't allow the dropping of a column in a database table (DROP COLUMN column_name).

Person:

LastName FirstName Address

Pettersen Kari Storgt 20

Example To add a column named "City" in the "Person" table:

ALTER TABLE Person ADD City varchar(30)

Result:

LastName FirstName Address City

Pettersen Kari Storgt 20  

Example To drop the "Address" column in the "Person" table:

ALTER TABLE Person DROP COLUMN Address

Result:

LastName FirstName City

Pettersen Kari  

 Function Syntax The syntax for built-in SQL functions is: SELECT function(column) FROM table Types of Functions There are several basic types and categories of functions in SQL. The basic types of functions are:

Aggregate Functions Scalar functions

Aggregate functions Aggregate functions operate against a collection of values, but return a single value. Note: If used among many other expressions in the item list of a SELECT statement, the SELECT must have a GROUP BY clause!! "Persons" table (used in most examples)

Name Age

Hansen, Ola 34

Svendson, Tove 45

Pettersen, Kari 19

Aggregate functions in MS Access

Function Description

AVG(column) Returns the average value of a column

COUNT(column) Returns the number of rows (without a NULL value) of a column

Page 42: PLSQL Tutorial

COUNT(*) Returns the number of selected rows

FIRST(column) Returns the value of the first record in the specified field

LAST(column) Returns the value of the last record in the specified field

MAX(column) Returns the highest value of a column

MIN(column) Returns the lowest value of a column

STDEV(column)  

STDEVP(column)  

SUM(column) Returns the total sum of a column

VAR(column)  

VARP(column)  

Aggregate functions in SQL Server

Function Description

AVG(column) Returns the average value of a column

BINARY_CHECKSUM  

CHECKSUM  

CHECKSUM_AGG  

COUNT(column) Returns the number of rows (without a NULL value) of a column

COUNT(*) Returns the number of selected rows

COUNT(DISTINCT column) Returns the number of distinct results

FIRST(column) Returns the value of the first record in the specified field

LAST(column) Returns the value of the last record in the specified field

MAX(column) Returns the highest value of a column

MIN(column) Returns the lowest value of a column

STDEV(column)  

STDEVP(column)  

SUM(column) Returns the total sum of a column

VAR(column)  

VARP(column)  Scalar functions  Scalar functions operate against a single value, and return a single value based on the input value. Useful Scalar Functions in MS Access

Function Description

UCASE(c) Converts a field to upper case

LCASE(c) Converts a field to lower case

MID(c,start[,end]) Extract characters from a text field

LEN(c) Returns the length of a text field

INSTR(c) Returns the numeric position of a named character within a text field

LEFT(c,number_of_char) Return the left part of a text field requested

RIGHT(c,number_of_char) Return the right part of a text field requested

ROUND(c,decimals) Rounds a numeric field to the number of decimals specified

MOD(x,y) Returns the remainder of a division operation

NOW() Returns the current system date

Page 43: PLSQL Tutorial

FORMAT(c,format) Changes the way a field is displayed

DATEDIFF(d,date1,date2) Used to perform date calculations

SELECT AVG(column) FROM table

SELECT AVG(Age) FROM Persons WHERE Age>20

SELECT COUNT(Age) FROM Persons

SELECT FIRST(Age) AS lowest_age

FROM Persons

ORDER BY Age

GROUP BY GROUP BY... was added to SQL because aggregate functions (like SUM) return the aggregate of all column values every time they are called, and without the GROUP BY function it was impossible to find the sum for each individual group of column values. The syntax for the GROUP BY function is:

SELECT column,SUM(column) FROM table GROUP BY column

GROUP BY Example This "Sales" Table:

Company Amount

W3Schools 5500

IBM 4500

W3Schools 7100

And This SQL:

SELECT Company, SUM(Amount) FROM Sales

Returns this result:

Company SUM(Amount)

W3Schools 17100

IBM 17100

W3Schools 17100

The above code is invalid because the column returned is not part of an aggregate. A GROUP BY clause will solve this problem:

SELECT Company,SUM(Amount) FROM Sales

GROUP BY Company

Returns this result:

Company SUM(Amount)

W3Schools 12600

IBM 4500

HAVING CLAUSEHAVING... was added to SQL because the WHERE keyword could not be used against aggregate functions (like SUM), and without HAVING... it would be impossible to test for result conditions. The syntax for the HAVING function is:

SELECT column,SUM(column) FROM table

GROUP BY column

HAVING SUM(column) condition value

This "Sales" Table:

Company Amount

Page 44: PLSQL Tutorial

W3Schools 5500

IBM 4500

W3Schools 7100

This SQL:

SELECT Company,SUM(Amount) FROM Sales

GROUP BY Company

HAVING SUM(Amount)>10000

Returns this result

Company SUM(Amount)

W3Schools 12600

 The SELECT INTO Statement The SELECT INTO statement is most often used to create backup copies of tables or for archiving records. Syntax

SELECT column_name(s) INTO newtable [IN externaldatabase]

FROM source

Make a Backup Copy The following example makes a backup copy of the "Persons" table:

SELECT * INTO Persons_backup

FROM Persons

The IN clause can be used to copy tables into another database:

SELECT Persons.* INTO Persons IN 'Backup.mdb'

FROM Persons

If you only want to copy a few fields, you can do so by listing them after the SELECT statement:

SELECT LastName, FirstName INTO Persons_backup

FROM Persons

You can also add a where clause. The following example creates a "Persons_backup" table with two columns (FirstName and LastName) by extracting the persons who lives in "Sandnes" from the "Persons" table:

SELECT LastName, Firstname INTO Persons_sandnes

FROM Persons

WHERE City='Sandnes'

Selecting data from more than one table is also possible. The following example creates a new table "Empl_Ord_backup" that contains data from the two tables Employees and Orders:

SELECT Employees.Name,Orders.Product

INTO Empl_Ord_backup

FROM Employees

INNER JOIN Orders

ON Employees.Employee_ID=Orders.Employee_ID 

Basic Structure of PL/SQL

Page 45: PLSQL Tutorial

PL/SQL stands for Procedural Language/SQL. PL/SQL extends SQL by adding constructs found in procedural languages, resulting in a structural language that is more powerful than SQL. The basic unit in PL/SQL is a block. All PL/SQL programs are made up of blocks, which can be nested within each other. Typically, each block performs a logical action in he program. A block has the following structure:

DECLARE

/* Declarative section: variables, types, and local subprograms. */

BEGIN

/* Executable section: procedural and SQL statements go here. */

/* This is the only section of the block that is required. */

EXCEPTION

/* Exception handling section: error handling statements go here. */

END;

Only the executable section is required. The other sections are optional. The only SQL statements allowed in a PL/SQL program are SELECT, INSERT, UPDATE, DELETE and several other data manipulation statements plus some transaction control. However, the SELECT statement has a special form in which a single tuple is placed in variables; more on this later. Data definition statements like CREATE, DROP, or ALTER are not allowed. The executable section also contains constructs such as assignments, branches, loops, procedure calls, and triggers, which are all described below (except triggers). PL/SQL is not case sensitive. C style comments (/* ... */) may be used.

To execute a PL/SQL program, we must follow the program text itself by

* A line with a single dot ("."), and then* A line with run;

As with Oracle SQL programs, we can invoke a PL/SQL program either by typing in sqlplus.

Variables and Types

Information is transmitted between a PL/SQL program and the database through variables. Every variable has a specific type associated with it. That type can be

* One of the types used by SQL for database columns* A generic type used in PL/SQL such as NUMBER* Declared to be the same as the type of some database column

The most commonly used generic type is NUMBER. Variables of type NUMBER can hold either an integer or a real number. The most commonly used character string type is VARCHAR(n), where n is the maximum length of the string in bytes. This length is required, and there is no default. For example, we might declare:

DECLARE

price NUMBER;

Page 46: PLSQL Tutorial

myBeer VARCHAR(20);

Note that PL/SQL allows BOOLEAN variables, even though Oracle does not support BOOLEAN as a type for database columns.

Types in PL/SQL can be tricky. In many cases, a PL/SQL variable will be used to manipulate data stored in a existing relation. In this case, it is essential that the variable have the same type as the relation column. If there is any type mismatch, variable assignments and comparisons may not work the way you expect. To be safe, instead of hard coding the type of a variable, you should use the %TYPE operator. For example:

DECLARE

myBeer Beers.name%TYPE;

gives PL/SQL variable myBeer whatever type was declared for the name column in relation Beers.

A variable may also have a type that is a record with several fields. The simplest way to declare such a variable is to use %ROWTYPE on a relation name. The result is a record type in which the fields have the same names and types as the attributes of the relation. For instance:

DECLARE

beerTuple Beers%ROWTYPE;

makes variable beerTuple be a record with fields name and manufacture, assuming that the relation has the schema Beers(name, manufacture).

The initial value of any variable, regardless of its type, is NULL. We can assign values to variables, using the ":=" operator. The assignment can occur either immediately after the type of the variable is declared, or anywhere in the executable portion of the program. An example:

DECLARE

a NUMBER := 3;

BEGIN

a := a + 1;

END;

run;

This program has no effect when run, because there are no changes to the database.

Simple Programs in PL/SQL The simplest form of program has some declarations followed by an executable section

consisting of one or more of the SQL statements with which we are familiar. The major nuance is that the form of the SELECT statement is different from its SQL form. After the SELECT clause, we must have an INTO clause listing variables, one for each attribute in the SELECT clause, into which the components of the retrieved tuple must be placed.

Page 47: PLSQL Tutorial

Notice we said "tuple" rather than "tuples", since the SELECT statement in PL/SQL only works if the result of the query contains a single tuple. The situation is essentially the same as that of the "single-row select" discussed in Section 7.1.5 of the text, in connection with embedded SQL. If the query returns more than one tuple, you need to use a cursor. Here is an example:

CREATE TABLE T1(

e INTEGER,

f INTEGER

);

DELETE FROM T1;

INSERT INTO T1 VALUES(1, 3);

INSERT INTO T1 VALUES(2, 4);

/* Above is plain SQL; below is the PL/SQL program. */

DECLARE

a NUMBER;

b NUMBER;

BEGIN

SELECT e,f INTO a,b FROM T1 WHERE e>1;

INSERT INTO T1 VALUES(b,a);

END;

run;

Fortuitously, there is only one tuple of T1 that has first component greater than 1, namely (2,4). The INSERT statement thus inserts (4,2) into T1.

Control Flow in PL/SQL

PL/SQL allows you to branch and create loops in a fairly familiar way.

An IF statement looks like:

IF <condition> THEN <statement_list> ELSE <statement_list> END IF;

The ELSE part is optional. If you want a multiway branch, use:

IF <condition_1> THEN ...

ELSIF <condition_2> THEN ...

Page 48: PLSQL Tutorial

... ...

ELSIF <condition_n> THEN ...

ELSE ...

END IF;

The following is an example, slightly modified from the previous one, where now we only do the insertion if the second component is 1. If not, we first add 10 to each component and then insert:

DECLARE

a NUMBER;

b NUMBER;

BEGIN

SELECT e,f INTO a,b FROM T1 WHERE e>1;

IF b=1 THEN

INSERT INTO T1 VALUES(b,a);

ELSE

INSERT INTO T1 VALUES(b+10,a+10);

END IF;

END;

run;

Loops are created with the following:

LOOP

<loop_body> /* A list of statements. */

END LOOP;

At least one of the statements in <loop_body> should be an EXIT statement of the form

EXIT WHEN <condition>;

The loop breaks if <condition> is true. For example, here is a way to insert each of the pairs (1, 1) through (100, 100) into T1 of the above two examples:

DECLARE

i NUMBER := 1;

BEGIN

Page 49: PLSQL Tutorial

LOOP

INSERT INTO T1 VALUES(i,i);

i := i+1;

EXIT WHEN i>100;

END LOOP;

END;

.run;

Some other useful loop-forming statements are:

* EXIT by itself is an unconditional loop break. Use it inside a conditional if you like.* A WHILE loop can be formed with

· WHILE <condition> LOOP

· <loop_body>

END LOOP;

* A simple FOR loop can be formed with:

· FOR <var> IN <start>..<finish> LOOP

· <loop_body>

·

END LOOP;

Here, <var> can be any variable; it is local to the for-loop and need not be declared. Also, <start> and <finish> are constants.

Cursors

A cursor is a variable that runs through the tuples of some relation. This relation can be a stored table, or it can be the answer to some query. By fetching into the cursor each tuple of the relation, we can write a program to read and process the value of each such tuple. If the relation is stored, we can also update or delete the tuple at the current cursor position.

The example below illustrates a cursor loop. It uses our example relation T1(e,f) whose tuples are pairs of integers. The program will delete every tuple whose first component is less than the second, and insert the reverse tuple into T1.

1) DECLARE

/* Output variables to hold the result of the query: */

2) a T1.e%TYPE;

Page 50: PLSQL Tutorial

3) b T1.f%TYPE;

/* Cursor declaration: */

4) CURSOR T1Cursor IS

5) SELECT e, f

6) FROM T1

7) WHERE e < f

8) FOR UPDATE;

9) BEGIN

10) OPEN T1Cursor;

11) LOOP

/* Retrieve each row of the result of the above query

into PL/SQL variables: */

12) FETCH T1Cursor INTO a, b;

/* If there are no more rows to fetch, exit the loop: */

13) EXIT WHEN T1Cursor%NOTFOUND;

/* Delete the current tuple: */

14) DELETE FROM T1 WHERE CURRENT OF T1Cursor;

/* Insert the reverse tuple: */

15) INSERT INTO T1 VALUES(b, a);

16) END LOOP;

/* Free cursor used by the query. */

17) CLOSE T1Cursor;

18) END;

19) .

20) run;

Here are explanations for the various lines of this program:

* Line (1) introduces the declaration section.* Lines (2) and (3) declare variables a and b to have types equal to the types of attributes e and f of the relation T1. Although we know these types are INTEGER, we wisely make sure that

Page 51: PLSQL Tutorial

whatever types they may have are copied to the PL/SQL variables (compare with the previous example, where we were less careful and declared the corresponding variables to be of type NUMBER).* Lines (4) through (8) define the cursor T1Cursor. It ranges over a relation defined by the SELECT-FROM-WHERE query. That query selects those tuples of T1 whose first component is less than the second component. Line (8) declares the cursor FOR UPDATE since we will modify T1 using this cursor later on Line (14). In general, FOR UPDATE is unnecessary if the cursor will not be used for modification.* Line (9) begins the executable section of the program.* Line (10) opens the cursor, an essential step.* Lines (11) through (16) are a PL/SQL loop. Notice that such a loop is bracketed by LOOP and END LOOP. Within the loop we find:o On Line (12), a fetch through the cursor into the local variables. In general, the FETCH statement must provide variables for each component of the tuple retrieved. Since the query of Lines (5) through (7) produces pairs, we have correctly provided two variables, and we know they are of the correct type.o On Line (13), a test for the loop-breaking condition. Its meaning should be clear: %NOTFOUND after the name of a cursor is true exactly when a fetch through that cursor has failed to find any more tuples.o On Line (14), a SQL DELETE statement that deletes the current tuple using the special WHERE condition CURRENT OF T1Cursor.o On Line (15), a SQL INSERT statement that inserts the reverse tuple into T1.* Line (17) closes the cursor.* Line (18) ends the PL/SQL program.* Lines (19) and (20) cause the program to execute.

Procedures

PL/SQL procedures behave very much like procedures in other programming language. Here is an example of a PL/SQL procedure addtuple1 that, given an integer i, inserts the tuple (i, 'xxx') into the following example relation:

CREATE TABLE T2 (

a INTEGER,

b CHAR(10)

);

CREATE PROCEDURE addtuple1(i IN NUMBER) AS

BEGIN

INSERT INTO T2 VALUES(i, 'xxx');

END addtuple1;

run;

A procedure is introduced by the keywords CREATE PROCEDURE followed by the procedure name and its parameters. An option is to follow CREATE by OR REPLACE. The advantage of doing so is that should you have already made the definition, you will not get an error. On the

Page 52: PLSQL Tutorial

other hand, should the previous definition be a different procedure of the same name, you will not be warned, and the old procedure will be lost.

There can be any number of parameters, each followed by a mode and a type. The possible modes are IN (read-only), OUT (write-only), and INOUT (read and write). Note: Unlike the type specifier in a PL/SQL variable declaration, the type specifier in a parameter declaration must be unconstrained. For example, CHAR(10) and VARCHAR(20) are illegal; CHAR or VARCHAR should be used instead. The actual length of a parameter depends on the corresponding argument that is passed in when the procedure is invoked.

Following the arguments is the keyword AS (IS is a synonym). Then comes the body, which is essentially a PL/SQL block. We have repeated the name of the procedure after the END, but this is optional. However, the DECLARE section should not start with the keyword DECLARE. Rather, following AS we have:

... AS

<local_var_declarations>

BEGIN

<procedure_body>

END;

.

run;

The run at the end runs the statement that creates the procedure; it does not execute the procedure. To execute the procedure, use another PL/SQL statement, in which the procedure is invoked as an executable statement. For example:

BEGIN addtuple1(99); END;

.

run;

The following procedure also inserts a tuple into T2, but it takes both components as arguments:

CREATE PROCEDURE addtuple2(

x T2.a%TYPE,

y T2.b%TYPE)

AS

BEGIN

INSERT INTO T2(a, b)

VALUES(x, y);

END addtuple2;

Page 53: PLSQL Tutorial

.

run;

Now, to add a tuple (10, 'abc') to T2:

BEGIN

addtuple2(10, 'abc');

END;

.

run;

The following illustrates the use of an OUT parameter:

CREATE TABLE T3 (

a INTEGER,

b INTEGER

);

CREATE PROCEDURE addtuple3(a NUMBER, b OUT NUMBER)

AS

BEGIN

b := 4;

INSERT INTO T3 VALUES(a, b);

END;

.

run;

DECLARE

v NUMBER;

BEGIN

addtuple3(10, v);

END;

run;

Page 54: PLSQL Tutorial

Note that assigning values to parameters declared as OUT or INOUT causes the corresponding input arguments to be written. Because of this, the input argument for an OUT or INOUT parameter should be something with an "lvalue", such as a variable like v in the example above. A constant or a literal argument should not be passed in for an OUT/INOUT parameter.

We can also write functions instead of procedures. In a function declaration, we follow the parameter list by RETURN and the type of the return value:

CREATE FUNCTION <func_name>(<param_list>) RETURN <return_type> AS ...

In the body of the function definition, "RETURN <expression>;" exits from the function and returns the value of <expression>.

To find out what procedures and functions you have created, use the following SQL query:

select object_type, object_name

from user_objects

where object_type = 'PROCEDURE'

or object_type = 'FUNCTION';

To drop a stored procedure/function:

drop procedure <procedure_name>;

drop function <function_name>;

Discovering Errors

PL/SQL does not always tell you about compilation errors. Instead, it gives you a cryptic message such as "procedure created with compilation errors". If you don't see what is wrong immediately, try issuing the command

show errors procedure <procedure_name>;

Alternatively, you can type, SHO ERR (short for SHOW ERRORS) to see the most recent compilation error.

Printing Variables

Sometimes we might want to print the value of a PL/SQL local variable. A ``quick-and-dirty'' way is to store it as the sole tuple of some relation and after the PL/SQL statement print the relation with a SELECT statement. A more couth way is to define a bind variable, which is the only kind that may be printed with a print command. Bind variables are the kind that must be prefixed with a colon in PL/SQL statements.

The steps are as follows:

1. We declare a bind variable as follows:

Page 55: PLSQL Tutorial

VARIABLE <name> <type>

where the type can be only one of three things: NUMBER, CHAR, or CHAR(n).

2. We may then assign to the variable in a following PL/SQL statement, but we must prefix it with a colon.3. Finally, we can execute a statement

PRINT :<name>;

outside the PL/SQL statement

Here is a trivial example, which prints the value 1.

VARIABLE x NUMBER

BEGIN

:x := 1;

END;

.

run;

PRINT :x;

PL/SQL BLOCKThe pl/sql block contains the following section:--

-----The DECLARE section.-----The Master BEGIN and END section that contains the EXCEPTION section.

The declare section contains declaration of memory variables, constants, cursors etc. The begin section contains sql executable statements and pl/sql executable statements. The exception section contains code to handle errors that may arise during the execution of the code block. The end declares the end of pl/sql block.

A bit about it's working. When you typed out the pl/sql block for execution. It is sent to the pl/sql engine, where procedural statements are executed; and sql statements are sent to the sql executor in the oracle engine. Since pl/sql engine resides in the oracle engine, the codes executes smoothly and efficiently.

PL/SQL DATA-TYPE

This is easy since it includes almost all the data types which u have

Page 56: PLSQL Tutorial

used in sql such as date, varchar, number, char etc etc... Some of the attributes such as %TYPE is also used. This attribute automatically takes in the default data type of the sql table from which u have passed the query. We will discuss this later.

Remember in pl/sql a variable name must begin with a character and can be followed by maximum of 29 other characters. Reserved words can't be used unless enclosed within double quotes. Variables must be separated from each other by at least one space or by a punctuation mark. You can assign values of operator using := operator. I won't discuss about logical comparisons operators such as <, > , >=, NOT, TRUE, AND, OR, NULL etc since they r quite easy to understand.

HOW TO DISPLAY MESSAGES ON SCREEN ---

DBMS_OUTPUT : is a package that includes a number of procedure and functions that accumulate information in a buffer so that it can be retrieved later. These functions can also be used to display messages to the user.PUT_LINE : Put a piece of information in the package buffer followed by an end-of-line marker. It can also be used to display message to the user. Put_line expects a single parameter of character data type. If used to display a message, it is the message 'string'.EG: dbms_output.put_line(x);

REMEMBER: To display messages to the user the SERVEROUTPUT should be set to ON. SERVEROUTPUT is a sql*plus environment parameter that displays the information pased as a parameter to the PUT_LINE function.EG: SET SERVEROUTPUT ON

A bit about comments. A comment can have 2 forms i.e.-- The comment line begins with a double hyphen (--). The entire line will be treated as a comment.-- The C style comment such as /* i am a comment */

CONDITIONAL CONTROL AND ITERATIVE CONTROL AND SEQUENTIAL CONTROL

IF and else.....IF --Condition THEN--ActionELSEIF --Condition THEN--ActionELSE--Action

Page 57: PLSQL Tutorial

END IF;

SIMPLE LOOPloop-- Sequence of statements;end loop;

the loop ends when u use EXIT WHEN statement --condition

WHILE LOOPWhile --conditionloop--sequence of statementsend loop;

FOR LOOPFOR i in 1..10loop--sequence of statementsend loop;

GOTO (sequential control)GOTO X;<< X >>

EXAMPLES

--ADDITIONdeclarea number;b number;c number;begina:=&a;b:=&b;c:=a+b; dbms_output.put_line('Sum of ' || a || ' and ' || b || ' is ' || c);

Here & is used to take user input at runtime.....

--SUM OF 100 NUMBERS

Declarea number;s1 number default 0;

Page 58: PLSQL Tutorial

Begina:=1;loops1:=s1+a;exit when (a=100);a:=a+1;end loop;dbms_output.put_line('Sum between 1 to 100 is '||s1);End;

--SUM OF odd NUMBERS USING USER INPUT...for loop

declaren number;sum1 number default 0;endvalue number;begin endvalue:=&endvalue;n:=1;for n in 1.. endvalueloopif mod(n,2)=1thensum1:=sum1+n;end ifend loop;dbms_output.put_line('sum = ' || sum1);end;

--SUM OF 100 ODD NUMBER .. WHILE LOOP

declaren number;endvalue number;sum1 number default 0;beginendvalue:=&endvalue;n:=1;while (n < endvalue)loopsum1:=sum1+n;n:=n+2;end loop;dbms_output.put_line('Sum of odd numbers between 1 and ' || endvalue || ' is ' || sum1);end;

Page 59: PLSQL Tutorial

--CALCULATION OF NET SALARY

declareename varchar2(15); basic number;da number;hra number;pf number;netsalary number;begin ename:=&ename;basic:=&basic;

da:=basic * (41/100);hra:=basic * (15/100);

if (basic < 3000)thenpf:=basic * (5/100);elsif (basic >= 3000 and basic <= 5000)then pf:=basic * (7/100);elsif (basic >= 5000 and basic <= 8000)thenpf:=basic * (8/100);elsepf:=basic * (10/100); end if;netsalary:=basic + da + hra -pf; dbms_output.put_line('Employee name : ' || ename);dbms_output.put_line('Providend Fund : ' || pf);dbms_output.put_line('Net salary : ' || netsalary);end;

--MAXIMUM OF 3 NUMBERS

Declarea number;b number;c number;d number;Begindbms_output.put_line('Enter a:');a:=&a;dbms_output.put_line('Enter b:');

Page 60: PLSQL Tutorial

b:=&b;dbms_output.put_line('Enter c:');c:=&b;if (a>b) and (a>c) thendbms_output.putline('A is Maximum');elsif (b>a) and (b>c) thendbms_output.putline('B is Maximum');elsedbms_output.putline('C is Maximum');end if;End;

--QUERY EXAMPLE--IS SMITH EARNING ENOUGH

declares1 emp.sal %type;beginselect sal into s1 from empwhere ename = 'SMITH';if(no_data_found) thenraise_application_error(20001,'smith is not present');end if;

if(s1 > 10000)thenraise_application_error(20002,'smith is earning enough');end if;

update emp set sal=sal + 500where ename='SMITH';end;

--PRIME NO OR NOT

DECLAREno NUMBER (3) := &no;a NUMBER (4);b NUMBER (2);BEGINFOR i IN 2..no - 1LOOPa := no MOD i;IF a = 0

Page 61: PLSQL Tutorial

THENGOTO out;END IF;END LOOP;<>IF a = 1THENDBMS_OUTPUT.PUT_LINE (no || ' is a prime number');ELSEDBMS_OUTPUT.PUT_LINE (no || ' is not a prime number');END IF;END;

--SIMPLE EXAMPLE OF LOOP STATEMENT I.E. EXIT WHEN

Declarea number:= 100;beginloopa := a+25;exit when a=250;end loop;dbms_output.put_line (to_Char(a));end;

--EXAMPLE OF WHILE LOOP

Declarei number:=0;j number:= 0;beginwhile i <=100 loopj := j+1;i := i +2;end loop;dbms_output.put_line(to_char(i));end;

--EXAMPLE OF FOR LOOP

Declarebeginfor i in 1..10loopdbms_output.put_line(to_char(i));end loop;

Page 62: PLSQL Tutorial

end;

--SEQUENTIAL CONTROL GOTO

declare--takes the default datatype of the column of the table pricecost price.minprice%type;beginselect stdprice into cost from price where prodial in (Select prodid from product where prodese = "shampoo");if cost > 7000 thengoto Upd;end if;<< Upd >>Update price set minprice = 6999 where prodid=111;end;

--CALCULATE THE AREA OF A CIRCLE FOR A VALUE OF RADIUS VARYING FROM 3 TO 7. STORE THE RADIUS AND THE CORRESPONDING VALUES OF CALCULATED AREA IN A TABLE AREAS.

Declarepi constant number(4,2) := 3.14;radius number(5);area number(14,2);

Beginradius := 3;While radius <=7Looparea := pi* power(radius,2);Insert into areas values (radius, area);radius:= radius+1;end loop;end;

--REVERSING A NUMBER 5639 TO 9365

Declaregiven_number varchar(5) := '5639';str_length number(2);inverted_number varchar(5);

Beginstr_length := length(given_number);For cntr in reverse 1..str_length

Page 63: PLSQL Tutorial

loopinverted_number := inverted_number || substr(given_number, cntr, 1);end loop;dbms_output.put_line('The Given no is ' || given_number);dbms_output.put_line('The inverted number is ' || inverted_number);end;

EXCEPTION HANDLING IN PLSQL

Errors in pl/sql block can be handled...error handling refers to the way we handle the errors in pl/sql block so that no crashing stuff of code takes place...This is exactly the same as we do in C++ or java..right!!There are two type:===> predefined exceptions===> user defined exceptionsThe above 2 terms are self explanatory

predefined exceptions:

No-data-found == when no rows are returnedCursor-already-open == when a cursor is opened in advanceDup-val-On-index == for duplicate entry of index..Storage-error == if memory is damagedProgram-error == internal problem in pl/sqlZero-divide == divide by zeroinvalid-cursor == if a cursor is not open and u r trying to close itLogin-denied == invalid user name or passwordInvalid-number == if u r inserting a string datatype for a number datatype which is already declaredToo-many-rows == if more rows r returned by select statement

SYNTAX

beginsequence of statements;exceptionwhen --exception name thensequence of statements;end;

EXAMPLES

--When there is no data returned by rowdeclareprice item.actualprice%type;begin

Page 64: PLSQL Tutorial

Select actual price into price from item where qty=888;when no-data-found thendbms_output.put_line('item missing');end;

--EXAMPLE OF USER DEFINED EXCEPTION

DECLAREe_rec emp%ROWTYPE;e1 EXCEPTION;sal1 emp.sal%TYPE;BEGINSELECT sal INTO sal1 FROM emp WHERE deptno = 30 AND ename = 'John';IF sal1 < 5000 THENRAISE e1;sal1 := 8500;UPDATE emp SET sal = sal1 WHERE deptno = 30 AND ename = 'John';END IF;EXCEPTIONWHEN no_data_found THENRAISE_APPLICATION_ERROR (-20001, 'John is not there.');WHEN e1 THENRAISE_APPLICATION_ERROR (-20002, 'Less Salary.');END;

--EXAMPLE OF RAISE-APPLICATION-ERROR... THIS IS YOUR OWN ERROR STATEMENT...YOU RAISE YOUR OWN ERROR

Declares1 emp.sal %type;beginselect sal into s1 from emp where ename='SOMDUTT';if(no-data-found) thenraise_application_error(20001, 'somdutt is not there');end if;if(s1 > 10000) thenraise_application_error(20002, 'somdutt is earing a lot');end if;update emp set sal=sal+500 where ename='SOMDUTT';end;

--INTERESTING EG OF USER DEFINED EXCEPTIONS

Declarezero-price exception;

Page 65: PLSQL Tutorial

price number(8);beginselect actualprice into price from item where ordid =400;if price=0 or price is null thenraise zero-price;end if;exceptionwhen zero-price thendbms_output.put_line('raised xero-price exception');end;

CURSORS

Cursor is a work area in pl/sql which is used by sql server used to store the result of a query. Each column value is pointed using pointer. You can independently manipulate cursor values. A bit about it's working..... suppose you ask for a query stored in the server ... at first a cursor consisting of query result is created in server...now the cursor is transferred to the client where again cursor is created and hence the result is displayed......

Cursors are of 2 types: implicit and explicit.......implicit cursors are created by oracle engine itself while explicit cursors are created by the users......cursors are generally used in such a case when a query returns more than one rows....normal pl/sql returning more than one rows givens error but using cursor this limitation can be avoided....so cursors are used....

Cursor attributes

%ISOPEN == returns true if ursor is open, false otherwise%FOUND == returns true if recod was fetched successfully, false otherwise%NOTFOUND == returns true if record was not fetched successfully, false otherwise%ROWCOUNT == returns number of records processed from the cursor.

Very important: Cursor can be controlled using following 3 control statements. They are Open, Fetch, Close.....open statement identifies the active set...i.e. query returned by select statement...close statement closes the cursor...and fetch statement fetches rows into the variables...Cursors can be made into use using cursor for loop and fetch statement...we will see the corresponding examples...

Page 66: PLSQL Tutorial

EXAMPLES

--EXAMPLE OF SQL%FOUND (IMPLICIT CURSORS)

beginupdate employee set salary=salary *0.15where emp_code = &emp_code;if sql%found thendbms_output.put_line('employee record modified successfully');elsedbms_output.put_line('employee no does not exist');end if;end;

--EXAMPLE FOR SQL%NOTFOUND (IMPLICIT CURSORS)

beginupdate employee set salary = salary*0.15 where emp_code = &emp_code;if sql%notfound thendbms_output.put_line('employee no . does not exist');elsedbms_output.put_line('employee record modified successfully');end if;end;

--EXAMPLE FOR SQL%ROWCOUNT (IMPLICIT CURSORS)

declarerows_affected char(4);beginupdate employee set salary = salary*0.15 where job='programmers';rows_affected := to_char(sql%rowcount);if sql%rowcount > 0 thendbms_output.put_line(rows_affected || 'employee records modified successfully');elsedbms_output.put_line('There are no employees working as programmers');end if;end;

Syntax of explicit cursor: Cursor cursorname is sql select statement;Syntax of fetch : fetch cursorname into variable1, variable2...;Syntax of close; close cursorname;Syntax of open cursor; open cursorname;

Page 67: PLSQL Tutorial

--EXPLICIT CURSOR EG

DECLARECURSOR c1 is SELECT * FROM emp;str_empno emp.empno%type;str_ename emp.ename%type;str_job emp.job%type;str_mgr emp.mgr%type;str_hiredate emp.hiredate%type;str_sal emp.sal%type;str_comm emp.comm%type;str_deptno emp.deptno%type;rno number;BEGINrno := &rno;FOR e_rec IN c1LOOPIF c1%rowcount = rno THENDBMS_OUTPUT.PUT_LINE (str_empno || ' ' || str_ename || ' ' || str_job || ' ' || str_mgr || ' ' || str_hiredate || ' ' || str_sal || ' ' || str_comm || ' ' || str_deptno);END IF;END LOOP;END;

--ANOTHER EG DISPLAYING VALUE OF A TABLE

DECLARECURSOR c1 IS SELECT * FROM emp;e_rec emp%rowtype;BEGINOPEN c1;LOOPFETCH c1 INTO e_rec;DBMS_OUTPUT.PUT_LINE('Number: ' || ' ' || e_rec.empno);DBMS_OUTPUT.PUT_LINE('Name : ' || ' ' || e_rec.ename);DBMS_OUTPUT.PUT_LINE('Salary: ' || ' ' || e_rec.sal);EXIT WHEN c1%NOTFOUND;END LOOP;CLOSE c1;END;

-- Display details of Highest 10 salary paid employee

Page 68: PLSQL Tutorial

DECLARECURSOR c1 IS SELECT * FROM emp ORDER BY sal DESC;e_rec emp%rowtype;BEGINFOR e_rec IN c1LOOPDBMS_OUTPUT.PUT_LINE('Number: ' || ' ' || e_rec.empno);DBMS_OUTPUT.PUT_LINE('Name : ' || ' ' || e_rec.ename);DBMS_OUTPUT.PUT_LINE('Salary: ' || ' ' || e_rec.sal);EXIT WHEN c1%ROWCOUNT >= 10;END LOOP;END;

-- EXAMPLE OF CURSOR FOR LOOP

declare cursor c1 is select * from somdutt;beginfor outvariable in c1loopexit when c1%notfound;if outvariable.age < 21 thendbms_output.put_line(outvariable.age || ' ' || outvariable.name);end if;end loop;end;

--ref STRONG CURSORS

DECLARETYPE ecursor IS REF CURSOR RETURN emp%ROWTYPE;ecur ecursor;e_rec emp%ROWTYPE;dn NUMBER;BEGINdn := &deptno;OPEN ecur FOR SELECT * FROM emp WHERE deptno = dn;FOR e_rec IN ecurLOOPDBMS_OUTPUT.PUT_LINE ('Employee No : ' || e_rec.empno);DBMS_OUTPUT.PUT_LINE ('Employee Salary: ' || e_rec.salary);END LOOP;END;

--REF WEAK CURSORS

DECLARE

Page 69: PLSQL Tutorial

TYPE tcursor IS REF CURSOR;tcur tcursor;e1 emp%ROWTYPE;d1 dept%ROWTYPE;tname VARCHAR2(20);BEGINtname := &tablename;IF tname = 'emp' THENOPEN tcur FOR SELECT * FORM emp;DBMS_OUTPUT.PUT_LINE ('Emp table opened.');close tcur;DBMS_OUTPUT.PUT_LINE ('Emp table closed.');ELSE IF tname = 'dept' THENOPEN tcur FOR SELECT * FROM dept;DBMS_OUTPUT.PUT_LINE ('Dept table opened.');close tcur;DBMS_OUTPUT.PUT_LINE ('Emp table closed.');ELSERAISE_APPLICATION_ERROR (-20004, 'Table name is wrong');END IF;END;

--CURSOR FOR LOOP WITH PARAMETERS

DeclareCursor c1(Dno number) is select * from emp where deptno = dno;beginfor empree in c1(10) loop;dbms_output.put_line(empree.ename);end loop;end;

TRIGGERS

Trigger is a stored procedure which is called implicitly by oracle engine whenever a insert, update or delete statement is fired.

Advantages of database triggers:---> Data is generated on it's own---> Replicate table can be maintained---> To enforce complex integrity contraints---> To edit data modifications---> To autoincrement a fieldetc..

Page 70: PLSQL Tutorial

Syntax: Create or replace trigger --triggername-- [before/after] [insert/pdate/delete] on --tablename-- [for each satement/ for each row] [when --condition--] plus..begin.and exception

Triggers are of following type: before or after trigger ....and for each row and for each statement trigger... before trigger is fired before insert/update/delete statement while after trigger is fired after insert/update/delete statement...for each row and for each statements triggers are self explainatory..

EXAMPLE

-- A database trigger that allows changes to employee table only during the business hours(i.e. from 8 a.m to 5.00 p.m.) from monday to saturday. There is no restriction on viewing data from the table -CREATE OR REPLACE TRIGGER Time_Check BEFORE INSERT OR UPDATE OR DELETE ON EMP BEGIN IF TO_NUMBER(TO_CHAR(SYSDATE,'hh24')) < 10 OR TO_NUMBER(TO_CHAR(SYSDATE,'hh24')) >= 17 OR TO_CHAR(SYSDATE,'DAY') = 'SAT' OR TO_CHAR(SYSDATE,'DAY') = 'SAT' THEN RAISE_APPLICATION_ERROR (-20004,'YOU CAN ACCESS ONLY BETWEEN 10 AM TO 5 PM ON MONDAY TO FRIDAY ONLY.'); END IF; END; --YOU HAVE 2 TABLES WITH THE SAME STRUCTURE. IF U DELETE A RECORD FROM ONE TABLE , IT WILL BE INSERTED IN 2ND TABLE ED TRIGGERNAME Create or replace trigger backup after delete on emp fro each row begin insert into emp/values (:old.ename,:old.job,:old.sal); end; save the file.. and then sql> @ triggername --To STICK IN SAL FIELD BY TRIGGER MEANS WHEN U ENTER GREATER THAN 5000, THEN THIS TRIGGER IS EXECUTED Create or replace trigger check before insert on emp for each row when (New.sal > 5000); begin raise_application_error(-20000, 'your no is greater than 5000'); end; --NO CHANGES CAN BE DONE ON A PARTICULAR TABLE ON SUNDAY AND SATURDAY Create or replace trigger change before on emp for each row when (to_char(sysdate,'dy') in ('SAT','SUN')) begin raise_application_error(-200001, 'u cannot enter data in saturnday and sunday'); end; --IF U ENTER IN EMP TABLE ENAME FIELD'S DATA IN ANY CASE IT WILL BE INSERTED IN CAPITAL LETTERS'S ONLY Create or replace trigger cap before insert on emp for each row begin :New.ename = upper(:New.ename); end; --A TRIGGER WHICH WILL NOT ALLOW U TO ENTER DUPLICATE VALUES IN FIELD EMPNO IN EMP TABLE Create or replace trigger dubb before insert on emp for each row Declare cursor c1 is select * from emp; x emp%rowtype; begin open c1; loop fetch c1 into x; if :New.empno = x.empno then dbms_output.put_line('you entered duplicated no'); elseif :New.empno is null then dbms_output.put_line('you empno is

Page 71: PLSQL Tutorial

null'); end if; exit when c1%notfound; end loop; close c1; end;

Remember trigger can be dropped using Drop Trigger triggername ; statement...

PROCEDURES AND FUNCTIONS

procedure is a subprogram...which consists of a set of sql statement. Procedures are not very different from functions. A procedure or function is a logically grouped set of SQL and PL/SQL statements that perform a specific task. A stored procedure or function is a named pl/sql code block that have been compiled and stored in one of the oracle engines's system tables.

To make a procedure or function dynamic either of them can be passed parameters before execution. A procedure or function can then change the way it works depending upon the parameters passed prior to its execution.

Procedures and function are made up of a declarative part, an executable part and an optional exception-handling part

A declaration part consists of declarations of variables. A executable part consists of the logic i.e. sql statements....and exception handling part handles any error during run-time

The oracle engine performs the following steps to execute a procedure or function....Verifies user access, Verifies procedure or function validity and executes the procedure or function. Some of the advantages of using procedures and functions are: security, performance, memory allocation, productivity, integrity.

Most important the difference between procedures and functions: A function must return a value back to the caller. A function can return only one value to the calling pl/sql block. By defining multiple out parameters in a procedure, multiple values can be passed to the caller. The out variable being global by nature, its value is accessible by any pl/sql code block including the calling pl/sql block.

Syntax for stored procedure:CREATE OR REPLACE PROCEDURE [schema] procedure name (argument { IN, OUT, IN OUT} data type, ..) {IS, AS}variable declarations; constant declarations; BEGINpl/sql subprogram body;EXCEPTIONexception pl/sql block;

Page 72: PLSQL Tutorial

END;

Syntax for stored function:CREATE OR REPLACE FUNCTION [schema] functionname(argument IN data type, ..) RETURN data type {IS, AS}variable declarations; constant declarations; BEGINpl/sql subprogram body;EXCEPTIONexception pl/sql block;END;

The above syntax i think is self explanatory...but i will give you some details...IN : specifies that a value for the argument must be specified when calling the procedure or function. argument : is the name of an argument to the procedure or function. parentheses can be omitted if no arguments are present. OUT : specifies that the procedure passes a value for this argument back to its calling environment after execution. IN OUT : specifies that a value for the argument must be specified when calling the procedure and that the procedure passes a value for this argument back to its calling environment after execution. By default it takes IN. Data type : is the data type of an argument.

EXAMPLES

--PROCEDURE USING NO ARGUMENT..AND USING CURSORCREATE OR REPLACE PROCEDURE P2 IScursor cur1 is select * from emp;beginfor erec in cur1 loopdbms_output.put_line(erec.ename);end loop;end;

--PROCEDURE USING ARGUMENTCREATE OR REPLACE PROCEDURE ME( X IN NUMBER) ISBEGINdbms_output.put_line(x*x);end;

sql> exec me(3);

--FUNCTION using argumentCREATE OR REPLACE FUNCTION RMT(X IN NUMBER) RETURN NUMBER IS

Page 73: PLSQL Tutorial

BEGINdbms_output.put_line(x*x); --return (x*x);end;

(make a block like this to run it.....)begindbms_output.put_line(rmt(3));end;

--CREATE A PROCEDURE THAT DELETE ROWS FROM ENQUIRY--WHICH ARE 1 YRS BEFORE

Create or replace procedure myprocedure is begindelete from enquiry where enquirydate <= sysdate - 1;end;

--CREATE A PROCEDURE THAT TAKES ARGUMENT STUDENT NAME,--AND FIND OUT FEES PAID BY THAT STUDENT

CREATE or REPLACE procedure me (namee in varchar) iscursor c1 is select a.feespaiddate from feespaid a, enrollment b, enquiry cwherec.enquiryno = b.enquiryno and a.rollno = b.rollno andc.fname = namee;beginfor erec in c1loopdbms_output.put_line(erec.feespaiddate);end loop;end;

--SUM OF 2 Numbers

CREATE or replace procedure p1 isDeclarea number;b number;c number;Begina:=50;b:=89;c:=a+b;

Page 74: PLSQL Tutorial

dbms_output.put_line('Sum of '||a||' and '||b||' is '||c);End;

--DELETION PROCEDURE

create or replace procedure myproc isbegindelete from enquiry where fname='somdutt';end;

--IN and OUT procedure example

Create or replace procedure lest ( a number, b out number) isidentify number;beginselect ordid into identity from item whereitemid = a;if identity < 1000 thenb := 100;end if;end l

--in out parameter

Create or replace procedure sample ( a in number, b in out number) isidentity number;beginselect ordid, prodid into identity, b from item where itemid=a;if b<600 thenb := b + 100;end if;end;

now procedure is called by passing parameter

declarea number;b number;beginsample(3000, b)dbms_output.put_line(1th value of b is 11 b);end ;

--SIMILAR EXAMPLE AS BEFORE

create or replace procedure getsal( sal1 in out number) is

Page 75: PLSQL Tutorial

beginselect sal into sal1 from empwhere empno = sal1;end ;

now use the above in plsql block

declaresal1 number := 7999;begingetsal(sal1);dbms_output.put_line('The employee salary is' || sal1);end ;

You can make a procedure and functions similarly.....also if u wanna drop a function then use drop function functionname and for procedure use drop procedure procedurename

PACKAGES

A package is an oracle object, which holds other objects within it. Objects commonly held within a package are procedures, functions, variables, constants, cursors and exceptions. Packages in plsql is very much similar to those packages which we use in JAVA......yeah!! java packages holds numerous classes..right!!!...

A package has 2 parts..... package specification and package body

A package specification part consists of all sort of declaration of functions and procedures while package body consists of codings and logic of declared functions and procedures...

EXAMPLE

--SIMPLEST EG

--specificationcreate or replace package pack2 isfunction rmt(x in number) return number;procedure rmt1(x in number);end;

--body

Page 76: PLSQL Tutorial

create or replace package body pack2 is function rmt(x in number) return number isbegin return (x*x);end;

procedure rmt1(x in number) isbegindbms_output.put_line(x*x);end;end;

(how to run.....)exec packagename.procedurenamei.e.exec pack2.rmt1(3);

As shown above u can put in complicated procedures and functions inside the package...I have just shown a simple example...you can easily modify the above code to fit your requirement......Just try out packages which includes cursors, procedures and functions..etc..Remeber pl/sql supports overloading...i.e. you can use the same function or procedure name in your application but with different no or type of arguments.