Sei sulla pagina 1di 112

INTRODUCTION TO PL/ SQL

Procedural Language Extension to SQL

By : Mrs. Suman Madan suman.madan@jimsindia.org

PL/SQL
Allows using general programming tools with SQL, for example: loops, conditions, functions, etc. This allows a lot more freedom than general SQL, and is lighter-weight than JDBC. We write PL/SQL code in a regular file, for example PL.sql, and load it with @PL in the sqlplus console.

Advantages : Support for SQL Higher productivity Better performance Portability Integration with oracle

Architecture of PL SQL
ORACLE SERVER

PL SQL ENGINE

PL SQL BLOCK
PROCEDURAL

STATEMENT EXECUTOR

S Q L

SQL Statement Executor

PL SQL CHARACTER SET


Upper and lower case letters Numerical form

All special symbols and characters


Tab ,space and carriage return All arithmetic operators

CONTROL STRUCTURES
CONDITIONAL CONTROL
ALL THE BASIC IF CONDITIONS

ITERATIVE CONTROL
LOOP ,FOR LOOP ,WHILE LOOP

SEQUENTIAL CONTROL
GOTO

PL/SQL Blocks
PL/SQL code is built of Blocks, with a unique structure. There are two types of blocks in PL/SQL: 1. Anonymous Blocks: have no name (like scripts) can be written and executed immediately in SQLPLUS can be used in a trigger Procedures Functions

2. Named Blocks:

INTRODUCTION TO PLSQL BLOCK


PLSQL BLOCK IS DIVIDED INTO THREE PARTS DECLARATIVE EXECUTABLE EXCEPTION HANDLING DECLARE { DECLARATIONS OF VARIABLES ETC. } BEGIN { EXECUTABLE STATEMENTS } EXCEPTION { HANDLERS } END;

DECLARE
Syntax
identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr];

Examples

Notice that PL/SQL includes all SQL types, and more DATE; NUMBER(2) NOT NULL := 27; VARCHAR2(13) := 'Levi'; CONSTANT NUMBER := 77; BOOLEAN NOT NULL := TRUE;

Declare birthday age name magic valid

SAMPLE PROGRAME1
Declare com emp.comm%type;

Begin
select comm into com from emp where empno=7876;

if com is null then update emp set comm=100 where empno=7876; else update emp set comm=200 where empno=7876; end if;
End; /

Declaring Variables with the %TYPE Attribute


Examples
DECLARE sname fav_boat my_fav_boat ... Accessing column sname in table Sailors Sailors.sname%TYPE; VARCHAR2(30); fav_boat%TYPE := 'Pinta'; Accessing another variable

Sample program 2
declare name emp.ename%TYPE; begin select ename into name from emp Where empno=&a; dbms_output.put_line(name); end; /

Declaring Variables with the %ROWTYPE Attribute


Declare a variable with the type of a ROW of a table.
Accessing table Reserves

reserves_record

Reserves%ROWTYPE;

And how do we access the fields in reserves_record?

reserves_record.sid:=9; Reserves_record.bid:=877;

Creating a PL/SQL Record


A record is a type of variable which we can define (like struct in C or object in Java)
DECLARE TYPE sailor_record_type IS RECORD (sname VARCHAR2(10), sid VARCHAR2(9), age NUMBER(3), rating NUMBER(3));
sailor_record sailor_record_type; ... BEGIN Sailor_record.sname:=peter; Sailor_record.age:=45;

CURSOR MANAGEMENT
A work area called private sql area is used by the Oracle server to execute SQL statements and to store processed information. PLSQL uses cursors to name the private area and to access the stored information.

Types of CURSORS
There are two types of cursors EXPLICIT CURSOR IMPLICIT CURSOR

Syntax cursor <cursor_name> is <select statement>

Creating a Cursor
We create a Cursor when we want to go over a result of a query

Syntax Example:
DECLARE cursor c is select * from sailors; sailorData sailors%ROWTYPE; BEGIN open c; fetch c into sailorData;
sailorData is a variable that can hold a ROW from the sailors table Here the first row of sailors is inserted into sailorData

Explicit cursor
The set of rows returned by the query can contain zero or multiple rows depending upon the query defined. These rows are called the active set. The cursor will point to the current row in active set. Once the cursor id defined ,we can use it using the following commands to control the cursor. OPEN it executes the query identifies the active set first row is pointed Syntax open <cursor_ name>; FETCH retrieves the current row and the next rows Syntax fetch <cursor_name> into <column_name>; CLOSE - After processing the last row in the active set-cursor is disabled Syntax Close <cursor_name>

Explicit Cursor Attributes


Obtain status information about a cursor.
Attribute %ISOPEN %NOTFOUND %FOUND Type Boolean Boolean Boolean Description Evaluates to TRUE if the cursor is open. Evaluates to TRUE if the most recent fetch does not return a row. Evaluates to TRUE if the most recent fetch returns a row; complement of %NOTFOUND Evaluates to the total number of rows returned so far.

%ROWCOUNT

Number

The following example illustrates explicit cursors.


