Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

PL/SQL

PL/SQL has the following features:

PL/SQL is tightly integrated with SQL.


It offers extensive error checking.
It offers numerous data types.
It offers a variety of programming structures.
It supports structured programming through functions and procedures.
It supports object-oriented programming.

Structure
DECLARE
<declarations section>
BEGIN
<executable command(s)>
EXCEPTION
<exception handling>
END;

Sample procedures
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;

--case
CASE
WHEN shape = 'square' THEN area := side * side;
WHEN shape = 'circle' THEN
BEGIN
area := pi * (radius * radius);
DBMS_OUTPUT.PUT_LINE('Value is not exact because pi is
irrational.');
END;
WHEN shape = 'rectangle' THEN area := length * width;
ELSE
BEGIN
DBMS_OUTPUT.PUT_LINE('No formula to calculate area of a' ||
shape);
RAISE PROGRAM_ERROR;
END;
END CASE;

--while
DECLARE
salary
emp.sal%TYPE := 0;
mgr_num
emp.mgr%TYPE;
last_name
emp.ename%TYPE;
starting_empno emp.empno%TYPE := 7499;
BEGIN
SELECT mgr INTO mgr_num FROM emp
WHERE empno = starting_empno;
WHILE salary <= 2500 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;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO temp VALUES (NULL, NULL, 'Not found');
COMMIT;
END;

--package
CREATE PACKAGE emp_actions AS -- package specification
PROCEDURE hire_employee (empno NUMBER, ename CHAR, ...);
PROCEDURE fire_employee (emp_id NUMBER);
END emp_actions;
CREATE PACKAGE BODY emp_actions AS -- package body
PROCEDURE hire_employee (empno NUMBER, ename CHAR, ...) IS
BEGIN
INSERT INTO emp VALUES (empno, ename, ...);
END hire_employee;
PROCEDURE fire_employee (emp_id NUMBER) IS
BEGIN
DELETE FROM emp WHERE empno = emp_id;
END fire_employee;

END emp_actions;

READING A FILE IN PL/SQL


set serveroutput on;

create or replace directory oracle_data as


'C:\Users\gautham\Desktop\oracle_data';

grant read on directory oracle_data to public;

DECLARE
V1 VARCHAR2(200); --32767
F1 UTL_FILE.FILE_TYPE;
V_PID PLAYER.PID%TYPE;
V_PNAME PLAYER.PNAME%TYPE;
BEGIN
F1 := UTL_FILE.FOPEN('ORACLE_DATA','temp.txt','R');
Loop
BEGIN
UTL_FILE.GET_LINE(F1,V1);
dbms_output.put_line(V1);
V_PID := TO_NUMBER(SUBSTR(V1,1,1));

v_PNAME := SUBSTR(V1,3);
INSERT INTO PLAYER VALUES (V_PID,V_PNAME);
EXCEPTION WHEN No_Data_Found THEN EXIT; END;
end loop;

IF UTL_FILE.IS_OPEN(F1) THEN
dbms_output.put_line('File is Open');
end if;

UTL_FILE.FCLOSE(F1);
END;
/
set serveroutput off;

select instr('gautham','g') from dual;


select substr('gautham',2) from dual;

SELECT TO_NUMBER('9999') FROM DUAL;

SELECT * FROM PLAYER;

EXECUTE THIS WHEN YOU WANT TO


UNDERSTAND READING
DECLARE
CURSOR C_PID IS SELECT PID FROM PLAYER;
TYPE PID_ARRAY IS VARRAY(100) OF PLAYER.PID%TYPE;
V1 VARCHAR2(200); --32767
F1 UTL_FILE.FILE_TYPE;
V_PID PLAYER.PID%TYPE;
V_PNAME PLAYER.PNAME%TYPE;
A_PID PID_ARRAY := PID_ARRAY();
COUNTER INTEGER := 0;
I INTEGER := 0;
FLAG BOOLEAN := FALSE;
N INTEGER := 0;
BEGIN
F1 := UTL_FILE.FOPEN('ORACLE_DATA','temp.txt','R');
Loop
FLAG := FALSE;
COUNTER :=0;
FOR N IN C_PID LOOP
COUNTER := COUNTER +1;
A_PID.EXTEND;
A_PID(COUNTER) := N.PID;
DBMS_OUTPUT.PUT_LINE (' AT '||COUNTER||'
ELEMENT IS '||N.PID);
END LOOP;

BEGIN
UTL_FILE.GET_LINE(F1,V1);
dbms_output.put_line(V1); --20
V_PID := TO_NUMBER(SUBSTR(V1,1,2));
v_PNAME := SUBSTR(V1,3);
DBMS_OUTPUT.PUT_LINE ( ' THE COUNTER IS ' ||
COUNTER);
I := 0;
WHILE (I < COUNTER) LOOP
I := I+1;
DBMS_OUTPUT.PUT_LINE ( ' I IS ' || I);
IF ( A_PID(I) = V_PID ) THEN
FLAG := TRUE;
END IF;
END LOOP;
IF ( FLAG = FALSE ) THEN
INSERT INTO PLAYER VALUES (V_PID,V_PNAME);
DBMS_OUTPUT.PUT_LINE('INSERTED ' || V_PID);
END IF;
EXCEPTION WHEN No_Data_Found THEN EXIT;
END;
end loop;

IF UTL_FILE.IS_OPEN(F1) THEN
dbms_output.put_line('File is Open');
end if;

UTL_FILE.FCLOSE(F1);
END;

CORRECT IMPLEMENTATION
CREATE OR REPLACE PROCEDURE READ_PLAYERS IS
BEGIN
DECLARE
CURSOR C_PID IS SELECT PID FROM PLAYER_BKP;
V1 VARCHAR2(200); --32767
F1 UTL_FILE.FILE_TYPE;
V_PID PLAYER_BKP.PID%TYPE;
V_PNAME PLAYER_BKP.PNAME%TYPE;
FLAG BOOLEAN := FALSE;
BEGIN
F1 := UTL_FILE.FOPEN('ORACLE_DATA','temp.txt','R');
Loop
FLAG := FALSE;
BEGIN
UTL_FILE.GET_LINE(F1,V1);
--dbms_output.put_line(V1); --20
V_PID := TO_NUMBER(SUBSTR(V1,1,2));
v_PNAME := SUBSTR(V1,3);
DBMS_OUTPUT.PUT_LINE ( V_PID || V_PNAME);

FOR N IN C_PID LOOP


DBMS_OUTPUT.PUT_LINE( N.PID ||'

'||

V_PID);
IF ( N.PID = V_PID ) THEN
FLAG := TRUE;
END IF;
END LOOP;
IF ( FLAG = FALSE ) THEN
INSERT INTO PLAYER_BKP VALUES
(V_PID,V_PNAME);
DBMS_OUTPUT.PUT_LINE('INSERTED ' || V_PID);
END IF;
EXCEPTION WHEN No_Data_Found THEN EXIT;
END;
end loop;

IF UTL_FILE.IS_OPEN(F1) THEN
dbms_output.put_line('File is Open');
end if;

UTL_FILE.FCLOSE(F1);
END;
END;

SELECT * FROM PLAYER_BKP;

SET SERVEROUTPUT ON;

begin
dbms_scheduler.create_job (
job_name => 'SCOTT.J_READ_PLAYERS',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN
READ_PLAYERS;
END;',
start_date

=> SYSTIMESTAMP,

repeat_interval => 'freq=minutely; bysecond=0',


end_date

=> SYSTIMESTAMP + 3,

enabled => TRUE,


comments => 'te read data automatically from temp.txt' );
commit;
end;
/

Creating a scheduled job to run the procedure


CREATE OR REPLACE PROCEDURE PL_READ_INFO IS
BEGIN
DECLARE
CURSOR C_PID IS SELECT PID FROM PLAYER;
TYPE PID_ARRAY IS VARRAY(500) OF PLAYER.PID%TYPE;
V1 VARCHAR2(200); --32767
F1 UTL_FILE.FILE_TYPE;

V_PID PLAYER.PID%TYPE;
V_PNAME PLAYER.PNAME%TYPE;
A_PID PID_ARRAY := PID_ARRAY();
COUNTER INTEGER := 0;
I INTEGER := 0;
FLAG BOOLEAN := FALSE;
N INTEGER := 0;
BEGIN
F1 := UTL_FILE.FOPEN('ORACLE_DATA','temp.txt','R');
Loop
FLAG := FALSE;
COUNTER :=0;
FOR N IN C_PID LOOP
COUNTER := COUNTER +1;
A_PID.EXTEND;
A_PID(COUNTER) := N.PID;
--DBMS_OUTPUT.PUT_LINE (' AT '||COUNTER||'
ELEMENT IS '||N.PID);
END LOOP;
BEGIN
UTL_FILE.GET_LINE(F1,V1);
--dbms_output.put_line(V1); --20
V_PID := TO_NUMBER(SUBSTR(V1,1,2));
v_PNAME := SUBSTR(V1,3);
--DBMS_OUTPUT.PUT_LINE ( ' THE COUNTER IS '
|| COUNTER);
I := 0;
WHILE (I < COUNTER) LOOP
I := I+1;
--DBMS_OUTPUT.PUT_LINE ( ' I IS ' || I);
IF ( A_PID(I) = V_PID ) THEN
FLAG := TRUE;
END IF;
END LOOP;
IF ( FLAG = FALSE ) THEN
INSERT INTO PLAYER VALUES (V_PID,V_PNAME);

--DBMS_OUTPUT.PUT_LINE('INSERTED ' ||
V_PID);
END IF;
EXCEPTION WHEN No_Data_Found THEN EXIT;
END;
end loop;
-- IF UTL_FILE.IS_OPEN(F1) THEN
--dbms_output.put_line('File is Open');
-- end if;
UTL_FILE.FCLOSE(F1);
END;
END;

execute PL_READ_INFO;

set serverout on

---job
begin
dbms_scheduler.create_job (
job_name => 'SCOTT.J_PL_READ_INFO4',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN
execute immediate 'execute PL_READ_INFO;';
END;',
start_date

=> SYSTIMESTAMP,

repeat_interval => 'freq=minutely; bysecond=0',


end_date

=> SYSTIMESTAMP + 3,

enabled => TRUE,


comments => 'te read data automatically from temp.txt' );
commit;
end;
/
select systimestamp, systimestamp+3 from dual;
select * from player order by pid desc;
delete from player where pid>7;
begin
PL_READ_INFO;
END;

You might also like