PLSQL Fundamentals: Difference between revisions

From Training Material
Jump to navigation Jump to search
Lsokolowski (talk | contribs)
 
mNo edit summary
 
Line 2: Line 2:




<slideshow style="nobleprog" headingmark="⌘" incmark="…" scaled="true" font="Trebuchet MS" >
 
;title: PL/SQL Fundamentals
;title: PL/SQL Fundamentals
;author: Lukasz Sokolowski
;author: Lukasz Sokolowski
</slideshow>
 


== PL/SQL Fundamentals ==
== PL/SQL Fundamentals ==
Line 15: Line 15:
{{Can I use your material}}
{{Can I use your material}}


== Introduction ==
== Introduction ==
* Aims and Objectives
* Aims and Objectives
* Course Schedule
* Course Schedule
Line 22: Line 22:
* Responsibilities
* Responsibilities


== What is PL/SQL? ==
== What is PL/SQL? ==
* '''What''' is PL/SQL?
* '''What''' is PL/SQL?
* '''Why''' Use PL/SQL?
* '''Why''' Use PL/SQL?
Line 31: Line 31:
* Update Example, Style Guide
* Update Example, Style Guide


=== What is PL/SQL? ===
=== What is PL/SQL? ===
* Developed in 1991 by Oracle Corporation as a '''procedural language extension''' to SQL
* Developed in 1991 by Oracle Corporation as a '''procedural language extension''' to SQL
* '''Integrates''' seamlessly with '''[[SQL_Programming|SQL]]'''  
* '''Integrates''' seamlessly with '''[[SQL_Programming|SQL]]'''  
Line 37: Line 37:
* Rich procedural extensions help in '''translating business logic''' within the Oracle Database
* Rich procedural extensions help in '''translating business logic''' within the Oracle Database


=== Why Use PL/SQL? ===
=== Why Use PL/SQL? ===
* ''Procedural Language-Structured Query Language'' (PL/SQL)
* ''Procedural Language-Structured Query Language'' (PL/SQL)
* Part of the Oracle Database product, '''no separate installation''' is required
* Part of the Oracle Database product, '''no separate installation''' is required
Line 47: Line 47:
* The '''built-in db optimizer''' refactors the code to improve the execution '''performance'''
* The '''built-in db optimizer''' refactors the code to improve the execution '''performance'''


=== The advantages of PL/SQL as a language ===
=== The advantages of PL/SQL as a language ===
* '''Supports''' all types of SQL statements, data types, static SQL, and dynamic SQL
* '''Supports''' all types of SQL statements, data types, static SQL, and dynamic SQL
* '''Runs''' on all platforms supported by the Oracle Database
* '''Runs''' on all platforms supported by the Oracle Database
Line 54: Line 54:
* Apps increase scalability by allowing '''multiple users''' to invoke the '''same program''' unit
* Apps increase scalability by allowing '''multiple users''' to invoke the '''same program''' unit


=== PL/SQL accomplishments ===
=== PL/SQL accomplishments ===
* '''Not''' used to build '''user interfaces'''
* '''Not''' used to build '''user interfaces'''
* '''For''' robust, secure, and portable '''interface layers'''
* '''For''' robust, secure, and portable '''interface layers'''
Line 65: Line 65:
** Procedures or subprograms can be '''invoked from client programs as executable statements'''
** Procedures or subprograms can be '''invoked from client programs as executable statements'''


=== PL/SQL program fundamental questions ===
=== PL/SQL program fundamental questions ===
* How do we '''handle''' an SQL '''execution''' in the program?
* How do we '''handle''' an SQL '''execution''' in the program?
* How do we handle the '''procedural execution flow''' in the program?
* How do we handle the '''procedural execution flow''' in the program?
Line 71: Line 71:
* How do we '''trace and debug''' the program code?
* How do we '''trace and debug''' the program code?


=== Block structure ===
=== Block structure ===
[[File:PlsqlBlockStr.jpg|480px]]
[[File:PlsqlBlockStr.jpg|480px]]


=== Block structure Expl ===
=== Block structure Expl ===
PL/SQL program has '''4 sections'''
PL/SQL program has '''4 sections'''
* Each section carries a '''specific objective'''
* Each section carries a '''specific objective'''
Line 88: Line 88:
* Keywords - ''EXCEPTION''; control lands into it and the appropriate '''exception handler''' is executed
* Keywords - ''EXCEPTION''; control lands into it and the appropriate '''exception handler''' is executed


=== PL/SQL program categories ===
=== PL/SQL program categories ===
Block is the '''elementary unit''' of a program
Block is the '''elementary unit''' of a program
* '''Groups''' a set of procedural statements
* '''Groups''' a set of procedural statements
Line 101: Line 101:
* '''Nested:''' block within another block, forms a nested block structure
* '''Nested:''' block within another block, forms a nested block structure


=== Anonymous unit, example ===
=== Anonymous unit, example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
/* Enable the Serveroutput to display block messages */
/* Enable the Serveroutput to display block messages */
Line 121: Line 121:
</syntaxhighlight>
</syntaxhighlight>


== SQL Tools ==
== SQL Tools ==
* Objectives
* Objectives
* SQL Developer
* SQL Developer
Line 142: Line 142:
* SQL*Plus Commands
* SQL*Plus Commands


== Variables ==
== Variables ==
* Variables
* Variables
* Datatypes
* Datatypes
Line 156: Line 156:
* Define and Undefine
* Define and Undefine
-->
-->
=== Variables, Datatypes, Setting ===
=== Variables, Datatypes, Setting ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
DECLARE
DECLARE
Line 170: Line 170:
</syntaxhighlight>
</syntaxhighlight>


=== Constants ===
=== Constants ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
DECLARE
DECLARE
Line 182: Line 182:
</syntaxhighlight>
</syntaxhighlight>


=== %TYPE Attribute ===
=== %TYPE Attribute ===
* Syntax - '''referencing_item referenced_item%TYPE;'''
* Syntax - '''referencing_item referenced_item%TYPE;'''
* Examples
* Examples
Line 200: Line 200:
</syntaxhighlight>
</syntaxhighlight>


=== Variables Scope ===  
=== Variables Scope ===  
<syntaxhighlight lang="sql">-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-language-fundamentals.html#GUID-2FC17012-FC99-4614-90DD-ADC99F2EDBE9</syntaxhighlight>
<syntaxhighlight lang="sql">-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-language-fundamentals.html#GUID-2FC17012-FC99-4614-90DD-ADC99F2EDBE9</syntaxhighlight>