Declare msal emp.sal%type; Cursor c1 is select sal from emp where empno =7876; begin Open c1; loop fetch c1 into msal; msal:=msal+msal*0.1; update emp set sal=msal where empno=7876; exit when c1 % notfound; dbms_output.put_line('one row updated'); end loop; close c1; end; /

Example 1- %notfound
Declare cursor c_emp is select emp_code,salary from employee where deptno=10; Str_emp_code employee.emp_code%type; Num_salary employee.salary%type; Begin open c_emp; loop fetch c_emp into str_emp_code, num_salary; exit when c_emp%notfound; Update employee set salary=num_salary+(num_salary*0.5) where emp_code=str_emp_code; Insert into emp_raise values(str_emp_code,sysdate,num_salary*0.5); End loop; Commit; Close c_emp; End; /

Declare cursor c_emp is select emp_code,salary from employee where deptno=10; Str_emp_code employee.emp_code%type; Num_salary employee.salary%type; Begin open c_emp; loop fetch c_emp into str_emp_code, num_salary; if c_emp%found then Update employee set salary=num_salary+(num_salary*0.5) where emp_code=str_emp_code; Insert into emp_raise values(str_emp_code,sysdate,num_salary*0.5); else exit; end if; End loop; Commit; Close c_emp; End; /

Example 2- %found

Example 3- %isopen
Declare cursor c_emp is select emp_code,salary from employee where deptno=10; Str_emp_code employee.emp_code%type; Num_salary employee.salary%type; Begin open c_emp; If c_emp%isopen then loop fetch c_emp into str_emp_code, num_salary; Update employee set salary=num_salary+(num_salary*0.5) where emp_code=str_emp_code; Insert into emp_raise values(str_emp_code,sysdate,num_salary*0.5); End loop; Commit; Close c_emp; Else dbms_output.put_line(unable to open the cursor); End if; End; /

Example - %rowcount display the names,dname and salary of first 5 employees


Declare Cursor c_emp is select ename,emp.deptno,sal from emp,dept where dept.deptno=emp.deptno order by sal desc; n emp.ename%type; d emp.deptno%type; s emp.sal%type; Begin open c_emp; dbms_output.put_line(name department salary); dbms_output.put_line(------------------- -------); Loop fetch c_emp into n,d,s; dbms_output.put_line(n|| ||d|| ||s); exit when c_emp%rowcount=5; End loop; End; /

Example - %isopen
Declare Cursor c4 is select ename,sal from emp where empno=7876; Begin If c4%isopen then Dbms_output.put_line('this message is not displaced'); Else Open c4; Dbms_output.put_line('cursor opened'); End if; Close c4; End; /

Example with accounts table(accno,bal)


Display the first 3 accounts having highest balance Declare Cursor c2 is select accno,bal from account order by bal desc; a accounts.accno%type; b accounts.bal%type; Begin Open c2; Loop fetch c2 into a,b; dbms_output.put_line(a|| ||b); exit when c2%rowcount=3; End loop; End; /

Example
RAD_VALS

radius
Rad_cursor

3 6 8

DECLARE Pi constant NUMBER(8,7) := 3.1415926; area NUMBER(14,2); cursor rad_cursor is select * from RAD_VALS; rad_val rad_cursor%ROWTYPE; BEGIN open rad_cursor; fetch rad_cursor into rad_val; area:=pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area); close rad_cursor; END; /

f e t c h
Rad_val

Radius 3

AREAS

Area 28.27

DECLARE cursor rad_cursor is select * from RAD_VALS; rad_val rad_cursor%ROWTYPE; BEGIN open rad_cursor; fetch rad_cursor into rad_val; area:=pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area);

DECLARE cursor rad_cursor is select * from RAD_VALS; rad_val RAD_VALS.radius%TYPE; BEGIN open rad_cursor; fetch rad_cursor into rad_val; area:=pi*power(rad_val,2); insert into AREAS values (rad_val, area);

DECLARE cursor rad_cursor is select * from RAD_VALS; rad_val RAD_VALS%ROWTYPE; BEGIN open rad_cursor; fetch rad_cursor into rad_val; area:=pi*power(rad_val.radius,2); insert into AREAS values (rad_val.radius, area);

DECLARE

cursor rad_cursor is select radius from RAD_VALS; rad_val RAD_VALS.radius%TYPE; BEGIN open rad_cursor; fetch rad_cursor into rad_val; area:=pi*power(rad_val,2); insert into AREAS values (rad_val, area);

Implicit cursor
Implicit cursor attributes can be used to access information about the most recently executed SQL statement. The most recently executed SQL statement is reffered as SQLCURSOR. The implicit cursor attributes are : %notfound %found %rowcount %isopen

1. 2. 3. 4.

%NOTFOUND: The %notfound attribute evaluate to true if DML statements do not return any row, else it evaluate to false. EXAMPLE : Begin Delete from customer where name=RAO; If sql %notfound then Dbms_output.put_line(value not found); End if; End;

%FOUND: The %found attribute is the logical opposite of the %notfound attribute. The %found attribute is evaluates to true if the SQL DML statement affects one or more rows,else it is evaluated to false. %ROWCOUNT: The %rowcount attribute counts the number of rows returned by an SQL DML statement .the %rowcount will return zero if the DML statements does not affect any row.

