You are on page 1of 19

PL/SQL

Difference between SQL and PLSQL


SQL PLSQL
1) SQL is a structured query language 1) PLSQL is a programming language
2) SQL is not support to control structure 2) PLSQL is support to consist control structure
(if condition & loops) 3) PLSQL is a group of operations
3) SQL performs single operation 4) PLSQL cant be embedded in sql
4) SQL can be embedded in pl/sql 5) SQL directly interact with data base server
5) SQL directly interact with data base server 6) PLSQL is application oriented language
6) SQL is data oriented language

PLSQL Definition
PLSQL is a procedural language designed specifically to embrace SQL statements with in its syntax.
Or
In oracle database management PLSQL is a procedural language extension to structured query
language(SQL)

PLSQL select statement


DBMS_OUTPUT.PUT_LINE;
DBMS_OUTPUT=package name
Select column list into variable list from table name where condition.

PLSQL print statement


DBMS_OUTPUT.PUT_LINE;
DBMS_OUTPUT=package name
PUT_LINE=procedure name

Anonymous block/plsql block(un name block)


 A block without name is an anonymous block
 Anonymous blocks is not saved in the oracle database server
 It is just for one time use
 Anonymous blocks can be used for testing purpose

PLSQL block structure


DECLARE
<Declaration section> ----------->(optional)
----variable,cursors,constants,types,exceptions------
BEGIN
<executable command>-------->(mandatory)
SQL statements,PLSQL statements
EXCEPTION
<exception handling>-------->(optional)
END;
------------>(mandatory)

Output:-SET SERVEROUTPUT ON;

EXAMPLE:-
DECLARE
Message varchar2(20):=’Hello world’;
BEGIN
DBMS_OUTPUT.PUT_LINE(message);
END;

NOTE:
:=Assignment operator
|| concatenation operator
; Statement terminator
PLSQL comments
 PLSQL supports single line and multi line comments
 Comments are ignored by the PLSQL compiler
 Single line comments start with the eclimiler(--)double hypen
 Multi line comments enclosed /* */

EXAMPLE:-
DECLARE
--Variable declaration
Message varchar2(20):=’Hello world’;
BEGIN
/* PLSQL executable statement */
DBMS_OUTPUT.PUT_LINE(message);
END;

PLSQL program units:


1) PLSQL blocks
2) Procedure
3) Function
4) Package specification
5) Package body
6) Type
7) Type body
8) Trigger

PLSQL data types:


It stores only one value

i) Numeric data types


 Number
 Pls_integer
 Binary_integer
ii) Boolean data types
Boolean data type has three data values
 True
 False
 Null
iii) Character data types
 Char
 Varchar2
 Long
 Long raw
 Row id
 Raw

Char(size)
Char (size) is fixed character type
Min=1 byte
Max=32,767 bytes

Varchar2(size)
Varchar2 size is variable length character data from
1 byte to 32,767 bytes

Date-time data type


Formate DD-MMM-YY
Maximum size 7 bytes

LOB-Large object data type(LOB)


Large object(LOB) data type refer to large data items such as text,graphic,images,video clips and sound
wave forms.

Datatype size
B file 4 GB
B LOB 8 to 128 TB
C LOB 8 to 128 TB
N LOB 8 to 128 TB

N CLOB=National Character large object

CONTROL STATEMENT
Conditional control:
Syntax:
IF< condition> then
<Action>
ELS IF <condition> then
<Action>
ELSE <Action>
End if;

EXAMPLE:-
Declare
A number (4):=5000;
Begin
If (a<100) then
DBMS_OUTPUT.PUT_LINE(‘A is less than 100’);
Else
DBMS_OUTPUT.PUT_LINE(‘A is greater than 100’);
Endif;
DBMS_OUTPUT.PUT_LINE(‘value A is=100’);
End;

RESULT
A is greater than 100
Value of A is =5000

EXAMPLE:-
Create table student(stuid number,
Sname varchar2 (20),
SAdd varchar2 (20),
Smarks number);
BEGIN
Insert into student values(1,’chiru’,’chittoor’,30);
Insert into student values(2,’raghu’,’pileru’,10);
Insert into student values(3,’anand’,’madanapalli’,20);
Insert into student values(4,’arun’,’tirupati’,40);
Insert into student values(5,’chanu’,’renigunta’,50);
Insert into student values(6,’rohan’,’kalahasti’,60);
Commit;
End;
/

