PLSQL
PLSQL
-----------------------===================-----------------------
-----------------------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;
----------------==================================---------------
-----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
-------------------------------------------------------------------------
-
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;
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;
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;
dbms_output.put_line('--------------');
dbms_output.put_line('--------------');
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 & 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;
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
end;
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
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;
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;
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 STATEMENT IS
BEGIN
DBMS_OUTPUT.PUT_LINE('All the changes are done successfully!');
END AFTER STATEMENT;
END;
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;
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;
/
/
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;
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;
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;
UTL_MAIL.send(
sender => '[email protected]',
recipients => '[email protected]',
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 => '[email protected]',
recipients => '[email protected]',
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;