The following example uses the %rowcount attribute to check if the cursor fetches any rows. Declare Cursor c1 is select name from customer where repid=10; Cust_rec c1%rowtype; Begin For cus_rec in c1 Loop Update customer set name=vivek where repid =10; If sql%rowcount >0 then Dbms_output.put_line(record exists); End if; End loop; End;

SQL Impicit Cursor Attributes


SQL cursor is automatically created after each SQL query. It has 4 useful attributes:
SQL%ROWCOUNT Number of rows affected by the most recent SQL statement (an integer value).
Boolean attribute that evaluates to TRUE if the most recent SQL statement affects one or more rows.

SQL%FOUND

SQL%NOTFOUND

Boolean attribute that evaluates to TRUE if the most recent SQL statement does not affect any rows.
Always evaluates to FALSE because PL/SQL closes implicit cursors immediately after they are executed.

SQL%ISOPEN

Solution (2)
BEGIN update mylog set logon_num = logon_num + 1 where who = user; if SQL%ROWCOUNT = 0 then insert into mylog values(user, 1); end if; commit; END; /

The salary of the employees is raised by 20%. Write a pl/sql code to accept a empno and update the sal and display some message Begin Update emp set sal=sal*.02 where empno=&empno; If sql%notfound then Dbms_output.put_line(empno does not exist); else Dbms_output.put_line(record modified); End if; End;

OR

Begin Update emp set sal=sal*.02 where empno=&empno; If sql%found then Dbms_output.put_line(record modified); else Dbms_output.put_line(empno does not exist); End if; End;

The salary of the employees is raised by 20% who are clerks. Write Pl/sql code to accept empno & update sal and display some message.

Declare Rows_effected char(4); Begin Update emp set sal=sal*.02 where job=clerk; Rows_effected:=to_char(sql%rowcount); If sql%rowcount>0 then Dbms_output.put_line(rows_effected||rows updated); else Dbms_output.put_line(no employees as clerks); End if; End;

%ISOPEN: %isopen is always evaluated to false.

SELECT Statements
DECLARE v_sname VARCHAR2(10); v_rating NUMBER(3); BEGIN SELECT sname, rating INTO v_sname, v_rating FROM Sailors WHERE sid = '112'; END; / INTO clause is required. Query must return exactly one row. Otherwise, a NO_DATA_FOUND or TOO_MANY_ROWS exception is thrown

Conditional logic
Condition: Nested conditions:

If <cond> then <command> elsif <cond2> then <command2> else <command3> end if;

If <cond> then if <cond2> then <command1> end if; else <command2> end if;

IF-THEN-ELSIF Statements
. . . IF rating > 7 THEN v_message := 'You are great'; ELSIF rating >= 5 THEN v_message := 'Not bad'; ELSE v_message := 'Pretty bad'; END IF; . . .

Suppose we have the following table:


create table mylog( who varchar2(30), logon_num number ); mylog who
logon_num

Peter

Want to keep track of how many times someone logged on to the DB When running, if user is already in table, increment logon_num. Otherwise, insert user into table

John
Moshe

4
2

Solution
DECLARE cnt NUMBER; BEGIN select count(*) into cnt from mylog where who = user;

if cnt > 0 then update mylog set logon_num = logon_num + 1 where who = user; else insert into mylog values(user, 1); end if; commit; end; /

Loops: Simple Loop


create table number_table( num NUMBER(10) );

DECLARE i number_table.num%TYPE := 1; BEGIN LOOP INSERT INTO number_table VALUES(i); i := i + 1; EXIT WHEN i > 10; END LOOP; END;

Loops: Simple Cursor Loop


create table number_table( num NUMBER(10) ); DECLARE cursor c is select * from number_table; cVal c%ROWTYPE; BEGIN open c; LOOP fetch c into cVal; EXIT WHEN c%NOTFOUND; insert into doubles values(cVal.num*2); END LOOP; END;

Loops: FOR Loop


DECLARE i number_table.num%TYPE; BEGIN FOR i IN 1..10 LOOP INSERT INTO number_table VALUES(i); END LOOP; END;

Notice that i is incremented automatically

Loops: For Cursor Loops


DECLARE cursor c is select * from number_table;

BEGIN for num_row in c loop insert into doubles_table values(num_row.num*2); end loop; END; / Notice that a lot is being done implicitly: declaration of num_row, open cursor, fetch cursor, the exit condition

Loops: WHILE Loop


DECLARE TEN number:=10; i number_table.num%TYPE:=1; BEGIN WHILE i <= TEN LOOP INSERT INTO number_table VALUES(i); i := i + 1; END LOOP; END;

Printing Output
You need to use a function in the DBMS_OUTPUT package in order to print to the output If you want to see the output on the screen, you must type the following (before starting):
set serveroutput on format wrapped size 1000000

Then print using


dbms_output. put_line(your_string);

dbms_output.put(your_string);

Input and output example


set serveroutput on format wrap size 1000000 ACCEPT high PROMPT 'Enter a number: ' DECLARE i number_table.num%TYPE:=1; BEGIN dbms_output.put_line('Look Ma, I can print from PL/SQL!!!'); WHILE i <= &high LOOP INSERT INTO number_table VALUES(i); i := i + 1; END LOOP; END;