CASE STATEMENT
Declare
Grade char(1):=’A’;
Begin
CASE grade
When ‘A’ then dbms_output.put_line(‘excellent’);
When ‘B’ then dbms_output.put_line(‘very good’);
When ‘C’ then dbms_output.put_line(‘good’);
When ‘D’ then dbms_output.put_line(‘avg’);
When ‘E’ then dbms_output.put_line(‘pass with grade’);
Else dbms_output.put_line(‘failed’);
End case;
End;

LOOP: loops are used to repeat the execution of one or more statements for specified number of
times.

Typer of PLSQL loops:


There are four types of loops are there
Simple loop
While loop
For loop
Cursor loop

Note:
Loops are used to repeat the execuation of one (or) more statements for specified number of times.

a) Simple loop:-
Basic loop structure enclosed sequence of statements in between the loop and end loop.

Syntax:
Loop This loop is also called as infinite loop. Here body
Sequence of statement; of the loop statements are executed repeatedly.
End loop;

Or
Loop
Statement;
End loop;

Or
Exit when condition
End loop;

EXAMPLE:-
DECLARE
i number := 1;
BEGIN
loop
exit when i > 10;
dbms_output.put_line(i);
i := i+1;
end loop;
END;

OUTPUT:
1
2
3
4
5
6
7
8
9
10
EXAMPLE:-
DECLARE
var1 number;
var2 number;
BEGIN
var1:=100;
var2:=1;
loop
dbms_output.put_line(var1*var2);
if(var2=10)
then
exit;
end if;
var2:=var2+1;
end loop;
end;
/

OUTPUT:
100
200
300
400
500
600
700
800
900
1000

b) While loop
While loop is used when a set of statements has to be executed as long as a condition is true. The while
loop is used .
WHILE (condition) Here body of the loop statements are executed
Loop repeatedly until condition is false. In
Statement; “while loop“ whenever condition is true then
End loop; only loop body is executed

EXAMPLE:-
DECLARE
i number := 1;
BEGIN
while (i <= 10)
loop
dbms_output.put_line(i);
i := i+1;
end loop;
END;
/
OUTPUT:
1
2
3
4
5
6
7
8
9
10
EXAMPLE:-
DECLARE
var1 number;
var2 number;
BEGIN
var1:=200;
var2:=1;
while (var2 <10)
loop
dbms_output.put_line(var1 * var2);
var2 := var2+1;
end loop;
END;
/
OUTPUT:
200
400
600
800
1000
1200
1400
1600
1800

EXAMPLE:-
DECLARE
var1 number;
var2 number;
BEGIN
var1:=100;
var2:=1;
while (var1 <110)
loop
dbms_output.put_line(var1 * var2);
var1 := var1+1;
end loop;
END;
OUTPUT:
100
101
102
103
104
105
106
107
108
109

c) FORLOOP: in oracle the for loop allows youto execute code repeatedly fro a fixed number of
times
For (variable in initial value to final value) Initial (lower bound)value to final(upper
Loop bound)value
Statement; For index name in lower bound to upper bound
End loop;
-->initial_value: starts in integer value -->final_value:end integer valu

EXAMPLE:-
DECLARE
k number(10);
BEGIN
for k in 1..10
loop
dbms_output.put_line(k);
end loop;
END;
OUTPUT:
1
2
3
4
5
6
7
8
9
10

EXAMPLE:-
DECLARE
var1 number;
BEGIN
var1:=10;
for var2 in 1..10
loop
dbms_output.put_line(var1 * var2);
end loop;
END;
OUTPUT:
10
20
30
40
50
60
70
80
90
100

EXAMPLE:-
DECLARE
var1 number;
BEGIN
var1:=10;
for var2 in reverse 1..10
loop
dbms_output.put_line(var1 * var2);
end loop;
END;
OUTPUT:
100
90
80
70
60
50
40
30
20
10

GOTO Statement:
Lable_name
Goto table_name;
--------------------
--------------------
<<lable_name>>
Statement;

