PLSQL Ora7
PLSQL Ora7
PLSQL Ora7
للكمــبـيـوتـر
PL/SQL is the procedural extension for SQL, which has many programming
languages properties; loops, if clauses … etc.
PL/SQL BLOCK
DECLARE -- optional
DECLARATION SECTION
BEGIN -- mandatory
BODY STATEMENTS
( SQL and PL/SQL Statements )
EXCEPTION -- Optional
STATEMENTS
END; -- mandatory
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
1
الـع ــالـــميـــة
للكمــبـيـوتـر
In the Body part the SQL and PL/SQL statements to be executed are written
to manipulate data.
In the Exception part statements are written to handle errors and exceptions,
which may also include SQL code.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
2
الـع ــالـــميـــة
للكمــبـيـوتـر
DECLARE -- optional
DECLARATION SECTION
BEGIN -- mandatory
BODY STATEMENTS
( SQL and PL/SQL Statements )
EXCEPTION -- Optional
STATEMENTS
END; -- mandatory
Variables
In PL/SQL variables are used to store values and reference them where:
Declare variable and assign initial values for them in the declarative
part.
Inside the PL/SQL block body new values might be assigned
Parameters could be passed to the variable in the block or received
from the block.
Variables values could be used in insert, update, delete … etc.
Variables might be assigned with an initial vale.
Variables could be declared as a NOT NULL variables.
Constants are also declared in the declarative part, their values
should not be changed in the PL/SQL body part
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
3
الـع ــالـــميـــة
للكمــبـيـوتـر
• float
• Decimal
• Numeric
• Real
• Integer
Examples on DECLARATIONS
• v_birthday Date;
• v_hiredt Date := sysdate + 7;
• v_count1 integer := 6; -- Note initialized variable
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
4
الـع ــالـــميـــة
للكمــبـيـوتـر
• v_count_tot binary_integer := 0;
• acc_id varchar2(10) not null --not valid
• v_acc_id varchar2(10) not null := ‘SHC’
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
5
الـع ــالـــميـــة
للكمــبـيـوتـر
• %TYPE Declaration
A variable could be declared using the %type attribute. Where the data
type for the variable depends on a previously declared variable or a
column in a table.
var1 Tablename.Field%Type;
Examples:
v_empno emp.empno%type;
v_dept_name scott.dept.deptno%type;
v_tot number(9,2);
v_comp_tot v_tot%type;
note: If the column in the database is defined as a not null column, this is not
inherited by the variable.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
6
الـع ــالـــميـــة
للكمــبـيـوتـر
• %ROWTYPE Declaration
A group of variables could be declared using the %rowtype attribute.
Where the data type for these variables depends on a previously
declared cursor or a table.
var1 Tablename%rowtype;
Examples:
emp_rec emp%rowtype;
dept_rec scott.dept%rowtype;
Sal_rec c1%rowtype;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
7
الـع ــالـــميـــة
للكمــبـيـوتـر
Examples :
1) Declare
emp_job char(10);
Begin
select job into emp_job
from emp
where empno = 7499;
If emp_job .. etc
......
end if;
end;
Declare
emp_job emp.job%type;
begin
select job into emp_job
from emp
where empno = 7499;
If emp_job .. etc
......
end if;
end;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
8
الـع ــالـــميـــة
للكمــبـيـوتـر
2) Declare
v_dno number(4);
v_dname char(14);
v_loc dept.loc%type;
begin
select * into v_dno, v_dname, v_loc
from emp
where deptno = 10;
if v_dname = ‘ACCOUNTING’ Then
.....
end if;
end;
Declare
dept_rec dept%rowtype;
begin
select * into dept_rec
from emp
where deptno = 10;
if dept_rec.dname = ‘ACCOUNTING’ Then
.....
end if;
end;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
9
الـع ــالـــميـــة
للكمــبـيـوتـر
3) Declare
cursor c_emp is select empno, ename, sal
from emp;
emp_r1 c_emp%rowtype;
begin
……
if emp_r1.sal < 1000 then ….
….
end if;
end;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
10
الـع ــالـــميـــة
للكمــبـيـوتـر
PL/SQL TABLES
To use PL/SQL tables, you must first Declare a new type called TABLE.
Then you define a variable of that type
Syntax:
Variable_name type_name;
EXAMPLES:-
1) Declare
TYPE my_table IS TABLE OF CHAR(10)
INDEX BY BINARY_INTEGER;
scottab my_table;
2) Declare
TYPE new_type IS TABLE OF dept.loc%Type
INDEX BY BINARY_INTEGER;
arr1 new_type;
arr2 new_type;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
11
الـع ــالـــميـــة
للكمــبـيـوتـر
3) Declare
Cursor C_mgr is select empno, mgr
from emp;
TYPE mgr_array IS TABLE OF C_MGR%Type
INDEX BY BINARY_INTEGER;
emp_rec mgr_array;
scottab(1) := sal*12;
Or by a loop
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
12
الـع ــالـــميـــة
للكمــبـيـوتـر
PLSQL RECORDS
A PL/SQL record is similar in structure to records in 3GL. And they are not the
same as a row in database table.
It allows the programmer to treat all the fields in the PL/SQL record as one
unit.
They are usually used to fetch a row of data from a table for processing it in a
PL/SQL block.
To use PL/SQL records, you must first declare a new type called RECORD.
Then you define a variable of that type.
You can define a record that holds the same structure of a record in the
database (but it is NOT the same as a row in the database) as follows:-
Syntax:
identifier_name type_name;
in defining fields datatype, one can use %TYPE and %ROWTYPE attributes,
also initial (default values) could be assigned to the fields, and they could be
defined as NOT NULL fields.
EXAMPLE:-
DECLARE
TYPE user_rec IS RECORD
(deptno Number(2) := 20,
dname varchar2(20),
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
13
الـع ــالـــميـــة
للكمــبـيـوتـر
loc dept.loc%type);
my_rec user_rec;
BEGIN my_rec
my_rec.dname :=‘ACCT’;
20 ACCT
END;
ASSIGNMENT
my_rec2 :=my_rec;
This is legal only if my_rec and my_rec2 belong to the same RECORD Type,
i.e. they are declared in the following way:
DECLARE
TYPE user_rec IS RECORD
(deptno Number(2) := 20,
dname varchar2(20),
loc dept.loc%type);
my_rec user_rec;
my_rec2 user_rec;
begin
…
my_rec2 := my_rec;
…
end;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
14
الـع ــالـــميـــة
للكمــبـيـوتـر
DECLARE
TYPE emp_rec IS RECORD
(EMPNO NUMBER(4),
SAL NUMBER(7,4),
DEPTNO NUMBER(3));
BEGIN
SHC.MGR := ‘2221’;
SHC.EMP.EMPNO := 1234;
END:
One of the advantages of RECORDS is that you collect information about the
attributes of an object in one name.
Later you can refer the object as a whole. For example, you can pass the
whole RECORD to a function instead of passing the individual fields.
The scope of a variable is the region that can refer to the variable.
You can reference the declared variable in the executable section.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
15
الـع ــالـــميـــة
للكمــبـيـوتـر
Declare
A REAL;
Begin
A := 5.2;
DECLARE
A Real;
Begin
A := 2.0;
END;
DBMS_OUPUT.PUT_LINE (‘The variable A = ‘|| A);
END;
The variable A declared in the inner block is different than the A declared in
the outer block and is local for the inner block
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
16
الـع ــالـــميـــة
للكمــبـيـوتـر
Example:
Any variable which does not have a value assigned to has an initial value of
NULL.
Example:
DECLARE
Iterate INTEGER;
BEGIN
Iterate := Iterate +1 ;
....
END:
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
17
الـع ــالـــميـــة
للكمــبـيـوتـر
Functions in PL/SQL
Single row functions ( numbers, character, date and data type conversion )
Group functions ( max, min, sum, … etc.) , Greatest and Least function are
not available in procedural statements.
Var1 := max(my_new_sal);
** , Not
* ,/
+ . - , ||
= , != , < , > , etc. .. Decreasing
And
Or
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
18
الـع ــالـــميـــة
للكمــبـيـوتـر
Note also that Zero Length strings are treated like null
EXCEPTIONS:
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
19
الـع ــالـــميـــة
للكمــبـيـوتـر
PREDEFINED EXCEPTIONS
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
20
الـع ــالـــميـــة
للكمــبـيـوتـر
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
21
الـع ــالـــميـــة
للكمــبـيـوتـر
Syntax:
Declare
Exception_name EXCEPTION
…
BIGIN
Statement1;
Statement2;
…
if … then
raise Exception_name;
end if;
Exception
When exception_name then
…
END;
Example:
DECLARE
angry EXCEPTION
...
BEGIN
...
IF x > 100 then
RAISE angry;
END IF;
EXCEPTION
WHEN angry THEN
.....
WHEN OTHERS THEN
....
END ;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
22
الـع ــالـــميـــة
للكمــبـيـوتـر
Syntax:
Declare
…
Exception_name EXCEPTION;
PRAGMA EXCEPTION_INIT(Exception_name,error number);
BEGIN
Statement1;
Statement2;
…
EXCEPTION
WHEN Exception_name THEN
…
END;
Exampe:
DECLARE
no_privileges EXCEPTION;
PRAGMA EXCEPTION_INIT(no_privileges,-1031);
-- -1031 is the error code associated with trying to update
-- a table for which you only have SELECT privileges
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
23
الـع ــالـــميـــة
للكمــبـيـوتـر
BEGIN
UPDATE team4.emp SET sal=sal+100;
EXCEPTION
WHEN no_privileges THEN
-- handle the newly defined exception
WHEN others THEN
-- Handle other exceptions
END;
RAISE_APPLICATION_ERROR
Example:
DECLARE
x number;
BEGIN
SELECT comm INTO x FROM emp WHERE empno= 7902;
IF x IS NULL THEN
raise_application_error(-20001,’Comm is Null’);
ELSE
UPDATE emp set comm = comm+200 where empno = 7902;
END IF;
END;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
24
الـع ــالـــميـــة
للكمــبـيـوتـر
Returns error conditions to the user in a manner consistent with other Oracle
Server errors.
Trapping Exceptions
SQLCODE
This returns the numeric value for the error code.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
25
الـع ــالـــميـــة
للكمــبـيـوتـر
SQLERRM
This returns the message associated with the error number.
Example:
Declare
val number ;
Begin
select sal into val from emp where empno=9989;
if val < 800 then
Update emp set sal=1000 where empno=9989;
end if;
Exception
When NO_DATA_FOUND Then
declare
val1 number;
val2 varchar2(50);
begin
val1 := sqlcode;
val2 := sqlerrm;
insert into log values (val1,val2);
end;
End;
Propagating Exceptions
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
26
الـع ــالـــميـــة
للكمــبـيـوتـر
RETRYING A TRANSATION :-
Example:
DECLARE
empno number(4) := 7755;
BEGIN
FOR i in 1 .. 3 LOOP -- Retry Three Times
BEGIN
SAVEPOINT start1; -- Mark a savepoint
INSERT INTO EMP (empno,sal)
VALUES( empno,1000);
END LOOP;
END;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
27
الـع ــالـــميـــة
للكمــبـيـوتـر
CONTROL STRUCTURES
IF and IF-THEN-ELSIF Statement
The use of the IF statement in PL/SQL is the same as in all other procedural
languages,
Syntax:
IF condition THEN
Statement(s);
ELSIF condition THEN
Statement(s);
…
ELSE
Statement(s);
END IF;
Example:
Begin
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
28
الـع ــالـــميـــة
للكمــبـيـوتـر
End;
make note of Elsif , it does not contain the letter ‘e’ after Els, nor there is
space before if i.e. (ELSIF)
DECLARE
overdrawn BOOLEAN;
......
BEGIN
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
29
الـع ــالـــميـــة
للكمــبـيـوتـر
IF overdrawn THEN
…
Nested IF statements:
LOOP
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
30
الـع ــالـــميـــة
للكمــبـيـوتـر
- Basic loops
- For loops
- While loops
1) Basic Loop
Syntax:
Loop
Statement1
Statement2
….
Exit When condition;
End loop;
Example:
Declare
Cnt number := 1;
Begin
Loop
Dbms_output.putline(to_char(x)||’ ‘||to_char(x * 9/5 + 32));
Cnt := cnt + 1;
Exit when cnt > 10;
End loop;
End;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
31
الـع ــالـــميـــة
للكمــبـيـوتـر
2) For Loop
Syntax:
Example:
For c in 1 .. 20 loop
Dbms_output.putline( c * 10 );
End loop;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
32
الـع ــالـــميـــة
للكمــبـيـوتـر
IF MOD(i,5) = 0 THEN
sequence of statements;
END IF;
END LOOP
3) While Loop
Syntax:
The statements inside the loop are repeated until the condition is
evaluated to FALSE.
Example:
Declare
Cnt number := 1;
Begin
While cnt <= 10 Loop
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
33
الـع ــالـــميـــة
للكمــبـيـوتـر
This will do the same as for the example in the Basic Loop.
NESTED LOOPS
Syntax:
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
34
الـع ــالـــميـــة
للكمــبـيـوتـر
Declare
…
begin
…
<< loop_1 >>
loop
v1 := v1 + 1;
exit when v1 = 25;
<< lp_2 >>
…
exit when x = 10; -- this will exit the inner loop(lp_2)
statement1;
…
exit loop_1 when count_a = 100; -- this will exit the outer loop
end loop lp_2;
…
end loop loop_1;
end;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
35
الـع ــالـــميـــة
للكمــبـيـوتـر
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
36
الـع ــالـــميـــة
للكمــبـيـوتـر
The set of rows returned by a query can consist of zero, one, or multiple rows,
depending on your search condition.
When query return multiple rows, you can explicitly define a cursor to process
the rows.
Explicit Declaration
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
37
الـع ــالـــميـــة
للكمــبـيـوتـر
Syntax:
Declare
…
CURSOR cursor_name IS select statement ;
…
begin
OPEN cursor_name;
…
FETCH cursor_name into variables;
…
CLOSE cursor_name;
…
End;
Do not include the INTO clause in the declaration on\f the cursor.
If the rows are to be processed in certain sequence, use the ORDER
BY clause in select statement.
The where clause could be used in the cursor declaration.
Open the cursor to execute the query, and identify the active set.
No exception is raised if the query returns no rows.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
38
الـع ــالـــميـــة
للكمــبـيـوتـر
emp table
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
39
الـع ــالـــميـــة
للكمــبـيـوتـر
CURSOR CONTROL
emp table
7369 SMITH CLERK 800 20
7499 ALLEN SALESMAN 1600 300 30
7521 WARD SALESMAN 1250 500 30
7566 JONES MANAGER 2975 20
7654 MARTIN SALESMAN 1250 1400 30
7698 BLAKE MANAGER 2850 30
20 800
7782 CLARK CLERK
MANAGERSMITH2450 7369 10
30 300 1600
7788 SCOTT NANALYST
SALESMAN 3000
ALLEN 207499
30 500 etc1250 ....SALESMAN WARD 7521
20 CURSOR C1 IS MANAGER
2975 SELECT EMPNO,ENAME,JOB
JONES 7566 FROM
30 EMP
1400 1250 SALESMAN MARTIN 7654
30 WHERE SAL
2850 > 1250;
MANAGER BLAKE 7698
OPEN
10 2450 MANAGER CLARK 7782
.... etc
FETCH
Current
FETCH SALESMAN ALLEN 7499 Row
MANAGER JONES 7566
Prepared By : MANAGER BLAKE 7698
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
MANAGER CLARK 7782
ANALYST 40SCOTT 7788
CLOSE
الـع ــالـــميـــة
للكمــبـيـوتـر
EXAMPLE
DECLARE
CURSOR my_cursor IS
SELECT sal+NVL(comm,0) wages , ename
FROM EMP;
X1 number;
x2 varchar2 (20);
BEGIN
OPEN my_cursor;
LOOP
FETCH my_cursor INTO x1,x2;
EXIT WHEN my_cursor%NOTFOUND;
IF x1 > 2000 THEN
INSERT INTO anytable VALUES (x1,...);
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
41
الـع ــالـــميـــة
للكمــبـيـوتـر
END IF;
END LOOP;
CLOSE my_cursor;
END;
The same thing can also be done as
follows
CURSOR my_cursor IS
SELECT sal+NVL(comm,0) wages , ename
FROM EMP;
my_rec my_cursor%ROWTYPE --
BEGIN
CONT .Next Page
OPEN my_cursor;
LOOP
FETCH my_cursor INTO my_rec;
EXIT WHEN my_cursor%NOTFOUND;
IF my_rec.wages > 2000 THEN
INSERT INTO anytable
VALUES (my_rec.sal, .);
END IF;
END LOOP;
CLOSE my_cursor;
END;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
42
الـع ــالـــميـــة
للكمــبـيـوتـر
DECLARE
CURSOR MY_C (VAR 1 NUMBER) IS
SELECT ENAME,SAL, DEPTNO FROM EMP
WHERE EMPNO=VAR1;
BEGIN
OPEN MY_C (7499);
etc.
END;
DECLARE
CURSOR C1 IS SELECT
EMPNO,ENAME,SAL FROM EMP;
m_empno NUMBER(10);
m_ename VARCHAR2(10);
m_sal NUMBER(2);
BEGIN
OPEN C1; -- ACTIVE SET IS IDENTIFIED.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
43
الـع ــالـــميـــة
للكمــبـيـوتـر
LOOP
FETCH C1 INTO
m_empno,m_ename,m_sal;
EXIT WHEN C1%NOTFOUND; -- when
EOF
IF m_sal < 2000 THEN
UPDATE EMP SET SAL=SAL*1.1
where
empno = m_empno;
END IF;
END LOOP;
CLOSE C1
END;
Note: What happens if during the fetch of a certain record whose
m_sal is <
2000, the same record was changed by another user? How to
correct the
problem
DECLARE
CURSOR C1 IS SELECT JOB FROM EMP;
JOB1 EMP.JOB%TYPE;
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO JOB;
EXIT WHEN C1%NOTFOUND;
...
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
44
الـع ــالـــميـــة
للكمــبـيـوتـر
END LOOP;
CURSOR ATTRIBUTES
%NOTFOUND
%FOUND
%ROWCOUNT
%ISOPEN
Before the first fetch, the %NOTFOUND evaluates
to NULL.
If the last fetch fails to return a row %NOTFOUND
evaluates to TRUE.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
45
الـع ــالـــميـــة
للكمــبـيـوتـر
num2 data_table.n2%TYPE;
num3 data_tablen3%TYPE;
result temp.col1%TYPE;
CURSOR c1 IS
SELECT n1,n2,n3 from data_table
WHERE experiment=1;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO num1,num2,num3;
EXIT WHEN c1%NOTFOUND; -- UNTIL
EOF
result := num2/(num1+num3);
INSERT INTO temp VALUES (result);
END LOOP;
CLOSE c1;
COMMIT;
END;
Note the Use of COMMIT to make sure
that
the inserted records are saved, the end of
the
block does not automatically commit a
trans.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
46
الـع ــالـــميـــة
للكمــبـيـوتـر
DECLARE
CURSOR C1 IS SELECT
EMPNO,ENAME,SAL FROM EMP;
m_empno NUMBER(10);
m_ename VARCHAR2(10);
m_sal NUMBER(2);
BEGIN
OPEN C1; -- ACTIVE SET IS IDENTIFIED.
LOOP
FETCH C1 INTO m_empno,m_ename,m_sal;
EXIT WHEN C1%NOTFOUND; -- when EOF
IF m_sal < 2000 THEN
UPDATE EMP SET SAL=SAL*1.1 where
empno = m_empno;
END IF;
END LOOP;
CLOSE C1
END;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
47
الـع ــالـــميـــة
للكمــبـيـوتـر
Notes:
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
48
الـع ــالـــميـــة
للكمــبـيـوتـر
LOOP
FETCH C1 INTO m_ename,m_sal;
EXIT WHEN C1%NOTFOUND; -- when EOF
IF m_sal < 2000 THEN
UPDATE EMP SET SAL=SAL*1.1 where
CURRENT OF C1;
END IF;
COMMIT -- This will cause an error
END LOOP;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
49
الـع ــالـــميـــة
للكمــبـيـوتـر
FIX:
The best fix to the above mentioned problem is not to use
the CURRENT OF construct. Instead, fetch the ROWID in
the cursor and use it in the where clause of the Update
statment to help identify the record being updated. The
usage of ROWID will guarantee the fastest access path to
your record. The following example illustrates:
DECLARE
CURSOR C1 IS SELECT
ENAME,SAL rowid FROM EMP FOR
UPDATE OF SAL;
m_ename VARCHAR2(10);
m_sal NUMBER(2);
m_rowid rowid;
BEGIN
OPEN C1; -- ACTIVE SET IS IDENTIFIED.
LOOP
FETCH C1 INTO m_ename,m_sal,m_rowid;
EXIT WHEN C1%NOTFOUND; -- when EOF
IF m_sal < 2000 THEN
UPDATE EMP SET SAL=SAL*1.1 where
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
50
الـع ــالـــميـــة
للكمــبـيـوتـر
rowid=m_rowid;
END IF;
COMMIT;
END LOOP;
CLOSE C1
END
IMPLICIT CURSORS
ORACLE implicitly opens a cursor to process each SQL
statement not associated with an explicitly declared
cursor.
You can refer to most recent implicit cursor as the “SQL”
cursor.
Example
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
51
الـع ــالـــميـــة
للكمــبـيـوتـر
IF SQL%NOTFOUND THEN
DELETE FROM EMP;
/* THIS action is never taken because
the function MAX evaluates to a value
or a NULL and %NOTFOUND evaluates
to FALSE */
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN NULL;
-- never reaches this part.
END:
CURSOR FOR LOOP
A cursor FOR LOOP implicitly declares its Loop
index
as a record of type %ROWTYPE, OPENS a cursor,
FETCHES records and CLOSES the cursor
DECLARE
result temp.col1%TYPE;
CURSOR C1 IS SELECT n1,n2,n3 from m_tab;
BEGIN
FOR my_record IN C1 LOOP;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
52
الـع ــالـــميـــة
للكمــبـيـوتـر
my_record.n1
my_record.n2
my_record.n3
DECLARE
CURSOR C1 IS SELECT n1,n2,n3 from m_tab;
my_record c1%ROWTYPE;
BEGIN
OPEN c1;
LOOP;
FETCH c1 into my_record.n1,
my_record_n2,my_record.n3;
EXIT WHEN C1%NOTFOUND;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
53
الـع ــالـــميـــة
للكمــبـيـوتـر
END LOOP;
CLOSE c1
END;
PL/SQL TABLES
If you try to reference an uninitialized row in a
PL/SQL table, then NO_DATA_FOUND exception
is raised.
More examples:-
Declare
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
54
الـع ــالـــميـــة
للكمــبـيـوتـر
Empno_tab tabtype;
ename_tab tabtype1;
scottab(i) := NULL;
Example
DECLARE
arr_null my_array;
arr1 my_array;
BEGIN
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
55
الـع ــالـــميـــة
للكمــبـيـوتـر
values (1,arr1(i),5);
END LOOP;
arr1 := arr_null; -- delete arr1
END;
PLSQL RECORDS
You can define a record that holds the same
structure of a record in the database (but it is NOT
the same as a row in the database) as follows:-
DEF_REC DEPT%ROWTYPE;
DECLARE
my_rec User_rec;
my_rec2 User_rec;
BEGIN my_rec
my_rec.dname :=‘ACCT’;
END;
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
56
الـع ــالـــميـــة
للكمــبـيـوتـر
Exercise
1-Write one SQL statement (NOT PL/SQL) that will
update the EMP table so that all employees whose salary
is more than 2000 will get 5% increase in salary and
empolyees whose salary is less or equal to 2000 will get
10% increase.
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
57
الـع ــالـــميـــة
للكمــبـيـوتـر
Prepared By :
Abdullah A. Safareeni Mobile: +962 79 5091611 E-Mail:
[email protected]
58