Anonymous Block Structure:


DECLARE BEGIN (optional) (mandatory)
/* Here you declare the variables you will use in this block */

/* Here you define the executable statements (what the block DOES!)*/

EXCEPTION (optional)
/* Here you define the actions that take place if an exception is thrown during the run of this block */

END; /

(mandatory)
A correct completion of a block will generate the following message: PL/SQL procedure successfully completed

Always put a new line with only a / at the end of a block! (This tells Oracle to run the block)

Concept of error handling


There are 2 types of exceptions. 1.predefined exceptions 2.user-defined exceptions

predefined exception:- predefined exceptions are raised automatically by the system during run time.
user-defined exceptions:- defined by the user

Predefined exception:- predefined exceptions are raised automatically by the system during run time. Syntax for predefined exception is as follows: Begin Sequence_of_statements; Exception When<exception name> then Sequence_of_statements; When others then /* the last exception in the exception handler*/ Sequence_of_statements; End;

Trapping Exceptions
Here we define the actions that should happen when an exception is thrown. Example Exceptions:
NO_DATA_FOUND TOO_MANY_ROWS ZERO_DIVIDE

When handling an exception, consider performing a rollback When multiple exception is raised, Only one exception is raised and handled at any time

PREDFINED EXCEPTION
No_data_found : This is raised when select statement returns no rows. Cursor_already _open : This is raised when we try to open a cursor which is already opened. Dup_val_on_index :This is raised when we insert duplicate values in a column, which is defined as unique index. Storage_error : This is raised if PL/SQL runs out of memory. Program_error : This is raised if PL/SQL has an internal problem. Zero_error : when we divide a number with zero Invalid _cursor : This is raised when we violate cursor operation. Login_denied :This is raised when we try to enter oracle using invalid user-name/password. invalid _number :This is raised if the conversion of character string to a number fails because the string does not represent a valid number. Too_many rows : returns more than one row.