=== Exercise ===  
=== Exercise ===  
Prepare necessary declarations for the draft or real invoice, print all of them to the screen(like below)  
Prepare necessary declarations for the draft or real invoice, print all of them to the screen(like below)  
* variables, initialised (item price, item name)
* variables, initialised (item price, item name)
Line 277: Line 277:
-->
-->


== SELECT INTO example ==
== SELECT INTO example ==
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
DECLARE
DECLARE
Line 291: Line 291:
</syntaxhighlight>
</syntaxhighlight>


=== %ROWTYPE attribute ===
=== %ROWTYPE attribute ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
---- Record variable that represents a row of the table "dept", assigns values to its fields, and prints them
---- Record variable that represents a row of the table "dept", assigns values to its fields, and prints them
Line 310: Line 310:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
When the TOOSK's subordinate was hired?
When the TOOSK's subordinate was hired?
* Use ''SELECT INTO''
* Use ''SELECT INTO''
Line 347: Line 347:
-->
-->


== Conditional Statement ==
== Conditional Statement ==
* IF Statement
* IF Statement
* Case Statement
* Case Statement
Line 353: Line 353:
** <syntaxhighlight lang="sql" inline>-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-control-statements.html#GUID-B7DD4E62-3ED2-41E9-AAE5-90A78788BB31</syntaxhighlight>
** <syntaxhighlight lang="sql" inline>-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-control-statements.html#GUID-B7DD4E62-3ED2-41E9-AAE5-90A78788BB31</syntaxhighlight>


=== IF Statement ===
=== IF Statement ===
* IF THEN
* IF THEN
* IF THEN ELSE
* IF THEN ELSE
* IF THEN ELSIF
* IF THEN ELSIF


=== IF THEN ELSE example ===
=== IF THEN ELSE example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
-- IF statement example
-- IF statement example
Line 389: Line 389:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
Reuse variables exercise and apply this logic
Reuse variables exercise and apply this logic
* When invoice is a draft set new variable 'Invoice Proforma Reference' with invoice number
* When invoice is a draft set new variable 'Invoice Proforma Reference' with invoice number
Line 413: Line 413:
-->
-->


=== Case Statement ===
=== Case Statement ===
* Appropriate when a '''different action''' is to be taken '''for each alternative'''
* Appropriate when a '''different action''' is to be taken '''for each alternative'''
* Two forms
* Two forms
Line 419: Line 419:
** '''Searched''', evaluates multiple conditions and chooses the first one that is true
** '''Searched''', evaluates multiple conditions and chooses the first one that is true


=== Simple Case example ===
=== Simple Case example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
DECLARE
DECLARE
Line 438: Line 438:
</syntaxhighlight>
</syntaxhighlight>


=== Searched Case example ===
=== Searched Case example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
DECLARE
DECLARE
Line 460: Line 460:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
Reuse invoice reference exercise and add this logic
Reuse invoice reference exercise and add this logic
* One Franchisee can have 1-3 instances of invoicing tool
* One Franchisee can have 1-3 instances of invoicing tool
Line 513: Line 513:
-->
-->


== Trapping Errors ==
== Trapping Errors ==
* Exception
* Exception
* System-defined
* System-defined
Line 519: Line 519:
* Propagation
* Propagation


=== Exception ===
=== Exception ===
* Unusual and unexpected flow during '''runtime''' might result in abnormal '''termination'''
* Unusual and unexpected flow during '''runtime''' might result in abnormal '''termination'''
** Such errors must be '''trapped''' and handled in the ''EXCEPTION'' section
** Such errors must be '''trapped''' and handled in the ''EXCEPTION'' section
Line 532: Line 532:
** Retrieve the error code and message for the '''most recent''' exception
** Retrieve the error code and message for the '''most recent''' exception


=== System-defined ===
=== System-defined ===
* '''Defined and maintained''' implicitly by the Oracle Database, STANDARD package
* '''Defined and maintained''' implicitly by the Oracle Database, STANDARD package
* db picks up the appropriate exception from the '''available list'''
* db picks up the appropriate exception from the '''available list'''
* Associated with a '''negative error code''' (except 1 to 100) and short name (for handlers)
* Associated with a '''negative error code''' (except 1 to 100) and short name (for handlers)


=== Using No Data Found ===
=== Using No Data Found ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
-- Example includes a SELECT statement to show details of employee 8265
-- Example includes a SELECT statement to show details of employee 8265
Line 563: Line 563:
</syntaxhighlight>
</syntaxhighlight>


=== Solution - EXCEPTION with handler ===
=== Solution - EXCEPTION with handler ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
(...)
(...)
Line 580: Line 580:
*/
*/
</syntaxhighlight>
</syntaxhighlight>
=== Exercise ===
=== Exercise ===
When did Blake come to the company?
When did Blake come to the company?
<!-- Solution example
<!-- Solution example
Line 605: Line 605:
-->
-->


=== Commonly used internal exceptions ===
=== Commonly used internal exceptions ===
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 637: Line 637:
|}
|}


=== User exceptions ===
=== User exceptions ===
* Has specified '''name''' and associated '''error code'''
* Has specified '''name''' and associated '''error code'''
* Raises statements '''in line''' with the implementation logic
* Raises statements '''in line''' with the implementation logic
Line 643: Line 643:
* ''RAISE'' statement in the ''BEGIN..END'' section
* ''RAISE'' statement in the ''BEGIN..END'' section


=== User exceptions, 3 ways of declaring ===
=== User exceptions, 3 ways of declaring ===
EXCEPTION type '''variable''' in the declaration section
EXCEPTION type '''variable''' in the declaration section
* Raise it '''explicitly''' in the program body (RAISE statement)
* Raise it '''explicitly''' in the program body (RAISE statement)
Line 653: Line 653:
RAISE_APPLICATION_ERROR - declares a '''dedicated''' error number and error message
RAISE_APPLICATION_ERROR - declares a '''dedicated''' error number and error message


=== User-defined exception, example ===
=== User-defined exception, example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
/* Declare a bind variable */
/* Declare a bind variable */
Line 693: Line 693:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
For each employee calculate the payout to commission ratio (ver1).
For each employee calculate the payout to commission ratio (ver1).
<!--
<!--
Line 718: Line 718:
/
/
-->
-->
=== Raise Application Error ===
=== Raise Application Error ===
RAISE_APPLICATION_ERROR - procedure, raises a '''user-defined''' exception with a '''custom''' exception message
RAISE_APPLICATION_ERROR - procedure, raises a '''user-defined''' exception with a '''custom''' exception message
* Exception can be '''optionally''' pre-defined (DECLARE)
* Exception can be '''optionally''' pre-defined (DECLARE)
Line 726: Line 726:
** '''last parameter''' - optional, adding to the current error '''stack'''
** '''last parameter''' - optional, adding to the current error '''stack'''