EXAMPLE:-
DECLARE
a number(2) := 10;
BEGIN
<<loopstart>>
-- while loop execution
WHILE a < 20 LOOP
dbms_output.put_line ('value of a: ' || a);
a := a + 1;
IF a = 15 THEN
a := a + 1;
GOTO loopstart;
END IF;
END LOOP;
END;
/
OUTPUT:
value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 16
value of a: 17
value of a: 18
value of a: 19

PLSQL Variables:

 If need to declare the variable first in the declaration section of a PLSQL block before using it.
 By default variable names are not case sensitive. A reserved PLSQL keyword

Syntax:
Variable_name [constant] data type [not null]
:=[default initial value]

Initialized variable:-
 The default keyword
 The assignment operator

EXAMPLE:-
DECLARE
a integer := 10;
b integer := 20;
c integer;
f real;
BEGIN
c := a + b;
dbms_output.put_line('Value of c: ' || c);
f := 70.0/3.0;
dbms_output.put_line('Value of f: ' || f);
END;
/
OUTPUT:
Value of c: 30
Value of f: 23.33333333333333333333333333333333333333

Variable scope:
Local variable:- local variable are the inner block variables which are not accessible to outer block.
Global variable:- global variable are declared in outer most block

EXAMPLE:-
DECLARE
-- Global variables
num1 number := 95;
num2 number := 85;
BEGIN
dbms_output.put_line('Outer Variable num1: ' || num1);
dbms_output.put_line('Outer Variable num2: ' || num2);
DECLARE
-- Local variables
num1 number := 195;
num2 number := 185;
BEGIN
dbms_output.put_line('Inner Variable num1: ' || num1);
dbms_output.put_line('Inner Variable num2: ' || num2);
END;
END;
/
OUTPUT:
Outer Variable num1: 95
Outer Variable num2: 85
Inner Variable num1: 195
Inner Variable num2: 185

CONSTANT:
Constant name: The constant word is a reserved word and its value doesnot change.

Syntax:
Variable name constant datatype:=value;

EXAMPLE:-
DECLARE
pi constant number := 3.141592654;
PLSQL select into:
SELECT column name into variable name from the table name where condition;

Selecting one column example:-


DECLARE
r_customer customers%ROWTYPE;
BEGIN
-- get the information of the customer 100
SELECT * INTO r_customer
FROM customers
WHERE customer_id = 100;
-- show the customer info
dbms_output.put_line( r_customer.name || ', website: ' || r_customer.website );
END;

%Type
%type is used to declare a field with the same types as that of a specified table column these in
specified column datatype in table

EXAMPLE:-
DECLARE
v_employeename employee.name%TYPE;
BEGIN
select name
into
v_employeename from emp%rowtype;
BEGIN
select employee * into employee form emp E where row number=1;
dbms_output.put_line(employee.emp employee.ename);
end;
/

%Row type
This is entire record datatype in the table

EXAMPLE:-
DECLARE
Employee %rowtype;
BEGIN
Select emp * into employee from emp e where rowno=1;
dbms_output.put_line(r employee.emp employee.ename);
end;
/

LITERALS
1) Character Literals:
‘A’
‘%’
‘q’
‘z’
‘c’
2) String Literals:
‘Hello World’
‘Tutorials point’
‘19-NOV-22’
EXAMPLE:-
DECLARE
Message varchar2(20):=’that is tutorials pointcom’;
BEGIN
dbms_output.put_line(message);
end;
/
EXAMPLE:-
write a pl sql block of code that first withdraws an amount of RS 1000 then deposits an amount of RS
1,40,000 update the current balance.then check to see that the current balance of all accounts in the
bank does not exceed RS 2,00,000.if the balance exceeds RS 2,00,000 then undo the deposit just the
made.
DECLARE
mBAL NUMBER(8,2);
BEGIN
/*insert a record into TRANSMSTR for withdrawls */
INSERT INTO TRANSMSTR (TRANSNO,
ACCTNO,DT,TYPE,TDETAILS,DR_CR,AMT,BALANCE);
VALUES('T100','SB10','07-OCT-10','W','MOBILE BILL','W',1000,30000);
/* Update the current balance of this account no, in the ACCTMSTR tablr */
UPDATE ACCTMSTR
SET CURBAL=CURBAL-1000
WHERE ACCTNO='SB10';
/* Define a savepoint */
SAVEPOINT no_update;
/* insert a record into transactionmaster for deposits */
INSERT INTO TRANSMATR
(TRANSNO,ACCTNO,DT,TYPE,TDETAILS,DR_CR,AMT,BALANCE);
VALUES('T101','SB10','07-COT-10','C','DEPOSIT','D',14000,171000);
/* Update the current balance of account no SB10 in the ACCTMSTR tablr */
UPDATE ACCTMSTR
SET CURBAL=CURBAL+140000
WHERE ACCTNO='SB10';
/* store the total current balance from the ACCTMSTR table into a variable */
SELECT SUM(SURBAL) INTO mBAL From acctmstr;
/* Now check if the current balance exceeds 200000 */
IF mBAL>200000 THEN
/* undo the changes made to the transaction master table */
ROLLBACK TO SAVEPOINT no_update:
END IF;
*/make the changes permanent */
COMMIT;
END;

