/*====
328lect05-1.sql
* creates and tests PL/SQL stored function job_count,
which also has a parameter
* creates and tests PL/SQL stored procedure job_overview,
which has a parameter, calls PL/SQL stored function
job_count, and includes an IF statement
* and, this also includes how to call a PL/SQL stored
function from SQL*Plus, including how to declare a
SQL*Plus local variable to assign to what the function returns,
and how to print that SQL*Plus variable's value
by: Sharon Tuttle
last modified: 2025-02-18
====*/
/*====
function: job_count: varchar2 -> integer
purpose: expects a job title, and returns the number
of employees with that job title
examples:
if set-up-ex-tbls.sql has been run, then:
job_count('President') = 1
job_count('Sales') = 4
job_count('Kitten Wrangler') = 0
====*/
create or replace function job_count(p_job_title varchar2)
return integer is
/* like a PL/SQL stored procedure, can't have keyword DECLARE before a
PL/SQL stored function's declaration part, either
*/
num_w_job integer;
begin
select count(*)
into num_w_job
from empl
where job_title = p_job_title;
return num_w_job;
end;
/
show errors
/*==== TESTING job_count ====*/
prompt
prompt ========
prompt testing job_count
prompt ========
/*==== sqlplus local variable to hold job_count's returned result ====*/
/*===
(note: SQL*Plus local variables have fewer available types
than those available in SQL, PL/SQL)
ah, this is a bind variable?
https://docs.oracle.com/cd/A81042_01/DOC/sqlplus.816/a75664/ch849.htm#1003221
available types include (this is pulled from nrs-projects SQL*Plus error
message when I tried a "bad" type):
Usage: VAR[IABLE] [ <variable> [ NUMBER | CHAR | CHAR (n [CHAR|BYTE]) |
VARCHAR2 (n [CHAR|BYTE]) | NCHAR | NCHAR (n) |
NVARCHAR2 (n) | CLOB | NCLOB | BLOB | BFILE
REFCURSOR | BINARY_FLOAT | BINARY_DOUBLE ] ]
====*/
var num_job number
/*====
you can assign to a sqlplus local variable (bind variable)
using the exec command
(note the : before its name, and the := for assignment)
====*/
exec :num_job := -1
/*==== here's my first testing call ====*/
exec :num_job := job_count('President')
prompt should be 1:
/*====
you can print the value of a SQL*Plus local variable (bind variable)
using the print command
====*/
print num_job
/*==== here are my other two testing calls ====*/
exec :num_job := job_count('Sales')
prompt should be 4:
print num_job
exec :num_job := job_count('Kitten Wrangler')
prompt should be 0:
print num_job
/*====
procedure: job_overview: varchar2 -> void
purpose: expects a job title, and has the side effect of
printing to the screen (if serveroutput is on)
a small report including that job_title,
how many employees currently have that job title,
and their average salary
uses: job_count
examples:
if set-up-ex-tbls.sql has been run, and serveroutput is on,:
exec job_overview('President')
...should print to the screen:
Job Title : President
# with Job: 1
Avg Salary: $5000
exec job_overview('Sales')
...should print to the screen:
Job Title : Sales
# with Job: 4
Avg Salary: $1400
exec job_overview('Kitten Wrangler')
...should print to the screen:
Job Title : Kitten Wrangler
# with Job: 0
Avg Salary: $0
====*/
create or replace procedure job_overview(p_job_title
empl.job_title%type) as
num_w_job integer;
job_avg_sal number(7, 2);
begin
/*====
note how PL/SQL stored function job_count is called here
====*/
num_w_job := job_count(p_job_title);
if (num_w_job = 0) then
job_avg_sal := 0;
else
select avg(salary)
into job_avg_sal
from empl
where job_title = p_job_title;
end if;
dbms_output.put_line('Job Title : ' || p_job_title);
dbms_output.put_line('# with Job: ' || num_w_job);
dbms_output.put_line('Avg Salary: $' || job_avg_sal);
end;
/
show errors
set serveroutput on
/*==== TESTING job_overview ====*/
prompt
prompt ========
prompt testing job_overview
prompt ========
prompt should see: President, 1, $5000:
prompt ========
exec job_overview('President')
prompt should see: Sales, 4, $1400:
prompt ========
exec job_overview('Sales')
prompt should see: Kitten Wrangler, 0, and $0:
prompt ========
exec job_overview('Kitten Wrangler')