=== Example ===
=== Example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
---- Example
---- Example
Line 758: Line 758:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
Show employees who have joined the company after 1st of Nov, 1981.
Show employees who have joined the company after 1st of Nov, 1981.
* Raise the exception if earlier
* Raise the exception if earlier
Line 783: Line 783:
-->
-->


==== Example con't ====
==== Example con't ====
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
-- Same example, but with named exception
-- Same example, but with named exception
Line 831: Line 831:
-->
-->


=== Nested Blocks Structure ===
=== Nested Blocks Structure ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
/*Parent block*/
/*Parent block*/
Line 856: Line 856:
</syntaxhighlight>
</syntaxhighlight>


=== Nested Blocks Expl ===
=== Nested Blocks Expl ===
* Exception raised in '''inner''' block '''--->''' program control flows down to exception section of it
* Exception raised in '''inner''' block '''--->''' program control flows down to exception section of it
* '''Inner''' block handles the exception, it's executed '''--->''' control '''returns''' to the next executable statement in the '''outer''' block
* '''Inner''' block handles the exception, it's executed '''--->''' control '''returns''' to the next executable statement in the '''outer''' block
Line 881: Line 881:
-->
-->


== Cursors ==
== Cursors ==
* Overview
* Overview
* Execution cycle
* Execution cycle
Line 887: Line 887:
* FOR loop
* FOR loop


=== Overview ===
=== Overview ===
* '''SQL''' is one of the critical parts of '''PL/SQL'''
* '''SQL''' is one of the critical parts of '''PL/SQL'''
** '''Statements''' embedded within a PL/SQL block are '''executed as a cursor'''
** '''Statements''' embedded within a PL/SQL block are '''executed as a cursor'''
Line 898: Line 898:
** We can explicitly declare an implicit cursor under the ''DECLARE'' section in ''SELECT'' query
** We can explicitly declare an implicit cursor under the ''DECLARE'' section in ''SELECT'' query


=== Execution cycle ===
=== Execution cycle ===
[[File:PlsqlCursorCycle.jpg|600px]]
[[File:PlsqlCursorCycle.jpg|600px]]


=== Execution cycle Expl ===
=== Execution cycle Expl ===
Cursor '''moves''' through the following '''stages''' during execution
Cursor '''moves''' through the following '''stages''' during execution
* implicit - all steps are carried out by db
* implicit - all steps are carried out by db
Line 914: Line 914:
* Releases the '''memory''' back to the UGA
* Releases the '''memory''' back to the UGA


=== Attributes ===
=== Attributes ===
Hold the information about the cursor processing at each stage of its execution
Hold the information about the cursor processing at each stage of its execution
* '''%ROWCOUNT''': number of rows, fetched until the '''last''' fetch  
* '''%ROWCOUNT''': number of rows, fetched until the '''last''' fetch  
Line 923: Line 923:
* '''%NOTFOUND''': FALSE/TRUE, cursor pointer switches but does '''not point''' to a record
* '''%NOTFOUND''': FALSE/TRUE, cursor pointer switches but does '''not point''' to a record


=== Attributes, example ===
=== Attributes, example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
SET SERVEROUTPUT ON
SET SERVEROUTPUT ON
Line 974: Line 974:
</syntaxhighlight>
</syntaxhighlight>


=== FOR loop ===
=== FOR loop ===
CURSOR FOR loop
CURSOR FOR loop
* Looping through '''all the records''' of a cursor object
* Looping through '''all the records''' of a cursor object
Line 983: Line 983:
** No need to explicitly open or close the cursor
** No need to explicitly open or close the cursor


=== FOR loop, example ===
=== FOR loop, example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
DECLARE
DECLARE
Line 1,009: Line 1,009:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
Pick the attribute with the wrong value
Pick the attribute with the wrong value


Line 1,097: Line 1,097:
-->
-->


== Procedures, Functions and Packages ==
== Procedures, Functions and Packages ==
* Procedures
* Procedures
* Functions
* Functions
* Packages
* Packages


=== Procedure ===
=== Procedure ===
'''Derivative''' of a PL/SQL block
'''Derivative''' of a PL/SQL block
* Has a '''name''' and is '''stored persistently''' within the db
* Has a '''name''' and is '''stored persistently''' within the db
Line 1,108: Line 1,108:
* Promotes a '''modular''' programming, breaks down complex logic into '''simple routines'''
* Promotes a '''modular''' programming, breaks down complex logic into '''simple routines'''


=== Procedure con't ===
=== Procedure con't ===
* Must be '''invoked''' from the executable section of a PL/SQL '''block'''
* Must be '''invoked''' from the executable section of a PL/SQL '''block'''
* Executable '''directly''' from SQLPLUS (''EXECUTE'')
* Executable '''directly''' from SQLPLUS (''EXECUTE'')
Line 1,117: Line 1,117:
* ''RETURN'' - '''skips''' the further execution of the program and '''exits''' control
* ''RETURN'' - '''skips''' the further execution of the program and '''exits''' control


=== Procedure parameter modes ===
=== Procedure parameter modes ===
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 1,133: Line 1,133:
|}
|}


=== Procedure syntax ===
=== Procedure syntax ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
CREATE [OR REPLACE] PROCEDURE [Procedure Name] [Parameter List]
CREATE [OR REPLACE] PROCEDURE [Procedure Name] [Parameter List]
Line 1,146: Line 1,146:
</syntaxhighlight>
</syntaxhighlight>


=== Procedure example ===
=== Procedure example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
---- Converts GeoJSON points into WKT(Well-known text)
---- Converts GeoJSON points into WKT(Well-known text)
Line 1,171: Line 1,171:
</syntaxhighlight>
</syntaxhighlight>


=== Calling Procedures ===
=== Calling Procedures ===
* From '''SQL*Plus'''
* From '''SQL*Plus'''
* Inside of PL/SQL '''block'''
* Inside of PL/SQL '''block'''


=== SQLPlus ===
=== SQLPlus ===
* Initial setup
* Initial setup
* Calling
* Calling


==== Initial setup ====
==== Initial setup ====
  sys as sysdba
  sys as sysdba
  asdf
  asdf
Line 1,185: Line 1,185:
  SQL> show user
  SQL> show user


==== Calling ====
==== Calling ====
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
---- Calling procedure from PL*SQL
---- Calling procedure from PL*SQL
Line 1,207: Line 1,207:
</syntaxhighlight>
</syntaxhighlight>


=== Calling procedure from anonymous unit ===
=== Calling procedure from anonymous unit ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
BEGIN
BEGIN
Line 1,216: Line 1,216:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
Wrap all the 'Invoice Reference' related code into procedure
Wrap all the 'Invoice Reference' related code into procedure
<!-- Solution example
<!-- Solution example
Line 1,349: Line 1,349:
* When '''invoked from PL/SQL''', the return type should be a '''valid PL/SQL type'''
* When '''invoked from PL/SQL''', the return type should be a '''valid PL/SQL type'''


=== Function syntax ===
=== Function syntax ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
CREATE [OR REPLACE] FUNCTION [Function Name] [Parameter List]
CREATE [OR REPLACE] FUNCTION [Function Name] [Parameter List]
Line 1,366: Line 1,366:
</syntaxhighlight>
</syntaxhighlight>


=== Function example ===
=== Function example ===
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
---- Get the date of birth from pesel
---- Get the date of birth from pesel
Line 1,408: Line 1,408:
</syntaxhighlight>
</syntaxhighlight>


=== Exercise ===
=== Exercise ===
# Wrap all the 'Franchisee' related code into function
# Wrap all the 'Franchisee' related code into function
#* HINT: redesign printing code (array?)
#* HINT: redesign printing code (array?)
Line 1,538: Line 1,538:
-->
-->


=== Packages ===
=== Packages ===
<syntaxhighlight lang="sql">-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-packages.html#GUID-C285EC5A-BE50-4192-A88E-48C0778B34E0</syntaxhighlight>
<syntaxhighlight lang="sql">-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-packages.html#GUID-C285EC5A-BE50-4192-A88E-48C0778B34E0</syntaxhighlight>
<!--
<!--

Latest revision as of 23:18, 29 October 2025



title
PL/SQL Fundamentals
author
Lukasz Sokolowski


PL/SQL Fundamentals

PL/SQL Fundamentals Training Materials

IMPORTANT NOTE for trainers only: 
Please DO NOT change these materials, especially the EXERCISES, without direct permission from: GRZEGORZ PRUSZCZYNSKI or LUKASZ SOKOLOWSKI.

Introduction

  • Aims and Objectives
  • Course Schedule
  • Introductions
  • Pre-requisites
  • Responsibilities

What is PL/SQL?

  • What is PL/SQL?
  • Why Use PL/SQL?
  • Block Structure
  • Displaying a Message
  • Sample Code
  • Setting SERVEROUTPUT
  • Update Example, Style Guide

What is PL/SQL?

  • Developed in 1991 by Oracle Corporation as a procedural language extension to SQL
  • Integrates seamlessly with SQL
  • Powerful language to construct the data access layer
  • Rich procedural extensions help in translating business logic within the Oracle Database

Why Use PL/SQL?

  • Procedural Language-Structured Query Language (PL/SQL)
  • Part of the Oracle Database product, no separate installation is required
  • Translates business logic in the db and exposes the program interface layer to the application
  • SQL is purely a data access language that directly interacts with the db
  • PL/SQL is a programming language
    • Multiple SQLs and procedural statements can be grouped in a program unit
    • Portable between Oracle Databases
  • The built-in db optimizer refactors the code to improve the execution performance

The advantages of PL/SQL as a language

  • Supports all types of SQL statements, data types, static SQL, and dynamic SQL
  • Runs on all platforms supported by the Oracle Database
  • Performance can be improved by the use of bind variables in direct SQL queries
  • Supports the object-oriented model of the Oracle Database
  • Apps increase scalability by allowing multiple users to invoke the same program unit

PL/SQL accomplishments

  • Not used to build user interfaces
  • For robust, secure, and portable interface layers
    • Can be exposed to a high-level programming language
  • Procedural: list of operations that can execute sequentially
    • SQL just declares, PL/SQL adds selective and iterative constructs
  • Db programming: server side programs run faster than the middle-tier
    • Easy code maintenance, needs to be re-written less frequently
  • Integral: apps developers can easily integrate it with other high-level programming interfaces (Java, C++, or .NET)
    • Procedures or subprograms can be invoked from client programs as executable statements

PL/SQL program fundamental questions

  • How do we handle an SQL execution in the program?
  • How do we handle the procedural execution flow in the program?
  • Does the program handle the exceptions?
  • How do we trace and debug the program code?

Block structure

Block structure Expl

PL/SQL program has 4 sections

  • Each section carries a specific objective
  • Must exist in the same sequence in a program

Header: optional, required for named blocks (procedures, functions, and triggers)

  • Contains the program name, the program's owner, and the parameter specification

Declaration: optional, declares local variables, cursors, and local subprograms

  • Keywords - DECLARE; can be skipped if no variables

Execution: procedural, comprises the main program body and an exception

  • Keywords - BEGIN, END; must contain at least one executable statement
  • Statements are parsed and sequentially executed by the engine

Exception: optional, for various errors, occurable in the program leading to abnormal termination

  • Keywords - EXCEPTION; control lands into it and the appropriate exception handler is executed

PL/SQL program categories

Block is the elementary unit of a program

  • Groups a set of procedural statements

Number of sections defines type of the unit

  • Anonymous: simplest; has no name, has DECLARE-BEGIN-END skeleton
    • Current execution as standalone block or embedded locally within another unit
    • Cannot be stored in the db
  • Named: routine stored persistently in db as a schema object
    • Invoked from db session or by another unit
    • Can be a function, procedure, trigger, or package
  • Nested: block within another block, forms a nested block structure

Anonymous unit, example

/* Enable the Serveroutput to display block messages */
-- SET SERVEROUTPUT ON;

/* Start the PL/SQL block */
DECLARE
/* Declare a local variable and initialize with a default value */
   MY_STR VARCHAR2(80) := 'Yes, I do like PL/SQL';
BEGIN
/* Print the result */
   DBMS_OUTPUT.PUT_LINE( 'Do you like it? ' || MY_STR );
END;
/
-----------------------------------
-- Do you like it? Yes, I do like PL/SQL

-- PL/SQL procedure successfully completed.

SQL Tools

  • Objectives
  • SQL Developer
  • SQL Developer - Connection
  • Viewing Table Information
  • Using SQL, SQL Developer - Query
  • SQL*Plus Login
  • Direct Connection
  • Using SQL*Plus
  • Ending the Session
  • SQL*Plus Commands
  • SQL*Plus Environment
  • SQL*Plus Prompt
  • Finding Information about Tables
  • Getting Help
  • Using SQL Files
  • iSQL*Plus, Entity Models
  • Course Tables Handout
  • SQL Statement Syntax
  • SQL*Plus Commands

Variables

  • Variables
  • Datatypes
  • Setting Variables
  • Constants
  • Local and Global Variables
  • %Type Variables

Variables, Datatypes, Setting

DECLARE
  part_number       NUMBER(6);     -- SQL data type, NULL
  part_name         VARCHAR2(20) := 'Gauss Rifle';  -- SQL data type, initialized with value
  in_stock          BOOLEAN;       -- PL/SQL-only data type, NULL(unknown)
  part_price        NUMBER(6,2);   -- SQL data type
  part_description  VARCHAR2(50);  -- SQL data type
BEGIN
  NULL;
END;
/

Constants

DECLARE
  credit_limit     CONSTANT REAL    := 5000.00;  -- SQL data type
  max_days_in_year CONSTANT INTEGER := 366;      -- SQL data type
  urban_legend     CONSTANT BOOLEAN := FALSE;    -- PL/SQL-only data type
BEGIN
  NULL;
END;
/

%TYPE Attribute

  • Syntax - referencing_item referenced_item%TYPE;
  • Examples
DECLARE
  ---- Variable of Same Type as Column
  emp_name  emp.ename%TYPE;
  name     VARCHAR(25) NOT NULL := 'Bond';
  ---- Variable of Same Type as Another Variable
  surname  name%TYPE := 'Dick';
BEGIN
  DBMS_OUTPUT.PUT_LINE('Full name =' || emp_name);
  DBMS_OUTPUT.PUT_LINE('name=' || name);
  DBMS_OUTPUT.PUT_LINE('surname=' || surname);
END;
/

Variables Scope

-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-language-fundamentals.html#GUID-2FC17012-FC99-4614-90DD-ADC99F2EDBE9

Exercise

Prepare necessary declarations for the draft or real invoice, print all of them to the screen(like below)

  • variables, initialised (item price, item name)
  • vars, not initialised (invoice's unique number, invoice type(draft or real), final cost, items total, date of issue, amount, VAT rate, Items)
  • constants (tax rate, item number)
  • inheriting type od data (Items from Final Cost)
/*
---- HEADERS ----
Date of Issue:      present_year-present_month-present_day
Invoice number:     INV201
Invoice type:       draft

---- INVOICE ITEMS ----
Item Number     Item Name       Amount      Price       Tax Rate       Final Cost
190.228.09      Gaus Rifle      20          800         0,20           16000

SUMMARY:
VAT rate:       20%
Items:          16000
Items total:    19200
(...)
*/

SELECT INTO example

DECLARE
  bonus   NUMBER(8,2);
BEGIN
  SELECT sal * 0.10 INTO bonus
  FROM emp
  WHERE id = 7900;

  DBMS_OUTPUT.PUT_LINE('bonus = ' || TO_CHAR(bonus));
END;
/

%ROWTYPE attribute

---- Record variable that represents a row of the table "dept", assigns values to its fields, and prints them
DECLARE
  dept_rec dept%ROWTYPE;
BEGIN
  -- Assign values to fields:  
  dept_rec.deptno   := 50;
  dept_rec.dname    := 'Administration';
  dept_rec.loc      := 'HongKong';
 
  -- Print fields: 
  DBMS_OUTPUT.PUT_LINE('dept_id:   ' || dept_rec.deptno);
  DBMS_OUTPUT.PUT_LINE('dept_name: ' || dept_rec.dname);
  DBMS_OUTPUT.PUT_LINE('loc:    ' || dept_rec.loc);
END;
/

Exercise

When the TOOSK's subordinate was hired?

  • Use SELECT INTO
  • Show the result like below
/*
Subordinate name = THATCHER
Hiredate = 80/12/17
*/


Conditional Statement

  • IF Statement
  • Case Statement
  • More here
    • -- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-control-statements.html#GUID-B7DD4E62-3ED2-41E9-AAE5-90A78788BB31

IF Statement

  • IF THEN
  • IF THEN ELSE
  • IF THEN ELSIF

IF THEN ELSE example

-- IF statement example
DECLARE
  PROCEDURE p (
    sales  NUMBER,
    quota  NUMBER,
    emp_id NUMBER
  )
  IS
    bonus  NUMBER := 0;
  BEGIN
    IF sales > (quota + 200) THEN
      bonus := (sales - quota)/4;
    ELSE
      bonus := 50;
    END IF;
 
    DBMS_OUTPUT.PUT_LINE('bonus = ' || bonus);
 
    UPDATE emp
    SET sal = sal + bonus 
    WHERE id = emp_id;
  END p;
BEGIN
  p(10100, 10000, 7369);
  p(10500, 10000, 121);
END;
/

Exercise

Reuse variables exercise and apply this logic

  • When invoice is a draft set new variable 'Invoice Proforma Reference' with invoice number
  • Otherwise set new variable 'Invoice Reference'

Case Statement

  • Appropriate when a different action is to be taken for each alternative
  • Two forms
    • Simple, evaluates a single expression and compares it to several potential values
    • Searched, evaluates multiple conditions and chooses the first one that is true

Simple Case example

DECLARE
  sal_grade NUMBER;
BEGIN
  sal_grade := 2;

  CASE sal_grade
    WHEN 1 THEN DBMS_OUTPUT.PUT_LINE('Poor');
    WHEN 2 THEN DBMS_OUTPUT.PUT_LINE('Peanuts');
    WHEN 3 THEN DBMS_OUTPUT.PUT_LINE('Still Peanuts');
    WHEN 4 THEN DBMS_OUTPUT.PUT_LINE('Pineapples');
    WHEN 5 THEN DBMS_OUTPUT.PUT_LINE('Coconuts');
    ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
  END CASE;
END;
/

Searched Case example

DECLARE
PROCEDURE print_bool (pb BOOLEAN)
AS
BEGIN
  DBMS_OUTPUT.PUT_LINE (
    CASE
      WHEN pb IS NULL THEN 'Unknown'
      WHEN pb THEN 'True'
      WHEN NOT pb THEN 'False'
    END
  );
END;

BEGIN
  print_bool(TRUE);
  print_bool(FALSE);
  print_bool(NULL);
END;

Exercise

Reuse invoice reference exercise and add this logic

  • One Franchisee can have 1-3 instances of invoicing tool
  • For each instance set 3 new variables
    • 'tool_key_var1' - set it with a string 'tool_key1_' concatenated with Franchsiee's Name(new var)
    • 'tool_secret_var1' - set it with 'tool_secret1_' with F's name
    • 'tool_acc_var1' - set 'tool_account1_' with F's name
  • Check which instance will be used to issue invoice (new var)
    • Default should say 'No such tool exists. Please contact the administrator.'

Trapping Errors

  • Exception
  • System-defined
  • User-defined
  • Propagation

Exception

  • Unusual and unexpected flow during runtime might result in abnormal termination
    • Such errors must be trapped and handled in the EXCEPTION section
  • Exceptions suppress the abnormal termination with an alternative and secured action
  • Important step in db programming
  • Unhandled exceptions
    • Can result in unplanned application outages
    • Impact business continuity
    • Frustrate end users
  • System-defined(implicitly raised) and user-defined(declared and raised in unit)
  • Utility functions - SQLCODE and SQLERRM
    • Retrieve the error code and message for the most recent exception

System-defined

  • Defined and maintained implicitly by the Oracle Database, STANDARD package
  • db picks up the appropriate exception from the available list
  • Associated with a negative error code (except 1 to 100) and short name (for handlers)

Using No Data Found

-- Example includes a SELECT statement to show details of employee 8265
-- Raises NO_DATA_FOUND - employee id 8265 doesn't exist
DECLARE
   V_ENAME VARCHAR2 (100);
   V_HIRED DATE;
   V_EMPNO NUMBER := 8265;
BEGIN
/*Write a SELECT statement */
   SELECT ENAME, HIREDATE
   INTO V_ENAME, V_HIRED
   FROM EMP
   WHERE ID = V_EMPNO;
END;
/
-----------------------------------
/*
DECLARE
(...)
ERROR at line 7:
ORA-01403: no data found
ORA-06512: at line 7
*/

Solution - EXCEPTION with handler

(...)
EXCEPTION
   /* Exception Handler */
   WHEN NO_DATA_FOUND THEN
   /* Display an informative message */
   DBMS_OUTPUT.PUT_LINE ('No Employee exists with the id ' || V_EMPNO);
END
/
-----------------------------------
/*
No Employee exists with the id 8265

PL/SQL procedure successfully completed.
*/

Exercise

When did Blake come to the company?

Commonly used internal exceptions

Error, ORA-_ Named exception Raised when
00001 DUP_VAL_ON_INDEX Duplicate value exists
01001 INVALID_CURSOR Cursor is invalid
01012 NOT_LOGGED_ON User is not logged in
01017 LOGIN_DENIED System error occurred
01403 NO_DATA_FOUND The query returns no data
01422 TOO_MANY_ROWS A single row query returns multiple rows
01476 ZERO_DIVIDE An attempt was made to divide a number by zero
01722 INVALID_NUMBER The number is invalid
06504 ROWTYPE_MISMATCH Mismatch occurred in row type
06511 CURSOR_ALREADY_OPEN Cursor is already open
06531 COLLECTION_IS_NULL Working with NULL collection
06532 SUBSCRIPT_OUTSIDE_LIMIT Collection index out of range
06533 SUBSCRIPT_BEYOND_COUNT Collection index out of count

User exceptions

  • Has specified name and associated error code
  • Raises statements in line with the implementation logic
  • Standardizes the exception handling to alter the program execution logic
  • RAISE statement in the BEGIN..END section

User exceptions, 3 ways of declaring

EXCEPTION type variable in the declaration section

  • Raise it explicitly in the program body (RAISE statement)
  • Handle it in the EXCEPTION section, no error code is involved

EXCEPTION variable associated with standard error number

  • using PRAGMA EXCEPTION_INIT
  • PRAGMA - directive to the compiler, manipulates the behavior during compilation (not at the time of execution)
  • Also mapping to non-predefined exception (standard errors not defined as PL/SQL exceptions)

RAISE_APPLICATION_ERROR - declares a dedicated error number and error message

User-defined exception, example

/* Declare a bind variable */
VARIABLE B_NO NUMBER;
/* Assign negative value to B_NO */
EXEC :B_NO := -4;
-- EXEC :B_NO := 9;

DECLARE
   I_NO NUMBER := :B_NO;
   I_SQR NUMBER;
   /* Declare an exception variable */
   NORESU EXCEPTION;
BEGIN
   /* Raise the exception if B_NO equals negative value */
   IF I_NO < 0 THEN
      RAISE NORESU;
   END IF;
   I_SQR := SQRT(I_NO);
   DBMS_OUTPUT.PUT_LINE('The result : ' || I_SQR);
EXCEPTION
   /* Exception handler for NORESU exception */
   WHEN NORESU THEN
      DBMS_OUTPUT.PUT_LINE('Number cannot be negative');
END;
/
---------------------------
/*
Number cannot be negative

PL/SQL procedure successfully completed.
*/
---------------------------
/*
The result : 3

PL/SQL procedure successfully completed.
*/

Exercise

For each employee calculate the payout to commission ratio (ver1).

Raise Application Error

RAISE_APPLICATION_ERROR - procedure, raises a user-defined exception with a custom exception message

  • Exception can be optionally pre-defined (DECLARE)
  • Syntax: RAISE_APPLICATION_ERROR (error_number, error_message[, {TRUE | FALSE}])
    • error_number - mandatory parameter, values range 20000-20999
    • error_message - user-defined, appears along with the exception
    • last parameter - optional, adding to the current error stack

Example

---- Example
-- Show employees who earn more than 2000 (excluding commision).
-- The program must raise an exception if monies are less than the given amount.
DECLARE
   G_MONEY NUMBER := 2000;
/* Declare a cursor to filter employees */
   CURSOR C_EMP IS
    SELECT id, ename, sal
    FROM emp;
BEGIN
   FOR E IN C_EMP
   LOOP
   /* Raise exception, if monies are less than 2000 */
      IF e.sal < g_money THEN
        /* Exception name is not used to create the exception handler */
        RAISE_APPLICATION_ERROR (-20008, 'Gets less, show the other one!');
      ELSE 
	DBMS_OUTPUT.PUT_LINE( e.ename || ' gets ' || e.sal);
      END IF;
   END LOOP;
END;
/
---------------
/*
Error starting at line : 171 in command -
ORA-20008: Gets less, show the other one!
ORA-06512: at line 12
*/

Exercise

Show employees who have joined the company after 1st of Nov, 1981.

  • Raise the exception if earlier

Example con't

-- Same example, but with named exception
(...)
/* Declare the exception var */
  INVAL_EMP_SAL EXCEPTION;
  PRAGMA EXCEPTION_INIT(INVAL_EMP_SAL, -20008);
(...)
    IF e.sal < g_money THEN
	   RAISE INVAL_EMP_SAL;
    ELSE
(...)
  END LOOP;
EXCEPTION
  WHEN INVAL_EMP_SAL THEN
    DBMS_OUTPUT.PUT_LINE(SQLERRM || 'Gets less, show the other one!');
END;
/

Nested Blocks Structure

/*Parent block*/
DECLARE
...
BEGIN
   /* Outer block executable statements */
...
   /* Child Block */
   DECLARE
  ...
   BEGIN
      ...
      /* Inner block executable statements */
      ...
   EXCEPTION
      /* Inner block exception handlers */
   END;
   ...
   /* Outer block executable statements */
EXCEPTION
/* Outer block exception handlers */
END;

Nested Blocks Expl

  • Exception raised in inner block ---> program control flows down to exception section of it
  • Inner block handles the exception, it's executed ---> control returns to the next executable statement in the outer block
  • Inner block doesn't handle the exception ---> control searches further and propagates to the exception section of the outer block
    • The execution of the outer block is skipped and the program control lands straight in to the exception section
  • Control will continue to propagate the unhandled exception in the outer blocks
    • Until the appropriate one is found and handled


Cursors

  • Overview
  • Execution cycle
  • Attributes
  • FOR loop

Overview

  • SQL is one of the critical parts of PL/SQL
    • Statements embedded within a PL/SQL block are executed as a cursor
  • Cursor - private memory area, temporarily allocated in the session's User Global Area (UGA)
    • Stores the result set retrieved from the SQL execution and cursor attributes
  • Cursors can be implicit or explicit
  • Implicit - is always created for all the included SQL statements
    • Its lifecycle is maintained by db
  • Explicit - execution cycle can be controlled by the user
    • We can explicitly declare an implicit cursor under the DECLARE section in SELECT query

Execution cycle

Execution cycle Expl

Cursor moves through the following stages during execution

  • implicit - all steps are carried out by db

OPEN - allocates the context area in the session's UGA

  • Starts with parsing and binding, followed by statement execution
  • In SELECT the record pointer points to the first record in the result set

FETCH - pulls the data from the query result set

  • In multi-record set, the record pointer moves incrementally with every fetch
  • Is alive until the last record is reached

CLOSE - closes the cursor

  • Flushes the context area
  • Releases the memory back to the UGA

Attributes

Hold the information about the cursor processing at each stage of its execution

  • %ROWCOUNT: number of rows, fetched until the last fetch
    • or impacted by the last DML operation (SELECT, DML)
  • %ISOPEN: TRUE/FALSE, cursor open or not, implicit is always FALSE
    • The only one accessible outside the cycle (!)
  • %FOUND: TRUE/FALSE, fetch operation switches and points to a record or not
  • %NOTFOUND: FALSE/TRUE, cursor pointer switches but does not point to a record

Attributes, example

SET SERVEROUTPUT ON

DECLARE

/* Declare a cursor to select employees info */
   CURSOR MY_C_EMP IS
      SELECT ID,ENAME
       FROM EMP;
   L_EMPNO EMP.ID%TYPE;
   L_ENAME EMP.ENAME%TYPE;
BEGIN

/* Check if the cursor is already open */
   IF NOT MY_C_EMP%ISOPEN THEN
     DBMS_OUTPUT.PUT_LINE('--- Employee Info ---');
   END IF;

/* Open the cursor and iterate in a loop */
   OPEN MY_C_EMP;
   LOOP

/* Fetch the cursor data into local variables */
   FETCH MY_C_EMP INTO L_EMPNO, L_ENAME;
   EXIT WHEN MY_C_EMP%NOTFOUND;

/* Display the employee info */
      DBMS_OUTPUT.PUT_LINE(chr(10) || 'Show Info for employee: ' || MY_C_EMP%ROWCOUNT);
      DBMS_OUTPUT.PUT_LINE('Id: ' || L_EMPNO);
      DBMS_OUTPUT.PUT_LINE('Name: ' || L_ENAME);
   END LOOP;
END;
/

/*
--- Employee Info ---

Show Info for employee:1
Id:7839
Name:BUSH

Show Info for employee:2
Id:7566
Name:PUTIN
(...)

PL/SQL procedure successfully completed.
*/

FOR loop

CURSOR FOR loop

  • Looping through all the records of a cursor object
  • Reduces the overhead of manually specifying the OPEN, FETCH, and CLOSE stages
  • Compacts the code when working with multi-row explicit cursors
  • No need to declare the block variables to capture the cursor columns
    • Index implicitly acts as a record of the cursor type
    • No need to explicitly open or close the cursor

FOR loop, example

DECLARE
/* Declare an explicit cursor to select employee info */
   CURSOR C_EMP IS
      SELECT ename, sal
      FROM emp;
BEGIN
/* Using the cursor C_EMP directly */
   FOR EMP IN C_EMP
   LOOP
/* Display result */
   DBMS_OUTPUT.PUT_LINE(EMP.ename || ' gains ' || EMP.sal || ' monthly');
   END LOOP;
END;
/

/*
BUSH gains 5000 monthly
PUTIN gains 2975 monthly
CARNEGIE gains 3000 monthly
FORD gains 1100 monthly
(...)
*/

Exercise

Pick the attribute with the wrong value

Query Cursor attributes
  BEGIN
  (...)
  SELECT ENAME, DEPTNO
  INTO V_ENAME, V_DEPTNO
  FROM EMP
  WHERE ID = 7900;
  (...)
  END;
  1. SQL%ROWCOUNT = 1
  2. SQL%ISOPEN = FALSE
  3. SQL%FOUND = FALSE
  4. SQL%NOTFOUND = FALSE

Procedures, Functions and Packages

  • Procedures
  • Functions
  • Packages

Procedure

Derivative of a PL/SQL block

  • Has a name and is stored persistently within the db
  • Schema object, primarily used to implement business logic on the server side
  • Promotes a modular programming, breaks down complex logic into simple routines

Procedure con't

  • Must be invoked from the executable section of a PL/SQL block
  • Executable directly from SQLPLUS (EXECUTE)
  • Can not be called from a SELECT statement
  • Can optionally accept parameters - IN, OUT, or IN OUT mode
  • Can't return a value
    • OUT params - is the only way (not via RETURN [value])
  • RETURN - skips the further execution of the program and exits control

Procedure parameter modes

IN OUT IN OUT
Default Has to be explicitly defined Has to be explicitly defined
Value passed to the program from the calling environment Value returned back to the calling environment Passes a value from the calling env to the program or returns value to the calling env
Passed by reference Passed by value Passed by value
Constant, literal, initialized variable Uninitialized variable Initialized variable
Can hold default value No default value No default value

Procedure syntax

CREATE [OR REPLACE] PROCEDURE [Procedure Name] [Parameter List]
[AUTHID DEFINER | CURRENT_USER]
IS
  [Declaration Statements]
BEGIN
 [Executable Statements]
EXCEPTION
 [Exception handlers]
END [Procedure Name];

Procedure example

---- Converts GeoJSON points into WKT(Well-known text)
-- GeoJSON is a standard format for encoding various of geographic data structures
-- WKT is a text markup language for representing vector geometry objects on a map
CREATE OR REPLACE PROCEDURE P_GJSON2WKT (POINTS_STR VARCHAR2, COORDINATES_STR VARCHAR2)
IS
/*Declare the local variables*/
   RESULT_POINTS_STR VARCHAR2(100);
   RESULT_COORDS_STR VARCHAR2(100);
BEGIN
   -- TRANSLATE( '[127.8, 75.6]', '[,]', '( )' )
   RESULT_POINTS_STR := TRANSLATE( POINTS_STR, '[,]', '( )' );
   DBMS_OUTPUT.PUT_LINE('Points : ' || RESULT_POINTS_STR);
   -- TRANSLATE( '(127.8 75.6)', '( )', '[,]' )
   RESULT_COORDS_STR := TRANSLATE( COORDINATES_STR, '( )', '[,]' );
   DBMS_OUTPUT.PUT_LINE('Coordinates : ' || RESULT_COORDS_STR);
END;
/
---------------
/*
Procedure P_GJSON2WKT compiled
*/

Calling Procedures

  • From SQL*Plus
  • Inside of PL/SQL block

SQLPlus

  • Initial setup
  • Calling

Initial setup

sys as sysdba
asdf
SQL> conn mike/mike@localhost/xepdb1
SQL> show user

Calling

---- Calling procedure from PL*SQL
SQL> SET SERVEROUTPUT ON
/* Session variable for the input */
SQL> VARIABLE P_STR VARCHAR2(100);
/* Test value */
SQL> EXECUTE :P_STR := '[127.8, 75.6]';
-- PL/SQL procedure successfully completed.
SQL> VARIABLE C_STR VARCHAR2(100);
SQL> EXECUTE :C_STR := '(127.8 75.6)';
-- PL/SQL procedure successfully completed.
/* Call the procedure P_GJSON2WKT */
SQL> EXECUTE P_GJSON2WKT(:P_STR, :C_STR);
/*
Points : (127.8  75.6)
Coordinates : [127.8,75.6]

PL/SQL procedure successfully completed.
*/

Calling procedure from anonymous unit

BEGIN
   /* Call the P_GJSON2WKT procedure */
   P_GJSON2WKT('[127.8, 75.6]', '(271.3 56.4)');
END;
/

Exercise

Wrap all the 'Invoice Reference' related code into procedure

Creating functions

Named derivative of a PL/SQL block, physically stored in db schema

  • Accepts parameters in all modes(IN, OUT, and IN OUT) and mandatorily returns a value
  • Can be called in SQL statements (SELECT and DMLs)
    • Must accept only IN parameters of valid SQL types
    • Function body must obey the database purity rules
    • Its return type should be a valid SQL data type
  • When invoked from PL/SQL, the return type should be a valid PL/SQL type

Function syntax

CREATE [OR REPLACE] FUNCTION [Function Name] [Parameter List]
RETURN [Data type]
[AUTHID DEFINER | CURRENT_USER]
[DETERMINISTIC | PARALLEL_ENABLED | PIPELINED]
[RESULT_CACHE [RELIES_ON (table name)]]
IS
  [Declaration Statements]
BEGIN
 [Executable Statements]
  RETURN [Value]
EXCEPTION
 [Exception handlers]
END [Function Name];

Function example

---- Get the date of birth from pesel
-- 82010901858
-- 820109
-- 82-01-09
--
CREATE OR REPLACE FUNCTION getDateOfBirthFromPesel (P_NUM NUMBER)
RETURN VARCHAR2
IS
  yearFromPesel     VARCHAR2(4); -- peselFromForm.substr(0, 2);
  monthFromPesel    yearFromPesel%TYPE; -- peselFromForm.substr(2, 2);
  dayFromPesel      yearFromPesel%TYPE; -- peselFromForm.substr(4, 2);
  D_BIRTH           VARCHAR2(100);
BEGIN
  /* On production we should validate pesel first */
  /* We should also consider the centuries bit first */
  yearFromPesel     := substr(to_char(P_NUM), 1, 2);
  monthFromPesel    := substr(to_char(P_NUM), 3, 2);
  dayFromPesel      := substr(to_char(P_NUM), 5, 2);

  D_BIRTH := yearFromPesel || '-' || monthFromPesel || '-' || dayFromPesel;
  
  RETURN D_BIRTH;
END;
/
-------------
-- Function GETDATEOFBIRTHFROMPESEL compiled

---------------------------------------------
---- MINI PROGRAM FOR EXECUTING OUR FUNC
---------------------------------------------
DECLARE
   DBIRTH VARCHAR2(100);
BEGIN
   DBIRTH := getDateOfBirthFromPesel(82010901858);
   DBMS_OUTPUT.PUT_LINE('Date of birth from pesel : ' || DBIRTH);
END;
/
---------------------------------------------

Exercise

  1. Wrap all the 'Franchisee' related code into function
    • HINT: redesign printing code (array?)
    • -- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-collections-and-records.html#GUID-8060F01F-B53B-48D4-9239-7EA8461C2170
      
  2. Validate PESEL, Polish social number

Packages

-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-packages.html#GUID-C285EC5A-BE50-4192-A88E-48C0778B34E0

Triggers

-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-triggers.html#GUID-217E8B13-29EF-45F3-8D0F-2384F9F1D231

Dynamic SQL

-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/dynamic-sql.html#GUID-7E2F596F-9CA3-4DC8-8333-0C117962DB73

Collections

-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-collections-and-records.html#GUID-7115C8B6-62F9-496D-BEC3-F7441DFE148A

Data Types

-- https://docs.oracle.com/en/database/oracle/oracle-database/18/lnpls/plsql-data-types.html#GUID-391C58FD-16AF-486C-AF28-173E309CDBA5