CURSOR
 Cursor is a private SQL area.
 A cursor is a pointer to the context area used by the oracle engine for executing SQL statements.
 In PLSQL database systems having two types of cursors
1) IMPLICIT CURSOR
2) EXPLICIT CURSOR
3) CURSOR FORLOOP
1) IMPLICIT CURSOR: The cursors which is automatically created,maintained and closed by the
engine.while execution of any DML commands like’DELETE,UPDATE,INSERT’ are called implicit
cursor are controlled by oracle server.
ATTRIBUTES DESCRIPTION
1 SQL%FOUND It returns value is true, if DML statements like
INSERT,UPDATE,DELETE effect at least one
row or more rows or select into statement one
rows other wise it returns false
2 SQL%NOT FOUND It returns value is true. If DML statements like
INSERT,UPDATE,DELETE effect no rows of a
select into statement returns no rows other wise if
returns false.it is just opposite of SQL%found
3 SQL% NOT FOUND It always return false for implicit cursor. Because
the SQL cursor is automatically closed after
existing associates SQL statement
4 SQL% ROW COUNT It returns the no of rows affected by DML
statements like INSERT,UPDATE,DELETE or
returned by a select into statement.
EXAMPLE:-
DECLARE
total_rows number;
BEGIN
update emp set sal = sal + 2000;
if sql%notfound then
dbms_output.put_line('NO CUSTOMERS UPDATED');
elsif sql%found then
total_rows := sql%rowcount;
dbms_output.put_line(total_rows||'CUSTOMERS UPDATED');
end if;
END;
OUTPUT:
15CUSTOMERS UPDATED

EXAMPLE:-
BEGIN
update emp set comm = comm where empno=7654;
if sql%notfound then
dbms_output.put_line('EMPLOYEE SUCESSFULLY TRANSFERED');
end if;
if sql%found then
dbms_output.put_line('EMPLOYEE NUMBER DOESNOT EXISTS');
end if;
END;
OUTPUT:
EMPLOYEE NUMBER DOESNOT EXISTS

EXAMPLE:-
DECLARE
rows_affected number;
BEGIN
update emp set status='A' where status='B'
and branch_no in(select empno from deptno where name='king')
rows_affected:=to_char sql%rowcount;
if sql%rowcount>0 then
dbms_output.put_line('rows_affected' || allows activated sucessfully);
else
dbms_output.put_line(currently there list no in active account in leving:empno);
end if;
END;

2) EXPLICIT CURSOR:

 SQL statements return multiple records is called explicit cursor and also this is an record by
record process
 Explicit cursor memory area is called also active set area

LIFE CYCLE OF THE EXPLICIT CURSOR


 DECLARING THE CURSOR
 OPENING CURSOR
 FETCHING DATA FROM THE CURSOR
 CLOSING THE CURSOR

Syntax:
DECLARE
CURSOR <cursor_name> IS <SELECT statement^>
<cursor_variable declaration>
BEGIN
OPEN <cursor_name>;
FETCH <cursor_name> INTO <cursor_variable>;
------------------
------------------
CLOSE <cursor_name>;
END;
CURSOR ATTRIBUTES
CURSOR ATTRIBUTES DESCRIPTION
1 CURSOR NAME%FOUND It returns the true, fetch at least one record
successfully, else it will return FALSE
2 CURSOR NAME%NOT FOUND It will return TRUE if fetched operations could
not able to fetch any record.
3 CURSOR NAME% NOT FOUND It returns TRUE if the given cursor is already
open,els if it returns FALSE
4 CURSOR NAME% ROW COUNT It returns the number of records fetched from the
cursor.

