Introduction to pl/sql
PL/SQL is a procedural language designed specifically to embrace SQL statements within its
syntax.
PL/SQL program units are compiled by the Oracle Database server and stored inside the database. And
at run-time, both PL/SQL and SQL run within the same server process, bringing optimal efficiency.
PL/SQL automatically inherits the robustness, security, and portability of the Oracle
Database.
PL/SQL is a powerful, yet straightforward database programming language. It is easy to both
write
and read, and comes packed with lots of out-of-the-box optimizations and security features.
advantages of plsql
- It is a standard database language and PL/SQL is strongly integrated with SQL. PL/SQL supports both static and also dynamic SQL. Static SQL is said to support DML operations and also the transaction control from PL/SQL block. In dynamic SQL, SQL allows embedding the DDL statements in the PL/SQL blocks.
- Also, It then allows sending an entire block of statements to the database at one time. It reduces network traffic and also provides high performance for the applications.
- It gives high productivity to programmers as it can query, transform and also update the data in the database.
- This is said to save time on the design and also the debugging by strong features, like the exception handling, encapsulation, data hiding and also object-oriented data types.
- Applications that are written in PL/SQL languages are portable.
- This provides high security level.
- It also provides access to the predefined SQL packages.
- It also supports for Object-oriented programming.
- It provides support for developing web applications and server pages.
BLOCK STRUCTURE
PL/SQL is a block-structured language whose code is organized into blocks. A PL/SQL block consists of
three sections: declaration, executable, and exception-handling sections. In a block, the executable
section is mandatory while the declaration and exception-handling sections are optional.
A PL/SQL block has a name. Functions or Procedures is an example of a named block. A named block is
stored into the Oracle Database server and can be reused later.
A block without a name is an anonymous block. An anonymous block is not saved in the Oracle Database
server, so it is just for one-time use. However, PL/SQL anonymous blocks can be useful for testing
purposes.
Syntax
declaration section
BEGIN
exception execution
EXCEPTION
exception section
END;
Example
DECLARE
message VARCHAR(255) : = 'HELLO DEVELOPER';
BEGIN
DBMS_OUTPUT.PUT_LINE(message);
END;
Output
HELLO DEVELOPER
Data types
Each value in PL/SQL such as a constant, variable and parameter has a data type that determines the
storage format, valid values, and allowed operations.
PL/SQL has two kinds of data types: scalar and composite. The scalar types are types
that store
single values such as number, Boolean, character, and datetime whereas the composite types are types
that store multiple values, for example, record and collection.
This tutorial explains the scalar data types that store values with no internal components.
Data type | Synonyms |
---|---|
NUMBER | DEC, DECIMAL, DOUBLE PRECISION, FLOAT, INTEGER, INT, NUMERIC, REAL, SMALLINT |
CHAR | CHARACTER, STRING |
VARCHAR2 | VARCHAR |
declaring variables
In PL/SQL, a variable is named storage location that stores a value of a particular data type. The value of the variable changes through the program. Before using a variable, you must declare it in the declaration section of a block.
Syntax
variable_name dataType [NOT NULL] [:= initial_value];
Default Values
PL/SQL allows you to set a default value for a variable at the declaration time. To assign a default value to a variable, you use the assignment operator (:=) or the DEFAULT keyword.
Example
DECLARE
l_product_name VARCHAR2( 100 ) DEFAULT 'Laptop';
BEGIN
NULL;
END;
NOT NULL CONSTRAINT
If you impose the NOT NULL constraint on a value, then the variable cannot accept a NULL value.
Besides, a variable declared with the NOT NULL must be initialized with a non-null value. Note that
PL/SQL treats a zero-length string as a NULL value.
The following example first declares a variable named l_shipping_status with the NOT NULL
constraint. Then, it assigns the variable a zero-length string.
Example
DECLARE
l_shipping_status VARCHAR2( 25 ) NOT
NULL := 'Shipped';
BEGIN
l_shipping_status := '';
END;
VARIABLE ASSIGNMENT
To assign a value to a variable, you use the assignment operator (:=)
Example
DECLARE
l_customer_group VARCHAR2(100) := 'Silver';
BEGIN
l_customer_group := 'Gold';
DBMS_OUTPUT.PUT_LINE(l_customer_group);
END;
Anchored declarations
Typically, you declare a variable and select a value from a table column to this variable. If the
data type of the table column changes, you must adjust the program to make it work with the new
type.
PL/SQL allows you to declare a variable whose data type anchor to a table column or another
variable. Consider the following example:
DECLARE
emp_name employee.name%TYPE;
emp_salary employee.salary%TYPE;
BEGIN
SELECT
name, salary
INTO
emp_name, emp_salary
FROM
employee
WHERE
id = 3;
DBMS_OUTPUT.PUT_LINE(emp_name || ':' || emp_salary );
END;
- First, declare two variables emp_name and emp_salary whose data type anchors to the name and salary columns respectively, in the declaration section of the block.
- Second, query employee name and salary of the employee id 3 and assign these column values to the emp_name and salary variables in the execution block.
OUTPUT
Kumar:9000
constant
Unlike a variable, a constant holds a value that does not change throughout the execution of the
program.
Constants make your code more readable.
Syntax
constant_name constant datatype [NOT NULL] := expression;
Example
DECLARE
co_pi CONSTANT REAL := 3.14159;
co_radius CONSTANT REAL := 10;
co_area CONSTANT REAL := (co_pi * co_radius**2);
BEGIN
DBMS_OUTPUT.PUT_LINE(co_area);
END;
Output
314.159
Operator Precedence
This term determines the grouping of the terms in an expression. This shows how an expression is evaluated. Certain operators will have higher precedence than others, like Multiplication operator has higher precedence than the addition operator.
Example
DECLARE
Y number:= 5 + 2 * 3;
BEGIN
DBMS_OUTPUT.PUT_LINE(Y);
END;
Output
11
In the above equation Y is assigned 11, not 21. Since, * has higher precedence than +. So, it first
gets multiplied with 2*3 and then adds into 5.
However, operators with the highest precedence appear at the top of the table, those with the lowest
precedence appear at the bottom. And then within the expression, higher precedence operators will be
evaluated first.
The precedence of the operators goes like as follow: =, <,>, <=,>=, <>, !=, ~=, ^=, IS NULL, LIKE,
BETWEEN, IN
Operator | Operation |
---|---|
** | Exponentiation |
+,- | Identity, negation |
+,-,|| | Addition, subtraction, concatenation |
NOT | Logical negation |
AND | conjunction |
OR | inclusion |
Conditional and Iterative Control
PL/SQL Iterative control statements allow a programmer to execute a set of statements multiple times. All iterative statements must have a conditional statement to check whether to continue to execute the block of statement another time.
- Simple loop
- While loop
- For loop
Additional Statements used with PL/SQL Iterative Control Statements
- exit
- exit when
- continue
Simple loop
The simple loop is infinite. The loop keeps on executing the enclosed statements infinitely. Simple loop needs an exit condition and exit statement to terminate.
Syntax
LOOP
Loop statements
Conditional exit using EXIT|EXIT WHEN
END LOOP;
Example
DECLARE
num NUMBER:=1;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE('Number = '||num);
num:=num+1;
IF num>3 THEN
EXIT;
END IF;
END LOOP;
END;
Output
Number = 1 |
Number = 2 |
Number = 3 |
WHILE loop
WHILE loop is not infinite. The condition of termination is defined after WHILE and before LOOP
keywords. Between WHILE LOOP and END LOOP the set of statements can be given. These statements are
executed as long as the condition in WHILE is true.
After every iteration or execution of block of statements control returns to WHILE. If the condition
is true, next iteration is initiated. If this condition is false, control is passed to statement
after END LOOP;
Syntax
WHILE condition expression LOOP
Loop statements
[CONTINUE| EXIT|EXIT WHEN with condition]
END LOOP;
Example
DECLARE
num NUMBER:=1;
BEGIN
WHILE num<=3 LOOP
DBMS_OUTPUT.PUT_LINE('Number = '||num);
num:=num+1;
END LOOP;
END;
Output
Number = 1 |
Number = 2 |
Number = 3 |
FOR loop
FOR Loop is not infinite. In the FOR loop header a counter variable is used which is compared between Lower Bound and Upper Bound values. The variable is initialized to the Lower bound value and is incremented with iterations. The statements block is executed as long as variable’s value remains less than or equal to upper bound value.
Syntax
FOR counter-variable IN Lower Bound..
Upper Bound LOOP
Loop statements
[CONTINUE| EXIT|EXIT WHEN with condition]
END LOOP;
Example
DECLARE
num NUMBER :=1;
BEGIN
FOR i IN num .. 3 LOOP
DBMS_OUTPUT.PUT_LINE ('Number = '||i);
END LOOP;
END;
Output
Number = 1 |
Number = 2 |
Number = 3 |
CURSOR
A cursor is a POINTER to this context area. PL/SQL controls the context area through a cursor.
A
cursor holds the rows (one or more) returned by a SQL statement. The set of rows the cursor holds is
referred to as the active set.
You can name a cursor so that it could be referred to in a program to fetch and process the rows
returned by the SQL statement, one at a time. There are two types of cursors :
- Implicit cursor
- Explicit cursor
Implicit cursor
Implicit cursors are automatically created by Oracle whenever an SQL statement is executed, when
there is no explicit cursor for the statement. Programmers cannot control the implicit cursors and
the information in it.
Whenever a DML statement (INSERT, UPDATE and DELETE) is issued, an implicit cursor is associated
with this statement. For INSERT operations, the cursor holds the data that needs to be inserted. For
UPDATE and DELETE operations, the cursor identifies the rows that would be affected.
Attribute | Description |
---|---|
%FOUND | Returns TRUE if an INSERT, UPDATE, or DELETE statement affected one or more rows or a SELECT INTO statement returned one or more rows. Otherwise, it returns FALSE. |
%NOTFOUND | The logical opposite of %FOUND. It returns TRUE if an INSERT, UPDATE, or DELETE statement affected no rows, or a SELECT INTO statement returned no rows. Otherwise, it returns FALSE. |
%ISOPEN | Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor automatically after executing its associated SQL statement. |
%ROWCOUNT | Returns the number of rows affected by an INSERT, UPDATE, or DELETE statement, or returned by a SELECT INTO statement. |
Employee table
id | name | salary |
---|---|---|
1 | Rohit | 5000 |
2 | Gill | 4000 |
3 | Kumar | 9000 |
Example
DECLARE
total_rows number(2);
BEGIN
UPDATE employee
SET salary = salary + 1000;
IF sql%notfound THEN
dbms_output.put_line('employee not found');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' updated ');
END IF;
END;
When the above code is executed at the SQL prompt, it produces the following result −
3 employee selected
PL/SQL procedure successfully completed.
If you check the records in employee table, you will find that the rows have been updated
Output
id | name | salary |
---|---|---|
1 | Rohit | 6000 |
2 | Gill | 5000 |
3 | Kumar | 10000 |
Explicit cursor
Explicit cursors are programmer-defined cursors for gaining more control over the context area. An explicit cursor should be defined in the declaration section of the PL/SQL Block. It is created on a SELECT Statement which returns more than one row.
Syntax for creating an explicit cursor :
CURSOR cursor_name IS select_statement;
Working with an explicit cursor includes the following steps :
- Declaring the cursor for initializing the memory
- Opening the cursor for allocating the memory
- Fetching the cursor for retrieving the data
- Closing the cursor to release the allocated memory
Declaring the Cursor
Declaring the cursor defines the cursor with a name and the associated SELECT statement.
Example
CURSOR emp_employee IS
SELECT id, name, salary FROM employee;
Opening the Cursor
Opening the cursor allocates the memory for the cursor and makes it ready for fetching the rows returned by the SQL statement into it.
Example
CURSOR emp_employee IS
SELECT id, name, salary FROM employee;
Fetching the Cursor
Fetching the cursor involves accessing one row at a time.
Example
FETCH emp_employee INTO emp_id, emp_name, emp_salary;
Closing the Cursor
Closing the cursor means releasing the allocated memory.
Example
CLOSE emp_employee;
Complete example of Explicit Cursor
DECLARE
emp_id employee.id%type;
emp_name employee.name%type;
emp_salary employee.salary%type;
CURSOR emp_employee is
SELECT id, name, salary FROM employee;
BEGIN
OPEN emp_employee;
LOOP
FETCH emp_employee into emp_id, emp_name, emp_salary;
EXIT WHEN emp_employee%notfound;
dbms_output.put_line(emp_id || ' ' || emp_name || ' ' || emp_salary);
END LOOP;
CLOSE emp_employee;
END;
Output
1 Rohit 5000
2 Gill 4000
3 Kumar 9000
Exception
Exceptions in PL/SQL. An exception is an error condition during a program execution. PL/SQL supports
programmers to catch such conditions using EXCEPTION block in the program and an appropriate action
is taken against the error condition.
There are two types of exceptions :
- system-defined exceptions
- user-defined exceptions
Syntax
DECLARE
declarations section
BEGIN
executable command(s)
EXCEPTION
exception handling goes here
WHEN exception1 THEN
exception1-handling-statements
WHEN exception2 THEN
exception2-handling-statements
........
WHEN others THEN
exception3-handling-statements
END;
Example
DECLARE
emp_id employee.id%type;
emp_name employee.name%type :='Sammy';
emp_salary employee.salary%type;
BEGIN
SELECT name, salary INTO emp_name, emp_salary
FROM employee
WHERE id = emp_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| emp_name);
DBMS_OUTPUT.PUT_LINE ('salary: ' || emp_salary);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('employee not found');
WHEN others THEN
dbms_output.put_line('Error!');
END;
Output
employee not found
PL/SQL procedure successfully completed.
User-defined Exceptions
PL/SQL allows you to define your own exceptions according to the need of your program. A user-defined exception must be declared and then raised explicitly, using either a RAISE statement or the procedure DBMS_STANDARD.RAISE_APPLICATION_ERROR.
Syntax
DECLARE
exception_name EXCEPTION;
Example
DECLARE
emp_id customers.id%type := &cemp_id;
emp_name customerS.Name%type;
emp_salary customers.salary%type;
-- user defined exception
ex_invalid_id EXCEPTION;
BEGIN
IF emp_id <= 0 THEN
RAISE ex_invalid_id;
ELSE
SELECT name, salary INTO emp_name, emp_salary
FROM customers
WHERE id = emp_id;
DBMS_OUTPUT.PUT_LINE ('Name: '|| emp_name);
DBMS_OUTPUT.PUT_LINE ('salary: ' || emp_salary);
END IF;
EXCEPTION
WHEN ex_invalid_id THEN
dbms_output.put_line('id must be greater than zero!');
WHEN no_data_found THEN
dbms_output.put_line('employee not found');
WHEN others THEN
dbms_output.put_line('Error!');
END;
Output
Enter value for cemp_id: -6 (let's enter a value -6)
old 2: emp_id customers.id%type := &cemp_id;
new 2: emp_id customers.id%type := -6;
id must be greater than zero!
PL/SQL procedure successfully completed.
Triggers
Triggers are stored programs, which are automatically executed or fired when some events occur.
Triggers are, in fact, written to be executed in response to any of the following events :
- database manipulation (DML) statement (DELETE, INSERT, or UPDATE)
- database definition (DDL) statement (CREATE, ALTER, or DROP).
- database operation (SERVERERROR, LOGON, LOGOFF, STARTUP, or SHUTDOWN).
Triggers can be defined on the table, view, schema, or database with which the event is associated.
Benefits of Triggers
- Generating some derived column values automatically
- Enforcing referential integrity
- Event logging and storing information on table access
- Synchronous replication of tables
- Imposing security authorizations
- Preventing invalid transactions
Syntax
CREATE [OR REPLACE ] TRIGGER
trigger_name
{BEFORE | AFTER | INSTEAD OF }
{INSERT [OR] | UPDATE [OR] | DELETE}
[OF col_name]
ON table_name
[REFERENCING OLD AS o NEW AS n]
[FOR EACH ROW]
WHEN (condition)
DECLARE
Declaration-statements
BEGIN
Executable-statements
EXCEPTION
Exception-handling-statements
END;
Employee table
id | name | salary |
---|---|---|
1 | Rohit | 5000 |
2 | Gill | 4000 |
3 | Kumar | 9000 |
Example of creating triggers
CREATE OR REPLACE TRIGGER
display_salary_changes
BEFORE DELETE OR INSERT OR UPDATE ON employee
FOR EACH ROW
WHEN (NEW.ID > 0)
DECLARE
sal_diff number;
BEGIN
sal_diff := :NEW.salary - :OLD.salary;
dbms_output.put_line('Old salary: ' || :OLD.salary);
dbms_output.put_line('New salary: ' || :NEW.salary);
dbms_output.put_line('Salary difference: ' || sal_diff);
END;
Triggering Triggers
Let us perform some DML operations on the employee table. Here is one update statement, which will update a record in the table
UPDATE employee
SET salary = salary + 1000
WHERE id = 1;
When a record is updated in the employee table, the above create trigger, display_salary_changes will be fired and it will display the following result −
Output
Old salary: 5000
New salary: 6000
Salary difference: 1000