Declaring & Initializing & Using Variables (Code Samples)
-----------------------===================-----------------------
-----------------------DECLARING VARIABLES-----------------------
-----------------------===================-----------------------
SET SERVEROUTPUT ON;
DECLARE
v varchar2(20) := 2 + 25 * 3;
BEGIN
dbms_output.put_line(v);
END;
-----------------------===================-----------------------
DECLARE
v_text varchar2(50) NOT NULL DEFAULT 'Hello';
v_number1 number := 50;
v_number2 number(2) := 50.42;
v_number3 number(10,2) := 50.42;
v_number4 PLS_INTEGER := 50;
v_number5 BINARY_float := 50.42;
v_DATE1 DATE := '22-NOV-18 12:01:32';
v_DATE2 timestamp := systimestamp;
v_DATE3 timestamp(9) WITH TIME ZONE := systimestamp;
v_DATE4 interval day(4) to second (3) := '124 02:05:21.012 ';
v_DATE5 interval year to month := '12-3';
BEGIN
V_TEXT := 'PL/SQL' || 'Course';
DBMS_OUTPUT.PUT_LINE(V_TEXT);
DBMS_OUTPUT.PUT_LINE(v_number1);
DBMS_OUTPUT.PUT_LINE(v_number2);
DBMS_OUTPUT.PUT_LINE(v_number3);
DBMS_OUTPUT.PUT_LINE(v_number4);
DBMS_OUTPUT.PUT_LINE(v_number5);
DBMS_OUTPUT.PUT_LINE(v_DATE1);
DBMS_OUTPUT.PUT_LINE(v_DATE2);
DBMS_OUTPUT.PUT_LINE(v_DATE3);
DBMS_OUTPUT.PUT_LINE(v_DATE4);
DBMS_OUTPUT.PUT_LINE(v_DATE5);
END;
----------------==================================---------------
----------------USING BOOLEAN DATA TYPE in PL/SQL----------------
----------------==================================---------------
DECLARE
v_boolean boolean := true;
BEGIN
dbms_output.put_line(sys.diutil.bool_to_int(v_boolean));
END;
----------------==================================---------------
Using %Type Attribute (Code Samples)
---------------------%TYPE ATTRIBUTE---------------------
desc employees;
declare
V_TYPE employees.JOB_ID%TYPE;
V_TYPE2 V_TYPE%TYPE;
V_TYPE3 employees.JOB_ID%TYPE ;
begin
v_type := 'IT_PROG';
v_type2 := 'SA_MAN';
v_type3 := NULL;
dbms_output.put_line(v_type);
dbms_output.put_line(v_type2);
dbms_output.put_line('HELLO' || v_type3);
end;
---------------------------------------------------------
PL/SQL Delimiters and Commenting (Code Samples)
------------------DELIMITERS AND COMMENTING------------------
DECLARE
V_TEXT VARCHAR2(10):= 'PL/SQL';
BEGIN
--This is a single line comment
/* This is a
multi line
comment */
--DBMS_OUTPUT.PUT_LINE(V_TEXT || ' is a good language');
null;
END;
-------------------------------------------------------------
PL SQL Variable Scope (Code Samples)
------------------------VARIABLE SCOPE--------------------------
begin <<outer>>
DECLARE
--v_outer VARCHAR2(50) := 'Outer Variable!';
v_text VARCHAR2(20) := 'Out-text';
BEGIN
DECLARE
v_text VARCHAR2(20) := 'In-text';
v_inner VARCHAR2(30) := 'Inner Variable';
BEGIN
--dbms_output.put_line('inside -> ' || v_outer);
--dbms_output.put_line('inside -> ' || v_inner);
dbms_output.put_line('inner -> ' || v_text);
dbms_output.put_line('outer -> ' || outer.v_text);
END;
--dbms_output.put_line('inside -> ' || v_inner);
--dbms_output.put_line(v_outer);
dbms_output.put_line(v_text);
END;
END outer;
----------------------------------------------------------------
Using Bind Variables (Code Samples)
--------------------------BIND VARIABLES--------------------------
set serveroutput on;
set autoprint on;
/
variable var_text varchar2(30);
/
variable var_number NUMBER;
/
variable var_date DATE;
/
declare
v_text varchar2(30);
begin
:var_text := 'Hello SQL';
:var_number := 20;
v_text := :var_text;
--dbms_output.put_line(v_text);
--dbms_output.put_line(:var_text);
end;
/
print var_text;
/
variable var_sql number;
/
begin
:var_sql := 100;
end;
/
select * from employees where employee_id = :var_sql;
-----NOTE: When you run a bind variable creation and select statement
together,
SQL Developer may return an error. But when you execute them separately,
there will be no problem
-------------------------------------------------------------------------
-
What are Control Structures & IF Statements (Code Samples)
------------------------------IF STATEMENTS------------------------------
--
set serveroutput on;
declare
v_number number := 30;
begin
if v_number < 10 then
dbms_output.put_line('I am smaller than 10');
elsif v_number < 20 then
dbms_output.put_line('I am smaller than 20');
elsif v_number < 30 then
dbms_output.put_line('I am smaller than 30');
else
dbms_output.put_line('I am equal or greater than 30');
end if;
end;
-------------------------------------------------------------------------
--
declare
v_number number := 5;
v_name varchar2(30) := 'Adam';
begin
if v_number < 10 or v_name = 'Carol' then
dbms_output.put_line('HI');
dbms_output.put_line('I am smaller than 10');
elsif v_number < 20 then
dbms_output.put_line('I am smaller than 20');
elsif v_number < 30 then
dbms_output.put_line('I am smaller than 30');
else
if v_number is null then
dbms_output.put_line('The number is null..');
else
dbms_output.put_line('I am equal or greater than 30');
end if;
end if;
end;
-------------------------------------------------------------------------
--
Case Expressions (Code Samples)
----------------------------CASE EXPRESSIONS-----------------------------
---
declare
v_job_code varchar2(10) := 'SA_MAN';
v_salary_increase number;
begin
v_salary_increase := case v_job_code
when 'SA_MAN' then 0.2
when 'SA_REP' then 0.3
else 0
end;
dbms_output.put_line('Your salary increase is : '|| v_salary_increase);
end;
-------------------------SEARCHED CASE EXPRESSION------------------------
----
declare
v_job_code varchar2(10) := 'IT_PROG';
v_department varchar2(10) := 'IT';
v_salary_increase number;
begin
v_salary_increase := case
when v_job_code = 'SA_MAN' then 0.2
when v_department = 'IT' and v_job_code = 'IT_PROG' then 0.3
else 0
end;
dbms_output.put_line('Your salary increase is : '|| v_salary_increase);
end;
---------------------------CASE STATEMENTS-------------------------------
-----
declare
v_job_code varchar2(10) := 'IT_PROG';
v_department varchar2(10) := 'IT';
v_salary_increase number;
begin
case
when v_job_code = 'SA_MAN' then
v_salary_increase := 0.2;
dbms_output.put_line('The salary increase for a Sales Manager is :
'|| v_salary_increase);
when v_department = 'IT' and v_job_code = 'IT_PROG' then
v_salary_increase := 0.2;
dbms_output.put_line('The salary increase for a Sales Manager is :
'|| v_salary_increase);
else
v_salary_increase := 0;
dbms_output.put_line('The salary increase for this job code is :
'|| v_salary_increase);
end CASE;
end;
-------------------------------------------------------------------------
------
Basic Loops (Code Samples)
-------------------------BASIC LOOPS--------------------------
declare
v_counter number(2) := 1;
begin
loop
dbms_output.put_line('My counter is : '|| v_counter);
v_counter := v_counter + 1;
--if v_counter = 10 then
-- dbms_output.put_line('Now I reached : '|| v_counter);
-- exit;
--end if;
exit when v_counter > 10;
end loop;
end;
--------------------------------------------------------------
While Loops (Code Samples)
------------------------------WHILE LOOPS-------------------------------
declare
v_counter number(2) := 1;
begin
while v_counter <= 10 loop
dbms_output.put_line('My counter is : '|| v_counter);
v_counter := v_counter + 1;
-- exit when v_counter > 3;
end loop;
end;
-------------------------------------------------------------------------
For Loops (Code Samples)
-----------------------------FOR LOOPS-----------------------------
begin
for i in REVERSE 1..3 loop
dbms_output.put_line('My counter is : '|| i);
end loop;
end;
-------------------------------------------------------------------
Nested Loops & Loop Labeling (Code Samples)
-------------------------------NESTED LOOPS------------------------------
-----
declare
v_inner number := 1;
begin
for v_outer in 1..5 loop
dbms_output.put_line('My outer value is : ' || v_outer );
v_inner := 1;
loop
v_inner := v_inner+1;
dbms_output.put_line(' My inner value is : ' || v_inner );
exit when v_inner*v_outer >= 15;
end loop;
end loop;
end;
-------------------------NESTED LOOPS WITH LABELS------------------------
------
declare
v_inner number := 1;
begin
<<outer_loop>>
for v_outer in 1..5 loop
dbms_output.put_line('My outer value is : ' || v_outer );
v_inner := 1;
<<inner_loop>>
loop
v_inner := v_inner+1;
dbms_output.put_line(' My inner value is : ' || v_inner );
exit outer_loop when v_inner*v_outer >= 16;
exit when v_inner*v_outer >= 15;
end loop inner_loop;
end loop outer_loop;
end;
-------------------------------------------------------------------------
-------
Continue Statement (Code Samples)
----------------------------CONTINUE STATEMENT---------------------------
-------
declare
v_inner number := 1;
begin
for v_outer in 1..10 loop
dbms_output.put_line('My outer value is : ' || v_outer );
v_inner := 1;
while v_inner*v_outer < 15 loop
v_inner := v_inner+1;
continue when mod(v_inner*v_outer,3) = 0;
dbms_output.put_line(' My inner value is : ' || v_inner );
end loop;
end loop;
end;
-------------------------------------------------------------------------
--------
declare
v_inner number := 1;
begin
<<outer_loop>>
for v_outer in 1..10 loop
dbms_output.put_line('My outer value is : ' || v_outer );
v_inner := 1;
<<inner_loop>>
loop
v_inner := v_inner+1;
continue outer_loop when v_inner = 10;
dbms_output.put_line(' My inner value is : ' || v_inner );
end loop inner_loop;
end loop outer_loop;
end;
-------------------------------------------------------------------------
---------
GOTO Statement (Code Samples)
------------------------------GOTO STATEMENT-----------------------------
-----
DECLARE
v_searched_number NUMBER := 22;
v_is_prime boolean := true;
BEGIN
FOR x in 2..v_searched_number-1 LOOP
IF v_searched_number MOD x = 0 THEN
dbms_output.put_line(v_searched_number|| ' is not a prime
number..');
v_is_prime := false;
GOTO end_point;
END IF;
END LOOP;
if v_is_prime then
dbms_output.put_line(v_searched_number|| ' is a prime number..');
end if;
<<end_point>>
dbms_output.put_line('Check complete..');
END;
-------------------------------------------------------------------------
------
DECLARE
v_searched_number NUMBER := 32457;
v_is_prime boolean := true;
x number := 2;
BEGIN
<<start_point>>
IF v_searched_number MOD x = 0 THEN
dbms_output.put_line(v_searched_number|| ' is not a prime
number..');
v_is_prime := false;
GOTO end_point;
END IF;
x := x+1;
if x = v_searched_number then
goto prime_point;
end if;
goto start_point;
<<prime_point>>
if v_is_prime then
dbms_output.put_line(v_searched_number|| ' is a prime number..');
end if;
<<end_point>>
dbms_output.put_line('Check complete..');
END;
-------------------------------------------------------------------------
--------
Operating WIth Selected Queries (Code Samples)
------------------------------OPERATING WITH SELECTED QUERIES------------
--------------------
declare
v_name varchar2(50);
v_salary employees.salary%type;
begin
select first_name ||' '|| last_name, salary into v_name, v_salary from
employees where employee_id = 130;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| v_salary);
end;
------------------------------
declare
v_name varchar2(50);
sysdates employees.hire_date%type;
begin
select first_name ||' '|| last_name, sysdates into v_name, sysdates
from employees where employee_id = 130;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| sysdates);
end;
------------------------------
declare
v_name varchar2(50);
v_sysdate employees.hire_date%type;
employee_id employees.employee_id%type := 130;
begin
select first_name ||' '|| last_name, sysdate into v_name, v_sysdate
from employees where employee_id = employee_id;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| v_sysdate
);
end;
------------------------------
declare
v_name varchar2(50);
v_salary employees.salary%type;
v_employee_id employees.employee_id%type := 130;
begin
select first_name ||' '|| last_name, salary into v_name, v_salary from
employees where employee_id = v_employee_id;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| v_salary
);
end;
DML Operations in PL/SQL (Code Samples)
------------------------------ DML OPERATIONS WITH PL/SQL----------------
------------------------
create table employees_copy as select * from employees;
DECLARE
v_employee_id pls_integer := 0;
v_salary_increase number := 400;
begin
for i in 217..226 loop
--insert into employees_copy
--(employee_id,first_name,last_name,email,hire_date,job_id,salary)
--values
--(i,
'employee#'||i,'temp_emp','abc@xmail.com',sysdate,'IT_PROG',1000);
--update employees_copy
--set salary = salary + v_salary_increase
--where employee_id = i;
delete from employees_copy
where employee_id = i;
end loop;
end;
Using Sequences in PL/SQL (Code Samples)
------------------------------OPERATING WITH SELECTED QUERIES------------
--------------------
declare
v_name varchar2(50);
v_salary employees.salary%type;
begin
select first_name ||' '|| last_name, salary into v_name, v_salary from
employees where employee_id = 130;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| v_salary);
end;
------------------------------
declare
v_name varchar2(50);
sysdates employees.hire_date%type;
begin
select first_name ||' '|| last_name, sysdates into v_name, sysdates
from employees where employee_id = 130;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| sysdates);
end;
------------------------------
declare
v_name varchar2(50);
v_sysdate employees.hire_date%type;
employee_id employees.employee_id%type := 130;
begin
select first_name ||' '|| last_name, sysdate into v_name, v_sysdate
from employees where employee_id = employee_id;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| v_sysdate
);
end;
------------------------------
declare
v_name varchar2(50);
v_salary employees.salary%type;
v_employee_id employees.employee_id%type := 130;
begin
select first_name ||' '|| last_name, salary into v_name, v_salary from
employees where employee_id = v_employee_id;
dbms_output.put_line('The salary of '|| v_name || ' is : '|| v_salary
);
end;
------------------------------ DML OPERATIONS WITH PL/SQL----------------
------------------------
create table employees_copy as select * from employees;
DECLARE
v_employee_id pls_integer := 0;
v_salary_increase number := 400;
begin
for i in 217..226 loop
--insert into employees_copy
--(employee_id,first_name,last_name,email,hire_date,job_id,salary)
--values
--(i,
'employee#'||i,'temp_emp','abc@xmail.com',sysdate,'IT_PROG',1000);
--update employees_copy
--set salary = salary + v_salary_increase
--where employee_id = i;
delete from employees_copy
where employee_id = i;
end loop;
end;
----------------------------- USING SEQUENCES IN PL/SQL -----------------
-----------------------
create sequence employee_id_seq
start with 207
increment by 1;
-----------------------------
begin
for i in 1..10 loop
insert into employees_copy
(employee_id,first_name,last_name,email,hire_date,job_id,salary)
values
(employee_id_seq.nextval,
'employee#'||employee_id_seq.nextval,'temp_emp','abc@xmail.com',sysdate,'
IT_PROG',1000);
end loop;
end;
----------------------------
declare
v_seq_num number;
begin
select employee_id_seq.nextval into v_seq_num from dual;
dbms_output.put_line(v_seq_num);
end;
----------------------------
declare
v_seq_num number;
begin
select employee_id_seq.nextval into v_seq_num from employees_copy where
rownum = 1;
dbms_output.put_line(v_seq_num);
end;
----------------------------
declare
v_seq_num number;
begin
v_seq_num := employee_id_seq.nextval;
dbms_output.put_line(v_seq_num);
end;
----------------------------
begin
dbms_output.put_line(employee_id_seq.nextval);
end;
----------------------------
begin
dbms_output.put_line(employee_id_seq.currval);
end;
PL/SQL Records (Code Samples)
-------------------------------------------------------------------------
-------------------------------------------
----------------------------------------------PL/SQL RECORDS-------------
-------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------
declare
r_emp employees%rowtype;
begin
select * into r_emp from employees where employee_id = '101';
--r_emp.salary := 2000;
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name|| ' earns
'||r_emp.salary||
' and hired at :' || r_emp.hire_date);
end;
------------------------------
declare
--r_emp employees%rowtype;
type t_emp is record (first_name varchar2(50),
last_name employees.last_name%type,
salary employees.salary%type,
hire_date date);
r_emp t_emp;
begin
select first_name,last_name,salary,hire_date into r_emp
from employees where employee_id = '101';
/* r_emp.first_name := 'Alex';
r_emp.salary := 2000;
r_emp.hire_date := '01-JAN-20'; */
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name|| ' earns
'||r_emp.salary||
' and hired at :' || r_emp.hire_date);
end;
-------------------------------
declare
type t_edu is record (primary_school varchar2(100),
high_school varchar2(100),
university varchar2(100),
uni_graduate_date date
);
type t_emp is record (first_name varchar2(50),
last_name employees.last_name%type,
salary employees.salary%type NOT NULL DEFAULT
1000,
hire_date date,
dept_id employees.department_id%type,
department departments%rowtype,
education t_edu
);
r_emp t_emp;
begin
select first_name,last_name,salary,hire_date,department_id
into
r_emp.first_name,r_emp.last_name,r_emp.salary,r_emp.hire_date,r_emp.dept_
id
from employees where employee_id = '146';
select * into r_emp.department from departments where department_id =
r_emp.dept_id;
r_emp.education.high_school := 'Beverly Hills';
r_emp.education.university := 'Oxford';
r_emp.education.uni_graduate_date := '01-JAN-13';
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name|| ' earns
'||r_emp.salary||
' and hired at :' || r_emp.hire_date);
dbms_output.put_line('She graduated from '||
r_emp.education.university|| ' at '||
r_emp.education.uni_graduate_date);
dbms_output.put_line('Her Department Name is : '||
r_emp.department.department_name);
end;
Easy DML With Records (Code Samples)
-------------------------------------------------------------------------
-------------------------------------------
-----------------------------------------EASY DML WITH RECORDS-----------
-------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------
create table retired_employees as select * from employees where 1=2;
select * from retired_employees;
/
declare
r_emp employees%rowtype;
begin
select * into r_emp from employees where employee_id = 104;
r_emp.salary := 0;
r_emp.commission_pct := 0;
insert into retired_employees values r_emp;
end;
-----------------------------------------
declare
r_emp employees%rowtype;
begin
select * into r_emp from employees where employee_id = 104;
r_emp.salary := 10;
r_emp.commission_pct := 0;
--insert into retired_employees values r_emp;
update retired_employees set row = r_emp where employee_id = 104;
end;
/
delete from retired_employees;
Varrays (Code Samples)
-------------------------------------------------------------------------
-------------------------------------------
---------------------------------------------------VARRAYS---------------
-------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------
---------------A simple working example
Declare
type e_list is varray(5) of varchar2(50);
employees e_list;
begin
employees := e_list('Alex','Bruce','John','Bob','Richard');
for i in 1..5 loop
dbms_output.put_line(employees(i));
end loop;
end;
---------------limit exceeding error example
declare
type e_list is varray(4) of varchar2(50);
employees e_list;
begin
employees := e_list('Alex','Bruce','John','Bob','Richard');
for i in 1..5 loop
dbms_output.put_line(employees(i));
end loop;
end;
---------------Subscript beyond cound error example
declare
type e_list is varray(5) of varchar2(50);
employees e_list;
begin
employees := e_list('Alex','Bruce','John','Bob');
for i in 1..5 loop
dbms_output.put_line(employees(i));
end loop;
end;
---------------A working count() example
declare
type e_list is varray(5) of varchar2(50);
employees e_list;
begin
employees := e_list('Alex','Bruce','John','Bob');
for i in 1..employees.count() loop
dbms_output.put_line(employees(i));
end loop;
end;
---------------A working first() last() functions example
declare
type e_list is varray(5) of varchar2(50);
employees e_list;
begin
employees := e_list('Alex','Bruce','John','Bob');
for i in employees.first()..employees.last() loop
dbms_output.put_line(employees(i));
end loop;
end;
--------------- A working exists() function example
declare
type e_list is varray(5) of varchar2(50);
employees e_list;
begin
employees := e_list('Alex','Bruce','John','Bob');
for i in 1..5 loop
if employees.exists(i) then
dbms_output.put_line(employees(i));
end if;
end loop;
end;
---------------A working limit() function example
declare
type e_list is varray(5) of varchar2(50);
employees e_list;
begin
employees := e_list('Alex','Bruce','John','Bob');
dbms_output.put_line(employees.limit());
end;
--------------- A create-declare at the same time error example
declare
type e_list is varray(5) of varchar2(50);
employees e_list('Alex','Bruce','John','Bob');
begin
-- employees := e_list('Alex','Bruce','John','Bob');
for i in 1..5 loop
if employees.exists(i) then
dbms_output.put_line(employees(i));
end if;
end loop;
end;
--------------- A post insert varray example
declare
type e_list is varray(15) of varchar2(50);
employees e_list := e_list();
idx number := 1;
begin
for i in 100..110 loop
employees.extend;
select first_name into employees(idx) from employees where
employee_id = i;
idx := idx + 1;
end loop;
for x in 1..employees.count() loop
dbms_output.put_line(employees(x));
end loop;
end;
--------------- An example for the schema level varray types
create type e_list is varray(15) of varchar2(50);
/
create or replace type e_list as varray(20) of varchar2(100);
/
declare
employees e_list := e_list();
idx number := 1;
begin
for i in 100..110 loop
employees.extend;
select first_name into employees(idx) from employees where
employee_id = i;
idx := idx + 1;
end loop;
for x in 1..employees.count() loop
dbms_output.put_line(employees(x));
end loop;
end;
/
DROP TYPE E_LIST;
Nested Tables (Code Samples)
-------------------------------------------------------------------------
-------------------------------------------
-------------------------------------------------NESTED TABLES-----------
-------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------
---------------The simple usage of nested tables
declare
type e_list is table of varchar2(50);
emps e_list;
begin
emps := e_list('Alex','Bruce','John');
for i in 1..emps.count() loop
dbms_output.put_line(emps(i));
end loop;
end;
---------------Adding a new value to a nested table after the
initialization
declare
type e_list is table of varchar2(50);
emps e_list;
begin
emps := e_list('Alex','Bruce','John');
emps.extend;
emps(4) := 'Bob';
for i in 1..emps.count() loop
dbms_output.put_line(emps(i));
end loop;
end;
---------------Adding values from the tabledeclare
type e_list is table of employees.first_name%type;
emps e_list := e_list();
idx pls_integer := 1;
begin
for x in 100 .. 110 loop
emps.extend;
select first_name into emps(idx) from employees where employee_id =
x;
idx := idx + 1;
end loop;
for i in 1..emps.count() loop
dbms_output.put_line(emps(i));
end loop;
end;
---------------delete example
declare
type e_list is table of employees.first_name%type;
emps e_list := e_list();
idx pls_integer := 1;
begin
for x in 100 .. 110 loop
emps.extend;
select first_name into emps(idx) from employees where employee_id =
x;
idx := idx + 1;
end loop;
emps.delete(3);
for i in 1..emps.count() loop
if emps.exists(i) then
dbms_output.put_line(emps(i));
end if;
end loop;
end;
Associative Arrays (Code Samples)
-------------------------------------------------------------------------
-------------------------------------------
----------------------------------------------ASSOCIATIVE ARRAYS---------
-------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------
---------------The first example
declare
type e_list is table of employees.first_name%type index by pls_integer;
emps e_list;
begin
for x in 100 .. 110 loop
select first_name into emps(x) from employees
where employee_id = x ;
end loop;
for i in emps.first()..emps.last() loop
dbms_output.put_line(emps(i));
end loop;
end;
---------------Error example for the select into clause
declare
type e_list is table of employees.first_name%type index by pls_integer;
emps e_list;
begin
for x in 100 .. 110 loop
select first_name into emps(x) from employees
where employee_id = x and department_id = 60;
end loop;
for i in emps.first()..emps.last() loop
dbms_output.put_line(i);
end loop;
end;
---------------Error example about reaching the empty indexdeclare
type e_list is table of employees.first_name%type index by pls_integer;
emps e_list;
begin
emps(100) := 'Bob';
emps(120) := 'Sue';
for i in emps.first()..emps.last() loop
dbms_output.put_line(emps(i));
end loop;
end;
---------------An example of iterating in associative arrays with while
loops
declare
type e_list is table of employees.first_name%type index by pls_integer;
emps e_list;
idx pls_integer;
begin
emps(100) := 'Bob';
emps(120) := 'Sue';
idx := emps.first;
while idx is not null loop
dbms_output.put_line(emps(idx));
idx := emps.next(idx);
end loop;
end;
---------------An example of using string based indexes with associative
arrays
declare
type e_list is table of employees.first_name%type index by
employees.email%type;
emps e_list;
idx employees.email%type;
v_email employees.email%type;
v_first_name employees.first_name%type;
begin
for x in 100 .. 110 loop
select first_name,email into v_first_name,v_email from employees
where employee_id = x;
emps(v_email) := v_first_name;
end loop;
idx := emps.first;
while idx is not null loop
dbms_output.put_line('The email of '|| emps(idx) ||' is : '|| idx);
idx := emps.next(idx);
end loop;
end;
---------------An example of using associative arrays with records
declare
type e_list is table of employees%rowtype index by
employees.email%type;
emps e_list;
idx employees.email%type;
begin
for x in 100 .. 110 loop
select * into emps(x) from employees
where employee_id = x;
end loop;
idx := emps.first;
while idx is not null loop
dbms_output.put_line('The email of '|| emps(idx).first_name
||' '||emps(idx).last_name||' is : '|| emps(idx).email);
idx := emps.next(idx);
end loop;
end;
---------------An example of using associative arrays with record types
declare
type e_type is record (first_name employees.first_name%type,
last_name employees.last_name%type,
email employees.email%type);
type e_list is table of e_type index by employees.email%type;
emps e_list;
idx employees.email%type;
begin
for x in 100 .. 110 loop
select first_name,last_name,email into emps(x) from employees
where employee_id = x;
end loop;
idx := emps.first;
while idx is not null loop
dbms_output.put_line('The email of '|| emps(idx).first_name
||' '||emps(idx).last_name||' is : '|| emps(idx).email);
idx := emps.next(idx);
end loop;
end;
---------------An example of printing from the last to the first
declare
type e_type is record (first_name employees.first_name%type,
last_name employees.last_name%type,
email employees.email%type);
type e_list is table of e_type index by employees.email%type;
emps e_list;
idx employees.email%type;
begin
for x in 100 .. 110 loop
select first_name,last_name,email into emps(x) from employees
where employee_id = x;
end loop;
--emps.delete(100,104);
idx := emps.last;
while idx is not null loop
dbms_output.put_line('The email of '|| emps(idx).first_name
||' '||emps(idx).last_name||' is : '|| emps(idx).email);
idx := emps.prior(idx);
end loop;
end;
---------------An example of inserting with associative arrays
create table employees_salary_history as select * from employees where
1=2;
alter table employees_salary_history add insert_date date;
select * from employees_salary_history;
/
declare
type e_list is table of employees_salary_history%rowtype index by
pls_integer;
emps e_list;
idx pls_integer;
begin
for x in 100 .. 110 loop
select e.*,'01-JUN-20' into emps(x) from employees e
where employee_id = x;
end loop;
idx := emps.first;
while idx is not null loop
emps(idx).salary := emps(idx).salary + emps(idx).salary*0.2;
insert into employees_salary_history values emps(idx);
dbms_output.put_line('The employee '|| emps(idx).first_name
||' is inserted to the history table');
idx := emps.next(idx);
end loop;
end;
/
drop table employees_salary_history;
Storing Collections in Tables (Code Samples)
-------------------------------------------------------------------------
-------------------------------------------
---------------------------------------STORING COLLECTIONS IN TABLES-----
-------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------
---------------Storing Varray Example
create or replace type t_phone_number as object (p_type varchar2(10),
p_number varchar2(50));
/
create or replace type v_phone_numbers as varray(3) of t_phone_number;
/
create table emps_with_phones (employee_id number,
first_name varchar2(50),
last_name varchar2(50),
phone_number v_phone_numbers);
/
select * from emps_with_phones;
/
insert into emps_with_phones values (10,'Alex','Brown',v_phone_numbers(
t_phone_number('HOME','111.111.1111'),
t_phone_number('WORK','222.222.2222'),
t_phone_number('MOBILE','333.333.3333')
));
insert into emps_with_phones values (11,'Bob','Green',v_phone_numbers(
t_phone_number('HOME','000.000.000'),
t_phone_number('WORK','444.444.4444')
));
/
---------------Querying the varray example
select e.first_name,last_name,p.p_type,p.p_number from emps_with_phones
e, table(e.phone_number) p;
---------------The codes for the storing nested table example
create or replace type n_phone_numbers as table of t_phone_number;
/
create table emps_with_phones2 (employee_id number,
first_name varchar2(50),
last_name varchar2(50),
phone_number n_phone_numbers)
NESTED TABLE phone_number STORE AS
phone_numbers_table;
/
select * from emps_with_phones2;
/
insert into emps_with_phones2 values (10,'Alex','Brown',n_phone_numbers(
t_phone_number('HOME','111.111.1111'),
t_phone_number('WORK','222.222.2222'),
t_phone_number('MOBILE','333.333.3333')
));
insert into emps_with_phones2 values (11,'Bob','Green',n_phone_numbers(
t_phone_number('HOME','000.000.000'),
t_phone_number('WORK','444.444.4444')
));
/
select e.first_name,last_name,p.p_type,p.p_number from emps_with_phones2
e, table(e.phone_number) p;
---------------new insert and update
insert into emps_with_phones2 values (11,'Bob','Green',n_phone_numbers(
t_phone_number('HOME','000.000.000'),
t_phone_number('WORK','444.444.4444'),
t_phone_number('WORK2','444.444.4444'),
t_phone_number('WORK3','444.444.4444'),
t_phone_number('WORK4','444.444.4444'),
t_phone_number('WORK5','444.444.4444')
));
select * from emps_with_phones2;
update emps_with_phones2 set phone_number = n_phone_numbers(
t_phone_number('HOME','000.000.000'),
t_phone_number('WORK','444.444.4444'),
t_phone_number('WORK2','444.444.4444'),
t_phone_number('WORK3','444.444.4444'),
t_phone_number('WORK4','444.444.4444'),
t_phone_number('WORK5','444.444.4444')
)
where employee_id = 11;
---------------Adding a new value into the nested table inside of a table
declare
p_num n_phone_numbers;
begin
select phone_number into p_num from emps_with_phones2 where employee_id
= 10;
p_num.extend;
p_num(5) := t_phone_number('FAX','999.99.9999');
UPDATE emps_with_phones2 set phone_number = p_num where employee_id =
10;
end;
Using Explicit Cursors (Code Samples)
declare
cursor c_emps is select first_name,last_name from employees;
v_first_name employees.first_name%type;
v_last_name employees.last_name%type;
begin
open c_emps;
fetch c_emps into v_first_name,v_last_name;
fetch c_emps into v_first_name,v_last_name;
fetch c_emps into v_first_name,v_last_name;
dbms_output.put_line(v_first_name|| ' ' || v_last_name);
fetch c_emps into v_first_name,v_last_name;
dbms_output.put_line(v_first_name|| ' ' || v_last_name);
close c_emps;
end;
--------------- cursor with join example
declare
cursor c_emps is select first_name,last_name, department_name from
employees
join departments using (department_id)
where department_id between 30 and 60;
v_first_name employees.first_name%type;
v_last_name employees.last_name%type;
v_department_name departments.department_name%type;
begin
open c_emps;
fetch c_emps into v_first_name, v_last_name,v_department_name;
dbms_output.put_line(v_first_name|| ' ' || v_last_name|| ' in the
department of '|| v_department_name);
close c_emps;
end;
Cursors with Records (Code Samples)
declare
type r_emp is record ( v_first_name employees.first_name%type,
v_last_name employees.last_name%type);
v_emp r_emp;
cursor c_emps is select first_name,last_name from employees;
begin
open c_emps;
fetch c_emps into v_emp;
dbms_output.put_line(v_emp.v_first_name|| ' ' || v_emp.v_last_name);
close c_emps;
end;
--------------- An example for using cursors table rowtype
declare
v_emp employees%rowtype;
cursor c_emps is select first_name,last_name from employees;
begin
open c_emps;
fetch c_emps into v_emp.first_name,v_emp.last_name;
dbms_output.put_line(v_emp.first_name|| ' ' || v_emp.last_name);
close c_emps;
end;
--------------- An example for using cursors with cursor%rowtype.
declare
cursor c_emps is select first_name,last_name from employees;
v_emp c_emps%rowtype;
begin
open c_emps;
fetch c_emps into v_emp.first_name,v_emp.last_name;
dbms_output.put_line(v_emp.first_name|| ' ' || v_emp.last_name);
close c_emps;
end;
Looping with Cursors (Code Samples)
declare
cursor c_emps is select * from employees where department_id = 30;
v_emps c_emps%rowtype;
begin
open c_emps;
loop
fetch c_emps into v_emps;
dbms_output.put_line(v_emps.employee_id|| ' ' ||v_emps.first_name|| '
' ||v_emps.last_name);
end loop;
close c_emps;
end;
---------------%notfound example
declare
cursor c_emps is select * from employees where department_id = 30;
v_emps c_emps%rowtype;
begin
open c_emps;
loop
fetch c_emps into v_emps;
exit when c_emps%notfound;
dbms_output.put_line(v_emps.employee_id|| ' ' ||v_emps.first_name|| '
' ||v_emps.last_name);
end loop;
close c_emps;
end;
---------------while loop example
declare
cursor c_emps is select * from employees where department_id = 30;
v_emps c_emps%rowtype;
begin
open c_emps;
fetch c_emps into v_emps;
while c_emps%found loop
dbms_output.put_line(v_emps.employee_id|| ' ' ||v_emps.first_name|| '
' ||v_emps.last_name);
fetch c_emps into v_emps;
--exit when c_emps%notfound;
end loop;
close c_emps;
end;
---------------for loop with cursor example
declare
cursor c_emps is select * from employees where department_id = 30;
v_emps c_emps%rowtype;
begin
open c_emps;
for i in 1..6 loop
fetch c_emps into v_emps;
dbms_output.put_line(v_emps.employee_id|| ' ' ||v_emps.first_name|| '
' ||v_emps.last_name);
end loop;
close c_emps;
end;
---------------FOR..IN clause example
declare
cursor c_emps is select * from employees where department_id = 30;
begin
for i in c_emps loop
dbms_output.put_line(i.employee_id|| ' ' ||i.first_name|| ' '
||i.last_name);
end loop;
end;
---------------FOR..IN with select example
begin
for i in (select * from employees where department_id = 30) loop
dbms_output.put_line(i.employee_id|| ' ' ||i.first_name|| ' '
||i.last_name);
end loop;
end;
PL SQL Cursors with Parameters (Code Samples)
declare
cursor c_emps (p_dept_id number) is select
first_name,last_name,department_name
from employees join departments using (department_id)
where department_id = p_dept_id;
v_emps c_emps%rowtype;
begin
open c_emps(20);
fetch c_emps into v_emps;
dbms_output.put_line('The employees in department of '||
v_emps.department_name|| ' are :');
close c_emps;
open c_emps(20);
loop
fetch c_emps into v_emps;
exit when c_emps%notfound;
dbms_output.put_line(v_emps.first_name|| ' ' ||v_emps.last_name);
end loop;
close c_emps;
end;
--------------- bind variables as parameters
declare
cursor c_emps (p_dept_id number) is select
first_name,last_name,department_name
from employees join departments using (department_id)
where department_id = p_dept_id;
v_emps c_emps%rowtype;
begin
open c_emps(:b_emp);
fetch c_emps into v_emps;
dbms_output.put_line('The employees in department of '||
v_emps.department_name|| ' are :');
close c_emps;
open c_emps(:b_emp);
loop
fetch c_emps into v_emps;
exit when c_emps%notfound;
dbms_output.put_line(v_emps.first_name|| ' ' ||v_emps.last_name);
end loop;
close c_emps;
end;
---------------cursors with two different parameters
declare
cursor c_emps (p_dept_id number) is select
first_name,last_name,department_name
from employees join departments using (department_id)
where department_id = p_dept_id;
v_emps c_emps%rowtype;
begin
open c_emps(:b_dept_id);
fetch c_emps into v_emps;
dbms_output.put_line('The employees in department of '||
v_emps.department_name|| ' are :');
close c_emps;
open c_emps(:b_dept_id);
loop
fetch c_emps into v_emps;
exit when c_emps%notfound;
dbms_output.put_line(v_emps.first_name|| ' ' ||v_emps.last_name);
end loop;
close c_emps;
open c_emps(:b_dept_id2);
fetch c_emps into v_emps;
dbms_output.put_line('The employees in department of '||
v_emps.department_name|| ' are :');
close c_emps;
open c_emps(:b_dept_id2);
loop
fetch c_emps into v_emps;
exit when c_emps%notfound;
dbms_output.put_line(v_emps.first_name|| ' ' ||v_emps.last_name);
end loop;
close c_emps;
end;
--------------- cursor with parameters - for in loops
declare
cursor c_emps (p_dept_id number) is select
first_name,last_name,department_name
from employees join departments using (department_id)
where department_id = p_dept_id;
v_emps c_emps%rowtype;
begin
open c_emps(:b_dept_id);
fetch c_emps into v_emps;
dbms_output.put_line('The employees in department of '||
v_emps.department_name|| ' are :');
close c_emps;
open c_emps(:b_dept_id);
loop
fetch c_emps into v_emps;
exit when c_emps%notfound;
dbms_output.put_line(v_emps.first_name|| ' ' ||v_emps.last_name);
end loop;
close c_emps;
open c_emps(:b_dept_id2);
fetch c_emps into v_emps;
dbms_output.put_line('The employees in department of '||
v_emps.department_name|| ' are :');
close c_emps;
for i in c_emps(:b_dept_id2) loop
dbms_output.put_line(i.first_name|| ' ' ||i.last_name);
end loop;
end;
---------------cursors with multiple parameters
declare
cursor c_emps (p_dept_id number , p_job_id varchar2) is select
first_name,last_name,job_id,department_name
from employees join departments using (department_id)
where department_id = p_dept_id
and job_id = p_job_id;
v_emps c_emps%rowtype;
begin
for i in c_emps(50,'ST_MAN') loop
dbms_output.put_line(i.first_name|| ' ' ||i.last_name|| ' - ' ||
i.job_id);
end loop;
dbms_output.put_line(' - ');
for i in c_emps(80,'SA_MAN') loop
dbms_output.put_line(i.first_name|| ' ' ||i.last_name|| ' - ' ||
i.job_id);
end loop;
end;
--------------- An error example of using parameter name with the column
name
declare
cursor c_emps (p_dept_id number , job_id varchar2) is select
first_name,last_name,job_id,department_name
from employees join departments using (department_id)
where department_id = p_dept_id
and job_id = job_id;
v_emps c_emps%rowtype;
begin
for i in c_emps(50,'ST_MAN') loop
dbms_output.put_line(i.first_name|| ' ' ||i.last_name|| ' - ' ||
i.job_id);
end loop;
dbms_output.put_line(' - ');
for i in c_emps(80,'SA_MAN') loop
dbms_output.put_line(i.first_name|| ' ' ||i.last_name|| ' - ' ||
i.job_id);
end loop;
end;
PL SQL Cursor Attributes (Code Samples)
declare
cursor c_emps is select * from employees where department_id = 50;
v_emps c_emps%rowtype;
begin
if not c_emps%isopen then
open c_emps;
dbms_output.put_line('hello');
end if;
dbms_output.put_line(c_emps%rowcount);
fetch c_emps into v_emps;
dbms_output.put_line(c_emps%rowcount);
dbms_output.put_line(c_emps%rowcount);
fetch c_emps into v_emps;
dbms_output.put_line(c_emps%rowcount);
close c_emps;
open c_emps;
loop
fetch c_emps into v_emps;
exit when c_emps%notfound or c_emps%rowcount>5;
dbms_output.put_line(c_emps%rowcount|| ' ' ||v_emps.first_name|| '
' ||v_emps.last_name);
end loop;
close c_emps;
end;
For Update Clause (Code Samples)
grant create session to my_user;
grant select any table to my_user;
grant update on hr.employees_copy to my_user;
grant update on hr.departments to my_user;
UPDATE EMPLOYEES_COPY SET PHONE_NUMBER = '1' WHERE EMPLOYEE_ID = 100;
declare
cursor c_emps is select
employee_id,first_name,last_name,department_name
from employees_copy join departments using (department_id)
where employee_id in (100,101,102)
for update;
begin
/* for r_emps in c_emps loop
update employees_copy set phone_number = 3
where employee_id = r_emps.employee_id;
end loop; */
open c_emps;
end;
--------------- example of wait with second
declare
cursor c_emps is select
employee_id,first_name,last_name,department_name
from employees_copy join departments using (department_id)
where employee_id in (100,101,102)
for update of employees_copy.phone_number,
departments.location_id wait 5;
begin
/* for r_emps in c_emps loop
update employees_copy set phone_number = 3
where employee_id = r_emps.employee_id;
end loop; */
open c_emps;
end;
---------------example of nowait
declare
cursor c_emps is select
employee_id,first_name,last_name,department_name
from employees_copy join departments using (department_id)
where employee_id in (100,101,102)
for update of employees_copy.phone_number,
departments.location_id nowait;
begin
/* for r_emps in c_emps loop
update employees_copy set phone_number = 3
where employee_id = r_emps.employee_id;
end loop; */
open c_emps;
end;
Where Current Of Clause (Code Samples)
declare
cursor c_emps is select * from employees
where department_id = 30 for update;
begin
for r_emps in c_emps loop
update employees set salary = salary + 60
where current of c_emps;
end loop;
end;
---------------Wrong example of using where current of clause
declare
cursor c_emps is select e.* from employees e, departments d
where
e.department_id = d.department_id
and e.department_id = 30 for update;
begin
for r_emps in c_emps loop
update employees set salary = salary + 60
where current of c_emps;
end loop;
end;
---------------An example of using rowid like where current of clause
declare
cursor c_emps is select e.rowid,e.salary from employees e, departments
d
where
e.department_id = d.department_id
and e.department_id = 30 for update;
begin
for r_emps in c_emps loop
update employees set salary = salary + 60
where rowid = r_emps.rowid;
end loop;
end;
Reference Cursors - (Code Samples)
declare
type t_emps is ref cursor return employees%rowtype;
rc_emps t_emps;
r_emps employees%rowtype;
begin
open rc_emps for select * from employees;
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name);
end loop;
close rc_emps;
end;
--------------- in two different queries
declare
type t_emps is ref cursor return employees%rowtype;
rc_emps t_emps;
r_emps employees%rowtype;
begin
open rc_emps for select * from retired_employees;
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name);
end loop;
close rc_emps;
dbms_output.put_line('--------------');
open rc_emps for select * from employees where job_id = 'IT_PROG';
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name);
end loop;
close rc_emps;
end;
---------------Example of using with %type when declaring records first
declare
r_emps employees%rowtype;
type t_emps is ref cursor return r_emps%type;
rc_emps t_emps;
--type t_emps2 is ref cursor return rc_emps%rowtype;
begin
open rc_emps for select * from retired_employees;
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name);
end loop;
close rc_emps;
dbms_output.put_line('--------------');
open rc_emps for select * from employees where job_id = 'IT_PROG';
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name);
end loop;
close rc_emps;
end;
---------------manually declared record type with cursors example
declare
type ty_emps is record (e_id number,
first_name employees.last_name%type,
last_name employees.last_name%type,
department_name
departments.department_name%type);
r_emps ty_emps;
type t_emps is ref cursor return ty_emps;
rc_emps t_emps;
begin
open rc_emps for select
employee_id,first_name,last_name,department_name
from employees join departments using
(department_id);
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name||
' is at the department of : '|| r_emps.department_name );
end loop;
close rc_emps;
end;
---------------first example of weak ref cursors
declare
type ty_emps is record (e_id number,
first_name employees.last_name%type,
last_name employees.last_name%type,
department_name
departments.department_name%type);
r_emps ty_emps;
type t_emps is ref cursor;
rc_emps t_emps;
q varchar2(200);
begin
q := 'select employee_id,first_name,last_name,department_name
from employees join departments using
(department_id)';
open rc_emps for q;
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name||
' is at the department of : '|| r_emps.department_name );
end loop;
close rc_emps;
end;
--------------- bind variables with cursors example
declare
type ty_emps is record (e_id number,
first_name employees.last_name%type,
last_name employees.last_name%type,
department_name
departments.department_name%type);
r_emps ty_emps;
type t_emps is ref cursor;
rc_emps t_emps;
r_depts departments%rowtype;
--r t_emps%rowtype;
q varchar2(200);
begin
q := 'select employee_id,first_name,last_name,department_name
from employees join departments using
(department_id)
where department_id = :t';
open rc_emps for q using '50';
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name||
' is at the department of : '|| r_emps.department_name );
end loop;
close rc_emps;
open rc_emps for select * from departments;
loop
fetch rc_emps into r_depts;
exit when rc_emps%notfound;
dbms_output.put_line(r_depts.department_id|| ' ' ||
r_depts.department_name);
end loop;
close rc_emps;
end;
---------------sys_refcursor example
declare
type ty_emps is record (e_id number,
first_name employees.last_name%type,
last_name employees.last_name%type,
department_name
departments.department_name%type);
r_emps ty_emps;
-- type t_emps is ref cursor;
rc_emps sys_refcursor;
r_depts departments%rowtype;
--r t_emps%rowtype;
q varchar2(200);
begin
q := 'select employee_id,first_name,last_name,department_name
from employees join departments using
(department_id)
where department_id = :t';
open rc_emps for q using '50';
loop
fetch rc_emps into r_emps;
exit when rc_emps%notfound;
dbms_output.put_line(r_emps.first_name|| ' ' || r_emps.last_name||
' is at the department of : '|| r_emps.department_name );
end loop;
close rc_emps;
open rc_emps for select * from departments;
loop
fetch rc_emps into r_depts;
exit when rc_emps%notfound;
dbms_output.put_line(r_depts.department_id|| ' ' ||
r_depts.department_name);
end loop;
close rc_emps;
end;
What are the Exceptions (Code Sample)
declare
v_name varchar2(6);
begin
select first_name into v_name from employees where employee_id = 50;
dbms_output.put_line('Hello');
end;
Handling the Exceptions (Code Samples)
----------------- Handling the exception
declare
v_name varchar2(6);
begin
select first_name into v_name from employees where employee_id = 50;
dbms_output.put_line('Hello');
exception
when no_data_found then
dbms_output.put_line('There is no employee with the selected id');
end;
----------------- Handling multiple exceptions
declare
v_name varchar2(6);
v_department_name varchar2(100);
begin
select first_name into v_name from employees where employee_id = 100;
select department_id into v_department_name from employees where
first_name = v_name;
dbms_output.put_line('Hello '|| v_name || '. Your department id is :
'|| v_department_name );
exception
when no_data_found then
dbms_output.put_line('There is no employee with the selected id');
when too_many_rows then
dbms_output.put_line('There are more than one employees with the name
'|| v_name);
dbms_output.put_line('Try with a different employee');
end;
----------------- when others then example
declare
v_name varchar2(6);
v_department_name varchar2(100);
begin
select first_name into v_name from employees where employee_id = 103;
select department_id into v_department_name from employees where
first_name = v_name;
dbms_output.put_line('Hello '|| v_name || '. Your department id is :
'|| v_department_name );
exception
when no_data_found then
dbms_output.put_line('There is no employee with the selected id');
when too_many_rows then
dbms_output.put_line('There are more than one employees with the name
'|| v_name);
dbms_output.put_line('Try with a different employee');
when others then
dbms_output.put_line('An unexpected error happened. Connect with the
programmer..');
end;
----------------- sqlerrm & sqlcode example
declare
v_name varchar2(6);
v_department_name varchar2(100);
begin
select first_name into v_name from employees where employee_id = 103;
select department_id into v_department_name from employees where
first_name = v_name;
dbms_output.put_line('Hello '|| v_name || '. Your department id is :
'|| v_department_name );
exception
when no_data_found then
dbms_output.put_line('There is no employee with the selected id');
when too_many_rows then
dbms_output.put_line('There are more than one employees with the name
'|| v_name);
dbms_output.put_line('Try with a different employee');
when others then
dbms_output.put_line('An unexpected error happened. Connect with the
programmer..');
dbms_output.put_line(sqlcode || ' ---> '|| sqlerrm);
end;
----------------- Inner block exception example
declare
v_name varchar2(6);
v_department_name varchar2(100);
begin
select first_name into v_name from employees where employee_id = 100;
begin
select department_id into v_department_name from employees where
first_name = v_name;
exception
when too_many_rows then
v_department_name := 'Error in department_name';
end;
dbms_output.put_line('Hello '|| v_name || '. Your department id is :
'|| v_department_name );
exception
when no_data_found then
dbms_output.put_line('There is no employee with the selected id');
when too_many_rows then
dbms_output.put_line('There are more than one employees with the name
'|| v_name);
dbms_output.put_line('Try with a different employee');
when others then
dbms_output.put_line('An unexpected error happened. Connect with the
programmer..');
dbms_output.put_line(sqlcode || ' ---> '|| sqlerrm);
end;
/
select * from employees where first_name = 'Steven';
Handling Nonpredefined Exceptions (Code Sample)
begin
UPDATE employees_copy set email = null where employee_id = 100;
end;
-----------------HANDLING a nonpredefined exception
declare
cannot_update_to_null exception;
pragma exception_init(cannot_update_to_null,-01407);
begin
UPDATE employees_copy set email = null where employee_id = 100;
exception
when cannot_update_to_null then
dbms_output.put_line('You cannot update with a null value!');
end;
Handling & Raising User-Defined Exceptions (Code Samples)
----------------- creating a user defined exception
declare
too_high_salary exception;
v_salary_check pls_integer;
begin
select salary into v_salary_check from employees where employee_id =
100;
if v_salary_check > 20000 then
raise too_high_salary;
end if;
--we do our business if the salary is under 2000
dbms_output.put_line('The salary is in an acceptable range');
exception
when too_high_salary then
dbms_output.put_line('This salary is too high. You need to decrease
it.');
end;
----------------- raising a predefined exception
declare
too_high_salary exception;
v_salary_check pls_integer;
begin
select salary into v_salary_check from employees where employee_id =
100;
if v_salary_check > 20000 then
raise invalid_number;
end if;
--we do our business if the salary is under 2000
dbms_output.put_line('The salary is in an acceptable range');
exception
when invalid_number then
dbms_output.put_line('This salary is too high. You need to decrease
it.');
end;
----------------- raising inside of the exception
declare
too_high_salary exception;
v_salary_check pls_integer;
begin
select salary into v_salary_check from employees where employee_id =
100;
if v_salary_check > 20000 then
raise invalid_number;
end if;
--we do our business if the salary is under 2000
dbms_output.put_line('The salary is in an acceptable range');
exception
when invalid_number then
dbms_output.put_line('This salary is too high. You need to decrease
it.');
raise;
end;
Using RAISE_APPLICATION_ERROR() Procedure (Code Samples)
declare
too_high_salary exception;
v_salary_check pls_integer;
begin
select salary into v_salary_check from employees where employee_id =
100;
if v_salary_check > 20000 then
--raise too_high_salary;
raise_application_error(-20243,'The salary of the selected employee is
too high!');
end if;
--we do our business if the salary is under 2000
dbms_output.put_line('The salary is in an acceptable range');
exception
when too_high_salary then
dbms_output.put_line('This salary is too high. You need to decrease
it.');
end;
----------------- raise inside of the exception section
declare
too_high_salary exception;
v_salary_check pls_integer;
begin
select salary into v_salary_check from employees where employee_id =
100;
if v_salary_check > 20000 then
raise too_high_salary;
end if;
--we do our business if the salary is under 2000
dbms_output.put_line('The salary is in an acceptable range');
exception
when too_high_salary then
dbms_output.put_line('This salary is too high. You need to decrease
it.');
raise_application_error(-01403,'The salary of the selected employee is
too high!',true);
end;
What are Functions & Procedures and Why We Use (Code Samples)
-----------------An anonymous block example
declare
cursor c_emps is select * from employees_copy for update;
v_salary_increase number:= 1.10;
v_old_salary number;
begin
for r_emp in c_emps loop
v_old_salary := r_emp.salary;
r_emp.salary := r_emp.salary*v_salary_increase + r_emp.salary *
nvl(r_emp.commission_pct,0);
update employees_copy set row = r_emp where current of c_emps;
dbms_output.put_line('The salary of : '|| r_emp.employee_id
|| ' is increased from '||v_old_salary||' to
'||r_emp.salary);
end loop;
end;
-----------------An anonymous block example 2
declare
cursor c_emps is select * from employees_copy for update;
v_salary_increase number:= 1.10;
v_old_salary number;
v_new_salary number;
v_salary_max_limit pls_integer := 20000;
begin
for r_emp in c_emps loop
v_old_salary := r_emp.salary;
--check salary area
v_new_salary := r_emp.salary*v_salary_increase + r_emp.salary *
nvl(r_emp.commission_pct,0);
if v_new_salary > v_salary_max_limit then
RAISE_APPLICATION_ERROR(-20000, 'The new salary of
'||r_emp.first_name|| ' cannot be higher than '|| v_salary_max_limit);
end if;
r_emp.salary := r_emp.salary*v_salary_increase + r_emp.salary *
nvl(r_emp.commission_pct,0);
----------
update employees_copy set row = r_emp where current of c_emps;
dbms_output.put_line('The salary of : '|| r_emp.employee_id
|| ' is increased from '||v_old_salary||' to
'||r_emp.salary);
end loop;
end;
Creating and Using Stored Procedures (Code Samples)
----------------- Creating a procedure
create procedure increase_salaries as
cursor c_emps is select * from employees_copy for update;
v_salary_increase number := 1.10;
v_old_salary number;
begin
for r_emp in c_emps loop
v_old_salary := r_emp.salary;
r_emp.salary := r_emp.salary * v_salary_increase + r_emp.salary *
nvl(r_emp.commission_pct,0);
update employees_copy set row = r_emp where current of c_emps;
dbms_output.put_line('The salary of : '|| r_emp.employee_id
|| ' is increased from '||v_old_salary||' to
'||r_emp.salary);
end loop;
end;
----------------- Multiple procedure usage
begin
dbms_output.put_line('Increasing the salaries!...');
INCREASE_SALARIES;
INCREASE_SALARIES;
INCREASE_SALARIES;
INCREASE_SALARIES;
dbms_output.put_line('All the salaries are successfully
increased!...');
end;
----------------- Different procedures in one block
begin
dbms_output.put_line('Increasing the salaries!...');
INCREASE_SALARIES;
new_line;
INCREASE_SALARIES;
new_line;
INCREASE_SALARIES;
new_line;
INCREASE_SALARIES;
dbms_output.put_line('All the salaries are successfully
increased!...');
end;
-----------------Creating a procedure to ease the dbms_output.put_line
procedure
create procedure new_line as
begin
dbms_output.put_line('------------------------------------------');
end;
-----------------Modifying the procedure with using the OR REPLACE
command.
create or replace procedure increase_salaries as
cursor c_emps is select * from employees_copy for update;
v_salary_increase number := 1.10;
v_old_salary number;
begin
for r_emp in c_emps loop
v_old_salary := r_emp.salary;
r_emp.salary := r_emp.salary * v_salary_increase + r_emp.salary *
nvl(r_emp.commission_pct,0);
update employees_copy set row = r_emp where current of c_emps;
dbms_output.put_line('The salary of : '|| r_emp.employee_id
|| ' is increased from '||v_old_salary||' to
'||r_emp.salary);
end loop;
dbms_output.put_line('Procedure finished executing!');
end
Using IN & OUT Parameters (Code Samples)
-----------------Creating a procedure with the IN parameters
create or replace procedure increase_salaries (v_salary_increase in
number, v_department_id pls_integer) as
cursor c_emps is select * from employees_copy where department_id =
v_department_id for update;
v_old_salary number;
begin
for r_emp in c_emps loop
v_old_salary := r_emp.salary;
r_emp.salary := r_emp.salary * v_salary_increase + r_emp.salary *
nvl(r_emp.commission_pct,0);
update employees_copy set row = r_emp where current of c_emps;
dbms_output.put_line('The salary of : '|| r_emp.employee_id
|| ' is increased from '||v_old_salary||' to
'||r_emp.salary);
end loop;
dbms_output.put_line('Procedure finished executing!');
end;
----------------- Creating a procedure with the OUT parameters
create or replace procedure increase_salaries
(v_salary_increase in out number, v_department_id pls_integer,
v_affected_employee_count out number) as
cursor c_emps is select * from employees_copy where department_id =
v_department_id for update;
v_old_salary number;
v_sal_inc number := 0;
begin
v_affected_employee_count := 0;
for r_emp in c_emps loop
v_old_salary := r_emp.salary;
r_emp.salary := r_emp.salary * v_salary_increase + r_emp.salary *
nvl(r_emp.commission_pct,0);
update employees_copy set row = r_emp where current of c_emps;
dbms_output.put_line('The salary of : '|| r_emp.employee_id
|| ' is increased from '||v_old_salary||' to
'||r_emp.salary);
v_affected_employee_count := v_affected_employee_count + 1;
v_sal_inc := v_sal_inc + v_salary_increase +
nvl(r_emp.commission_pct,0);
end loop;
v_salary_increase := v_sal_inc / v_affected_employee_count;
dbms_output.put_line('Procedure finished executing!');
end;
-----------------Another example of creating a procedure with the IN
parameter
CREATE OR REPLACE PROCEDURE PRINT(TEXT IN VARCHAR2) IS
BEGIN
DBMS_OUTPUT.PUT_LINE(TEXT);
END;
-----------------Using the procedures that has the IN parameters
begin
PRINT('SALARY INCREASE STARTED!..');
INCREASE_SALARIES(1.15,90);
PRINT('SALARY INCREASE FINISHED!..');
end;
-----------------Using the procedure that has OUT parameters
declare
v_sal_inc number := 1.2;
v_aff_emp_count number;
begin
PRINT('SALARY INCREASE STARTED!..');
INCREASE_SALARIES(v_sal_inc,80,v_aff_emp_count);
PRINT('The affected employee count is : '|| v_aff_emp_count);
PRINT('The average salary increase is : '|| v_sal_inc || ' percent!..');
PRINT('SALARY INCREASE FINISHED!..');
end;
Named & Mixed Notations and Default Option (Code Samples)
----------------- A standard procedure creation with a default value
create or replace PROCEDURE PRINT(TEXT IN VARCHAR2 := 'This is the print
function!.') IS
BEGIN
DBMS_OUTPUT.PUT_LINE(TEXT);
END;
-----------------Executing a procedure without any parameter. It runs
because it has a default value.
exec print();
-----------------Running a procedure with null value will not use the
default value
exec print(null);
-----------------Procedure creation of a default value usage
create or replace procedure add_job(job_id pls_integer, job_title
varchar2,
min_salary number default 1000,
max_salary number default null) is
begin
insert into jobs values (job_id,job_title,min_salary,max_salary);
print('The job : '|| job_title || ' is inserted!..');
end;
-----------------A standard run of the procedure
exec ADD_JOB('IT_DIR','IT Director',5000,20000);
-----------------Running a procedure with using the default values
exec ADD_JOB('IT_DIR2','IT Director',5000);
-----------------Running a procedure with the named notation
exec ADD_JOB('IT_DIR5','IT Director',max_salary=>10000);
-----------------Running a procedure with the named notation example 2
exec ADD_JOB(job_title=>'IT Director',job_id=>'IT_DIR7',max_salary=>10000
, min_salary=>500);
Creating and Using PL/SQL Functions (Code Samples)
CREATE OR REPLACE FUNCTION get_avg_sal (p_dept_id
departments.department_id%type) RETURN number AS
v_avg_sal number;
BEGIN
select avg(salary) into v_avg_sal from employees where department_id =
p_dept_id;
RETURN v_avg_sal;
END get_avg_sal;
----------------- using a function in begin-end block
declare
v_avg_salary number;
begin
v_avg_salary := get_avg_sal(50);
dbms_output.put_line(v_avg_salary);
end;
----------------- using functions in a select clause
select
employee_id,first_name,salary,department_id,get_avg_sal(department_id)
avg_sal from employees;
----------------- using functions in group by, order by, where clauses
select get_avg_sal(department_id) from employees
where salary > get_avg_sal(department_id)
group by get_avg_sal(department_id)
order by get_avg_sal(department_id);
----------------- dropping a function
drop function get_avg_sal;
Local Subprograms (Code Samples)
----------------- creating and using subprograms in anonymous blocks -
false usage
create table emps_high_paid as select * from employees where 1=2;
/
declare
procedure insert_high_paid_emp(emp_id employees.employee_id%type) is
emp employees%rowtype;
begin
emp := get_emp(emp_id);
insert into emps_high_paid values emp;
end;
function get_emp(emp_num employees.employee_id%type) return
employees%rowtype is
emp employees%rowtype;
begin
select * into emp from employees where employee_id = emp_num;
return emp;
end;
begin
for r_emp in (select * from employees) loop
if r_emp.salary > 15000 then
insert_high_paid_emp(r_emp.employee_id);
end if;
end loop;
end;
----------------- reating and using subprograms in anonymous blocks -
true usage
declare
function get_emp(emp_num employees.employee_id%type) return
employees%rowtype is
emp employees%rowtype;
begin
select * into emp from employees where employee_id = emp_num;
return emp;
end;
procedure insert_high_paid_emp(emp_id employees.employee_id%type) is
emp employees%rowtype;
begin
emp := get_emp(emp_id);
insert into emps_high_paid values emp;
end;
begin
for r_emp in (select * from employees) loop
if r_emp.salary > 15000 then
insert_high_paid_emp(r_emp.employee_id);
end if;
end loop;
end;
----------------- The scope of emp record
declare
procedure insert_high_paid_emp(emp_id employees.employee_id%type) is
emp employees%rowtype;
e_id number;
function get_emp(emp_num employees.employee_id%type) return
employees%rowtype is
begin
select * into emp from employees where employee_id = emp_num;
return emp;
end;
begin
emp := get_emp(emp_id);
insert into emps_high_paid values emp;
end;
begin
for r_emp in (select * from employees) loop
if r_emp.salary > 15000 then
insert_high_paid_emp(r_emp.employee_id);
end if;
end loop;
end;
Overloading the Subprograms (Code Samples)
declare
procedure insert_high_paid_emp(p_emp employees%rowtype) is
emp employees%rowtype;
e_id number;
function get_emp(emp_num employees.employee_id%type) return
employees%rowtype is
begin
select * into emp from employees where employee_id = emp_num;
return emp;
end;
function get_emp(emp_email employees.email%type) return
employees%rowtype is
begin
select * into emp from employees where email = emp_email;
return emp;
end;
begin
emp := get_emp(p_emp.employee_id);
insert into emps_high_paid values emp;
end;
begin
for r_emp in (select * from employees) loop
if r_emp.salary > 15000 then
insert_high_paid_emp(r_emp);
end if;
end loop;
end;
----------------- overloading with multiple usages
declare
procedure insert_high_paid_emp(p_emp employees%rowtype) is
emp employees%rowtype;
e_id number;
function get_emp(emp_num employees.employee_id%type) return
employees%rowtype is
begin
select * into emp from employees where employee_id = emp_num;
return emp;
end;
function get_emp(emp_email employees.email%type) return
employees%rowtype is
begin
select * into emp from employees where email = emp_email;
return emp;
end;
function get_emp(f_name varchar2, l_name varchar2) return
employees%rowtype is
begin
select * into emp from employees where first_name = f_name and
last_name = l_name;
return emp;
end;
begin
emp := get_emp(p_emp.employee_id);
insert into emps_high_paid values emp;
emp := get_emp(p_emp.email);
insert into emps_high_paid values emp;
emp := get_emp(p_emp.first_name,p_emp.last_name);
insert into emps_high_paid values emp;
end;
begin
for r_emp in (select * from employees) loop
if r_emp.salary > 15000 then
insert_high_paid_emp(r_emp);
end if;
end loop;
end;
Handling the Exceptions in Subprograms (Code Samples)
----------------- An unhandled exception in function
create or replace function get_emp(emp_num employees.employee_id%type)
return employees%rowtype is
emp employees%rowtype;
begin
select * into emp from employees where employee_id = emp_num;
return emp;
end;
----------------- calling that function in an anonymous block
declare
v_emp employees%rowtype;
begin
dbms_output.put_line('Fetching the employee data!..');
v_emp := get_emp(10);
dbms_output.put_line('Some information of the employee are : ');
dbms_output.put_line('The name of the employee is : '||
v_emp.first_name);
dbms_output.put_line('The email of the employee is : '|| v_emp.email);
dbms_output.put_line('The salary of the employee is : '||
v_emp.salary);
end;
----------------- hanling the exception wihout the return clause - not
working
create or replace function get_emp(emp_num employees.employee_id%type)
return employees%rowtype is
emp employees%rowtype;
begin
select * into emp from employees where employee_id = emp_num;
return emp;
exception
when no_data_found then
dbms_output.put_line('There is no employee with the id '|| emp_num);
end;
----------------- handling and raising the exception
create or replace function get_emp(emp_num employees.employee_id%type)
return employees%rowtype is
emp employees%rowtype;
begin
select * into emp from employees where employee_id = emp_num;
return emp;
exception
when no_data_found then
dbms_output.put_line('There is no employee with the id '|| emp_num);
raise no_data_found;
end;
----------------- handling all possible exception cases
create or replace function get_emp(emp_num employees.employee_id%type)
return employees%rowtype is
emp employees%rowtype;
begin
select * into emp from employees where employee_id = emp_num;
return emp;
exception
when no_data_found then
dbms_output.put_line('There is no employee with the id '|| emp_num);
raise no_data_found;
when others then
dbms_output.put_line('Something unexpected happened!.');
return null;
end;
Regular & Pipelined Table Functions (Code Samples)
CREATE TYPE t_day AS OBJECT (
v_date DATE,
v_day_number INT
);
----------------- creating a nested table type
CREATE TYPE t_days_tab IS TABLE OF t_day;
----------------- creating a regular table function
CREATE OR REPLACE FUNCTION f_get_days(p_start_date DATE , p_day_number
INT)
RETURN t_days_tab IS
v_days t_days_tab := t_days_tab();
BEGIN
FOR i IN 1 .. p_day_number LOOP
v_days.EXTEND();
v_days(i) := t_day(p_start_date + i, to_number(to_char(p_start_date +
i, 'DDD')));
END LOOP;
RETURN v_days;
END;
----------------- querying from the regular table function
select * from table(f_get_days(sysdate,1000000));
----------------- querying from the regular table function without the
table operator
select * from f_get_days(sysdate,1000000);
----------------- creating a pipelined table function
create or replace function f_get_days_piped (p_start_date date ,
p_day_number int)
return t_days_tab PIPELINED is
begin
for i in 1 .. p_day_number loop
PIPE ROW (t_day(p_start_date + i,
to_number(to_char(p_start_date + i,'DDD'))));
end loop;
RETURN;
end;
----------------- querying from the pipelined table function
select * from f_get_days_piped(sysdate,1000000)
Creating & Using & Modifying & Removing the Packages (Code Samples)
-------------------------------------------------------------------------
-------------------------------------------
--------------------------------------------CREATING & USING PACKAGES----
-------------------------------------------
-------------------------------------------------------------------------
-------------------------------------------
----------------- Creating first package specification
CREATE OR REPLACE
PACKAGE EMP AS
v_salary_increase_rate number := 0.057;
cursor cur_emps is select * from employees;
procedure increase_salaries;
function get_avg_sal(p_dept_id int) return number;
END EMP;
----------------- Creating the package body
CREATE OR REPLACE
PACKAGE BODY EMP AS
procedure increase_salaries AS
BEGIN
for r1 in cur_emps loop
update employees_copy set salary = salary + salary *
v_salary_increase_rate;
end loop;
END increase_salaries;
function get_avg_sal(p_dept_id int) return number AS
v_avg_sal number := 0;
BEGIN
select avg(salary) into v_avg_sal from employees_copy where
department_id = p_dept_id;
RETURN v_avg_sal;
END get_avg_sal;
END EMP;
----------------- using the subprograms in packages
exec EMP_PKG.increase_salaries;
----------------- using the variables in packages
begin
dbms_output.put_line(emp_pkg.get_avg_sal(50));
dbms_output.put_line(emp_pkg.v_salary_increase_rate);
end;
Visibility of Package Objects (Code Samples)
-------------------------------------------------------------------------
--------------------
--------------------------------VISIBILITY OF VARIABLES IN PACKAGES------
--------------------
-------------------------------------------------------------------------
--------------------
create or replace PACKAGE BODY EMP_PKG AS
v_sal_inc int := 500;
v_sal_inc2 int := 500;
procedure print_test is
begin
dbms_output.put_line('Test : '|| v_sal_inc);
end;
procedure increase_salaries AS
BEGIN
for r1 in cur_emps loop
update employees_copy set salary = salary + salary *
v_salary_increase_rate
where employee_id = r1.employee_id;
end loop;
END increase_salaries;
function get_avg_sal(p_dept_id int) return number AS
v_avg_sal number := 0;
BEGIN
print_test;
select avg(salary) into v_avg_sal from employees_copy where
department_id = p_dept_id;
RETURN v_avg_sal;
END get_avg_sal;
END EMP_PKG;
-----------------
create or replace PACKAGE BODY EMP_PKG AS
v_sal_inc int := 500;
v_sal_inc2 int := 500;
function get_sal(e_id employees.employee_id%type) return number;
procedure print_test is
begin
dbms_output.put_line('Test : '|| v_sal_inc);
dbms_output.put_line('Test salary : '|| get_sal(102));
end;
procedure increase_salaries AS
BEGIN
for r1 in cur_emps loop
update employees_copy set salary = salary + salary *
v_salary_increase_rate
where employee_id = r1.employee_id;
end loop;
END increase_salaries;
function get_avg_sal(p_dept_id int) return number AS
v_avg_sal number := 0;
BEGIN
print_test;
select avg(salary) into v_avg_sal from employees_copy where
department_id = p_dept_id;
RETURN v_avg_sal;
END get_avg_sal;
function get_sal(e_id employees.employee_id%type) return number is
v_sal number := 0;
begin
select salary into v_sal from employees where employee_id = e_id;
end;
end;
Persistent State of Packages (Code Samples)
-------------------------------------------------------------------------
--------------------
----------------------------------PERSISTENT STATE OF PACKAGES-----------
--------------------
-------------------------------------------------------------------------
--------------------
-----------------
execute dbms_output.put_line(constants_pkg.v_salary_increase);
grant execute on constants_pkg to my_user;
revoke execute on constants_pkg from my_user;
-----------------
-----------------
begin
constants_pkg.v_company_name := 'ACME';
dbms_output.put_line(constants_pkg.v_company_name);
dbms_lock.sleep(20);
end;
exec dbms_output.put_line(constants_pkg.v_company_name);
-----------------
create or replace package constants_pkg is
PRAGMA SERIALLY_REUSABLE;
v_salary_increase constant number:= 0.04;
cursor cur_emps is select * from employees;
t_emps_type employees%rowtype;
v_company_name varchar2(20) := 'ORACLE';
end;
-----------------
begin
constants_pkg.v_company_name := 'ACME';
dbms_output.put_line(constants_pkg.v_company_name);
dbms_lock.sleep(20);
end;
-----------------
declare
v_emp employees%rowtype;
begin
open constants_pkg.cur_emps;
fetch constants_pkg.cur_emps into v_emp;
dbms_output.put_line(v_emp.first_name);
close constants_pkg.cur_emps;
end;
-----------------
declare
v_emp employees%rowtype;
begin
fetch constants_pkg.cur_emps into v_emp;
dbms_output.put_line(v_emp.first_name);
end;
Using Collections in Packages (Code Samples)
-------------------------------------------------------------------------
--------------------
---------------------------------USING COLLECTIONS IN PACKAGES-----------
--------------------
-------------------------------------------------------------------------
--------------------
create or replace PACKAGE EMP_PKG AS
type emp_table_type is table of employees%rowtype index by pls_integer;
v_salary_increase_rate number := 1000;
v_min_employee_salary number := 5000;
cursor cur_emps is select * from employees;
procedure increase_salaries;
function get_avg_sal(p_dept_id int) return number;
v_test int := 4;
function get_employees return emp_table_type;
function get_employees_tobe_incremented return emp_table_type;
procedure increase_low_salaries;
function arrange_for_min_salary(v_emp employees%rowtype) return
employees%rowtype;
END EMP_PKG;
----------------- package body
create or replace PACKAGE BODY EMP_PKG AS
v_sal_inc int := 500;
v_sal_inc2 int := 500;
function get_sal(e_id employees.employee_id%type) return number;
procedure print_test is
begin
dbms_output.put_line('Test : '|| v_sal_inc);
dbms_output.put_line('Tests salary :'|| get_sal(102));
end;
procedure increase_salaries AS
BEGIN
for r1 in cur_emps loop
update employees_copy set salary = salary + salary *
v_salary_increase_rate
where employee_id = r1.employee_id;
end loop;
END increase_salaries;
function get_avg_sal(p_dept_id int) return number AS
v_avg_sal number := 0;
BEGIN
print_test;
select avg(salary) into v_avg_sal from employees_copy where
department_id = p_dept_id;
RETURN v_avg_sal;
END get_avg_sal;
function get_sal(e_id employees.employee_id%type) return number is
v_sal number := 0;
begin
select salary into v_sal from employees where employee_id = e_id;
return v_sal;
end;
/*
This function returns all the employees in employees table
*/
function get_employees return emp_table_type is
v_emps emp_table_type;
begin
for cur_emps in (select * from employees_copy) loop
v_emps(cur_emps.employee_id) := cur_emps;
end loop;
return v_emps;
end;
/*
This function returns the employees which are under the minimum
salary
of the company standards and to be incremented by the new minimum
salary
*/
function get_employees_tobe_incremented return emp_table_type is
v_emps emp_table_type;
i employees.employee_id%type;
begin
v_emps := get_employees;
i := v_emps.first;
while i is not null loop
if v_emps(i).salary > v_min_employee_salary then
v_emps.delete(i);
end if;
i := v_emps.next(i);
end loop;
return v_emps;
end;
/*
This procedure increases the salary of the employees who has a less
salary
then the company standard
*/
procedure increase_low_salaries as
v_emps emp_table_type;
v_emp employees%rowtype;
i employees.employee_id%type;
begin
v_emps := get_employees_tobe_incremented;
i := v_emps.first;
while i is not null loop
v_emp := arrange_for_min_salary(v_emps(i));
update employees_copy set row = v_emp
where employee_id = i;
i := v_emps.next(i);
end loop;
end increase_low_salaries;
/*
This function returns the employee by arranging the salary based on
the
company standard.
*/
function arrange_for_min_salary(v_emp in out employees%rowtype) return
employees%rowtype is
begin
v_emp.salary := v_emp.salary + v_salary_increase_rate;
if v_emp.salary < v_min_employee_salary then
v_emp.salary := v_min_employee_salary;
end if;
return v_emp;
end;
/**********************************************/
BEGIN
v_salary_increase_rate := 500;
insert into logs values ('EMP_PKG','Package initialized!',sysdate);
END EMP_PKG;
Specifying the Timing of Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
------------------------------SPECIFYING THE TIMING OF TRIGGERS----------
--------------------
-------------------------------------------------------------------------
--------------------
----------------- The create code of the first trigger
create or replace trigger first_trigger
before insert or update on employees_copy
begin
dbms_output.put_line('An insert or update occurred in employees_copy
table!.');
end;
----------------- sql commands to or not to run the trigger
update employees_copy set salary = salary + 100;
delete from employees_copy;
Statement & Row Level Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
-------------------------------STATEMENT & ROW LEVEL TRIGGERS------------
--------------------
-------------------------------------------------------------------------
--------------------
----------------- before statement level trigger example
create or replace trigger before_statement_emp_cpy
before insert or update on employees_copy
begin
dbms_output.put_line('Before Statement Trigger is Fired!.');
end;
----------------- after statement level trigger example
create or replace trigger after_statement_emp_cpy
after insert or update on employees_copy
begin
dbms_output.put_line('After Statement Trigger is Fired!.');
end;
----------------- before row level trigger example
create or replace trigger before_row_emp_cpy
before insert or update on employees_copy
for each row
begin
dbms_output.put_line('Before Row Trigger is Fired!.');
end;
----------------- after row level trigger example
create or replace trigger after_row_emp_cpy
after insert or update on employees_copy
for each row
begin
dbms_output.put_line('After Row Trigger is Fired!.');
end;
----------------- sql queries used in this lecture
update employees_copy set salary = salary + 100 where employee_id = 100;
update employees_copy set salary = salary + 100 where employee_id = 99;
update employees_copy set salary = salary + 100
where department_id = 30;
Using New & Old Qualifiers in Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
-------------------------------:NEW & :OLD QUALIFIERS IN TRIGGERS--------
--------------------
-------------------------------------------------------------------------
--------------------
create or replace trigger before_row_emp_cpy
before insert or update or delete on employees_copy
referencing old as O new as N
for each row
begin
dbms_output.put_line('Before Row Trigger is Fired!.');
dbms_output.put_line('The Salary of Employee '||:o.employee_id
||' -> Before:'|| :o.salary||' After:'||:n.salary);
Using Conditional Predicates (Code Samples)
-------------------------------------------------------------------------
--------------------
--------------------------------USING CONDITIONAL PREDICATES ------------
--------------------
-------------------------------------------------------------------------
--------------------
create or replace trigger before_row_emp_cpy
before insert or update or delete on employees_copy
referencing old as O new as N
for each row
begin
dbms_output.put_line('Before Row Trigger is Fired!.');
dbms_output.put_line('The Salary of Employee '||:o.employee_id
||' -> Before:'|| :o.salary||' After:'||:n.salary);
if inserting then
dbms_output.put_line('An INSERT occurred on employees_copy table');
elsif deleting then
dbms_output.put_line('A DELETE occurred on employees_copy table');
elsif updating ('salary') then
dbms_output.put_line('A DELETE occurred on the salary column');
elsif updating then
dbms_output.put_line('An UPDATE occurred on employees_copy table');
end if;
end;
Using RAISE_APPLICATION_ERROR Procedure in Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
------------------------USING RAISE_APPLICATION_ERROR PROCEDURE WITH
TRIGGERS----------------
-------------------------------------------------------------------------
--------------------
create or replace trigger before_row_emp_cpy
before insert or update or delete on employees_copy
referencing old as O new as N
for each row
begin
dbms_output.put_line('Before Row Trigger is Fired!.');
dbms_output.put_line('The Salary of Employee '||:o.employee_id
||' -> Before:'|| :o.salary||' After:'||:n.salary);
if inserting then
if :n.hire_date > sysdate then
raise_application_error(-20000,'You cannot enter a future hire..');
end if;
elsif deleting then
raise_application_error(-20001,'You cannot delete from the
employees_copy table..');
elsif updating ('salary') then
if :n.salary > 50000 then
raise_application_error(-20002,'A salary cannot be higher than
50000..');
end if;
elsif updating then
dbms_output.put_line('An UPDATE occurred on employees_copy table');
end if;
end;
Using Update Of Event in Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
--------------------------------USING UPDATE OF EVENT IN TRIGGERS--------
--------------------
-------------------------------------------------------------------------
--------------------
create or replace trigger prevent_updates_of_constant_columns
before update of hire_date,salary on employees_copy
for each row
begin
raise_application_error(-20005,'You cannot modify the hire_date and
salary columns');
end;
Using When Clause in Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
----------------------------------USING WHEN CLAUSE ON TRIGGERS----------
--------------------
-------------------------------------------------------------------------
--------------------
create or replace trigger prevent_high_salary
before insert or update of salary on employees_copy
for each row
when (new.salary > 50000)
begin
raise_application_error(-20006,'A salary cannot be higher than
50000!.');
end;
Instead of Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
-----------------------------------USING INSTEAD OF TRIGGERS-------------
--------------------
-------------------------------------------------------------------------
--------------------
----------------- creating a complex view -----------------
CREATE OR REPLACE VIEW VW_EMP_DETAILS AS
SELECT UPPER(DEPARTMENT_NAME) DNAME, MIN(SALARY) MIN_SAL, MAX(SALARY)
MAX_SAL
FROM EMPLOYEES_COPY JOIN DEPARTMENTS_COPY
USING (DEPARTMENT_ID)
GROUP BY DEPARTMENT_NAME;
----------------- updating the complex view -----------------
UPDATE VW_EMP_DETAILS SET DNAME = 'EXEC DEPT' WHERE
UPPER(DNAME) = 'EXECUTIVE';
----------------- Instead of trigger -----------------
CREATE OR REPLACE TRIGGER EMP_DETAILS_VW_DML
INSTEAD OF INSERT OR UPDATE OR DELETE ON VW_EMP_DETAILS
FOR EACH ROW
DECLARE
V_DEPT_ID PLS_INTEGER;
BEGIN
IF INSERTING THEN
SELECT MAX(DEPARTMENT_ID) + 10 INTO V_DEPT_ID FROM DEPARTMENTS_COPY;
INSERT INTO DEPARTMENTS_COPY VALUES (V_DEPT_ID,
:NEW.DNAME,NULL,NULL);
ELSIF DELETING THEN
DELETE FROM DEPARTMENTS_COPY WHERE UPPER(DEPARTMENT_NAME) =
UPPER(:OLD.DNAME);
ELSIF UPDATING('DNAME') THEN
UPDATE DEPARTMENTS_COPY SET DEPARTMENT_NAME = :NEW.DNAME
WHERE UPPER(DEPARTMENT_NAME) = UPPER(:OLD.DNAME);
ELSE
RAISE_APPLICATION_ERROR(-20007,'You cannot update any data other than
department name!.');
END IF;
END;
Creating Disabled Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
-----------------------------------CREATING DISABLED TRIGGERS------------
--------------------
-------------------------------------------------------------------------
--------------------
create or replace trigger prevent_high_salary
before insert or update of salary on employees_copy
for each row
disable
when (new.salary > 50000)
begin
raise_application_error(-20006,'A salary cannot be higher than
50000!.');
end;
Additional Real-World Examples for DML Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
-----------------------------REAL-WORLD EXAMPLES ON DML TRIGGERS---------
--------------------
-------------------------------------------------------------------------
--------------------
create sequence seq_dep_cpy
start with 280
increment by 10;
----------------- primary key example
create or replace trigger trg_before_insert_dept_cpy
before insert on departments_copy
for each row
begin
--select seq_dep_cpy.nextval into :new.department_id from dual;
:new.department_id := seq_dep_cpy.nextval;
end;
-----------------
insert into departments_copy
(department_name,manager_id,location_id)
values
('Security',200,1700);
-----------------
desc departments_copy;
----------------- creating the audit log table
create table log_departments_copy
(log_user varchar2(30), log_date date, dml_type varchar2(10),
old_department_id number(4), new_department_id number(4),
old_department_name varchar2(30), new_department_name
varchar2(30),
old_manager_id number(6), new_manager_id number(6),
old_location_id number(4), new_location_id number(4));
----------------- audit log trigger
create or replace trigger trg_department_copy_log
after insert or update or delete on departments_copy
for each row
declare v_dml_type varchar2(10);
begin
if inserting then
v_dml_type := 'INSERT';
elsif updating then
v_dml_type := 'UPDATE';
elsif deleting then
v_dml_type := 'DELETE';
end if;
insert into log_departments_copy values
(user, sysdate, v_dml_type,
:old.department_id, :new.department_id,
:old.department_name, :new.department_name,
:old.manager_id, :new.manager_id,
:old.location_id, :new.location_id);
end;
----------------- other sql codes used in this lecture
insert into departments_copy (department_name, manager_id,location_id)
values ('Cyber Security', 100, 1700);
select * from LOG_DEPARTMENTS_COPY;
update departments_copy set manager_id = 200 where DEPARTMENT_NAME =
'Cyber Security';
delete from departments_copy where DEPARTMENT_NAME = 'Cyber Security';
Compound Triggers (Code Samples)
-------------------------------------------------------------------------
--------------------
------------------------------------- COMPOUND TRIGGERS -----------------
--------------------
-------------------------------------------------------------------------
--------------------
----------------- The first simple compound trigger
create or replace trigger trg_comp_emps
for insert or update or delete on employees_copy
compound trigger
v_dml_type varchar2(10);
before statement is
begin
if inserting then
v_dml_type := 'INSERT';
elsif updating then
v_dml_type := 'UPDATE';
elsif deleting then
v_dml_type := 'DELETE';
end if;
dbms_output.put_line('Before statement section is executed with the
'||v_dml_type ||' event!.');
end before statement;
before each row is
t number;
begin
dbms_output.put_line('Before row section is executed with the
'||v_dml_type ||' event!.');
end before each row;
after each row is
begin
dbms_output.put_line('After row section is executed with the
'||v_dml_type ||' event!.');
end after each row;
after statement is
begin
dbms_output.put_line('After statement section is executed with the
'||v_dml_type ||' event!.');
end after statement;
end;
-----------------
CREATE OR REPLACE TRIGGER TRG_COMP_EMPS
FOR INSERT OR UPDATE OR DELETE ON EMPLOYEES_COPY
COMPOUND TRIGGER
TYPE T_AVG_DEPT_SALARIES IS TABLE OF EMPLOYEES_COPY.SALARY%TYPE INDEX
BY PLS_INTEGER;
AVG_DEPT_SALARIES T_AVG_DEPT_SALARIES;
BEFORE STATEMENT IS
BEGIN
FOR AVG_SAL IN (SELECT AVG(SALARY) SALARY , NVL(DEPARTMENT_ID,999)
DEPARTMENT_ID
FROM EMPLOYEES_COPY GROUP BY DEPARTMENT_ID) LOOP
AVG_DEPT_SALARIES(AVG_SAL.DEPARTMENT_ID) := AVG_SAL.SALARY;
END LOOP;
END BEFORE STATEMENT;
AFTER EACH ROW IS
V_INTERVAL NUMBER := 15;
BEGIN
IF :NEW.SALARY > AVG_DEPT_SALARIES(:NEW.DEPARTMENT_ID) +
AVG_DEPT_SALARIES(:NEW.DEPARTMENT_ID)*V_INTERVAL/100 THEN
RAISE_APPLICATION_ERROR(-20005,'A raise cannot be '||
V_INTERVAL|| ' percent higher than
its department''s average!');
END IF;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
DBMS_OUTPUT.PUT_LINE('All the changes are done successfully!');
END AFTER STATEMENT;
END;
Handling Mutating Table Errors (Code Samples)
-------------------------------------------------------------------------
--------------------
------------------------------------ MUTATING TABLE ERRORS --------------
--------------------
-------------------------------------------------------------------------
--------------------
----------------- A mutating table error example
create or replace trigger trg_mutating_emps
before insert or update on employees_copy
for each row
declare
v_interval number := 15;
v_avg_salary number;
begin
select avg(salary) into v_avg_salary from employees_copy where
department_id = :new.department_id;
if :new.salary > v_avg_salary*v_interval/100 then
RAISE_APPLICATION_ERROR(-20005, 'A raise cannot be '||
v_interval|| ' percent higher than its department''s average');
end if;
end;
----------------- Getting mutating table error within a compound trigger
create or replace trigger trg_comp_emps
for insert or update or delete on employees_copy
compound trigger
type t_avg_dept_salaries is table of employees_copy.salary%type index
by pls_integer;
avg_dept_salaries t_avg_dept_salaries;
before statement is
begin
for avg_sal in (select avg(salary) salary,nvl(department_id,999)
department_id from employees_copy group by department_id) loop
avg_dept_salaries(avg_sal.department_id) := avg_sal.salary;
end loop;
end before statement;
after each row is
v_interval number := 15;
begin
update employees_copy set commission_pct = commission_pct;
if :new.salary >
avg_dept_salaries(:new.department_id)*v_interval/100 then
RAISE_APPLICATION_ERROR(-20005, 'A raise cannot be '||
v_interval|| ' percent higher than its department''s average');
end if;
end after each row;
after statement is
begin
dbms_output.put_line('All the updates are done successfully!.');
end after statement;
end;
----------------- An example of getting maximum level of recursive SQL
levels
create or replace trigger trg_comp_emps
for insert or update or delete on employees_copy
compound trigger
type t_avg_dept_salaries is table of employees_copy.salary%type index
by pls_integer;
avg_dept_salaries t_avg_dept_salaries;
before statement is
begin
update employees_copy set commission_pct = commission_pct where
employee_id = 100;
for avg_sal in (select avg(salary) salary,nvl(department_id,999)
department_id from employees_copy group by department_id) loop
avg_dept_salaries(avg_sal.department_id) := avg_sal.salary;
end loop;
end before statement;
after each row is
v_interval number := 15;
begin
if :new.salary >
avg_dept_salaries(:new.department_id)*v_interval/100 then
RAISE_APPLICATION_ERROR(-20005, 'A raise cannot be '||
v_interval|| ' percent higher than its department''s average');
end if;
end after each row;
after statement is
begin
update employees_copy set commission_pct = commission_pct where
employee_id = 100;
dbms_output.put_line('All the updates are done successfully!.');
end after statement;
end;
Granting Debug Privileges to a User
/*
1)You need to connect with the "SYS" or "SYSTEM" user,
2)Execute the following codes to be able to debug your PL/SQL codes &
subprograms.
3)You can grant debug privileges to another user by replacing HR within
the following codes if you need to.
*/
GRANT DEBUG CONNECT SESSION TO hr;
GRANT DEBUG ANY PROCEDURE TO hr;
BEGIN
dbms_network_acl_admin.append_host_ace
(host=>'127.0.0.1',
ace=>
sys.xs$ace_type(privilege_list=>sys.xs$name_list('JDWP') ,
principal_name=>'HR',
principal_type=>sys.xs_acl.ptype_db) );
END;
Source Code: Debugging the Anonymous Blocks
/*Lecture: Debugging the Anonymous Blocks*/
DECLARE
CURSOR c_emps IS SELECT * FROM employees_copy;
BEGIN
dbms_output.put_line('Update started at : '|| systimestamp);
FOR r_emp IN c_emps LOOP
IF NVL(r_emp.commission_pct,0) = 0 THEN
UPDATE employees_copy SET commission_pct = 0.3 WHERE
employee_id = r_emp.employee_id;
end if;
END LOOP;
dbms_output.put_line('Update finished at : '|| systimestamp);
ROLLBACK;
END;
Execute Immediate Statement (Code Samples)
BEGIN
EXECUTE IMMEDIATE 'GRANT SELECT ON EMPLOYEES TO SYS';
END;
/
BEGIN
EXECUTE IMMEDIATE 'GRANT SELECT ON EMPLOYEES TO SYS;';
END;
/
CREATE OR REPLACE PROCEDURE prc_create_table_dynamic
(p_table_name IN VARCHAR2, p_col_specs IN VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE '||p_table_name||'
('||p_col_specs||')';
END;
/
EXEC prc_create_table_dynamic('dynamic_temp_table', 'id NUMBER PRIMARY
KEY, name VARCHAR2(100)');
/
SELECT * FROM dynamic_temp_table;
/
CREATE OR REPLACE PROCEDURE prc_generic (p_dynamic_sql IN VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE p_dynamic_sql;
END;
/
EXEC prc_generic('drop table dynamic_temp_table');
/
EXEC prc_generic('drop procedure PRC_CREATE_TABLE_DYNAMIC');
/
DROP PROCEDURE prc_generic;
EXECUTE IMMEDIATE STATEMENT with the USING Clause (Code Samples)
CREATE TABLE names (ID NUMBER PRIMARY KEY, NAME VARCHAR2(100));
/
CREATE OR REPLACE FUNCTION insert_values (ID IN VARCHAR2, NAME IN
VARCHAR2) RETURN PLS_INTEGER IS
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO names VALUES(:a, :b)' USING ID,NAME;
RETURN SQL%rowcount;
END;
/
SET SERVEROUTPUT ON;
DECLARE
v_affected_rows PLS_INTEGER;
BEGIN
v_affected_rows := insert_values(2,'John');
dbms_output.put_line(v_affected_rows|| ' row inserted!');
END;
/
SELECT * FROM names;
/
ALTER TABLE names ADD (last_name VARCHAR2(100));
/
CREATE OR REPLACE FUNCTION update_names (ID IN VARCHAR2, last_name IN
VARCHAR2) RETURN PLS_INTEGER IS
v_dynamic_sql VARCHAR2(200);
BEGIN
v_dynamic_sql := 'UPDATE names SET last_name = :1 WHERE id = :2' ;
EXECUTE IMMEDIATE v_dynamic_sql USING last_name, ID;
RETURN SQL%rowcount;
END;
/
DECLARE
v_affected_rows PLS_INTEGER;
BEGIN
v_affected_rows := update_names(2,'Brown');
dbms_output.put_line(v_affected_rows|| ' row updated!');
END;
/
CREATE OR REPLACE FUNCTION update_names (ID IN VARCHAR2, last_name IN OUT
VARCHAR2) RETURN PLS_INTEGER IS
v_dynamic_sql VARCHAR2(200);
BEGIN
v_dynamic_sql := 'UPDATE names SET last_name = :1 WHERE id = :2' ;
EXECUTE IMMEDIATE v_dynamic_sql USING IN OUT last_name, ID;
RETURN SQL%rowcount;
END;
/
CREATE OR REPLACE FUNCTION update_names (ID IN VARCHAR2, last_name IN
VARCHAR2, first_name OUT VARCHAR2) RETURN PLS_INTEGER IS
v_dynamic_sql VARCHAR2(200);
BEGIN
v_dynamic_sql := 'UPDATE names SET last_name = :1 WHERE id = :2 :3' ;
EXECUTE IMMEDIATE v_dynamic_sql USING last_name, ID, OUT first_name;
RETURN SQL%rowcount;
END;
/
DECLARE
v_affected_rows PLS_INTEGER;
v_first_name VARCHAR2(100);
BEGIN
v_affected_rows := update_names(2,'KING',v_first_name);
dbms_output.put_line(v_affected_rows|| ' row updated!');
dbms_output.put_line(v_first_name);
END;
/
CREATE OR REPLACE FUNCTION update_names (ID IN VARCHAR2, last_name IN
VARCHAR2, first_name OUT VARCHAR2) RETURN PLS_INTEGER IS
v_dynamic_sql VARCHAR2(200);
BEGIN
v_dynamic_sql := 'UPDATE names SET last_name = :1 WHERE id = :2
RETURNING name INTO :3' ;
EXECUTE IMMEDIATE v_dynamic_sql USING last_name, ID RETURNING INTO
first_name;
RETURN SQL%rowcount;
END;
/
DROP TABLE names;
DROP FUNCTION insert_values;
DROP FUNCTION update_names;
EXECUTE IMMEDIATE STATEMENT with the USING and INTO Clauses (Code
Samples)
CREATE OR REPLACE FUNCTION get_count (table_name IN VARCHAR2) RETURN
PLS_INTEGER IS
v_count PLS_INTEGER;
BEGIN
EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM ' || table_name INTO v_count;
RETURN v_count;
END;
/
SET SERVEROUTPUT ON;
BEGIN
dbms_output.put_line('There are '||get_count('employees')||' rows in
the employees table!');
END;
/
DECLARE
v_table_name VARCHAR2(50);
BEGIN
FOR r_table IN (SELECT table_name FROM user_tables) LOOP
dbms_output.put_line('There are
'||get_count(r_table.table_name)||' rows in the '||r_table.table_name||'
table!');
END LOOP;
END;
/
DECLARE
v_table_name VARCHAR2(50);
BEGIN
FOR r_table IN (SELECT table_name FROM user_tables) LOOP
IF get_count(r_table.table_name) > 100 THEN
dbms_output.put_line('There are
'||get_count(r_table.table_name)||' rows in the '||r_table.table_name||'
table!');
dbms_output.put_line('It should be considered for
partitioning');
END IF;
END LOOP;
END;
/
CREATE TABLE stock_managers AS SELECT * FROM employees WHERE job_id =
'ST_MAN';
/
CREATE TABLE stock_clerks AS SELECT * FROM employees WHERE job_id =
'ST_CLERK';
/
CREATE OR REPLACE FUNCTION get_avg_sals (p_table IN VARCHAR2, p_dept_id
IN NUMBER) RETURN PLS_INTEGER IS
v_average PLS_INTEGER;
BEGIN
EXECUTE IMMEDIATE 'SELECT AVG(salary) FROM :1 WHERE department_id =
:2' INTO v_average USING p_table, p_dept_id;
RETURN v_average;
END;
/
SELECT get_avg_sals('stock_clerks','50') FROM dual;
/
CREATE OR REPLACE FUNCTION get_avg_sals (p_table IN VARCHAR2, p_dept_id
IN NUMBER) RETURN PLS_INTEGER IS
v_average PLS_INTEGER;
BEGIN
EXECUTE IMMEDIATE 'SELECT AVG(salary) FROM '||p_table||' WHERE
department_id = :2' INTO v_average USING p_dept_id;
RETURN v_average;
END;
/
SELECT get_avg_sals('stock_managers','50') FROM dual;
/
DROP FUNCTION get_count;
DROP FUNCTION get_avg_sals;
DROP TABLE stock_clerks;
DROP TABLE stock_managers;
Execute Immediate with Bulk Collect (Code Samples)
DECLARE
TYPE t_name IS TABLE OF VARCHAR2(20);
names t_name;
BEGIN
EXECUTE IMMEDIATE 'SELECT distinct first_name FROM employees'
BULK COLLECT INTO names;
FOR i IN 1..names.COUNT LOOP
dbms_output.put_line(names(i));
END LOOP;
END;
/
CREATE TABLE employees_copy AS SELECT * FROM employees;
/
DECLARE
TYPE t_name IS TABLE OF VARCHAR2(20);
names t_name;
BEGIN
EXECUTE IMMEDIATE 'UPDATE employees_copy SET salary = salary + 1000
WHERE department_id = 30 RETURNING first_name INTO :a'
RETURNING BULK COLLECT INTO names;
FOR i IN 1..names.COUNT LOOP
dbms_output.put_line(names(i));
END LOOP;
END;
/
DROP TABLE employees_copy;
Dynamic PL/SQL Blocks (Code Sample)
BEGIN
FOR r_emp in (SELECT * FROM employees) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
END LOOP;
END;
/
DECLARE
v_dynamic_text varchar2(1000);
BEGIN
v_dynamic_text := q'[BEGIN
FOR r_emp in (SELECT * FROM employees) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
END LOOP;
END;]';
EXECUTE IMMEDIATE v_dynamic_text;
END;
/
DECLARE
v_dynamic_text VARCHAR2(1000);
v_department_id PLS_INTEGER := 30;
BEGIN
v_dynamic_text := q'[BEGIN
FOR r_emp in (SELECT * FROM employees WHERE department_id =
v_department_id) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
END LOOP;
END;]';
EXECUTE IMMEDIATE v_dynamic_text;
END;
/
DECLARE
v_dynamic_text VARCHAR2(1000);
--v_department_id pls_integer := 30;
BEGIN
v_dynamic_text := q'[DECLARE
v_department_id pls_integer := 30;
BEGIN
FOR r_emp in (SELECT * FROM employees WHERE department_id =
v_department_id) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
END LOOP;
END;]';
EXECUTE IMMEDIATE v_dynamic_text;
END;
/
CREATE OR REPLACE PACKAGE pkg_temp AS
v_department_id_pkg PLS_INTEGER := 50;
END;
/
DECLARE
v_dynamic_text VARCHAR2(1000);
--v_department_id pls_integer := 30;
BEGIN
v_dynamic_text := q'[BEGIN
FOR r_emp in (SELECT * FROM employees WHERE department_id =
pkg_temp.v_department_id_pkg) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
END LOOP;
END;]';
EXECUTE IMMEDIATE v_dynamic_text;
END;
/
DECLARE
v_dynamic_text VARCHAR2(1000);
v_department_id PLS_INTEGER := 30;
BEGIN
v_dynamic_text := q'[BEGIN
FOR r_emp in (SELECT * FROM employees WHERE department_id = :1) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
END LOOP;
END;]';
EXECUTE IMMEDIATE v_dynamic_text USING v_department_id;
END;
/
DECLARE
v_dynamic_text VARCHAR2(1000);
v_department_id PLS_INTEGER := 30;
v_max_salary PLS_INTEGER := 0;
BEGIN
v_dynamic_text := q'[BEGIN
FOR r_emp in (SELECT * FROM employees WHERE department_id = :1) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
if r_emp.salary > :sal then
:sal := r_emp.salary;
end if;
END LOOP;
END;]';
EXECUTE IMMEDIATE v_dynamic_text USING v_department_id, IN OUT
v_max_salary;
dbms_output.put_line('The maximum salary of this department is :
'||v_max_salary);
END;
/
DECLARE
v_dynamic_text VARCHAR2(1000);
v_department_id PLS_INTEGER := 30;
v_max_salary PLS_INTEGER := 0;
BEGIN
v_dynamic_text := q'[BEGIN
FOR r_emp in (SELECT * FROM employeese WHERE department_id = :1) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
if r_emp.salary > :sal then
:sal := r_emp.salary;
end if;
END LOOP;
END;]';
EXECUTE IMMEDIATE v_dynamic_text USING v_department_id, IN OUT
v_max_salary;
dbms_output.put_line('The maximum salary of this department is :
'||v_max_salary);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('The error is : '||sqlerrm);
END;
/
DECLARE
v_dynamic_text VARCHAR2(1000);
v_department_id PLS_INTEGER := 30;
v_max_salary PLS_INTEGER := 0;
BEGIN
v_dynamic_text := q'[BEGIN
FOR r_emp in (SELECT * FROM employeese WHERE department_id = :1) LOOP
dbms_output.put_line(r_emp.first_name||' '||r_emp.last_name);
if r_emp.salary > :sal then
:sal := r_emp.salary;
end if;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('The error is : '||SQLERRM);
END;]';
EXECUTE IMMEDIATE v_dynamic_text USING v_department_id, IN OUT
v_max_salary;
dbms_output.put_line('The maximum salary of this department is :
'||v_max_salary);
END;
/
DROP PACKAGE pkg_temp;
OPEN - FOR, FETCH Statements (Code Sample)
DECLARE
TYPE emp_cur_type IS REF CURSOR;
emp_cursor emp_cur_type;
emp_record employees%rowtype;
BEGIN
OPEN emp_cursor FOR 'SELECT * FROM employees WHERE job_id =
''IT_PROG''';
FETCH emp_cursor INTO emp_record;
dbms_output.put_line(emp_record.first_name||emp_record.last_name);
CLOSE emp_cursor;
END;
/
DECLARE
TYPE emp_cur_type IS REF CURSOR;
emp_cursor emp_cur_type;
emp_record employees%rowtype;
BEGIN
OPEN emp_cursor FOR 'SELECT * FROM employees WHERE job_id = :job' USING
'IT_PROG';
FETCH emp_cursor INTO emp_record;
dbms_output.put_line(emp_record.first_name||emp_record.last_name);
CLOSE emp_cursor;
END;
/
DECLARE
TYPE emp_cur_type IS REF CURSOR;
emp_cursor emp_cur_type;
emp_record employees%rowtype;
BEGIN
OPEN emp_cursor FOR 'SELECT * FROM employees WHERE job_id = :job' USING
'IT_PROG';
LOOP
FETCH emp_cursor INTO emp_record;
EXIT WHEN emp_cursor%notfound;
dbms_output.put_line(emp_record.first_name||emp_record.last_name);
END LOOP;
CLOSE emp_cursor;
END;
/
DECLARE
TYPE emp_cur_type IS REF CURSOR;
emp_cursor emp_cur_type;
emp_record employees%rowtype;
v_table_name VARCHAR(20);
BEGIN
v_table_name := 'employees';
OPEN emp_cursor FOR 'SELECT * FROM '||v_table_name||' WHERE job_id =
:job' USING 'IT_PROG';
LOOP
FETCH emp_cursor INTO emp_record;
EXIT WHEN emp_cursor%notfound;
dbms_output.put_line(emp_record.first_name||emp_record.last_name);
END LOOP;
CLOSE emp_cursor;
END;
Using the DBMS_SQL Package (Code Samples)
CREATE TABLE employees_copy AS SELECT * FROM employees;
/
set serveroutput on;
DECLARE
v_table_name VARCHAR2(20) := 'employees_copy';
v_cursor_id PLS_INTEGER;
v_affected_rows PLS_INTEGER;
BEGIN
v_cursor_id := dbms_sql.open_cursor;
dbms_sql.parse(v_cursor_id, 'update '||v_table_name||' set
salary=salary+500',dbms_sql.NATIVE);
v_affected_rows := dbms_sql.EXECUTE(v_cursor_id);
dbms_output.put_line(v_affected_rows|| ' rows are updated by
dbms_sql!');
dbms_sql.close_cursor(v_cursor_id);
END;
select * from employees_copy;
DECLARE
v_table_name varchar2(20) := 'employees_copy';
v_cursor_id pls_integer;
v_affected_rows pls_integer;
BEGIN
v_cursor_id := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cursor_id, 'update '||v_table_name||' set
salary=salary+500 WHERE job_id = :jid',DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(v_cursor_id, ':jid','IT_PROG');
v_affected_rows := DBMS_SQL.EXECUTE(v_cursor_id);
dbms_output.put_line(v_affected_rows|| ' rows are updated by
dbms_sql!');
DBMS_SQL.CLOSE_CURSOR(v_cursor_id);
END;
DECLARE
v_table_name varchar2(20) := 'employees_copy';
v_cursor_id pls_integer;
v_affected_rows pls_integer;
BEGIN
v_cursor_id := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cursor_id, 'update '||v_table_name||' set
salary=salary+:inc WHERE job_id = :jid',DBMS_SQL.NATIVE);
DBMS_SQL.BIND_VARIABLE(v_cursor_id, ':jid','IT_PROG');
DBMS_SQL.BIND_VARIABLE(v_cursor_id, ':inc','5');
v_affected_rows := DBMS_SQL.EXECUTE(v_cursor_id);
dbms_output.put_line(v_affected_rows|| ' rows are updated by
dbms_sql!');
DBMS_SQL.CLOSE_CURSOR(v_cursor_id);
END;
SELECT * FROM user_tab_columns;
EXEC prc_method4_example('employees');
EXEC prc_method4_example('departments');
EXEC prc_method4_example('countries');
EXEC prc_method4_example('locations');
/
create or replace PROCEDURE prc_method4_example (p_table_name IN
VARCHAR2) IS
TYPE t_columns IS TABLE OF user_tab_columns%rowtype INDEX BY
PLS_INTEGER;
v_columns t_columns;
v_columns_with_commas VARCHAR2(32767);
v_number_value NUMBER;
v_string_value VARCHAR2(32767);
v_date_value DATE;
v_output_string VARCHAR2(32767);
cur_dynamic INTEGER;
BEGIN
SELECT * BULK COLLECT INTO v_columns FROM user_tab_columns WHERE
table_name = upper(p_table_name);
v_columns_with_commas:=v_columns(1).column_name;
FOR i IN 2..v_columns.COUNT LOOP
v_columns_with_commas:=v_columns_with_commas||','||v_columns(i).column_na
me;
END LOOP;
cur_dynamic := dbms_sql.open_cursor;
dbms_sql.parse(cur_dynamic,'SELECT '||v_columns_with_commas||' FROM
'||p_table_name,dbms_sql.NATIVE);
FOR idx IN 1..v_columns.COUNT LOOP
IF v_columns(idx).data_type = 'NUMBER' THEN
dbms_sql.define_column(cur_dynamic,idx,1);
ELSIF v_columns(idx).data_type IN ('VARCHAR2','VARCHAR','CHAR')
THEN
dbms_sql.define_column(cur_dynamic,idx,'dummy
text',v_columns(idx).char_length);
ELSIF v_columns(idx).data_type = 'DATE' THEN
dbms_sql.define_column(cur_dynamic,idx,sysdate);
END IF;
v_output_string:=v_output_string||'
'||rpad(v_columns(idx).column_name,20);
END LOOP;
dbms_output.put_line(v_output_string);
v_number_value:=dbms_sql.execute(cur_dynamic);
WHILE dbms_sql.fetch_rows(cur_dynamic) > 0 LOOP
v_output_string:=NULL;
FOR t IN 1..v_columns.COUNT LOOP
IF v_columns(T).data_type = 'NUMBER' THEN
dbms_sql.column_value(cur_dynamic,t,v_number_value);
v_output_string := v_output_string||'
'||rpad(nvl(to_char(v_number_value),' '),20);
ELSIF v_columns(T).data_type IN ('VARCHAR2','VARCHAR','CHAR')
THEN
dbms_sql.column_value(cur_dynamic,t,v_string_value);
v_output_string := v_output_string||'
'||rpad(nvl(to_char(v_string_value),' '),20);
ELSIF v_columns(T).data_type = 'DATE' THEN
dbms_sql.column_value(cur_dynamic,t,v_date_value);
v_output_string := v_output_string||'
'||rpad(nvl(to_char(v_date_value),' '),20);
END IF;
END LOOP;
dbms_output.put_line(v_output_string);
END LOOP;
END;
Using the DBMS_OUTPUT Package (Code Samples)
EXEC dbms_output.put_line('Test No:1');
/
SET SERVEROUTPUT ON;
EXEC dbms_output.put_line('Test No:2');
/
EXEC dbms_output.put('Test No:3');
/
EXEC dbms_output.put_line('Test No:4');
/
SET SERVEROUTPUT OFF
/
CREATE TABLE temp_table(ID NUMBER GENERATED ALWAYS AS IDENTITY, text
VARCHAR2(1000));
/
EXEC dbms_output.enable;
EXEC dbms_output.put_line('Hi');
/
DECLARE
v_buffer VARCHAR2(1000);
v_status INTEGER;
BEGIN
dbms_output.put('...');
dbms_output.put_line('Hello');
dbms_output.put_line('How are you');
FOR I IN 1..10 LOOP
dbms_output.get_line(v_buffer,v_status);
IF v_status = 0 THEN
INSERT INTO temp_table(text) VALUES (v_buffer);
END IF;
END LOOP;
END;
/
SELECT * FROM temp_table;
/
SET SERVEROUTPUT ON;
DECLARE
v_buffer VARCHAR2(1000);
v_status INTEGER;
BEGIN
dbms_output.put('...');
dbms_output.put_line('Hello');
dbms_output.put_line('How are you');
dbms_output.get_line(v_buffer,v_status);
END;
/
SET SERVEROUTPUT OFF;
EXEC dbms_output.enable;
/
DECLARE
v_buffer dbms_output.chararr;
v_num_lines INTEGER:= 30;
BEGIN
dbms_output.put('...');
dbms_output.put_line('Hello');
dbms_output.put_line('How are you');
dbms_output.get_lines(v_buffer,v_num_lines);
FOR i IN 1..v_num_lines LOOP
INSERT INTO temp_table(text) VALUES (v_buffer(I));
END LOOP;
END;
/
DROP TABLE temp_table;
Using the UTL_FILE Package (Code Samples)
--------------------CREATE DIRECTORY------------------------------------
CREATE DIRECTORY test_dir AS 'C:\My Folder';
/
-------------------GET ALL THE EXISTING DIRECTORIES--------------------
SELECT * FROM all_directories;
/
-------------------READ FROM A FILE------------------------------------
SET SERVEROUTPUT ON;
DECLARE
v_file UTL_FILE.FILE_TYPE;
v_line VARCHAR2(32767);
BEGIN
v_file := UTL_FILE.FOPEN('TEST_DIR', 'temp file.txt', 'R', 32767);
LOOP
UTL_FILE.GET_LINE(v_file, v_line);
dbms_output.put_line (v_line);
END LOOP;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('The whole file is read!');
UTL_FILE.FCLOSE(v_file);
END;
/
-------------------GRANT OR REVOKE READ-WRITE PRIVILEGES---------------
GRANT READ, WRITE ON DIRECTORY test_dir TO hr;
REVOKE READ, WRITE ON DIRECTORY test_dir FROM hr;
/
-------------------WRITE TO A FILE USING PUT_LINE PROCEDURE-------------
DECLARE
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN('TEST_DIR', 'temp file.txt', 'w', 32767);
FOR r_emp IN (select * from employees) LOOP
UTL_FILE.PUT_LINE(v_file, r_emp.first_name||'
'||r_emp.last_name);
END LOOP;
UTL_FILE.FCLOSE(v_file);
END;
/
-------------------WRITE TO A FILE USING PUT AND NEW_LINE---------------
DECLARE
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN('TEST_DIR', 'temp file.txt', 'w', 32767);
FOR r_emp IN (select * from employees) LOOP
UTL_FILE.PUT(v_file, r_emp.first_name||' '||r_emp.last_name);
UTL_FILE.NEW_LINE(v_file);
END LOOP;
UTL_FILE.FCLOSE(v_file);
END;
/
-------------------WRITE TO A FILE USING PUTF---------------------------
DECLARE
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN('TEST_DIR', 'temp file.txt', 'w', 32767);
FOR r_emp IN (select * from employees) LOOP
UTL_FILE.PUTF(v_file, '--> %s
%s',r_emp.first_name,r_emp.last_name);
--UTL_FILE.NEW_LINE(v_file);
--UTL_FILE.PUTF(v_file, '--> %s
%s\n',r_emp.first_name,r_emp.last_name);
END LOOP;
UTL_FILE.FCLOSE(v_file);
END;
/
-------------------USING FFLUSH TO WRITE IMMEDIATELY-------------------
DECLARE
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN('TEST_DIR', 'temp file.txt', 'w', 32767);
FOR r_emp IN (select * from employees) LOOP
UTL_FILE.PUT_LINE(v_file,r_emp.first_name||' '||r_emp.last_name);
--UTL_FILE.FFLUSH(v_file);
--UTL_FILE.PUT_LINE(v_file,r_emp.first_name||'
'||r_emp.last_name,true);
DBMS_SESSION.SLEEP(1);
END LOOP;
UTL_FILE.FCLOSE(v_file);
END;
/
-------------------CHECK FILE ATTRIBUTES-----------------------------
DECLARE
v_fexists BOOLEAN;
v_file_length NUMBER;
v_block_size BINARY_INTEGER;
BEGIN
UTL_FILE.FGETATTR('TEST_DIR','temp
file.txt',v_fexists,v_file_length,v_block_size);
IF v_fexists THEN
DBMS_OUTPUT.PUT_LINE('The file exists');
DBMS_OUTPUT.PUT_LINE('Its length is :'||v_file_length);
DBMS_OUTPUT.PUT_LINE('Its block size is :'||v_block_size);
ELSE
DBMS_OUTPUT.PUT_LINE('The file does not exist!');
END IF;
END;
/
-------------------COPY THE FILE---------------------------------------
EXECUTE UTL_FILE.FCOPY('TEST_DIR','temp file.txt','TEST_DIR','temp file
copy.txt');
/
-------------------COPY THE FILE EX2-----------------------------------
EXECUTE UTL_FILE.FCOPY('TEST_DIR','temp file.txt','TEST_DIR','temp file
copy2.txt',1,5);
/
-------------------RENAME THE FILE-------------------------------------
EXECUTE UTL_FILE.FRENAME('TEST_DIR','temp file
copy2.txt','TEST_DIR','temp file renamed.txt');
/
-------------------REMOVE THE FILE-------------------------------------
EXECUTE UTL_FILE.FREMOVE('TEST_DIR','temp file renamed.txt');
EXECUTE UTL_FILE.FREMOVE('TEST_DIR','temp file copy.txt');
EXECUTE UTL_FILE.FREMOVE('TEST_DIR','temp file.txt');
/
-------------------DROP THE DIRECTORY-----------------------------------
DROP DIRECTORY test_dir;
Using the UTL_MAIL Package (Code Samples)
--Sending an email with the least number of parameters
BEGIN
UTL_MAIL.send(
sender => 'somebody@somedomain.com',
recipients => 'oraclemaster@outlook.com',
subject => 'Example 1: Test Email Subject',
message => 'This is a test email from someone.'
);
END;
/
--Sending an email with specific names to the sender and recipients
BEGIN
UTL_MAIL.send(
sender => 'Some Person <somebody@somedomain.com>',
recipients => 'Oracle Masters
<oraclemaster@outlook.com>',
subject => 'Example 2: Test Email Subject',
message => 'This is a test email from someone.'
);
END;
/
--Sending an email with using all of the parameters
BEGIN
UTL_MAIL.send(
sender => 'somebody@somedomain.com',
recipients => 'oraclemaster@outlook.com',
cc =>
'somemanager@somedomain.something,someotherperson@somedomain.something',
bcc => 'someothermanager@somedomain.com',
subject => 'Example 3: Test Email Subject',
message => 'This is a test email from someone.',
mime_type => 'text/plain; charset=us-ascii',
priority => 1,
replyto => 'somereplyaddress@somedomain.com'
);
END;
/
--Sending an email by dynamically filling the message body
DECLARE
cursor cur_top_earning_emps is
select employee_id, first_name, last_name, salary
from hr.employees
where salary > 10000
order by salary desc;
v_message varchar2(32767);
BEGIN
v_message := 'EMPLOYEE ID'||CHR(9)||'FIRST NAME'||CHR(9)||'LAST
NAME'||CHR(9)||'EMPLOYEE ID'||CHR(13);
for r_top in cur_top_earning_emps loop
v_message :=
v_message||r_top.employee_id||CHR(9)||r_top.first_name||CHR(9)||r_top.las
t_name||CHR(9)||r_top.salary||CHR(13);
end loop;
UTL_MAIL.send(
sender => 'topearnings@somedns.com',
recipients => 'oraclemaster@outlook.com',
subject => 'Example 4: The Employees Earning More
Than $10000',
message => v_message
);
END;
/
--Sending an HTTP mail
DECLARE
cursor cur_top_earning_emps is
select employee_id, first_name, last_name, salary
from hr.employees
where salary > 10000
order by salary desc;
v_message varchar2(32767);
BEGIN
v_message := '<!DOCTYPE html>
<html>
<head>
<meta charset=''Cp1252''>
<title>Top Earning Employees</title>
<meta name="viewport" content="width=device-
width, initial-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
}
body {
font: 14px/1.4 Georgia, Serif;
}
/*
Generic Styling, for Desktops/Laptops
*/
table {
width: 100%;
border-collapse: collapse;
}
/* Zebra striping */
tr:nth-of-type(odd) {
background: #eee;
}
th {
background: #333;
color: white;
font-weight: bold;
}
td, th {
padding: 6px;
border: 1px solid #9B9B9B;
text-align: left;
}
@media
only screen and (max-width: 760px),
(min-device-width: 768px) and (max-device-
width: 1024px) {
table, thead, tbody, th, td, tr { display:
block; }
thead tr { position: absolute;top: -
9999px;left: -9999px;}
tr { border: 1px solid #9B9B9B; }
td { border: none;border-bottom: 1px solid
#9B9B9B; position: relative;padding-left: 50%; }
td:before { position: absolute;top:
6px;left: 6px;width: 45%; padding-right: 10px; white-space: nowrap;}
/*
Label the data
*/
td:nth-of-type(0):before { content:
"EMPLOYEE_ID"; }
td:nth-of-type(1):before { content:
"FIRST_NAME"; }
td:nth-of-type(2):before { content:
"LAST_NAME"; }
td:nth-of-type(3):before { content:
"SALARY"; }
}
}
</style>
<!--<![endif]-->
</head>
<body>
<h1 style = ''text-align :center;
color:green;''>Employees Earning more than $10.000 Per/month</h1>
<br>
<table>
<thead>
<tr>
<th>EMPLOYEE_ID</th>
<th>FIRST_NAME</th>
<th>LAST_NAME</th>
<th>SALARY</th>
</tr>
</thead>
<tbody id="data">';
for r_top in cur_top_earning_emps loop
v_message := v_message|| '<tr>'||
'<td
align="right">'||r_top.employee_id||'</td>'||
'<td>'||r_top.first_name||'</td>'||
'<td>'||r_top.last_name||'</td>'||
'<td
align="right">'||r_top.salary||'</td>'||
'</tr>';
end loop;
v_message := v_message||' </tbody>
</table>
</body>
</html>';
UTL_MAIL.send(
sender => 'topearnings@somedns.com',
recipients => 'oraclemaster@outlook.com',
subject => 'Example 5: The Employees Earning More
Than $10000 (HTML Formatted)',
message => v_message,
mime_type => 'text/html'
);
END;
/
------------------SEND ATTACH RAW------------
--Create a temp table
CREATE TABLE temp_table(
id NUMBER,
blob_data BLOB
);
/
--2) Create a directory object
CREATE OR REPLACE DIRECTORY BLOB_DIR AS 'C:\blob_directory\';
/
--3)Write a PL/SQL Block to load your external file into a BLOB/CLOB
column.
DECLARE
v_bfile BFILE;
v_blob BLOB;
v_dest_offset INTEGER := 1;
v_src_offset INTEGER := 1;
BEGIN
INSERT INTO temp_table (id, blob_data)
VALUES (222, empty_blob())
RETURNING blob_data INTO v_blob;
v_bfile := BFILENAME('BLOB_DIR', 'test_file.jpeg');
DBMS_LOB.fileopen(v_bfile, DBMS_LOB.file_readonly);
DBMS_LOB.loadblobfromfile (
dest_lob => v_blob, -- Destination lob
src_bfile => v_bfile, -- Source file path and
name in the OS
amount => DBMS_LOB.lobmaxsize, -- Maximum LOB size.
dest_offset => v_dest_offset, -- Destination offset.
src_offset => v_src_offset); -- Source offset.
DBMS_LOB.fileclose(v_bfile);
COMMIT;
END;
/
--4) Check the table to see if we could insert the blob file or not
SELECT * FROM temp_table;
/
--5) Send email with an attachment
DECLARE
v_file BLOB;
v_rawbuf RAW(32767);
BEGIN
select blob_data into v_file from temp_table where rownum = 1;
v_rawbuf := dbms_lob.substr(v_file);
UTL_MAIL.send_attach_raw
(
sender => 'somebody@somedomain.com',
recipients => 'oraclemaster@outlook.com',
subject => 'Example 6: Attachment Test',
message => 'This is a raw data',
attachment => v_rawbuf,
att_inline => TRUE,
att_filename => 'testImage.jpeg'
);
END;
/
DROP DIRECTORY blob_dir;
DROP TABLE temp_table;
/
--5) Send email with a text attachment
BEGIN
UTL_MAIL.send_attach_varchar2
(
sender => 'somebody@somedomain.com',
recipients => 'oraclemaster@outlook.com',
subject => 'Example 7: Text Attachment Test',
message => 'This is a text data',
attachment => 'This is the text that will be written inside of
the text file.',
att_inline => TRUE,
att_filename => 'testTextFile.txt'
);
END;