EXAMPLE:-
DECLARE
CURSOR guru99_det IS SELECT emp_name FROM emp;
lv_emp_name emp.emp_name%type;

BEGIN
OPEN guru99_det;

LOOP
FETCH guru99_det INTO lv_emp_name;
IF guru99_det%NOTFOUND
THEN
EXIT;
END IF;
Dbms_output.put_line(‘Employee Fetched:‘||lv_emp_name);
END LOOP;
Dbms_output.put_line(‘Total rows fetched is‘||guru99_det%R0WCOUNT);
CLOSE guru99_det;
END:
/
OUTPUT:
Employee Fetched:BBB
Employee Fetched:XXX
Employee Fetched:YYY
Total rows fetched is 3
EXAMPLE:-
DECLARE
c_id customers.id%type;
c_name customer.name%type;
c_addr customers.address%type;
CURSOR c_customers is
SELECT id, name, address FROM customers;
BEGIN
OPEN c_customers;
LOOP
FETCH c_customers into c_id, c_name, c_addr;
EXIT WHEN c_customers%notfound;
dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);
END LOOP;
CLOSE c_customers;
END;
/
OUTPUT:
1 ramesh ahmedabad
2 ashok tirupati
3 kumar skht
4 muni chennai
5 ramu banglore
6 rani sec
7 sanju tml
8 manoj hyd
9 anu mpl
9 anu mpl

EXAMPLE:-
declare
cursor c1 is select * from emp;
i emp%rowtype;
begin
open c1;
loop
fetch c1 into i;
exit when c1%notfound;
dbms_output.put_line(i.empno||' '||i.ename||' '||i.deptno);
end loop;
open c1;
end;
/
OUTPUT:
declare
cursor c1 is select * from emp;
i emp%rowtype;
begin
open c1;
loop
fetch c1 into i;
exit when c1%notfound;
dbms_output.put_line(i.empno||' '||i.ename||' '||i.deptno);
end loop;
open c1;
end;
/
3) CURSOR FORLOOP:
Using cursor for loops we are eliminating explicit life cycle here we are no need to open,fetch,close
statement explicitly. When ever we are using cursor for loop internally oracle server only open the
cursor fetch the data for the cursor and close the cursor automatically.
Or
The cursor variable opening of cursor,fetching and closing of the cursor will be done implicitly by the
for loop.

Syntax:
DECLARE
CURSOR <cursor_name> IS <SELECT statement^>
<cursor_variable declaration>
BEGIN
OPEN <cursor_name>;
FETCH <cursor_name> INTO <cursor_variable>;
.
.
CLOSE <cursor_name>;
END;
NOTE:
In cursor for loop index variable,internally be laves like a record type variable(%rowtype)

EXAMPLE:-
write a pl/sql cursor program to display are employee name and their salary from emp by using cursor
for loop

DECLARE
CURSOR C1 IS SELECT * FROM emp;
BEGIN
FOR I IN C1
LOOP
Dbms_output.put_line(I.ename||' '||I.sal);
END LOOP;
END;
/
OUTPUT:
KING 5000
BLAKE 2850
CLARK 2450
JONES 2975
SCOTT 3000
FORD 3000
SMITH 800
ALLEN 1600
WARD 1250
MARTIN 1250
TURNER 1500
ADAMS 1100
JAMES 950
MILLER 1300
govinda 5000

EXAMPLE:-
write a pl/sql cursor program to display 5th record from emp by using cursor for loop

DECLARE
CURSOR C1 IS SELECT * FROM emp;
BEGIN
FOR I IN C1
LOOP
if c1 %rowcount=5
then
Dbms_output.put_line(I.ename||' '||I.sal);
end if;
END LOOP;
END;
/
OUTPUT:
SCOTT 3000

EXAMPLE:-
write a pl/sql cursor program to display total salary from emp table.

DECLARE
CURSOR C1 IS SELECT sum(sal) total_sal FROM emp;
v_total number;
BEGIN
open C1;
LOOP
fetch C1 into v_total;
Dbms_output.put_line('total_sal is'||' '||v_total);
END LOOP;
close C1;
END;
/