Q. Accept an employee no and display the sal and an exception handler. declare mempno emp.empno%type; memp emp.sal%type; begin select sal into memp from emp where empno=&mempno; dbms_output.put_line( the salary of that empno is||memp exception when no_data_found then dbms_output.put_line('there is no employee with empno); end; /

DECLARE num_row number_table%ROWTYPE; BEGIN select * into num_row from number_table; dbms_output.put_line(1/num_row.num); EXCEPTION WHEN NO_DATA_FOUND THEN dbms_output.put_line('No data!'); WHEN TOO_MANY_ROWS THEN dbms_output.put_line('Too many!'); WHEN OTHERS THEN dbms_output.put_line(Error); end;

USER-DEFINED EXCEPTION:A user defined exceptions should be declared and raised explicitly by a raise statement.it can be declared only in the declarative part of the PL/SQL block. SYNTAX: <exception_name> exception; SYNTAX FOR RAISE STATEMENT: Raise <exception_name>;

DECLARE e_number1 EXCEPTION; cnt NUMBER; BEGIN select count(*) into cnt from number_table;

User-Defined Exception

IF cnt = 1 THEN RAISE e_number1; ELSE dbms_output.put_line(cnt); END IF; EXCEPTION WHEN e_number1 THEN dbms_output.put_line('Count = 1'); end;

declare Example User mempno emp.empno%type; Defined Exception msal emp.sal%type; mcom emp.comm%type; myexec exception; mynextexec exception; begin select sal,comm into msal,mcom from emp where empno=&mempno; dbms_output.put_line( the salary of that empno is||msal); If msal<1000 then raise myexec; elsif msal>2000 then raise mynextexec; end if; exception When myexec then dbms_output.put_line(sal is less than 1000); When mynextexec then dbms_output.put_line(sal is more than 2000); when no_data_found then dbms_output.put_line('there is no employee with empno); end; /

Functions and Procedures


Up until now, our code was in an anonymous block It was run immediately It is useful to put code in a function or procedure so it can be called several times Once we create a procedure or function in a Database, it will remain until deleted (like a

Creating Procedures
CREATE [OR REPLACE] PROCEDURE procedure_name [(parameter1 [mode1] datatype1, parameter2 [mode2] datatype2, . . .)] IS|AS PL/SQL Block; Modes:
IN: procedure must be called with a value for the parameter. Value cannot be changed OUT: procedure must be called with a variable for the parameter. Changes to the parameter are seen by the user (i.e., call by reference) IN OUT: value can be sent, and changes to the parameter are seen by the user

Default Mode is: IN

Example- what does this do?


Table mylog

who

logon_ num

Pete

John
Joe

4
2

create or replace procedure num_logged (person IN mylog.who%TYPE, num OUT mylog.logon_num%TYPE) IS BEGIN select logon_num into num from mylog where who = person; END; /

Calling the Procedure


declare howmany mylog.logon_num%TYPE; begin num_logged(John',howmany); dbms_output.put_line(howmany); end; /

Errors in a Procedure
When creating the procedure, if there are errors in its definition, they will not be shown To see the errors of a procedure called myProcedure, type
SHOW ERRORS PROCEDURE myProcedure

in the SQLPLUS prompt For functions, type


SHOW ERRORS FUNCTION myFunction

Creating a Function
Almost exactly like creating a procedure, but you supply a return type
CREATE [OR REPLACE] FUNCTION function_name [(parameter1 [mode1] datatype1, parameter2 [mode2] datatype2, . . .)] RETURN datatype IS|AS PL/SQL Block;

A Function
create or replace function rating_message(rating IN NUMBER) return VARCHAR2 NOTE THAT YOU AS DON'T SPECIFY THE BEGIN SIZE IF rating > 7 THEN return 'You are great'; ELSIF rating >= 5 THEN return 'Not bad'; ELSE return 'Pretty bad'; END IF; END; /

Calling the function


declare paulRate:=9; Begin dbms_output.put_line(ratingMessage(paulRate)); end; /

Creating a function:
create or replace function squareFunc(num in number) return number is BEGIN return num*num; End; /

Using the function: BEGIN dbms_output.put_line(squareFunc(3.5)); END; /

DATABASE TRIGGERS
A database trigger is a stored procedure that is fired when an insert, update or delete statement is issued against the associated table. Database triggers can be used for the following purposes. To generate data automatically. To enforce complex integrity constraints. To customize complex security authorizations. To maintain replicate tables. To audit data modifications.

SYNTAX: Create or replace trigger<trigger_name> [before/after] [insert/update/delete] on <table-name> [for each statement/for each row] [when <condition>]; PARTS OF TRIGGER: THERE ARE 3 PARTS OF TRIGGER: 1.TRIGGER STATEMENTS: The trigger statement specifies the DML statement like update,delete and insert and it fires the trigger body. It also specifies the table to which the trigger is associated. 2.TRIGGER BODY: It is PL/SQL block that is executed when a triggering statement is issued. 3.TRIGGER RESTRICTION: Restrictions on a trigger can be achieved using the WHEN clause.WHEN clause is evaluated for each row that is affected by the trigger.

EXAMPLE 1:
Create or replace trigger trig Before insert On emp For each row Declare eno emp.empno%type; Begin Select empno into eno from emp where deptno=10; If eno =1000 then Raise_application_error(-20001,enter some other number); End if; End;

EXAMPLE 2: Create or replace trigger sun_trig Before insert or update or delete On emp Declare enter_date char; Begin enter_date := to_char(sysdate ,dy); If enter_date in(sat,sun) then Raise_application_error(-20001,try on any weekdays); End if; End; application error_numbers is 20000 to -20999 Message is character string up to 2048 bytes of length

ENABLING AND DISABLING TRIGGERS: A triggers can be enabled or disabled. An enabled trigger executes the trigger body if the triggering statements is issued. By default, triggers are enabled. Disabled trigger does not execute the trigger body even if the triggering statements is issued.

SYNTAX: Alter trigger <trigger_name> disable;


DROPPING TRIGGER: To drop a trigger from the database, the drop trigger command is used. SYNTAX: Drop trigger<trigger_name>; >Alter table emp Disable all triggers;

EXAMPLES

Example Programs - LOOP


declare a number : = 100; begin loop a := a + 25 ; exit when a=250; dbms_output.put_line(a); end loop; end; /

Example Programs - WHILE declare i number:=0; j number := 0; begin while i<=10 loop j:=j+i; i:=i+2; dbms_output.put_line(to_char(j)); end loop; end; /

Example Programs - FOR


declare a emp.empno%type; b emp.sal%type; begin for i in 1..5 loop update emp set sal=1000 where empno=7876; select empno,sal into a,b from emp where empno=7876; dbms_output.put_line(a); dbms_output.put_line(b); end loop; end; /

Example Programs - FOR declare amt number(10,2); i number; begin amt:=2000; for i in 1..5 loop amt:=amt+100; dbms_output.put_line(amt); end loop; end; /

EXAMPLE - FOR %FOUND&%ROWCOUNT


declare Cursor c2 is select empno,ename,sal,comm from emp where deptno=10; s emp.sal%type; c emp.comm%type; e emp.empno%type; n emp.ename%type; Begin Open c2; Loop Fetch c2 into e,n,s,c; If c2%found then Dbms_output.put_line('fetches more than two rows'); Dbms_output.put_line(e||n||s||c); else Exit when c2%rowcount>2; End if; End loop; Close c2; End; /

EXAMPLE : pl/sql code for cursor for loop Declare Cursor for_cus is select name from customer where city=hyd; a for_cus%rowtype; Begin For cust_rec in fro_cur loop Delete from customer where name=readymoney; Commit; End loop; Dbms_output.put_line(name has been deleted); End;

Example :Check for the employee called rao and delete the record Declare Cursor for_emp is select ename from emp ; a for_emp%rowtype; Begin For cust_rec in for_emp loop exit when for_emp%notfound; Delete from emp where ename='rao' ; Commit; End loop; Dbms_output.put_line('name has been deleted'); End; /

DECLARE CURSOR c1 is SELECT ename, empno, sal FROM emp ORDER BY sal DESC; -- start with highest-paid employee my_ename CHAR(10); my_empno NUMBER(4); my_sal NUMBER(7,2); BEGIN OPEN c1; FOR i IN 1..5 LOOP FETCH c1 INTO my_ename, my_empno, my_sal; EXIT WHEN c1%NOTFOUND; /* in case the number requested is more than the total number of employees */ INSERT INTO temp VALUES (my_sal, my_empno, my_ename); COMMIT; END LOOP; CLOSE c1; END; /

DECLARE acct_balance NUMBER(11,2); acct CONSTANT NUMBER(4) := 3; debit_amt CONSTANT NUMBER(5,2) := 500.00; BEGIN SELECT bal INTO acct_balance FROM accounts WHERE account_id = acct FOR UPDATE OF bal; IF acct_balance >= debit_amt THEN UPDATE accounts SET bal = bal - debit_amt WHERE account_id = acct; ELSE INSERT INTO temp VALUES (acct, acct_balance, 'Insufficient funds'); -- insert account, current balance, and message END IF; COMMIT; END; /

DECLARE salary emp.sal%TYPE; mgr_num emp.mgr%TYPE; last_name emp.ename%TYPE; starting_empno CONSTANT NUMBER(4) := 7902; BEGIN SELECT sal, mgr INTO salary, mgr_num FROM emp WHERE empno = starting_empno; WHILE salary < 4000 LOOP SELECT sal, mgr, ename INTO salary, mgr_num, last_name FROM emp WHERE empno = mgr_num; END LOOP; INSERT INTO temp VALUES (NULL, salary, last_name); COMMIT; END; /

use of %ROWTYPE is allowed. (Column names in a cursor declaration

** must have aliases if they are not simple names.)


DECLARE CURSOR my_cursor IS SELECT sal + NVL(comm, 0) wages, ename FROM emp; my_rec my_cursor%ROWTYPE; BEGIN OPEN my_cursor; LOOP

FETCH my_cursor INTO my_rec;


EXIT WHEN my_cursor%NOTFOUND; IF my_rec.wages > 2000 THEN INSERT INTO temp VALUES (NULL, my_rec.wages, my_rec.ename); END IF; END LOOP; CLOSE my_cursor; END;

This block calculates the total wages (salary plus commission) paid to employees in department 20. It also determines how many of the employees have salaries higher than $2000, and how many have commissions larger than their salaries. DECLARE CURSOR emp_cursor(dnum NUMBER) IS SELECT sal, comm FROM emp WHERE deptno = dnum;

total_wages NUMBER(11,2) := 0;
high_paid NUMBER(4) := 0;

higher_comm NUMBER(4) := 0; BEGIN /* The number of iterations will equal the number of rows returned by emp_cursor */ FOR emp_record IN emp_cursor(20) LOOP

emp_record.comm := NVL(emp_record.comm, 0);


total_wages := total_wages + emp_record.sal + emp_record.comm;

IF emp_record.sal > 2000.00 THEN

high_paid := high_paid + 1;
END IF; IF emp_record.comm > emp_record.sal THEN higher_comm := higher_comm + 1; END IF; END LOOP; INSERT INTO temp VALUES (high_paid, higher_comm, 'Total Wages: ' || TO_CHAR(total_wages)); COMMIT; END;

Write a pl/sql code to accept account number and print the name and balance of account holder. Tablename:bank ACCNO NAME 101 Renuka 102 madhu

BAL 5000 2000

Declare a number(3); b number(7,2); m varchar(10); Begin Select name,bal into m,b from bank where accno=&a; Dbms_output.put_line(m||b); End;

PROGRAM2: Write a pl/sql code accept accno, ttype and amount as inputs from the user to update balance and to print everything. TABLENAME:BANK ACCNO NAME BAL 101 renu 6000 102 satya 6000 103 madhu 7000 Declare a bank.accno%type; n bank.name%type; b bank.bal%type; ttype varchar(1); amt number(7,2); begin a:=&a ; select name,bal into n,b from bank where accno=a;

ttype:=&ttype; amt:=amt; if ttype=c then update bank set bal=b+amt where accno=a;

elsif
ttype=d then update bank set bal=b-amt where accno=a; else dbms_output.put_line(invalid transaction); end if; dbms_output.put_line(a|| ||n||||b); end;

PROGRAM NO 3Write a pl/sql code to take a customer number as input and update his due amount with 5% interest TABLE NAME:CUSTOMER
CODE 1 2 3 NAME Anu Aryani Madhu DAMT 5000 1000 900

Declare c customer.code%type; n customer.name%type; d customer.damt%type; Begin C:=&c; Select name,damt into m,d from customer where code=c; Update customer set damt=damt+dmt*0.05 where code=c; Dbms_output.put_line(c|| ||m|| ||d); End;

PROGRAM NO:4 Write a PL/SQL code to accept code as input from the user,check for the due amt.if the due amount is zero delete the record from the table.
TABLENAME:CUST CODE NAME 101 A 102 B 103 C DAMT 700 700 800

Declare a cust.code%type; b cust.damt%type; Begin a:=&a; select damt into b from cust where code=a ; if b=0 then delete from cust where code=a; else dbms_output.put_line(damt is not zero); end if; end;

PROGRAM NO.5 Write a PL/SQL code to accept a customer code as input check for the due amount,if the due amount is zero,delete the record from the table.use procedure for the above progrram.
TABLE NAME:CUSTOMER CODE NAME 101 divya 102 eistein 103 fathima DAMT 580 790 0

Declare

Begin c:=&c; Select damt ,name into d,m from customer where code=c; If d=0 then Goto dele; Else Dbms_output.put_line(damt is not zero); Endif; <<dele>> delete from customer where code=c; end;

c customer.code%type; m customer.name%type; d customer.damt%type;

PROGRAM NO.6 Write a PL/SQL code to accept a student no. and give them a grace of 10 marks,if his total is in between 250 and 255.
TABLE NAME:STUDENT SNO NAME TOT 101 Anu 250 102 ARYU 245 103 CLINTON 255

Declare r student.sno%type; m student.name%type; t student.tot%type; begin r:=&r; select name,tot into m,t from student where rno=r; if t>=250 and t<=255 then update student set tot=tot+10 where sno=r; endif; end;

PROGRAM 7 Write a pl/sql code to add 10 grace marks to every student who secured total marks between 250 & 255
TABLENAME: student RNO NAME 101 a 102 b 103 c TOTAL 260 245 279

Declare r stud.r no%type; n stud.name%type t stud.total%type; begin update student set total=total+10 where total>=250 and total>=255; end;

PROGRAM 8 Write a pl/sql code to read a record from a table and store the rows in the second table
TABLENAME: student RNO NAME 101 a 102 b 103 c TABLENAME:TEMP RNO NAME TOTAL 260 245 279 TOTAL

Declare r student.rno %type; n student.name%type; t student.total%type; begin r:=&r; select name, total into n,t from student where rno=r; insert into temp values(r,n,t); end;

PROGRAM NO9 : Create a student table with rno and name. Create a marks table with rno,marks and total. Write a pl/sql code to accept rno and display name,marks and total. TABLENAME:student RNO NAME TABLENAME:MARKS RNO M1 M2 M3 TOTAL 101 40 50 35 125 Declare r student.rno%type; n student.name%type; a marks.m1%type; b marks.m2%type; c marks.m3%type; t marks.total%type; begin r:=&r; select name,m1,m2,m3,total into n,a,b,c,t from student,marks where student.rno=r and marks.rno=r; dbms_output_put_line(n||||a||||b||||c||||t); end;

PROGRAM 10 Write pl/sql code to calculate interest on due amount for a particular candidate and add the amount to due amount for that customer interest is calculated. Damt interest >=10000 5% >=5000 2.5% >=2500 1.25% else 0.25% TABLENAME CUSTOMER CODE NAME DAMT 101 a 1000 102 b 4000 103 c 6000 104 d 7000

Declare c customer.code%type; d customer.damt%type; begin c:=&c; select damt into d from customer where code=c; if d>=10000 then update customer set damt=d+a*5/100 where code=c; elsif d>=5000 then update customer set damt=d+a*2.5/100 where code=c; elsif d>=2500 then update customer set damt=d+a*1.25/100 where code=c; else update customer set damt=d+a*0.25/100 where code=c;] end if; end;

PROGRAM 11 Write a pl/sql code using pre-defined exception to accept accno as input from the user and display bal on the screen. Raise two exception when data not found and too many rows. TABLENAME BANK ACCNO NAME 101 A 102 B 103 C 104 D

BAL
600 700 800 600

Declare a bank.accno%type; b bank.bal%type; n bank.name%type; begin a:=&a; select name, bal into n,b from bank where accno=a; dbms_output.put_line(n||||b); Exception When no_data_found then Dbms_output.put_line(record not found); When too_many_rows then Dbms_output.put_line(too many rows); End;

PROGRAM 12 Write a pl/sql code using user defined exception to accept accno as input from the user and print the bal on the screen Raise an exception if bal is zero or bal is null;

TABLE NAME BANK


ACCNO NAME BAL

101 102 103 104

A B C D

0 2000 4000

Declare a bank.accno%type; b bank.bal%type; n bank.name%type; begin a:=&a; select name,bal into b,n from bank where accno=a; if b==0 or b is null then raise e; else dbms_output.put_line(n||||b); end if; exception when e then dbms_output.put_line(no bal exist); end;

PROGRAM 13 Write a pl/sql code to accept accno and amt as input from the user. If ttype=c update bal with amount. If ttype=d update bal=bal-amt. Raise an exception if ttype as null; TABLE NAME BANK

ACCNO 101 102 103

NAME A B C

BAL 4000 5000 5000

TTYPE D C NULL

Declare t bank.ttype%type; a bank.accno%type; b bank.bal%type; n bank.name%type; amt number(7,2); e exception; begin a:=&a; amt:=&amt; select name,bal,ttype into n,b,t from bank where accno=a; if t=c then update bank set bal=bal+amt where accno=a; elsif t=d then update bank set bal=bal-amt where accno=a; elsif t=null then raise e; end if; exception when e then dbms_output.put_line(ttype is null); end;

PROGRAM 14
Write a pl/sql code to explain the use of predefined exception

TABLENAME BANK ACCNO NAME 201 A 202 B 203 C

BAL 5000 6000 7000

Declare

m bank.accno%type;
b bank.bal%type; begin m:=&m; select bal into b from bank where accno=m; dbms_output.put_line(b); exception

when no_data_found then


dbms_output.put_line(not found); end;

PROGRAM 15

Write a pl/sql code to explain the use of predefined exceptions


TABLENAME BANK ACCNO NAME 101 102 103 104

BAL A B D E 5000 6000 5000 1000

PROGRAM m bank.accno%type; b bank.bal%type; begin m:=&m; select bal into b from bank where accno=m; dbms_output.put_line(b); exception when no_data_found then dbms_output.put_line(not found); end; OUTPUT SQL>sta p5 Enter value for m:204 Not found

PROGRAM 16 Write a pl/sql code to fire a trigger before deletion. The user should not be allowed to delete the record if bal=1000 TABLE NAME BANK ACCNO NAME BAL 100 A 2000 101 B 5000 102 V 1000 PROGRAM Create or replace trigger trig4 before delete on bank Declare b bank.bl%type; begin select bal into b from bank where accno=101; if b=1000 then raise_application_error(-2000,DELETION NOT POSIBLE); end if; end; OUTPUT SQL>sta renu Trigger created

PROGRAM 17 Write a pl/sql code to fire a trigger before insertion. The user should not be allowed to insert any record on Wednesday. PROGRAM Create or replace trigger trig1 before insert on bank Declare S varchar(3); Begin S:=to_char(sysdate,dd); If s=wed then
Raise_application_error(-20020,insertion is not possible on wed);

End if; End;

PROGRAM 18 Write a pl/sql code to update balance with 30% interest using cursors. TABLENAME BANK ACCNO NAME BAL 100 A 2000 101 B 4000 102 CV 6000 Declare b bank.bal%type; n bank.name%type; a bank.accno%type; cursor c1 is select bal from bank where accno=101; begin open c1; loop fetch c1 into b; exit when c1% notfound; if c1% found then update bank set bal=b*30/100 +b where accno=101; dbms_output.put_line(record update); end if; end loop; close c1; end;

PROGRAM 19 Write a pl/sql code to display record using cursors and display appropriate message for records found and not found TABLENAME BANK ACCNO NAME BAL 100 A 2000 101 B 4000 102 CV 6000

Declare
b bank.bal%type; n bank.name%type; a bank.accno%type; cursor c1 is select bal from bank where accno=101;

begin
open c1; loop; fetch c1 into b; exit when c1%notfound; if c1%found then dbms_output.put_line(record found); end if; end loop; close c1;

PROGRAM 20 Write a pl/sql code with cursors to update damt with 5% interest and display message if not found
TABLENAME CUSTOMER CODE 100 101 102 103 NAME A B C D DAMT 500 600 700 500

Declare

begin

d customer.damt%type; c customer.code%type; n customer.name%type; cusor c3 is select damt,name from customer where code=100; open c3; loop fetch c3 into d,n; exit when c3% not found; update customer set damt = damt * 5/100 + damt where code100; dbms_output.put_line(d||||n); end loop; close c3;

end;

PROGRAM 21 Write a pl/sql code with implicit cursors to accept the accno and amount from the user and update the table. Display appropriate messages for found and not found. Display the updated bal on the screen.
TABLENAME BANK ACCNO 100 101 102 NAME A B CV BAL 2000 4000 6000

Declare a number(5); b number(7,2); amt number(7,2); begin

amt:=&amt; a:=&a; update bank set bal=bal+amt where accno=a; if sql%notfound then dbms_ouput.put_line(not found); else select bal into b from bank where accno=a; dbms_output.put_line(record found||b); end if;
end;

Practice Sheet - JOINS


1. Display employee names, department number and department names for all departments including the department in which no employee is currently working. Display all rows in the EMP table, which is the left table even if there is no match in the DEPT table. (left outer join) Display all rows in the DEPT table, which is the right table even if there is no match in the EMP table. (right outer join) Display all rows in the EMP table, even if there is no match in the DEPT table. It also retrieves all rows in the DEPT table, even if there is no match in the EMP table. Display the employee last name and employee number along with their managers last name and manager number. (self join) Display all employees including King, who has no manager. Order the results by the employee number. Create a query that displays employee last names, department numbers, and all the employees who work in the same department as a given employee. Give each column an appropriate label.

2. 3. 4.

5. 6. 7.

Practice Sheet PL/SQL/Cursor/Triggers/Procedure


1.
2.

3. 4. 5. 6.

Create a PL/SQL block that selects the maximum department no fro DEPT table and store it in a variable. Print the output on the screen. Create a PL/SQL block that computes the commission amount for a given employee based on the employee salary. Accept the employee number as user input. If sal <1000 then comm = 10% of sal, if sal >=1000 and sal <= 1500 then comm = 15% of sal, if sal >1500 then comm = 20% of sal. Update the emp table with new commission amount for the employee. Write a pl/sql code to display record of employees 1000 and 1001 using cursors and display appropriate message for record found and not found. Write a pl/sql code to fire a trigger before insertion of a record in EMP table. The user should not be allowed to insert any record on Wednesday. Write a pl/sql code to fire a trigger before deletion of a record from EMP table. The user should not be allowed to delete the record if salary=1000 Write a PL/SQL procedure that accepts the salary of employee from the user and add Rs. 2000 /- to the salary of all employees having salary less than the entered salary.

Potrebbero piacerti anche