EXAMPLE:-
Write a plsql cursor program to update salary of the employee in emp table based on following
condition
1) if job=’clerk’ then increment_sal>100;
2) If job=’salesman’then decrement_sal>200;

declare
cursor c1 is select * from emp;
i emp%rowtype;
begin
open c1;
loop
fetch c1 into i;
exit when c1%notfound;
if i.job='CLERK' then
update emp set sal=sal+100
where empno=i.empno;
elsif i.job='SALESMAN' then
update emp set sal=sal-200
where empno=i.empno;
end if;
end loop;
close c1;
end;
/

IMPLICT CURSOR:
PLSQL select statement writing single record is called IMPLICT CURSOR.

EXAMPLE:-
declare
v_ename varchar2(20);
v_sal number(10);
begin
select ename, sal into v_ename, v_sal from emp where empno= &empno;
dbms_output.put_line(v_ename||' '||v_sal);
end;
/
OUTPUT:
Enter value for empno: 7788
old 5: select ename, sal into v_ename, v_sal from emp where empno= &empno;
new 5: select ename, sal into v_ename, v_sal from emp where empno= 7788;
SCOTT 3000

EXAMPLE:-
begin
delete from emp where ename=’welcome’;
if sql%found then
dbms_output.put_line('your record deleted');
elsif sql%notfound then
dbms_output.put_line('your record input does not exist');
endif;
end;
/

EXAMPLE:-
begin
update emp set sal=sal+100 where job='clerk';
dbms_output.put_line('affected number of clerks are' || sql%rowcount);
end;
/

1) %ROWCOUNT:
This attribute always returns number datatype row count noof records fetched from the cursor;

Syntax
Cursor name %rowcount;

EXAMPLE:-
declare
cursor c1 is select ename, sal from emp;
v_ename varchar2(10);
v_sal number(10);
begin
open c1;
loop
fetch c1 into v_ename, v_sal;
exit when c1%notfound;
dbms_output.put_line(v_ename||' '||v_sal);
end loop;
dbms_output.put_line('number of records fetch from the cursors' || C1%rowcount);
close c1;
end;
/
OUTPUT:
KING 5000
BLAKE 2850
CLARK 2450
JONES 2975
SCOTT 3000
FORD 3000
SMITH 1000
ALLEN 1200
WARD 850
MARTIN 850
TURNER 1100
ADAMS 1300
JAMES 1150
MILLER 1500
govinda 5000
number of records fetch from the cursors15

2) %IS OPEN:
This attribute also return either true or false this attribute returns true when cursor already open. If
returns false when cursor is not open.

Syntax
Cursor name %is open;

EXAMPLE:-
declare
cursor c1 is select * from emp;
i emp%rowtype;
begin
if not c1%isopen then
open c1;
end if;
loop
fetch c1 into i;
exit when c1%notfound;
dbms_output.put_line(i.ename||' '||i.sal);
end loop;
close c1;
end;
/
OUTPUT:
KING 5000
BLAKE 2850
CLARK 2450
JONES 2975
SCOTT 3000
FORD 3000
SMITH 1000
ALLEN 1200
WARD 850
MARTIN 850
TURNER 1100
ADAMS 1300
JAMES 1150
MILLER 1500
govinda 5000

3) %found:

Syntax
Cursor name %found;

EXAMPLE:-
declare
cursor c1 is select * from emp where ename='@ename';
i emp%rowtype;
begin
open c1;
fetch c1 into I;
if c1%found then
dbms_output.put_line(' your employee exist'||' '||i.ename||' '||i.sal);
elsif c1%notfound then
dbms_output.put_line(' your employee doesnot exist');
end if;
close c1;
end;
/
OUTPUT:
your employee doesnot exist

REF CURSOR/CURSOR VARIABLE/DYNAMIC CURSOR:

Ref cursor are used to execute noof select statements dynamically for a single active set area ref cursor
Or
This is an user defined type which is used to process multiple records and also this is a record by record
process.

Types of Ref cursor:


1) Strong ref cursor
2) Weak ref cursor

1) Strong ref cursor:


Strong ref cursor is a ref cursors which have return type,where as weak ref cursor has no return type

Syntax[Strong ref cursor]


A) Type typename is ref cursor return record type data type;
B) Variable ename typename
Strong ref cursor variable name

You might also like