SlideShare a Scribd company logo
1 of 280
Download to read offline
PL/SQL New and Advanced Features
for Extreme Performance
Zohar Elkayam
CTO, Brillix
Zohar@Brillix.co.il
www.realdbamagic.com
Twitter: @realmgic
2
• Zohar Elkayam, CTO at Brillix
• Programmer, DBA, team leader, database trainer, public speaker, and
a senior consultant for over 19 years
• Oracle ACE Since 2014
• ilOUG Board Member – Israel Oracle User Group
• Blogger – www.realdbamagic.com and www.ilDBA.co.il
Who am I?
3
About Brillix
• We offer complete, integrated end-to-end solutions based on best-of-
breed innovations in database, security and big data technologies
• We provide complete end-to-end 24x7 expert remote database
services
• We offer professional customized on-site trainings, delivered by our
top-notch world recognized instructors
4
Some of Our Customers
5
• Founded in 1999, over 7000 members at its peak
• Divided into Technologies (Databases) and Applications groups
• Free Bi-monthly meetups for DBAs and Developers at Oracle Israel offices
• Yearly conference with guests speakers from all over the world:
• January 22-23, 2018
• Over 30 Speakers from all over the world: Ask TOM team, Oracle product mangers
and Oracle ACEs from 9 different countries!
• You can join our community: meetup group, facebook group or follow us
on twitter (@ilOUG_org)!
• Our website: www.ilOUG.org
ilOUG – Israel Oracle User Group
6
• Developing PL/SQL:
• Composite datatypes, advanced cursors, dynamic SQL, tracing, and more…
• Compiling PL/SQL:
• dependencies, optimization levels, and DBMS_WARNING
• Tuning PL/SQL:
• GTT, Result cache and Memory handling
• Oracle 11g, 12c and 18c cool, new and useful features
• SQLcl – New replacement tool for SQL*Plus (if we have time)
Agenda
7
• Learning new and old PL/SQL techniques
• We will not expert everything
• Getting to know new features (12cR1 and 12cR2)
• Hear about Oracle 18c
• This is a starting point – don’t be afraid to try
Our Goal Today
8
•‫דעתכם‬ ‫חוות‬ ‫את‬ ‫לקבל‬ ‫ונשמח‬ ‫משוב‬ ‫טופס‬ ‫יחולק‬ ‫הסמינר‬ ‫יום‬ ‫בסיום‬.
•‫חשובה‬ ‫דעתכם‬:‫יותר‬ ‫טובים‬ ‫הסמינרים‬ ‫את‬ ‫לעשות‬ ‫לנו‬ ‫המאפשרת‬ ‫זו‬ ‫היא‬!
Our REAL Agenda
10:30-10:45‫הפסקה‬
12:30-13:30‫משתתפ‬ ‫לכל‬ ‫צהריים‬ ‫ארוחת‬‫המלון‬ ‫בגן‬ ‫הכנס‬ ‫י‬
15:00-15:15‫הפנים‬ ‫קבלת‬ ‫במתחם‬ ‫מתוקה‬ ‫הפסקה‬
16:30‫הביתה‬ ‫הולכים‬
9
Oracle LiveSQL
• Oracle provides free "live" 12.2 SQL tool
• Includes available code library
• Ability to save scripts and share
• Online database design including
Sample Schemas
• https://livesql.oracle.com
• A short demo before we start…
Developing PL/SQL
11
• Composite datatypes
• Advanced Cursors and Bulk operations
• Dynamic SQL and SQL Injection
• Autonomous Transactions
• 11g mentionable features
• 12cR1 new development features
• 12cR2 new features
• Oracle 18c
Developing PL/SQL
Composite Datatypes
13
• Collections
• Nested table, varray
• Associative arrays/PLSQL tables
• Use collections methods
• Manipulate collections
• Distinguish between the different types of collections and when to
use them
Composite Datatypes
14
• A collection is a group of elements, all of the same type.
• Collections work like arrays.
• Collections can store instances of an object type and, conversely, can
be attributes of an object type.
• Types of collections in PL/SQL:
• Associative arrays
• String-indexed collections
• INDEX BY pls_integer or BINARY_INTEGER
• Nested tables
• Varrays
Understanding Collections
15
Collection Types
Nested table Varray
Associative array
1 2 3 4 5 6 a f i o t w
Index by
PLS_INTEGER
Index by
VARCHAR2
17
Associative arrays:
• That are indexed by strings can improve performance
• Are pure memory structures that are much faster than schema-level
tables
• Provide significant additional flexibility
Using Associative Arrays
Associative arrays
1 2 3 4 5 6 a f i o t w
Index by
PLS_INTEGER
Index by
VARCHAR2
19
Associative array in PL/SQL (string-indexed):
Creating the Array
TYPE type_name IS TABLE OF element_type
INDEX BY VARCHAR2(size)
CREATE OR REPLACE PROCEDURE report_credit
(p_last_name customers.cust_last_name%TYPE,
p_credit_limit customers.credit_limit%TYPE)
IS
TYPE typ_name IS TABLE OF customers%ROWTYPE
INDEX BY customers.cust_email%TYPE;
v_by_cust_email typ_name;
i VARCHAR2(30);
PROCEDURE load_arrays IS
BEGIN
FOR rec IN (SELECT * FROM customers WHERE cust_email IS NOT NULL)
LOOP
-- Load up the array in single pass to database table.
v_by_cust_email (rec.cust_email) := rec;
END LOOP;
END;
...
Create the string-indexed
associative array type.
Create the string-indexed
associative array variable.
Populate the string-indexed
associative array variable.
20
Traversing the Array
...
BEGIN
load_arrays;
i:= v_by_cust_email.FIRST;
dbms_output.put_line ('For credit amount of: ' || p_credit_limit);
WHILE i IS NOT NULL LOOP
IF v_by_cust_email(i).cust_last_name = p_last_name
AND v_by_cust_email(i).credit_limit > p_credit_limit
THEN dbms_output.put_line ( 'Customer '||
v_by_cust_email(i).cust_last_name || ': ' ||
v_by_cust_email(i).cust_email || ' has credit limit of: ' ||
v_by_cust_email(i).credit_limit);
END IF;
i := v_by_cust_email.NEXT(i);
END LOOP;
END report_credit;
/
EXECUTE report_credit('Walken', 1200)
For credit amount of: 1200
Customer Walken: Emmet.Walken@LIMPKIN.COM has credit limit of: 3600
Customer Walken: Prem.Walken@BRANT.COM has credit limit of: 3700
22
Nested table characteristics:
• A table within a table
• Unbounded
• Available in both SQL and PL/SQL as
well as the database
• Array-like access to individual rows
Using Nested Tables
Nested table:
23
pOrder nested table:
• Nested tables are stored out-of-line in storage tables.
Nested Table Storage
Storage table:
ORDID SUPPLIER REQUESTER ORDERED ITEMS
500 50 5000 30-OCT-07
800 80 8000 31-OCT-07
NESTED_TABLE_ID PRODID PRICE
55 555
56 566
57 577
NESTED_TABLE_ID PRODID PRICE
88 888
24
To create a nested table in the database:
To create a nested table in PL/SQL:
Creating Nested Tables
CREATE [OR REPLACE] TYPE type_name AS TABLE OF
Element_datatype [NOT NULL];
TYPE type_name IS TABLE OF element_datatype [NOT NULL];
25
• First, define an object type:
• Second, declare a column of that collection type:
Declaring Collections: Nested Table
CREATE TYPE typ_item AS OBJECT --create object
(prodid NUMBER(5),
price NUMBER(7,2) )
/
CREATE TYPE typ_item_nst -- define nested table type
AS TABLE OF typ_item
/
CREATE TABLE pOrder ( -- create database table
ordid NUMBER(5),
supplier NUMBER(5),
requester NUMBER(4),
ordered DATE,
items typ_item_nst)
NESTED TABLE items STORE AS item_stor_tab
/
1
2
3
26
Using Nested Tables
Add data to the nested table:
INSERT INTO pOrder
VALUES (500, 50, 5000, sysdate, typ_item_nst(
typ_item(55, 555),
typ_item(56, 566),
typ_item(57, 577)));
INSERT INTO pOrder
VALUES (800, 80, 8000, sysdate,
typ_item_nst (typ_item (88, 888)));
ORDID SUPPLIER REQUESTER ORDERED ITEMS
500 50 5000 30-OCT-07
800 80 8000 31-OCT-07
PRODID PRICE
55 555
56 566
57 577
PRODID PRICE
88 888
1
2
1
2
pOrder nested table
27
• Querying the results:
• Querying the results with the TABLE function:
Using Nested Tables
SELECT * FROM porder;
ORDID SUPPLIER REQUESTER ORDERED
---------- ---------- ---------- ---------
ITEMS(PRODID, PRICE)
-----------------------------------------------------------------
500 50 5000 31-OCT-07
TYP_ITEM_NST(TYP_ITEM(55, 555), TYP_ITEM(56, 566), TYP_ITEM(57, 577))
800 80 8000 31-OCT-07
TYP_ITEM_NST(TYP_ITEM(88, 888))
SELECT p2.ordid, p1.*
FROM porder p2, TABLE(p2.items) p1;
ORDID PRODID PRICE
---------- ---------- ----------
800 88 888
500 57 577
500 55 555
500 56 566
28
Use the collection name and a subscript to reference a collection element:
• Syntax:
• Example:
• To reference a field in a collection:
Referencing Collection Elements
collection_name(subscript)
v_with_discount(i)
p_new_items(i).prodid
29
Using Nested Tables in PL/SQL
CREATE OR REPLACE PROCEDURE add_order_items
(p_ordid NUMBER, p_new_items typ_item_nst)
IS
v_num_items NUMBER;
v_with_discount typ_item_nst;
BEGIN
v_num_items := p_new_items.COUNT;
v_with_discount := p_new_items;
IF v_num_items > 2 THEN
--ordering more than 2 items gives a 5% discount
FOR i IN 1..v_num_items LOOP
v_with_discount(i) :=
typ_item(p_new_items(i).prodid,
p_new_items(i).price*.95);
END LOOP;
END IF;
UPDATE pOrder
SET items = v_with_discount
WHERE ordid = p_ordid;
END;
30
Using Nested Tables in PL/SQL
-- caller pgm:
DECLARE
v_form_items typ_item_nst:= typ_item_nst();
BEGIN
-- let's say the form holds 4 items
v_form_items.EXTEND(4);
v_form_items(1) := typ_item(1804, 65);
v_form_items(2) := typ_item(3172, 42);
v_form_items(3) := typ_item(3337, 800);
v_form_items(4) := typ_item(2144, 14);
add_order_items(800, v_form_items);
END;
PRODID PRICE
1804 65
3172 42
3337 800
2144 14
v_form_items variable
ORDID SUPPLIER REQUESTER ORDERED ITEMS
500 50 5000 30-OCT-07
800 80 8000 31-OCT-07
Resulting data in the pOrder nested table
PRODID PRICE
1804 61.75
3172 39.9
3337 760
2144 13.3
The prices are added
after discounts.
31
• To create a varray in the database:
• To create a varray in PL/SQL:
Understanding Varrays
Varray:
CREATE [OR REPLACE] TYPE type_name AS VARRAY
(max_elements) OF element_datatype [NOT NULL];
TYPE type_name IS VARRAY (max_elements) OF
element_datatype [NOT NULL];
32
CREATE TABLE department ( -- create database table
dept_id NUMBER(2),
name VARCHAR2(25),
budget NUMBER(12,2),
projects typ_ProjectList) -- declare varray as column
/
• First, define a collection type:
• Second, declare a collection of that type:
Declaring Collections: Varray
CREATE TYPE typ_Project AS OBJECT( --create object
project_no NUMBER(4),
title VARCHAR2(35),
cost NUMBER(12,2))
/
CREATE TYPE typ_ProjectList AS VARRAY (50) OF typ_Project
-- define VARRAY type
/
1
2
3
33
Add data to the table containing a varray column:
Using Varrays
INSERT INTO department
VALUES (10, 'Exec Admn', 30000000,
typ_ProjectList(
typ_Project(1001, 'Travel Monitor', 400000),
typ_Project(1002, 'Open World', 10000000)));
INSERT INTO department
VALUES (20, 'IT', 5000000,
typ_ProjectList(
typ_Project(2001, 'DB11gR2', 900000)));
1
2
DEPT_ID NAME BUDGET PROJECTS
PROJECT_NO TITLE COSTS
10 Exec Admn 30000000 1001 Travel Monitor 400000
1002 Open World 10000000
20 IT 5000000 2001 DB11gR2 900000
1
2
DEPARTMENT table
34
• Querying the results:
• Querying the results with the TABLE function:
Using Varrays
SELECT * FROM department;
DEPT_ID NAME BUDGET
---------- ------------------------- ----------
PROJECTS(PROJECT_NO, TITLE, COST)
-----------------------------------------------------------------
10 Executive Administration 30000000
TYP_PROJECTLIST(TYP_PROJECT(1001, 'Travel Monitor', 400000),
TYP_PROJECT(1002, 'Open World', 10000000))
20 Information Technology 5000000
TYP_PROJECTLIST(TYP_PROJECT(2001, 'DB11gR2', 900000))
SELECT d2.dept_id, d2.name, d1.*
FROM department d2, TABLE(d2.projects) d1;
DEPT_ID NAME PROJECT_NO TITLE COST
------- ------------------------ ---------- -------------- --------
10 Executive Administration 1001 Travel Monitor 400000
10 Executive Administration 1002 Open World 10000000
20 Information Technology 2001 DB11gR2 900000
35
• You can declare collections as the formal parameters of procedures and functions.
• You can specify a collection type in the RETURN clause of a function specification.
• Collections follow the usual scoping and instantiation rules.
Working with Collections in PL/SQL
CREATE OR REPLACE PACKAGE manage_dept_proj
AS
PROCEDURE allocate_new_proj_list
(p_dept_id NUMBER, p_name VARCHAR2, p_budget NUMBER);
FUNCTION get_dept_project (p_dept_id NUMBER)
RETURN typ_projectlist;
PROCEDURE update_a_project
(p_deptno NUMBER, p_new_project typ_Project,
p_position NUMBER);
FUNCTION manipulate_project (p_dept_id NUMBER)
RETURN typ_projectlist;
FUNCTION check_costs (p_project_list typ_projectlist)
RETURN boolean;
END manage_dept_proj;
38
Three ways to initialize:
• Use a constructor.
• Fetch from the database.
• Assign another collection variable directly.
Initializing Collections
PROCEDURE allocate_new_proj_list
(p_dept_id NUMBER, p_name VARCHAR2, p_budget NUMBER)
IS
v_accounting_project typ_projectlist;
BEGIN
-- this example uses a constructor
v_accounting_project :=
typ_ProjectList
(typ_Project (1, 'Dsgn New Expense Rpt', 3250),
typ_Project (2, 'Outsource Payroll', 12350),
typ_Project (3, 'Audit Accounts Payable',1425));
INSERT INTO department
VALUES(p_dept_id, p_name, p_budget, v_accounting_project);
END allocate_new_proj_list;
39
FUNCTION get_dept_project (p_dept_id NUMBER)
RETURN typ_projectlist
IS
v_accounting_project typ_projectlist;
BEGIN -- this example uses a fetch from the database
SELECT projects INTO v_accounting_project
FROM department WHERE dept_id = p_dept_id;
RETURN v_accounting_project;
END get_dept_project;
Initializing Collections
FUNCTION manipulate_project (p_dept_id NUMBER)
RETURN typ_projectlist
IS
v_accounting_project typ_projectlist;
v_changed_list typ_projectlist;
BEGIN
SELECT projects INTO v_accounting_project
FROM department WHERE dept_id = p_dept_id;
-- this example assigns one collection to another
v_changed_list := v_accounting_project;
RETURN v_changed_list;
END manipulate_project;
1
2
40
Referencing Collection Elements
-- sample caller program to the manipulate_project function
DECLARE
v_result_list typ_projectlist;
BEGIN
v_result_list := manage_dept_proj.manipulate_project(10);
FOR i IN 1..v_result_list.COUNT LOOP
dbms_output.put_line('Project #: '
||v_result_list(i).project_no);
dbms_output.put_line('Title: '||v_result_list(i).title);
dbms_output.put_line('Cost: ' ||v_result_list(i).cost);
END LOOP;
END;
Project #: 1001
Title: Travel Monitor
Cost: 400000
Project #: 1002
Title: Open World
Cost: 10000000
41
• EXISTS
• COUNT
• LIMIT
• FIRST and LAST
• PRIOR and NEXT
• EXTEND
• TRIM
• DELETE
Using Collection Methods
collection_name.method_name [(parameters)]
43
FUNCTION check_costs (p_project_list typ_projectlist)
RETURN boolean
IS
c_max_allowed NUMBER := 10000000;
i INTEGER;
v_flag BOOLEAN := FALSE;
BEGIN
i := p_project_list.FIRST ;
WHILE i IS NOT NULL LOOP
IF p_project_list(i).cost > c_max_allowed then
v_flag := TRUE;
dbms_output.put_line (p_project_list(i).title || '
exceeded allowable budget.');
RETURN TRUE;
END IF;
i := p_project_list.NEXT(i);
END LOOP;
RETURN null;
END check_costs;
Traverse collections with the following methods:
Using Collection Methods
44
Using Collection Methods
-- sample caller program to check_costs
set serverout on
DECLARE
v_project_list typ_projectlist;
BEGIN
v_project_list := typ_ProjectList(
typ_Project (1,'Dsgn New Expense Rpt', 3250),
typ_Project (2, 'Outsource Payroll', 120000),
typ_Project (3, 'Audit Accounts Payable',14250000));
IF manage_dept_proj.check_costs(v_project_list) THEN
dbms_output.put_line('Project rejected: overbudget');
ELSE
dbms_output.put_line('Project accepted, fill out forms.');
END IF;
END;
Audit Accounts Payable exceeded allowable budget.
Project rejected: overbudget
PROJECT_NO TITLE COSTS
1 Dsgn New Expense Rpt 3250
2 Outsource Payroll 120000
3 Audit Accounts Payable 14250000
V_PROJECT_LIST variable:
45
PROCEDURE update_a_project
(p_deptno NUMBER, p_new_project typ_Project, p_position NUMBER)
IS
v_my_projects typ_ProjectList;
BEGIN
v_my_projects := get_dept_project (p_deptno);
v_my_projects.EXTEND; --make room for new project
/* Move varray elements forward */
FOR i IN REVERSE p_position..v_my_projects.LAST - 1 LOOP
v_my_projects(i + 1) := v_my_projects(i);
END LOOP;
v_my_projects(p_position) := p_new_project; -- insert new one
UPDATE department SET projects = v_my_projects
WHERE dept_id = p_deptno;
END update_a_project;
Manipulating Individual Elements
46
Manipulating Individual Elements
-- check the table prior to the update:
SELECT d2.dept_id, d2.name, d1.*
FROM department d2, TABLE(d2.projects) d1;
DEPT_ID NAME PROJECT_NO TITLE COST
------- ------------------------- ---------- ----------------------------- --
10 Executive Administration 1001 Travel Monitor 400000
10 Executive Administration 1002 Open World 10000000
20 Information Technology 2001 DB11gR2 900000
-- caller program to update_a_project
BEGIN
manage_dept_proj.update_a_project(20,
typ_Project(2002, 'AQM', 80000), 2);
END;
DEPT_ID NAME PROJECT_NO TITLE COST
------- ------------------------- ---------- ----------------------------- --
10 Executive Administration 1001 Travel Monitor 400000
10 Executive Administration 1002 Open World 10000000
20 Information Technology 2001 DB11gR2 900000
20 Information Technology 2002 AQM 80000
-- check the table after the update:
SELECT d2.dept_id, d2.name, d1.*
FROM department d2, TABLE(d2.projects) d1;
47
Listing Characteristics for Collections
PL/SQL
Nested
Tables
DB
Nested
Tables
PL/SQL
Varrays
DB
Varrays
PL/SQL
Associative
Arrays
Maximum
size
No No Yes Yes Dynamic
Sparsity Can be No Dense Dense Yes
Storage N/A Stored out-of-
line
N/A Stored inline
(if < 4,000
bytes)
N/A
Ordering Does not
retain ordering
and subscripts
Does not
retain ordering
and subscripts
Retains
ordering and
subscripts
Retains
ordering and
subscripts
Retains
ordering and
subscripts
48
• Varrays involve fewer disk accesses and are more efficient.
• Use nested tables for storing large amounts of data.
• Use varrays to preserve the order of elements in the collection
column.
• If you do not have a requirement to delete elements in the middle of
a collection, favor varrays.
• Varrays do not allow piecewise updates.
• After deleting the elements, release the unused memory with
DBMS_SESSION.FREE_UNUSED_USER_MEMORY
Guidelines for Using Collections Effectively
Advanced Cursors
50
• Fetch into a record when fetching from a cursor.
• Benefit
• No individual variables declaration is needed.
• You can automatically use the structure of the SELECT column list.
Cursor Design: Use Records
DECLARE
CURSOR cur_cust IS
SELECT customer_id, cust_last_name, cust_email
FROM customers WHERE credit_limit = 1200;
v_cust_record cur_cust%ROWTYPE;
BEGIN
OPEN cur_cust;
LOOP
FETCH cur_cust INTO v_cust_record;
...
51
• Reference implicit cursor attributes immediately after the SQL statement executes.
• Benefit
• Doing so ensures that you are dealing with the result of the correct SQL statement.
Guidelines for Good Cursor Design
BEGIN
UPDATE customers
SET credit_limit = p_credit_limit
WHERE customer_id = p_cust_id;
get_avg_order(p_cust_id); -- procedure call
IF SQL%NOTFOUND THEN
...
``
52
• Create cursors with parameters.
• Benefit
• Parameters increase the cursor’s flexibility and reusability.
• Parameters help avoid scoping problems.
Use Cursor Parameters
CURSOR cur_cust
(p_crd_limit NUMBER, p_acct_mgr NUMBER)
IS
SELECT customer_id, cust_last_name, cust_email
FROM customers
WHERE credit_limit = p_crd_limit
AND account_mgr_id = p_acct_mgr;
BEGIN
OPEN cur_cust(p_crd_limit_in, p_acct_mgr_in);
...
CLOSE cur_cust;
...
OPEN cur_cust(v_credit_limit, 145);
...
END;
53
• Simplify coding with cursor FOR loops.
• Benefit
• Reduces the volume of code
• Automatically handles the open, fetch, and close operations, and defines a record type that matches the cursor
definition
Using the Cursor For Loop
CREATE OR REPLACE PROCEDURE cust_pack
(p_crd_limit_in NUMBER, p_acct_mgr_in NUMBER)
IS
v_credit_limit NUMBER := 1500;
CURSOR cur_cust
(p_crd_limit NUMBER, p_acct_mgr NUMBER)
IS
SELECT customer_id, cust_last_name, cust_email
FROM customers WHERE credit_limit = p_crd_limit
AND account_mgr_id = p_acct_mgr;
BEGIN
FOR cur_rec IN cur_cust (p_crd_limit_in, p_acct_mgr_in)
LOOP -- implicit open and fetch
...
END LOOP; -- implicit close
...
END;
54
CREATE OR REPLACE PROCEDURE cust_list
IS
CURSOR cur_cust IS
SELECT customer_id, cust_last_name, credit_limit*1.1
FROM customers;
cust_record cur_cust%ROWTYPE;
BEGIN
OPEN cur_cust;
LOOP
FETCH cur_cust INTO cust_record;
DBMS_OUTPUT.PUT_LINE('Customer ' ||
cust_record.cust_last_name || ' wants credit '
|| cust_record.(credit_limit * 1.1));
EXIT WHEN cur_cust%NOTFOUND;
END LOOP;
...
• Make a DBA happy: Close a cursor when it is no longer needed.
• Use column aliases in cursors for calculated columns fetched into records declared with
%ROWTYPE.
More Guidelines for Good Cursor Design
Use col. alias
55
• A Ref Cursor is a Cursor variable
• It hold a pointer to the result set of a previously opened cursor
• The actual SQL statement of the cursor is dynamic and determined at
execution time
• A single Ref Cursor can point to different result sets at different times
Returning Result Sets From PL/SQL
56
Memory
Cursor Variables: Overview
1 Southlake, Texas 1400
2 San Francisco 1500
3 New Jersey 1600
4 Seattle, Washington 1700
5 Toronto 1800
REF
CURSOR
memory
locator
57
Working with Cursor Variables
Define and
declare the
cursor
variable.
Open the
cursor
variable.
Fetch rows
from the
result set.
Close the
cursor
variable.
1 2 3 4
58
• Strong REF CURSOR:
• Is restrictive
• Specifies a RETURN type
• Associates only with type-compatible queries
• Is less error prone
• Weak REF CURSOR:
• Is nonrestrictive
• Associates with any query
• Is very flexible
Strong Versus Weak REF CURSOR Variables
59
DECLARE
TYPE rt_cust IS REF CURSOR
RETURN customers%ROWTYPE;
...
Define a REF CURSOR type:
• ref_type_name is a type specified in subsequent declarations.
• return_type represents a record type.
• RETURN keyword indicates a strong cursor.
Step 1: Defining a REF CURSOR Type
TYPE ref_type_name IS REF CURSOR
[RETURN return_type];
60
Declare a cursor variable of a cursor type:
• cursor_variable_name is the name of the cursor variable.
• ref_type_name is the name of a REF CURSOR type.
Step 1: Declaring a Cursor Variable
DECLARE
TYPE rt_cust IS REF CURSOR
RETURN customers%ROWTYPE;
cv_cust rt_cust;
cursor_variable_name ref_type_name;
61
Options:
• Use %TYPE and %ROWTYPE.
• Specify a user-defined record in the RETURN clause.
• Declare the cursor variable as the formal parameter of a stored procedure
or function.
Step 1: Declaring a REF CURSOR Return Type
62
• Associate a cursor variable with a multiple-row SELECT statement.
• Execute the query.
• Identify the result set:
• cursor_variable_name is the name of the
cursor variable.
• select_statement is the SQL SELECT statement.
Step 2: Opening a Cursor Variable
OPEN cursor_variable_name
FOR select_statement;
64
• Retrieve rows from the result set one at a time.
• The return type of the cursor variable must be compatible with the
variables named in the INTO clause of the FETCH statement.
Step 3: Fetching from a Cursor Variable
FETCH cursor_variable_name
INTO variable_name1
[,variable_name2,. . .]
| record_name;
65
• Disable a cursor variable.
• The result set is undefined.
• Accessing the cursor variable after it is closed raises the
INVALID_CURSOR predefined exception.
Step 4: Closing a Cursor Variable
CLOSE cursor_variable_name;
66
You can pass query result sets among PL/SQL-stored subprograms and
various clients.
Passing Cursor Variables as Arguments
Access by a host variable
on the client side
Pointer
to the
result
set
67
Passing Cursor Variables as Arguments
69
Using the SYS_REFCURSOR Predefined Type
CREATE OR REPLACE PROCEDURE REFCUR
(p_num IN NUMBER)
IS
refcur sys_refcursor;
empno emp.empno%TYPE;
ename emp.ename%TYPE;
BEGIN
IF p_num = 1 THEN
OPEN refcur FOR SELECT empno, ename FROM emp;
DBMS_OUTPUT.PUT_LINE('Employee# Name');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
FETCH refcur INTO empno, ename;
EXIT WHEN refcur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(empno || ' ' || ename);
END LOOP;
ELSE
....
SYS_REFCURSOR is a built-in
REF CURSOR type that allows
any result set to be associated
with it.
71
• You cannot use cursor variables with remote subprograms on
another server.
• You cannot use comparison operators to test cursor variables.
• You cannot assign a null value to cursor variables.
• You cannot use REF CURSOR types in CREATE TABLE or VIEW
statements.
• Cursors and cursor variables are not interoperable.
Rules for Cursor Variables
72
Cursor variables have the following benefits:
• Are dynamic and ensure more flexibility
• Are not tied to a single SELECT statement
• Hold the value of a pointer
• Can reduce network traffic
• Give access to query work areas after a
block completes
Comparing Cursor Variables with Static Cursors
Ref Cursor Demo
74
• Use explicit locking to deny access to other sessions for the duration
of a transaction
• Lock the rows before the update or delete
• Syntax:
Using the For Update Clause
SELECT ...
FROM ...
FOR UPDATE [OF column_reference][NOWAIT | WAIT n];
75
• Select for Update default is to wait for locked rows
• We can set the wait time to be limited with a time frame or fail if
rows are already locked
• We can also ask the query to skip the locked rows and return the
unlocked rows:
Handling Locked Rows
SELECT ...
FROM ...
FOR UPDATE SKIP LOCKED;
76
• When using cursor with FOR UPDATE clause, we might want to change
that same record
• We can use the WHERE CURRENT OF cursor to get a fast ROWID access
to that row
Using WHERE CURRENT OF Clause
UPDATE employees
SET salary = 12000
WHERE CURRENT OF emp_cursor;
77
• Include the RETURNING clause with an INSERT, UPDATE, and DELETE
to return column values.
• Benefit:
• Eliminates the need to SELECT the row after DML
• Fewer network round trips
• Less server CPU time
• Fewer cursors
• Less server memory is required
Using the RETURNING Clause
78
Using RETURNING Clause Example
DECLARE
v_emp_sal employees.salary%type;
BEGIN
UPDATE employees e
set salary = salary * 1.2
WHERE e.employee_id = 202
RETURNING e.salary into v_emp_sal;
dbms_output.put_line('The new salary is ' ||
v_emp_sal);
END;
/
The new salary is 7200
79
Use bulk binds to reduce context switches between the PL/SQL engine
and the SQL engine.
Using Bulk Binding
SQL enginePL/SQL run-time engine
PL/SQL block
FORALL j IN 1..1000
INSERT …
(OrderId(j),
OrderDate(j), …);
SQL
statement
executor
Procedural
statement
executor
80
Bind whole arrays of values simultaneously, rather than looping to
perform fetch, insert, update, and delete on multiple rows.
• Instead of:
• Use:
Using Bulk Binding
...
FOR i IN 1 .. 50000 LOOP
INSERT INTO bulk_bind_example_tbl
VALUES(...);
END LOOP; ...
...
FORALL i IN 1 .. 50000
INSERT INTO bulk_bind_example_tbl
VALUES(...);
...
82
Use BULK COLLECT to improve performance:
Using Bulk Binding
CREATE OR REPLACE PROCEDURE process_customers
(p_account_mgr customers.account_mgr_id%TYPE)
IS
TYPE typ_numtab IS TABLE OF
customers.customer_id%TYPE;
TYPE typ_chartab IS TABLE OF
customers.cust_last_name%TYPE;
TYPE typ_emailtab IS TABLE OF
customers.cust_email%TYPE;
v_custnos typ_numtab;
v_last_names typ_chartab;
v_emails typ_emailtab;
BEGIN
SELECT customer_id, cust_last_name, cust_email
BULK COLLECT INTO v_custnos, v_last_names, v_emails
FROM customers
WHERE account_mgr_id = p_account_mgr;
...
END process_customers;
83
Use the RETURNING clause to retrieve information about the rows
that are being modified:
Using Bulk Binding
DECLARE
TYPE typ_replist IS VARRAY(100) OF NUMBER;
TYPE typ_numlist IS TABLE OF
orders.order_total%TYPE;
repids typ_replist :=
typ_replist(153, 155, 156, 161);
totlist typ_numlist;
c_big_total CONSTANT NUMBER := 60000;
BEGIN
FORALL i IN repids.FIRST..repids.LAST
UPDATE orders
SET order_total = .95 * order_total
WHERE sales_rep_id = repids(i)
AND order_total > c_big_total
RETURNING order_total BULK COLLECT INTO Totlist;
END;
85
• You can use the SAVE EXCEPTIONS keyword in your FORALL statements:
• Exceptions raised during execution are saved in the %BULK_EXCEPTIONS cursor
attribute.
• The attribute is a collection of records with two fields:
• Note that the values always refer to the most recently executed FORALL statement.
Using SAVE EXCEPTIONS
FORALL index IN lower_bound..upper_bound
SAVE EXCEPTIONS
{insert_stmt | update_stmt | delete_stmt}
Field Definition
ERROR_INDEX Holds the iteration of the FORALL statement where the
exception was raised
ERROR_CODE Holds the corresponding Oracle error code
86
Handling FORALL Exceptions
DECLARE
TYPE NumList IS TABLE OF NUMBER;
num_tab NumList :=
NumList(100,0,110,300,0,199,200,0,400);
bulk_errors EXCEPTION;
PRAGMA EXCEPTION_INIT (bulk_errors, -24381 );
BEGIN
FORALL i IN num_tab.FIRST..num_tab.LAST
SAVE EXCEPTIONS
DELETE FROM orders WHERE order_total < 500000/num_tab(i);
EXCEPTION WHEN bulk_errors THEN
DBMS_OUTPUT.PUT_LINE('Number of errors is: '
|| SQL%BULK_EXCEPTIONS.COUNT);
FOR j in 1..SQL%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE (
TO_CHAR(SQL%BULK_EXCEPTIONS(j).error_index) ||
' / ' ||
SQLERRM(-SQL%BULK_EXCEPTIONS(j).error_code) );
END LOOP;
END;
/
Dynamic SQL and
SQL Injection
88
• Used for two main reasons:
• Modify commands dynamically to retrieve or filter columns based on input
• Run DDL and DCL commands from PL/SQL
• PLEASE don’t use it for running DMLs!
• Two main ways to run dynamic commands:
• EXECUTE IMMDIATE
• DBMS_SQL
Dynamic SQL
89
• Easy syntax:
• Accepts all command types
• Accept bind variables with the USING clause
• Allows dynamic PL/SQL creation
Advantages of Native Dynamic SQL
EXECUTE_IMMEDIATE dynamic_string
{
INTO { define_variable [, define_variable ...] | record_name }
| BULK COLLECT INTO { collection_name [, collection_name ...] |
:host_array_name }
}
[ USING [ IN | OUT | IN OUT ] bind_argument
[, [ IN | OUT | IN OUT ] bind_argument] ... ] [ returning_clause ] ;
90
• DBMS_SQL supports statements with unknown number of inputs or
outputs
• We can use DESCRIBE_COLUMNS procedure in the DBMS_SQL
package to describe columns for a cursor opened/parsed through
DBMS_SQL
• DBMS_SQL Supports SQL statements larger than 32 KB
• DBMS_SQL Lets you reuse SQL statements
Advantages of DBMS_SQL
91
Using Execute Immediate
CREATE OR REPLACE PROCEDURE del_rows
(p_condition varchar2, p_rows_deld out number)
IS
BEGIN
EXECUTE IMMEDIATE 'DELETE FROM employees ' || p_condition;
p_rows_deld:=sql%ROWCOUNT;
END;
/
DECLARE
cnt number;
BEGIN
del_rows(‘where employee_id = 201’, cnt);
END;
/
92
Using DBMS_SQL
CREATE OR REPLACE
PROCEDURE del_rows
(p_condition in varchar2, p_rows_del out number)
is
cursor_id integer;
BEGIN
cursor_id := dbms_sql.open_cursor;
dbms_sql.parse (cursor_id,'DELETE FROM employees ‘ ||p_condition,
dbms_sql.native);
p_rows_del := dbms_sql.execute (cursor_id);
dbms_sql.close_cursor (cursor_id);
END;
/
93
• Starting Oracle 11g, we can transform a DBMS_SQL cursor into a
PL/SQL REF CURSOR and vice versa
Transforming DBMS_SQL
Cursor into a REF CURSOR
DBMS_SQL.TO_REFCURSOR (cursor_number IN INTEGER) RETURN SYS_REFCURSOR;
DBMS_SQL.TO_CURSOR_NUMBER (rc IN OUT SYS_REFCURSOR) RETURN INTEGER;
94
• Dynamic SQL is not checked until runtime
• Syntax
• Structure validity
• Permissions
• Dynamic SQL can be used as SQL injection entry point
Disadvantages of Dynamic SQL
95
SQL injection is a technique for maliciously exploiting applications that
use client-supplied data in SQL statements.
• Attackers trick the SQL engine into executing unintended commands.
• SQL injection techniques may differ, but they all exploit a single vulnerability
in the application.
• To immunize your code against SQL injection attacks, use bind arguments or
validate and sanitize all input concatenated to dynamic SQL.
Understanding SQL Injection
96
SQL Injection: Example
-- First order attack
CREATE OR REPLACE PROCEDURE GET_EMAIL
(p_last_name VARCHAR2 DEFAULT NULL)
AS
TYPE cv_custtyp IS REF CURSOR;
cv cv_custtyp;
v_email customers.cust_email%TYPE;
v_stmt VARCHAR2(400);
BEGIN
v_stmt := 'SELECT cust_email FROM customers
WHERE cust_last_name = '''|| p_last_name || '''';
DBMS_OUTPUT.PUT_LINE('SQL statement: ' || v_stmt);
OPEN cv FOR v_stmt;
LOOP
FETCH cv INTO v_email;
EXIT WHEN cv%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Email: '||v_email);
END LOOP;
CLOSE cv;
EXCEPTION WHEN OTHERS THEN
dbms_output.PUT_LINE(sqlerrm);
dbms_output.PUT_LINE('SQL statement: ' || v_stmt);
END;
String literals that are incorrectly
validated or not validated are
concatenated into a dynamic SQL
statement, and interpreted as code by the
SQL engine.
97
Assessing Vulnerability
Code
Uses bind
arguments for all
dynamic
components
Vulnerable
Safe
Contains dynamic
SQL?
Filters input
correctly?
No
No
No
Yes
Yes
YesLateral injection
vulnerability
No
98
Use the following strategies to reduce attack surface:
• Use invoker’s rights.
• Reduce arbitrary inputs.
• Use Bind arguments.
• The Filter pitfall.
Reducing the Attack Surface
99
• Give out privileges appropriately.
• Run code with invoker’s rights when possible.
• Ensure that the database privilege model is upheld when using
definer’s rights.
Avoiding Privilege Escalation
Invoker’s rights
Definer’s rights
100
• Using invoker’s rights:
• Helps to limit the privileges
• Helps to minimize the security exposure.
• The following example does not use invoker's rights:
Using Invoker’s Rights
CREATE OR REPLACE
PROCEDURE change_password(p_username VARCHAR2 DEFAULT NULL,
p_new_password VARCHAR2 DEFAULT NULL)
IS
v_sql_stmt VARCHAR2(500);
BEGIN
v_sql_stmt := 'ALTER USER '||p_username ||' IDENTIFIED BY '
|| p_new_password;
EXECUTE IMMEDIATE v_sql_stmt;
END change_password;
GRANT EXECUTE ON change_password to OE, HR, SH;
1
2
Note the use of dynamic SQL with
concatenated input values.
101
• OE is successful at changing the SYS password, because, by default,
CHANGE_PASSWORD executes with SYS privileges:
• Add the AUTHID to change the privileges to the invokers:
Using Invoker’s Rights
EXECUTE sys.change_password ('SYS', 'mine')
CREATE OR REPLACE
PROCEDURE change_password(p_username VARCHAR2 DEFAULT NULL,
p_new_password VARCHAR2 DEFAULT NULL)
AUTHID CURRENT_USER
IS
v_sql_stmt VARCHAR2(500);
BEGIN
v_sql_stmt := 'ALTER USER '||p_username ||' IDENTIFIED BY '
|| p_new_password;
EXECUTE IMMEDIATE v_sql_stmt;
END change_password;
102
• Reduce the end-user interfaces to only those that are actually
needed.
• In a Web application, restrict users to accessing specified Web pages.
• In a PL/SQL API, expose only those routines that are intended for customer
use.
• Where user input is required, make use of language features to
ensure that only data of the intended type can be specified.
• Do not specify a VARCHAR2 parameter when it will be used as a number.
• Do not use numbers if you need only positive integers; use natural instead.
Reducing Arbitrary Inputs
103
DBMS_ASSERT functions:
Understanding DBMS_ASSERT
Function Description
ENQUOTE_LITERAL Encloses string literal in single quotes
SIMPLE_SQL_NAME Verifies that the string is a simple SQL name
104
• Example 1: The object name used as an identifier:
• Example 2: The object name used as a literal:
• Example 3: The object name used as a quoted (normal format) identifier:
• The "orders" table referenced in example 3 is a different table compared to the orders table in
examples 1 and 2.
• It is vulnerable to SQL injection.
SELECT num_rows FROM user_tables
WHERE table_name = 'ORDERS';
SELECT count(*) records FROM orders;
Formatting Oracle Identifiers
SELECT count(*) records FROM "orders";
105
• For your identifiers, determine:
1. Where will the input come from: user or data dictionary?
2. What verification is required?
3. How will the result be used, as an identifier or a literal value?
• These three factors affect:
• What preprocessing is required (if any) prior to calling the verification
functions
• Which DBMS_ASSERT verification function is required
• What post-processing is required before the identifier can actually be used
Working with Identifiers in Dynamic SQL
106
Avoiding Injection by Using
DBMS_ASSERT.ENQUOTE_LITERAL
CREATE OR REPLACE PROCEDURE Count_Rows(w in varchar2)
authid definer as
Quote constant varchar2(1) := '''';
Quote_Quote constant varchar2(2) := Quote||Quote;
Safe_Literal varchar2(32767) :=
Quote||replace(w,Quote,Quote_Quote)||Quote;
Stmt constant varchar2(32767) :=
'SELECT count(*) FROM t WHERE a='||
DBMS_ASSERT.ENQUOTE_LITERAL(Safe_Literal);
Row_Count number;
BEGIN
EXECUTE IMMEDIATE Stmt INTO Row_Count;
DBMS_OUTPUT.PUT_LINE(Row_Count||' rows');
END;
/
Verify whether the literal
is well-formed.
109
Avoiding Injection by Using
DBMS_ASSERT.SIMPLE_SQL_NAME
CREATE OR REPLACE PROCEDURE show_col2 (p_colname varchar2,
p_tablename varchar2)
AS
type t is varray(200) of varchar2(25);
Results t;
Stmt CONSTANT VARCHAR2(4000) :=
'SELECT '||dbms_assert.simple_sql_name( p_colname ) || ' FROM
'|| dbms_assert.simple_sql_name( p_tablename ) ;
BEGIN
DBMS_Output.Put_Line ('SQL Stmt: ' || Stmt);
EXECUTE IMMEDIATE Stmt bulk collect into Results;
for j in 1..Results.Count() loop
DBMS_Output.Put_Line(Results(j));
end loop;
END show_col2;
Verify that the input string conforms to
the basic characteristics of a simple
SQL name.
111
• Most common vulnerability:
• Dynamic SQL with string concatenation
• Your code design must:
• Avoid input string concatenation in dynamic SQL
• Use bind arguments, whether automatically via static SQL or explicitly via
dynamic SQL statements
Using Bind Arguments
112
• Filter parameter:
• P_WHERE_CLAUSE is a filter.
• It is difficult to protect against SQL injection.
• Prevention methods:
• Do not specify APIs that allow arbitrary query parameters to be exposed.
• Any existing APIs with this type of functionality must be deprecated and
replaced with safe alternatives.
Beware of Filter Parameters
stmt := 'SELECT session_id FROM sessions
WHERE' || p_where_clause;
113
• An Autonomous Transaction is an independent Transaction started by
another transaction.
• The main transaction will hold for the AT and wait until it is
completed
• Uses PRAGMA compiler directive
• Allowed in individual routines
• Commonly used for loggers, progress bars, and concurrent
operations
Autonomous Transactions
114
AT Example: Main Transaction
DECLARE
tmp NUMBER;
BEGIN
FOR i IN 1..10
LOOP
tmp := i;
INSERT INTO t
VALUES (TRUNC(i/2));
END LOOP;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
logger('Failed on ' || TO_CHAR(tmp));
ROLLBACK;
RAISE;
END;
/
115
AT Example: Logger (Autonomous)
PROCEDURE logger (message IN VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION
BEGIN
INSERT INTO logger VALUES (sysdate, message);
COMMIT;
END;
/
Cool, New and Useful
Features for Developers
11gR2, 12cR1, 12cR2 and what’s coming for 18c?
Cool Features in 11gR2
118
• For a specified measure, LISTAGG orders data within each group
specified in the ORDER BY clause and then concatenates the values
of the measure column
• Limited to 4000 chars (in 11g, see 12cR2 enhancement!)
Using the LISTAGG Function
LISTAGG(measure_expr [, 'delimiter'])
WITHIN GROUP (order_by_clause) [OVER
query_partition_clause]
119
Using LISTAGG: Example
SELECT department_id "Dept", hire_date
"Date",
last_name "Name",
LISTAGG(last_name, ', ') WITHIN GROUP
(ORDER BY hire_date, last_name)
OVER (PARTITION BY department_id) as
"Emp_list"
FROM hr.employees
WHERE hire_date < '01-SEP-2003'
ORDER BY "Dept", "Date", "Name";
120
• Returns the N-th values in an ordered set of values
• Different default window: RANGE BETWEEN UNBOUNDED
PRECEDING AND CURRENT ROW
The NTH_VALUE Analytic Function
NTH_VALUE (measure_expr, n)
[ FROM { FIRST | LAST } ][ { RESPECT | IGNORE } NULLS ]
OVER (analytic_clause)
121
Using NTH_VALUE: Example
SELECT prod_id, channel_id, MIN(amount_sold),
NTH_VALUE ( MIN(amount_sold), 2) OVER (PARTITION BY
prod_id ORDER BY channel_id
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED
FOLLOWING) nv
FROM sh.sales
WHERE prod_id BETWEEN 13 and 16
GROUP BY prod_id, channel_id;
122
• Virtual columns are dynamic (not stored) columns of a table (no views
required)
• Virtual columns obtain their value be evaluating as expression:
• Columns from the same table
• Constraints
• Function Calls (user defined)
• Might be used for
• Eliminate views
• Control table partitioning
• Manage “Binary” XMLType data
• Index values (function based index)
Virtual Columns
123
Virtual Columns Example
column_name [datatype] [GENERATED ALWAYS] AS (expression) [VIRTUAL]
CREATE TABLE employees (
id NUMBER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
salary NUMBER(9,2),
comm1 NUMBER(3),
comm2 NUMBER(3),
salary1 AS (ROUND(salary*(1+comm1/100),2)),
salary2 NUMBER GENERATED ALWAYS AS
(ROUND(salary*(1+comm2/100),2)) VIRTUAL,
CONSTRAINT employees_pk PRIMARY KEY (id)
);
Trigger Improvements
125
• A single trigger on a table that allows you to specify actions for each
of the following four timing points:
• Before the firing statement
• Before each row that the firing statement affects
• After each row that the firing statement affects
• After the firing statement
What Is a Compound Trigger?
126
• The compound trigger body supports a common PL/SQL state that
the code for each timing point can access.
• The compound trigger common state is:
• Established when the triggering statement starts
• Destroyed when the triggering statement completes
• A compound trigger has a declaration section and a section for each
of its timing points.
Working with Compound Triggers
127
• You can use compound triggers to:
• Program an approach where you want the actions you implement for the
various timing points to share common data.
• Accumulate rows destined for a second table so that you can periodically
bulk-insert them
• Avoid the mutating-table error (ORA-04091)by allowing rows destined
for a second table to accumulate and then bulk-inserting them
The Benefits of Using a Compound Trigger
128
• A compound trigger defined on a table has one or more of the
following timing-point sections. Timing-point sections must appear in
the order shown in the table.
Timing-Point Sections of a
Table Compound Trigger
Timing Point Compound Trigger Section
Before the triggering statement executes BEFORE statement
After the triggering statement executes AFTER statement
Before each row that the triggering statement affects BEFORE EACH ROW
After each row that the triggering statement affects AFTER EACH ROW
129
Compound Trigger Structure for Tables
CREATE OR REPLACE TRIGGER schema.trigger
FOR dml_event_clause ON schema.table
COMPOUND TRIGGER
-- Initial section
-- Declarations
-- Subprograms
-- Optional section
BEFORE STATEMENT IS ...;
-- Optional section
BEFORE EACH ROW IS ...;
-- Optional section
AFTER EACH ROW IS ...;
-- Optional section
AFTER STATEMENT IS ...;
1
2
130
• A mutating table is:
• A table that is being modified by an UPDATE, DELETE, or INSERT statement, or
• A table that might be updated by the effects of a DELETE CASCADE constraint
• The session that issued the triggering statement cannot query or modify a
mutating table.
• This restriction prevents a trigger from seeing an inconsistent set of data.
• This restriction applies to all triggers that use the FOR EACH ROW clause.
• Views being modified in the INSTEAD OF triggers are not considered
mutating.
Trigger Restrictions on Mutating Tables
131
Using a Compound Trigger to
Resolve the Mutating Table Error
CREATE OR REPLACE TRIGGER check_salary
FOR INSERT OR UPDATE OF salary, job_id
ON employees
WHEN (NEW.job_id <> 'AD_PRES')
COMPOUND TRIGGER
TYPE salaries_t IS TABLE OF employees.salary%TYPE;
min_salaries salaries_t;
max_salaries salaries_t;
TYPE department_ids_t IS TABLE OF employees.department_id%TYPE;
department_ids department_ids_t;
TYPE department_salaries_t IS TABLE OF employees.salary%TYPE
INDEX BY VARCHAR2(80);
department_min_salaries department_salaries_t;
department_max_salaries department_salaries_t;
-- example continues on next slide
132
Using a Compound Trigger to
Resolve the Mutating Table Error
. . .
BEFORE STATEMENT IS
BEGIN
SELECT MIN(salary), MAX(salary), NVL(department_id, -1)
BULK COLLECT INTO min_Salaries, max_salaries, department_ids
FROM employees
GROUP BY department_id;
FOR j IN 1..department_ids.COUNT() LOOP
department_min_salaries(department_ids(j)) := min_salaries(j);
department_max_salaries(department_ids(j)) := max_salaries(j);
END LOOP;
END BEFORE STATEMENT;
AFTER EACH ROW IS
BEGIN
IF :NEW.salary < department_min_salaries(:NEW.department_id)
OR :NEW.salary > department_max_salaries(:NEW.department_id) THEN
RAISE_APPLICATION_ERROR(-20505,'New Salary is out of acceptable
range');
END IF;
END AFTER EACH ROW;
END check_salary;
133
• A compound trigger must be a DML trigger and defined on either a
table or a view
• An exception that occurs in one section must be handled in that
section. It cannot transfer control to another section
• :OLD and :NEW cannot appear in the declaration, BEFORE
STATEMENT, or the AFTER STATEMENT sections
• Only the BEFORE EACH ROW section can change the value of :NEW
• The firing order of compound triggers is not guaranteed unless you
use the FOLLOWS clause
Compound Trigger Restrictions
134
• To ensure that a trigger fires after certain other triggers on the same
object, use the FOLLOWS clause
• Lets you order the executions of multiple triggers relative to each
other
• Applies to both compound and simple triggers
• Applies only to the section of the compound trigger with the same
timing point as the simple trigger
FOLLOWS Clause
135
• Consider two AFTER ROW ... FOR UPDATE triggers defined on the
same table. One trigger needs to reference the :OLD value and the
other trigger needs to change the :OLD value.
• In this case, you can use the FOLLOWS clause to order the firing
sequence
FOLLOWS Clause Example
CREATE OR REPLACE TRIGGER change_product
AFTER UPDATE of product_id ON order_items
FOR EACH ROW
FOLLOWS oe1.compute_total
BEGIN
dbms_output.put_line ('Do processing here…');
END;
Pivot and Unpivot
Turning things around!
137
• You can use the PIVOT operator of the SELECT statement to write
cross-tabulation queries that rotate the column values into new
columns, aggregating data in the process.
• You can use the UNPIVOT operator of the SELECT statement to
rotate columns into values of a column.
PIVOT and UNPIVOT
PIVOT UNPIVOT
138
Pivoting on the QUARTER
Column: Conceptual Example
30,000
40,000
60,000
30,000
40,000
20,000
AMOUNT_
SOLD
2,500Q1IUSAKids Jeans
2,000Q2CJapanKids Jeans
2,000Q3SUSAShorts
I
P
C
CHANNEL
Kids Jeans
Shorts
Shorts
PRODUCT
1,000Q2Germany
1,500Q4USA
Q2
QUARTER
2,500Poland
QUANTITY_
SOLD
COUNTRY
2,000
Q3
Kids Jeans
Shorts
PRODUCT
3,500
2,000
Q2
1,5002,500
Q4Q1
139
• Pivoting the data before 11g was a complex query which required the
use of the CASE or DECODE functions
Pivoting Before Oracle 11g
select product,
sum(case when quarter = 'Q1' then amount_sold else null end) Q1,
sum(case when quarter = 'Q2' then amount_sold else null end) Q2,
sum(case when quarter = 'Q3' then amount_sold else null end) Q3,
sum(case when quarter = 'Q4' then amount_sold else null end) Q4
from sales
group by product;
140
PIVOT Clause Syntax
table_reference PIVOT [ XML ]
( aggregate_function ( expr ) [[AS] alias ]
[, aggregate_function ( expr ) [[AS] alias ] ]...
pivot_for_clause
pivot_in_clause )
-- Specify the column(s) to pivot whose values are to
-- be pivoted into columns.
pivot_for_clause =
FOR { column |( column [, column]... ) }
-- Specify the pivot column values from the columns you
-- specified in the pivot_for_clause.
pivot_in_clause =
IN ( { { { expr | ( expr [, expr]... ) } [ [ AS] alias] }...
| subquery | { ANY | ANY [, ANY]...} } )
142
Creating a New View: Example
CREATE OR REPLACE VIEW sales_view AS
SELECT
prod_name AS product,
country_name AS country,
channel_id AS channel,
SUBSTR(calendar_quarter_desc, 6,2) AS quarter,
SUM(amount_sold) AS amount_sold,
SUM(quantity_sold) AS quantity_sold
FROM sales, times, customers, countries, products
WHERE sales.time_id = times.time_id AND
sales.prod_id = products.prod_id AND
sales.cust_id = customers.cust_id AND
customers.country_id = countries.country_id
GROUP BY prod_name, country_name, channel_id,
SUBSTR(calendar_quarter_desc, 6, 2);
144
Selecting the SALES VIEW Data
SELECT product, country, channel, quarter, quantity_sold
FROM sales_view;
PRODUCT COUNTRY CHANNEL QUARTER QUANTITY_SOLD
------------ ------------ ---------- -------- -------------
Y Box Italy 4 01 21
Y Box Italy 4 02 17
Y Box Italy 4 03 20
. . .
Y Box Japan 2 01 35
Y Box Japan 2 02 39
Y Box Japan 2 03 36
Y Box Japan 2 04 46
Y Box Japan 3 01 65
. . .
Bounce Italy 2 01 34
Bounce Italy 2 02 43
. . .
9502 rows selected.
145
Pivoting the QUARTER Column
in the SH Schema: Example
SELECT *
FROM
(SELECT product, quarter, quantity_sold
FROM sales_view) PIVOT (sum(quantity_sold)
FOR quarter IN ('01', '02', '03', '04'))
ORDER BY product DESC;
. . .
147
Unpivoting the QUARTER Column:
Conceptual Example
2,000
Q3
Kids Jeans
Shorts
PRODUCT
3,500
2,000
Q2
1,5002,500
Q4Q1
2,500Q1Kids Jeans
2,000Q2Kids Jeans
3,500Q2Shorts
1,500Q4Kids Jeans
Q3
QUARTER
2,000Shorts
SUM_OF_QUANTITYPRODUCT
148
• Univoting the data before 11g requires multiple queries on the table
using the UNION ALL operator
Unpivoting Before Oracle 11g
SELECT *
FROM (
SELECT product, '01' AS quarter, Q1_value FROM sales
UNION ALL
SELECT product, '02' AS quarter, Q2_value FROM sales
UNION ALL
SELECT product, '03' AS quarter, Q3_value FROM sales
UNION ALL
SELECT product, '04' AS quarter, Q4_value FROM sales
);
149
• An UNPIVOT operation does not reverse a PIVOT operation;
instead, it rotates data found in multiple columns of a single row into
multiple rows of a single column.
• If you are working with pivoted data, UNPIVOT cannot reverse any
aggregations that have been made by PIVOT or any other means.
Using the UNPIVOT Operator
UNPIVOT
150
• The UNPIVOT clause rotates columns from a previously pivoted
table or a regular table into rows. You specify:
• The measure column or columns to be unpivoted
• The name or names for the columns that result from the UNPIVOT
operation
• The columns that are unpivoted back into values of the column specified in
pivot_for_clause
• You can use an alias to map the column name to another value.
Using the UNPIVOT Clause
151
UNPIVOT Clause Syntax
table_reference UNPIVOT [{INCLUDE|EXCLUDE} NULLS]
-- specify the measure column(s) to be unpivoted.
( { column | ( column [, column]... ) }
unpivot_for_clause
unpivot_in_clause )
-- Specify one or more names for the columns that will
-- result from the unpivot operation.
unpivot_for_clause =
FOR { column | ( column [, column]... ) }
-- Specify the columns that will be unpivoted into values of
-- the column specified in the unpivot_for_clause.
unpivot_in_clause =
( { column | ( column [, column]... ) }
[ AS { constant | ( constant [, constant]... ) } ]
[, { column | ( column [, column]... ) }
[ AS { constant | ( constant [, constant]...) } ] ]...)
152
Creating a New Pivot Table: Example
. . .
CREATE TABLE pivotedtable AS
SELECT *
FROM
(SELECT product, quarter, quantity_sold
FROM sales_view) PIVOT (sum(quantity_sold)
FOR quarter IN ('01' AS Q1, '02' AS Q2,
'03' AS Q3, '04' AS Q4));
SELECT * FROM pivotedtable
ORDER BY product DESC;
153
• Unpivoting the QUARTER Column in the SH Schema:
Unpivoting the QUARTER Column : Example
SELECT *
FROM pivotedtable
UNPIVOT (quantity_sold For Quarter IN (Q1, Q2, Q3, Q4))
ORDER BY product DESC, quarter;
. . .
154
• More information and examples could be found on my Blog:
https://www.realdbamagic.com/he/pivot-a-table/
More Examples…
Oracle 12cR1
156
• Oracle 12c allows SQL VARCHAR2 to be the same size as PL/SQL VARCHAR2
• This is not the default behavior and needs to be turned on:
• Create table with 32k varchar2:
• See https://www.realdbamagic.com/he/varchar2-size-change-oracle12c/ for more
details
32K VARCHAR2/NVARCHAR2
ALTER SYSTEM set MAX_STRING_SIZE = EXTENDED scope = SPFILE;
CREATE TABLE Applicants
(id NUMBER GENERATED AS IDENTITY,
first_name varchar2(30),
last_name varchar2(30),
application date,
CV varchar2(32767)
);
157
• Columns can be marked as “invisible”
• The invisible column will not be available for users unless explicitly
mentioned in the query
• This is very useful when doing application migration for example
• The *_TAB_COLUMNS views see all of the columns (even invisible and
unused)
Invisible Columns
158
Invisible Column Example
CREATE TABLE tab1 (
id NUMBER,
description VARCHAR2(50) INVISIBLE
);
INSERT INTO tab1 VALUES (1);
SELECT * FROM tab1;
ID
----------
1
INSERT INTO tab1 (id, description) VALUES (2, 'TWO');
COMMIT;
SELECT id, description
FROM tab1;
ID DESCRIPTION
---------- ----------------------------------------------
1
2 TWO
159
• In previous releases, there was no direct equivalent of the
AutoNumber or Identity functionality of other database engines
• This behavior had to be implemented using a combination of
sequences and trigger
• Oracle 12c introduces the ability to define an identity clause against a
table column defined using a numeric type
• User should have the create sequence privilege
• Identity columns are always not null
Identity Column Type
160
• ALWAYS
• Forces the use of the identity. If an insert statement references the identity
column, an error is produced
• BY DEFAULT
• Allows using the identity if the column isn't referenced in the insert
statement. If the column is referenced, the specified value will be used in
place of the identity
• BY DEFAULT ON NULL
• Allows the identity to be used if the identity column is referenced, but a
value of NULL is specified
Identity Column Type – Options
161
• You can specify only one identity column per table
• When specifying identity clause, you must specify a numeric data
type for datatype in the column definition clause
• When specifying identity clause, you cannot specify
the DEFAULT clause in the column definition clause
• When specifying identity clause, the NOT NULL constraint is implicitly
specified
• CREATE TABLE AS SELECT will not inherit the identity property on
a column
Identity Column Type – Restrictions
162
• You can specify CURRVAL and NEXTVAL as default values for a
column
• Default value is used when the column is not referenced by the insert
or when the DEFAULT keyword is used
• Gives you the ability to auto-populate master-detail relationships
• Only makes sense if you can guarantee the inserts into the detail table
would always immediately follow the insert into the master table
Default Value Using a Sequence
163
• In an insert statement, when the column is explicitly referenced, even
when using the value NULL, the default value is not used
• Oracle database 12c allows you to modify this behavior using the ON
NULL clause in the default definition
Default Value on Explicit Nulls
164
• You can define PL/SQL functions and procedures in the WITH clause
of a subquery and then use them as you would any other built-in or
user-defined function
• The “;” does not work as a terminator to the SQL statement when the
PL/SQL declaration is included in the WITH clause
• Functions defined in the PL/SQL declaration section of the WITH
clause take precedence over objects with the same name defined at
the schema level
• Provides better performance as compared with schema level
functions
Calling PL/SQL from SQL
165
Functions in the WITH Clause (12.1)
with
function sumascii (str in varchar2) return number is
x number := 0;
begin
for i in 1..length (str)
loop
x := x + ascii (substr (str, i, 1)) ;
end loop;
return x;
end;
select /*+ WITH_PLSQL */ h.EMPLOYEE_ID, h.last_name,
sumascii (h.last_name)
from hr.employees h
Top-N and Paging Queries
In Oracle 12c
167
• A Top-N query is used to retrieve the top or bottom N rows from an
ordered set
• Combining two Top-N queries gives you the ability to page through
an ordered set
• Oracle 12c has introduced the row limiting clause to simplify Top-N
queries
Top-N Queries
168
• This is ANSI syntax
• The default offset is 0
• Null values in offset, rowcount or percent will return no rows
Top-N in 12cR1
[ OFFSET offset { ROW | ROWS } ]
[ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ]
{ ROW | ROWS } { ONLY | WITH TIES } ]
169
Top-N Examples
SELECT last_name, salary
FROM hr.employees
ORDER BY salary
FETCH FIRST 4 ROWS ONLY;
SELECT last_name, salary
FROM hr.employees
ORDER BY salary
FETCH FIRST 4 ROWS WITH TIES;
SELECT last_name, salary
FROM hr.employees
ORDER BY salary DESC
FETCH FIRST 10 PERCENT ROWS ONLY;
170
• Before 12c we had to use the rownum pseudo column to filter out
rows
• That will require sorting the entire rowset
Paging Before 12c
SELECT val
FROM (SELECT val, rownum AS rnum
FROM (SELECT val
FROM rownum_order_test
ORDER BY val)
WHERE rownum <= 10)
WHERE rnum >= 5;
171
• After 12c we have a syntax improvement for paging using the Top-N
queries
• This will use ROW_NUMBER and RANK in the background – there is no
real optimization improvements
Paging in Oracle 12c
SELECT val
FROM rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 5 ROWS ONLY;
172
• More information and examples could be found on my blog:
https://www.realdbamagic.com/he/12c-top-n-query/
More Examples
Pattern Matching in
Oracle 12c
174
• Identify and group rows with consecutive values
• Consecutive in this regards – row after row
• Uses regular expression like syntax to find patterns
What is Pattern Matching
175
• Finding sequences of events in security applications
• Locating dropped calls in a CDR listing
• Financial price behaviors (V-shape, W-shape U-shape, etc.)
• Fraud detection and sensor data analysis
Common Business Challenges
176
MATCH_RECOGNIZE Syntax
SELECT
FROM [row pattern input table]
MATCH_RECOGNIZE
( [ PARTITION BY <cols> ]
[ ORDER BY <cols> ]
[ MEASURES <cols> ]
[ ONE ROW PER MATCH | ALL ROWS PER MATCH ]
[ SKIP_TO_option]
PATTERN ( <row pattern> )
DEFINE <definition list>
)
177
• Our goal: find groups of users with sequences IDs
• This can be useful for detecting missing employees in a table, or to
locate “gaps” in a group
Example: Sequential Employee IDs
FIRSTEMP LASTEMP
---------- ----------
7371 7498
7500 7520
7522 7565
7567 7653
7655 7697
7699 7781
7783 7787
7789 7838
178
Pattern Matching Example
SELECT *
FROM Emps
MATCH_RECOGNIZE (
ORDER BY emp_id
PATTERN (STRT B*)
DEFINE B AS emp_id = PREV(emp_id)+1
ONE ROW PER MATCH
MEASURES
STRT.emp_id firstemp,
LAST(emp_id) lastemp
AFTER MATCH SKIP PAST LAST ROW
);
1. Define input
2. Pattern Matching
3. Order input
4. Process pattern
5. Using defined conditions
6. Output: rows per match
7. Output: columns per row
8. Where to go after match?
Original concept by Stew Ashton
179
Pattern Matching Example
SELECT *
FROM Emps
MATCH_RECOGNIZE (
ORDER BY emp_id
MEASURES
STRT.emp_id firstemp,
LAST(emp_id) lastemp
ONE ROW PER MATCH
AFTER MATCH SKIP PAST LAST ROW
PATTERN (STRT B*)
DEFINE B AS emp_id = PREV(emp_id)+1
);
1. Define input
2. Pattern Matching
3. Order input
4. Process pattern
5. Using defined conditions
6. Output: rows per match
7. Output: columns per row
8. Where to go after match?
Original concept by Stew Ashton
180
Oracle 11g Analytic Function Solution
select firstemp, lastemp
From (select nvl (lag (r) over (order by r), minr) firstemp, q
lastemp
from (select emp_id r,
lag (emp_id) over (order by emp_id) q,
min (emp_id) over () minr,
max (emp_id) over () maxr
from emps e1)
where r != q + 1 -- groups including lower end
union
select q,
nvl (lead (r) over (order by r), maxr)
from ( select emp_id r,
lead (emp_id) over (order by emp_id) q,
min (emp_id) over () minr,
max (emp_id) over () maxr
from emps e1)
where r + 1 != q -- groups including higher end
);
181
Supported Regular Expression Patterns
• Concatenation: No operator between elements.
• Quantifiers:
• * 0 or more matches.
• + 1 or more matches
• ? 0 or 1 match.
• {n} Exactly n matches.
• {n,} n or more matches.
• {n, m} Between n and m (inclusive) matches.
• {, m} Between 0 an m (inclusive) matches.
• Alternation: |
• Grouping: ()
182
• Test all cases: pattern matching can be very tricky
• Don’t forget to test your data with no matches
• There is no LISTAGG and no DISTINCT when using match
recognition
• Pattern variables cannot be used as bind variables
Few Last Tips
183
• Session-specific sequence
• Truncate CASCADE command
• Temporal Validity
• Temporary Undo
• Online DML Operations
• And tons of new features for DBAs too!
More 12cR1 Developers’ Features…
184
• More information and examples could be found on my Blog:
https://www.realdbamagic.com/he/pivot-a-table/
https://www.realdbamagic.com/he/12c-top-n-query/
https://www.realdbamagic.com/he/with-pl-sql-oracle-12c/
https://www.realdbamagic.com/he/session-level-sequence-12c/
More Examples…
Oracle 12cR2
186
• Up to Oracle 12cR2, objects name length (tables, columns, indexes,
constraints etc.) were limited to 30 chars
• Starting Oracle 12cR2, length is now limited to 128 bytes
Object Names Length
create table with_a_really_really_really_really_really_long_name (
and_lots_and_lots_and_lots_and_lots_and_lots_of int,
really_really_really_really_really_long_columns int
);
187
LISTAGG in Oracle 12c
• Limited to output of 4000 chars or 32000 with extended column sizes
• Oracle 12cR2 provides overflow handling:
• Example:
listagg (
measure_expr, ','
[ on overflow (truncate|error) ]
[ text ] [ (with|without) count ]
) within group (order by cols)
select listagg(table_name, ',' on overflow truncate)
within group (order by table_name) table_names
from dba_tables
188
Verify Data Type Conversions (12.2)
• If we try to validate using regular conversion we might hit an error:
ORA-01858: a non-numeric character was found where a numeric was expected
• Use validate_conversion to validate the data without an error
select t.*
from dodgy_dates t
where validate_conversion(is_this_a_date as date) = 1;
select t.*
from dodgy_dates t
where validate_conversion(is_this_a_date as date, 'yyyymmdd') = 1;
189
• Let’s say we convert the value of a column using cast. What happens
if some of the values doesn’t fit?
• The cast function can now handle conversion errors:
Handle Casting Conversion Errors (12.2)
select cast (
'not a date' as date
default date'0001-01-01' on conversion error
) dt
from dual;
190
• JSON in 12cR1 used to work with JSON documents stored in the
database
• 12cR2 brought the ability to create and modify JSON:
• JSON_object
• JSON_objectagg
• JSON_array
• JSON_arrayagg
JSON in 12.2.0.1
191
• 12.2.0.1 also introduced PL/SQL object to handle JSON. The key object types
are:
• json_element_t – a supertype for json docs and arrays
• json_document_t – for working with JSON documents
• json_array_t – for working with JSON arrays
• The treat function casts elements to the right type
Handling JSON Documents from PL/SQL
emps := treat(doc.get('employees') as json_array_t);
for i in 0 .. emps.get_size - 1 loop
emp := treat(emps.get(i) as json_object_t);
emp.put('title', '');
emp.put('name', upper(emp.get_String('name')));
end loop;
192
• Approximate Query Enhancements
• PL/SQL Code Coverage using new DBMS package:
dbms_plsql_code_coverage
• Partitions enhancements
• List partition major changes: Auto-list, multi-column
• Read only partitions
• More…
More 12c Developers’ Features…
Oracle 18c
194
• Oracle is changing the way they number products
• Products will be release more often
• Version names will be based on last two digits of the year and a
subversion
• There is no more Release 1-Release 2 for major versions, we can’t tell
when we jumped to the next major version and when for the next minor
• Examples:
• 12.2.0.1 will be followed by 18.1 (and not 12.2.0.2)
• SQL Developer 4.2.1 was followed by 17.3
• Read more at the updated MOS Note 742060.1 – Release Schedule of
Current Database Releases
Wait! 18c?! What happened to 13c?
195
• Improved JSON support
• Private Temporary Tables (more on that later!)
• Machine Learning Algorithms in the database
• “Autonomous Database”
18c Developers’ Features (preview)
Compiling PL/SQL
197
• Native and Interpreted Compilation
• Deprecating Functions (12cR2)
• Code inlining
• Fine-grain Dependency management
Compiling PL/SQL
198
Two compilation methods:
• Interpreted compilation
• Default compilation method
• Interpreted at run time
• Native compilation
• Compiles into native code
• Stored in the SYSTEM tablespace
Native and Interpreted Compilation
199
• Use the interpreted mode when (typically during development):
• You are using a debugging tool, such as SQL Developer
• You need the code compiled quickly
• Use the native mode when (typically post development):
• Your code is heavily PL/SQL based
• You are looking for increased performance in production
Deciding on a Compilation Method
Native
Interpreted
200
• PLSQL_CODE_TYPE: Specifies the compilation mode for the PL/SQL library units
• PLSQL_OPTIMIZE_LEVEL: Specifies the optimization level to be used to compile the
PL/SQL library units
• In general, for fastest performance, use the following setting:
Setting the Compilation Method
PLSQL_CODE_TYPE = { INTERPRETED | NATIVE }
PLSQL_OPTIMIZE_LEVEL = { 0 | 1 | 2 | 3}
PLSQL_CODE_TYPE = NATIVE
PLSQL_OPTIMIZE_LEVEL = 2
202
• Use the USER|ALL|DBA_PLSQL_OBJECT_SETTINGS data dictionary views to display
the settings for a PL/SQL object:
Viewing the Compilation Settings
DESCRIBE ALL_PLSQL_OBJECT_SETTINGS
Name Null? Type
------------------------- -------- --------------------
OWNER NOT NULL VARCHAR2(30)
NAME NOT NULL VARCHAR2(30)
TYPE VARCHAR2(12)
PLSQL_OPTIMIZE_LEVEL NUMBER
PLSQL_CODE_TYPE VARCHAR2(4000)
PLSQL_DEBUG VARCHAR2(4000)
PLSQL_WARNINGS VARCHAR2(4000)
NLS_LENGTH_SEMANTICS VARCHAR2(4000)
PLSQL_CCFLAGS VARCHAR2(4000)
PLSCOPE_SETTINGS VARCHAR2(4000)
203
Viewing the Compilation Settings
SELECT name, plsql_code_type, plsql_optimize_level
FROM user_plsql_object_settings;
NAME PLSQL_CODE_TYP PLSQL_OPTIMIZE_LEVEL
-------------------- -------------- --------------------
ACTIONS_T INTERPRETED 2
ACTION_T INTERPRETED 2
ACTION_V INTERPRETED 2
ADD_ORDER_ITEMS INTERPRETED 2
CATALOG_TYP INTERPRETED 2
CATALOG_TYP INTERPRETED 2
CATALOG_TYP INTERPRETED 2
CATEGORY_TYP INTERPRETED 2
CATEGORY_TYP INTERPRETED 2
COMPOSITE_CATEGORY_TYP INTERPRETED 2
...
204
• This requires DBA privileges.
• The PLSQL_CODE_TYPE compilation parameter must be set to
NATIVE.
• The benefits apply to all the built-in PL/SQL packages that are used
for many database operations.
Setting Up a Database for Native Compilation
ALTER SYSTEM SET PLSQL_CODE_TYPE = NATIVE;
205
Compiling a Program Unit for Native Compilation
SELECT name, plsql_code_type, plsql_optimize_level
FROM user_plsql_object_settings
WHERE name = 'ADD_ORDER_ITEMS';
NAME PLSQL_CODE_T PLSQL_OPTIMIZE_LEVEL
---------------------- ------------ --------------------
ADD_ORDER_ITEMS INTERPRETED 2
ALTER SESSION SET PLSQL_CODE_TYPE = 'NATIVE';
ALTER PROCEDURE add_order_items COMPILE;
SELECT name, plsql_code_type, plsql_optimize_level
FROM user_plsql_object_settings
WHERE name = 'ADD_ORDER_ITEMS';
NAME PLSQL_CODE_T PLSQL_OPTIMIZE_LEVEL
---------------------- ------------ --------------------
ADD_ORDER_ITEMS NATIVE 2
1
2
3
4
206
• We can turn on checking for certain warning conditions
• Warning messages can be issued during compilation of PL/SQL
subprograms (not for anonymous blocks )
• Use the SQL*Plus SHOW ERRORS command or query the
USER_ERRORS data dictionary view, to see any warnings generated
during compilation
• PL/SQL warning messages use the prefix PLW
• Use PLSQL_WARNINGS initialization parameter, or the DBMS_WARNING
package
PL/SQL Compile-Time Warnings
207
• SEVERE: Messages for conditions that might cause unexpected behavior
or wrong results, such as aliasing problems with parameters
• PERFORMANCE: Messages for conditions that might cause performance
problems, such as passing a VARCHAR2 value to a NUMBER column in an
INSERT statement.
• INFORMATIONAL: Messages for conditions that do not have an effect on
performance or correctness, but that you might want to change to make
the code more maintainable, such as unreachable code that can never be
executed.
• All: refer to all warning messages
PL/SQL Warning Categories
208
• Can be set at
• System level
• Session level
• Single compilation level
PLSQL_WARNINGS Parameter
ALTER SYSTEM SET PLSQL_WARNINGS='ENABLE:PERFORMANCE';
ALTER SESSION SET PLSQL_WARNINGS='DISABLE:ALL';
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:SEVERE',
'DISABLE:PERFORMANCE', 'ERROR:07204';
ALTER PROCEDURE query_emp COMPILE
PLSQL_WARNINGS='ENABLE:ALL';
209
• This warning means that the OTHERS handler of PL/SQL subroutine
can exit without executing some form of RAISE or a call to the
standard RAISE_APPLICATION_ERROR procedure.
• Good programming practices suggest that the OTHERS handler should
pass an exception upward to avoid the risk of having exceptions go
unnoticed
PLW-06009 Warning Message
210
• Mark a function as deprecated
Pragma Deprecate (12.2)
alter session set plsql_warnings = 'enable:(6019,6020,6021,6022)';
create or replace procedure your_old_code is
pragma deprecate ( your_old_code,
'This is deprecated. Use new_code instead!' );
begin
-- old code here
null;
end your_old_code;
/
show error
Warning(2,3): PLW-06019: entity YOUR_OLD_CODE is deprecated
211
• Errors will show when compiling calling code:
Pragma Deprecate (cont.)
alter session set plsql_warnings = 'error:6020';
create or replace procedure calling_old_code is
begin
your_old_code();
end calling_old_code;
/
SQL> show error
Errors for PROCEDURE CALLING_OLD_CODE:
LINE/COL ERROR
-------- ---------------------------------------------------------------
4/3 PLS-06020: reference to a deprecated entity: YOUR_OLD_CODE
declared in unit YOUR_OLD_CODE[1,11]. This is deprecated. Use
new_code instead!
Inlining
213
• Definition:
• Inlining is defined as the replacement of a call to subroutine with a copy of
the body of the subroutine that is called.
• The copied procedure generally runs faster than the original.
• The PL/SQL compiler can automatically find the calls that should be inlined.
• Benefits:
• Inlining can provide large performance gains when applied judiciously by a
factor of 2–10 times.
Intra Unit Inlining
214
• Influence implementing inlining via two methods:
• Oracle parameter PLSQL_OPTIMIZE_LEVEL
• PRAGMA INLINE
• Recommend that you:
• Inline small programs
• Inline programs that are frequently executed
• Use performance tools to identify hot spots suitable for inline
applications:
• plstimer
Use of Inlining
215
• Noninlined program:
Inlining Concepts
CREATE OR REPLACE PROCEDURE small_pgm
IS
a NUMBER;
b NUMBER;
PROCEDURE touch(x IN OUT NUMBER, y NUMBER)
IS
BEGIN
IF y > 0 THEN
x := x*x;
END IF;
END;
BEGIN
a := b;
FOR I IN 1..10 LOOP
touch(a, -17);
a := a*b;
END LOOP;
END small_pgm;
216
• Examine the loop after inlining:
Inlining Concepts
...
BEGIN
a := b;
FOR i IN 1..10 LOOP
IF –17 > 0 THEN
a := a*a;
END IF;
a := a*b;
END LOOP;
END small_pgm;
...
217
• The loop is transformed in several steps:
Inlining Concepts
a := b;
FOR i IN 1..10 LOOP ...
IF false THEN
a := a*a;
END IF;
a := a*b;
END LOOP;
a := b;
FOR i IN 1..10 LOOP ...
a := a*b;
END LOOP;
a := b;
a := a*b;
FOR i IN 1..10 LOOP ...
END LOOP;
a := b*b;
FOR i IN 1..10 LOOP ...
END LOOP;
218
• Set the PLSQL_OPTIMIZE_LEVEL session-level parameter to a value
of 2 or 3:
• Setting it to 2 means no automatic inlining is attempted.
• Setting it to 3 means automatic inlining is attempted and no pragmas are
necessary.
• Within a PL/SQL subroutine, use PRAGMAINLINE
• NO means no inlining occurs regardless of the level and regardless of the YES
pragmas.
• YES means inline at level 2 of a particular call and increase the priority of inlining
at level 3 for the call.
Inlining: Example
ALTER PROCEDURE small_pgm COMPILE
PLSQL_OPTIMIZE_LEVEL = 3 REUSE SETTINGS;
219
• After setting the PLSQL_OPTIMIZE_LEVEL parameter, use a
pragma:
Inlining: Example
CREATE OR REPLACE PROCEDURE small_pgm
IS
a PLS_INTEGER;
FUNCTION add_it(a PLS_INTEGER, b PLS_INTEGER)
RETURN PLS_INTEGER
IS
BEGIN
RETURN a + b;
END;
BEGIN
pragma INLINE (small_pgm, 'YES');
a := add_it(3, 4) + 6;
END small_pgm;
220
• Pragmas apply only to calls in the next statement following the
pragma.
• Programs that make use of smaller helper subroutines are good
candidates for inlining.
• Only local subroutines can be inlined.
• You cannot inline an external subroutine.
• Cursor functions should not be inlined.
• Inlining can increase the size of a unit.
• Be careful about suggesting to inline functions that are deterministic.
Inlining: Guidelines
Fine Grain Dependency
Management
222
• Procedure A is a direct dependent of View B. View B is a direct dependent of Table C. Procedure A is
an indirect dependent of Table C.
• Direct dependents are invalidated only by changes to the referenced object that affect them.
• Indirect dependents can be invalidated by changes to the reference object that do not affect them.
Invalidation of Dependent Objects
View B Table CProcedure A
223
• Before 11g, adding column D to table T invalidated the dependent
objects.
• Oracle Database 11g records additional, finer-grained dependency
management:
• Adding column D to table T does not impact view V and does not invalidate the
dependent objects
More Precise Dependency Metadata
Procedure P Function FView V
Columns: A,B
Table T
Columns: A,B
Add column D
224
• In Oracle Database 11g, dependencies are now tracked at the level of
element within unit.
• Element-based dependency tracking covers the following:
• Dependency of a single-table view on its base table
• Dependency of a PL/SQL program unit (package specification, package body,
or subprogram) on the following:
• Other PL/SQL program units
• Tables
• Views
Fine-Grained Dependency Management
225
Fine-Grained Dependency Management:
Example 1
CREATE TABLE t2 (col_a NUMBER, col_b NUMBER, col_c NUMBER);
CREATE VIEW v AS SELECT col_a, col_b FROM t2;
ALTER TABLE t2 ADD (col_d VARCHAR2(20));
SELECT ud.name, ud.type, ud.referenced_name,
ud.referenced_type, uo.status
FROM user_dependencies ud, user_objects uo
WHERE ud.name = uo.object_name AND ud.name = 'V';
SELECT ud.name, ud.type, ud.referenced_name,
ud.referenced_type, uo.status
FROM user_dependencies ud, user_objects uo
WHERE ud.name = uo.object_name AND ud.name = 'V';
226
Fine-Grained Dependency Management:
Example 1
ALTER TABLE t2 MODIFY (col_a VARCHAR2(20));
SELECT ud.name, ud.referenced_name, ud.referenced_type,
uo.status
FROM user_dependencies ud, user_objects uo
WHERE ud.name = uo.object_name AND ud.name = 'V';
227
Fine-Grained Dependency Management:
Example 2
CREATE PACKAGE pkg IS
PROCEDURE proc_1;
END pkg;
/
CREATE OR REPLACE PROCEDURE p IS
BEGIN
pkg.proc_1();
END p;
/
CREATE OR REPLACE PACKAGE pkg
IS
PROCEDURE proc_1;
PROCEDURE unheard_of;
END pkg;
/
228
• To reduce invalidation of dependent objects:
Guidelines for Reducing Invalidation
Add new items to the
end of the package
Reference each table
through a view
229
• An object that is not valid when it is referenced must be validated
before it can be used.
• Validation occurs automatically when an object is referenced; it does
not require explicit user action.
• If an object is not valid, its status is either COMPILED WITH
ERRORS, UNAUTHORIZED, or INVALID.
Object Revalidation
Tuning PL/SQL
231
• Memory handing in PL/SQL
• Global Temporary Tables (GTT)
• PL/SQL result cache
• Tips and Tricks
Tuning PL/SQL
232
• Create packages that contain logically related program units
• Reserve space for large allocations:
• Set the SHARED_POOL_RESERVED_SIZE initialization parameter
• Prevent large or frequently used objects from being aged out:
• Use the DBMS_SHARED_POOL package
Packages: Memory Issues
ORA-04031: unable to allocate 4160 bytes of shared memory..
233
• Use dbms_shared_pool package:
• Flags:
• P – Package, Procedure or Function
• T – Type
• R – Trigger
• Q – Sequence
Pinning Objects
DBMS_SHARED_POOL.KEEP(object_name, flag)
DBMS_SHARED_POOL.UNKEEP(object_name, flag)
234
• Memory is used more efficiently for scalability (more users consume
more memory)
• Package global memory is kept in the SGA (instead of the UGA) and is
reused for different users
• Package global memory is only used within a unit of work (a client-
server call or a server to different server call)
• Memory can be released and reused by another user
Reusing Package Memory
Pragma SERIALLY_REUSABLE
235
SERIALLY_REUSABLE - Example
CREATE OR REPLACE PACKAGE maintain_state
IS
pragma serially_reusable;
num1 number:= 0;
END maintain_state;
/
CREATE OR REPLACE PACKAGE regular_state
IS
num1 number:= 0;
END regular_state;
/
236
SERIALLY_REUSABLE - Example
BEGIN
dbms_output.put_line(chr(10) || 'THE MAINTAIN PACKAGE');
dbms_output.put_line('Original Value: ' || maintain_state.num1);
maintain_state.num1 := maintain_state.num1 + 10;
dbms_output.put_line('New Value: ' || maintain_state.num1 || chr(10));
dbms_output.put_line('THE REGULAR PACKAGE');
dbms_output.put_line('Original Value: ' || regular_state.num1);
regular_state.num1 := regular_state.num1 + 10;
dbms_output.put_line('New Value: ' || regular_state.num1 || chr(10));
dbms_output.put_line(chr(10)||chr(10));
dbms_output.put_line('THE MAINTAIN PACKAGE');
dbms_output.put_line('Original Value: ' || maintain_state.num1);
maintain_state.num1 := maintain_state.num1 + 10;
dbms_output.put_line('New Value: ' || maintain_state.num1 || chr(10));
dbms_output.put_line('THE REGULAR PACKAGE');
dbms_output.put_line('Original Value: ' || regular_state.num1);
regular_state.num1 := regular_state.num1 + 10;
dbms_output.put_line('New Value: ' || regular_state.num1 || chr(10));
END;
/
237
SERIALLY_REUSABLE - Example
First Run Second Run
237
THE MAINTAIN PACKAGE
Original Value: 0
New Value: 10
THE REGULAR PACKAGE
Original Value: 0
New Value: 10
THE MAINTAIN PACKAGE
Original Value: 10
New Value: 20
THE REGULAR PACKAGE
Original Value: 10
New Value: 20
THE MAINTAIN PACKAGE
Original Value: 0
New Value: 10
THE REGULAR PACKAGE
Original Value: 20
New Value: 30
THE MAINTAIN PACKAGE
Original Value: 10
New Value: 20
THE REGULAR PACKAGE
Original Value: 30
New Value: 40
238
• Since we’re giving up state managing, we can now avoid ORA-4068
when compiling
• For more information, visit my blog:
https://www.realdbamagic.com/he/solving-ora-04068/
SERIALLY_REUSABLE – Side Effect
239
• The flexibility built into PL/SQL enables you to pass:
• Simple scalar variables
• Complex data structures
• You can use the NOCOPY hint to improve performance with the IN
OUT parameters.
Passing Data Between PL/SQL Programs
240
• The hint enables the PL/SQL compiler to pass OUT and IN OUT
parameters by reference, as opposed to passing by value
• Enhances performance by reducing overhead when passing
parameters since less memory is being used
• The Compiler will ignore the hint if it is not possible to reference the
original structure (type conversion, constraints, for loop variable,
etc.)
NOCOPY Hint
241
NOCOPY - Example
CREATE OR REPLACE PACKAGE show_emp_pkg
IS
TYPE EmpTabTyp IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER;
PROCEDURE show_emp (p_Deptno IN NUMBER,
p_EmpTab OUT NOCOPY EmpTabTyp);
END;
/
242
• Can be used in functions as an optimization hint
• Indicates that a function can be used in a parallelized query or
parallelized DML statement
Using the PARALLEL_ENABLE Hint
CREATE OR REPLACE FUNCTION f2 (p_p1 NUMBER)
RETURN NUMBER PARALLEL_ENABLE IS
BEGIN
RETURN p_p1 * 2;
END f2;
243
• Large result sets can be stored in Table Variables or Temporary Tables
• Temporary tables can be created to hold session-private data that exists only for the duration of
a transaction or session.
• Each session sees its own separate set of rows
• DML locks are not acquired on the data
• We can create indexes, views, and triggers on temporary tables
• Using temporary tables instead of program variables for large
• record sets, can reduce memory consumption
Global Temporary Tables
CREATE GLOBAL TEMPORARY TABLE hr.employees_temp
ON COMMIT PRSERVE ROWS;
244
• Temporary objects you can create, use and then they disappear
automatically
• Like Global Temporary Tables, they can hold temporary data for the duration
of the transaction or session
• Unlike GTT – the structure itself is temporary and might be limited for the
transaction or session
• Each session sees only their own PTTs
Private Temporary Tables (18c)
Result Cache
246
• The result cache allows SQL query and PL/SQL function results to be
stored in cache memory.
• Subsequent executions of the same query or function can be served
directly out of the cache, improving response times.
• This technique can be especially effective for SQL queries and PL/SQL
functions that are executed frequently.
• Cached query results become invalid when the database data accessed by
the query is modified.
What Is Result Caching?
Data dictionary
cache
Library
cache
SGA
Result
cache
Shared pool
247
• You can increase the small, default result cache memory size by using the
RESULT_CACHE_MAX_SIZE initialization parameter.
Increasing Result Cache Memory Size
SGA
Default
result
cache
Shared pool
Increased
result
cache
248
• Set Result_Cache_Max_Size from the command line or in an
initialization file created by a DBA.
• The cache size is dynamic and can be changed either permanently or
until the instance is restarted.
Setting Result_Cache_Max_Size
SQL> ALTER SYSTEM SET result_cache_max_size = 2M SCOPE =
MEMORY;
System altered.
SQL> SELECT name, value
2 FROM v$parameter
3 WHERE name = 'result_cache_max_size';
NAME VALUE
---------------------------------------- ------------------
result_cache_max_size 2097152
1 row selected.
249
• Use the RESULT_CACHE_MODE initialization parameter in the
database initialization parameter file.
• RESULT_CACHE_MODE can be set to:
• MANUAL (default): You must add the RESULT_CACHE hint to your queries for
the results to be cached.
• FORCE: Results are always stored in the result cache memory, if possible.
Enabling Query Result Cache
250
• Definition:
• Cache the results of the current query or query fragment in memory, and
then use the cached results in future executions of the query or query
fragments.
• Cached results reside in the result cache memory portion of the SGA.
• Benefits:
• Improved performance
SQL Query Result Cache
251
• Scenario:
• You need to find the greatest average value of credit limit grouped by state over
the whole population.
• The query returns a large number of rows being analyzed to yield a few or one
row.
• In your query, the data changes fairly slowly (say every hour) but the query is
repeated fairly often (say every second).
• Solution:
• Use the new optimizer hint /*+ result_cache */ in your query:
SQL Query Result Cache
SELECT /*+ result_cache */
AVG(cust_credit_limit), cust_state_province
FROM sh.customers
GROUP BY cust_state_province;
252
Clearing the Shared Pool and Result Cache
--- flush.sql
--- Start with a clean slate. Flush the cache and shared
pool.
--- Verify that memory was released.
SET ECHO ON
SET FEEDBACK 1
SET SERVEROUTPUT ON
execute dbms_result_cache.flush
alter system flush shared_pool
/
253
• Definition:
• Enables data that is stored in cache to be shared across sessions
• Stores the function result cache in an SGA, making it available to any session
that runs your application
• Benefits:
• Improved performance
• Improved scalability
PL/SQL Function Result Cache
254
• Scenario:
• You need a PL/SQL function that derives a complex metric.
• The data that your function calculates changes slowly, but the function is
frequently called.
• Solution:
• Use the new RESULT_CACHE clause in your function definition.
• You can also have the cache purged when a dependent table experiences a
DML operation, by using the RELIES_ON clause.
Marking PL/SQL Function Results to Be Cached
255
CREATE OR REPLACE FUNCTION ORD_COUNT(cust_no number)
RETURN NUMBER
RESULT_CACHE RELIES_ON (orders)
IS
V_COUNT NUMBER;
BEGIN
SELECT COUNT(*) INTO V_COUNT
FROM orders
WHERE customer_id = cust_no;
return v_count;
end;
• Include the RESULT_CACHE option in the function definition.
• Optionally, include the RELIES_ON clause.
Creating a PL/SQL Function
Using the RESULT_CACHE Clause
Specifies that the result
should be cached
Specifies the table upon which
the function relies
(not needed in 11.2+)
256
• Specify DETERMINISTIC to indicate that the function returns the
same result value whenever it is called with the same values for its
arguments.
• This helps the optimizer avoid redundant function calls.
• If a function was called previously with the same arguments, the
optimizer can elect to use the previous result.
• Do not specify DETERMINISTIC for a function whose result
depends on the state of session variables or schema objects.
Using the DETERMINISTIC Clause with Functions
257
Calling the PL/SQL Function Inside a Query
select cust_last_name, ord_count(customer_id) no_of_orders
from customers
where cust_last_name = 'MacGraw'
258
Verifying Memory Allocation
--- Establish the cache content
set serveroutput on
execute dbms_result_cache.memory_report
259
Viewing Cache Results Created
col name format a55
select * from v$result_cache_statistics
/
260
Calling the PL/SQL Function Again
select cust_last_name, ord_count(customer_id) no_of_orders
from customers
where cust_last_name = 'MacGraw'
261
Viewing Cache Results Found
col name format a55
select * from v$result_cache_statistics
/
262
Confirming That the Cached Result Was Used
select type, namespace,status, scan_count,name
from v$result_cache_objects
/
263
• Beware of result caching of timed actions: DBMS_LOCK.SLEEP will
also be cached overriding the sleep
• Cannot be used with invoker's rights or in an anonymous block
• Cannot be used with pipelined table function
• Cannot be used with OUT or IN OUT parameters.
PL/SQL Result Cache Pitfall
Tips and Tricks
265
You can tune your PL/SQL code by:
• Identifying the data type and constraint issues
• Data type conversion
• The NOT NULL constraint
• PLS_INTEGER
• SIMPLE_INTEGER
• Writing smaller executable sections of code
• Comparing SQL with PL/SQL
• Rephrasing conditional statements
Tuning PL/SQL Code
266
DECLARE
n NUMBER;
BEGIN
n := n + 15; -- converted
n := n + 15.0; -- not converted
...
END;
• PL/SQL performs implicit conversions between structurally different data
types.
• Example: When assigning a PLS_INTEGER variable to a NUMBER variable
Avoiding Implicit Data Type Conversion
strings
dates
numbers
267
Understanding the NOT NULL Constraint
PROCEDURE calc_m IS
m NUMBER; --no constraint
...
BEGIN
m := a + b;
IF m IS NULL THEN
-- raise error
END IF;
END;
PROCEDURE calc_m IS
m NUMBER NOT NULL:=0;
a NUMBER;
b NUMBER;
BEGIN
m := a + b;
END;
The value of the expression a + b is
assigned to a temporary variable,
which is then tested for nullity.
A better way to check nullity; no
performance overhead
268
Use PLS_INTEGER when dealing with integer data.
• It is an efficient data type for integer variables.
• It requires less storage than INTEGER or NUMBER.
• Its operations use machine arithmetic, which is faster than library
arithmetic.
Using the PLS_INTEGER Data Type for Integers
269
• Definition:
• Is a predefined subtype
• Has the range –2147483648 .. 2147483648
• Does not include a null value
• Is allowed anywhere in PL/SQL where the PLS_INTEGER data type is allowed
• Benefits:
• Eliminates the overhead of overflow
checking
• Is estimated to be 2–10 times faster
when compared with the PLS_INTEGER
type with native PL/SQL compilation
Using the SIMPLE_INTEGER Data Type
270
Each has its own benefits:
• SQL:
• Accesses data in the database
• Treats data as sets
• PL/SQL:
• Provides procedural capabilities
• Has more flexibility built into the language
Comparing SQL with PL/SQL
271
• Some simple set processing is markedly faster than the equivalent PL/SQL.
• Avoid using procedural code when it may be better to use SQL.
Comparing SQL with PL/SQL
...FOR I IN 1..5600 LOOP
counter := counter + 1;
SELECT product_id, warehouse_id
INTO v_p_id, v_wh_id
FROM big_inventories WHERE v_p_id = counter;
INSERT INTO inventories2 VALUES(v_p_id, v_wh_id);
END LOOP;...
BEGIN
INSERT INTO inventories2
SELECT product_id, warehouse_id
FROM main_inventories;
END;
272
If your business logic results in one condition being true, use the
ELSIF syntax for mutually exclusive clauses:
Rephrasing Conditional
Control Statements
IF v_acct_mgr = 145 THEN
process_acct_145;
END IF;
IF v_acct_mgr = 147 THEN
process_acct_147;
END IF;
IF v_acct_mgr = 148 THEN
process_acct_148;
END IF;
IF v_acct_mgr = 149 THEN
process_acct_149;
END IF;
IF v_acct_mgr = 145
THEN
process_acct_145;
ELSIF v_acct_mgr = 147
THEN
process_acct_147;
ELSIF v_acct_mgr = 148
THEN
process_acct_148;
ELSIF v_acct_mgr = 149
THEN
process_acct_149;
END IF;
SQL Developer Command
Line (SQLcl)
The Next Generation of SQL*Plus?
274
• Introduced in Oracle 5 (1985)
• Looks very simple but has tight integration with other Oracle
infrastructure and tools
• Very good for reporting, scripting, and automation
• Replaced old CLI tool called …
UFI (“User Friendly Interface”)
SQL*Plus
275
• Nothing really wrong with SQL*Plus – it is being updated constantly
but it is missing a lot of functionality
• SQL*Plus forces us to use GUI tools to complete some basic tasks
• Easy to understand, a bit hard to use
• Not easy for new users or developers
What’s Wrong With SQL*Plus?
276
• SQL Developer is a free GUI tool to handle common database
operations
• Comes with Oracle client installation starting Oracle 11g
• Good for development and management of databases
• Developer mode
• DBA mode
• Modeling mode
• Has a Command Line interface (SDCLI) – but it’s not interactive
Using SQL Developer
277
• The SQL Developer Command Line (SQLcl, priv. SDSQL) is a new
command line interface (CLI) for SQL developers, report users, and
DBAs
• It is part of the SQL Developer suite – developed by the same team:
Oracle Database Development Tools Team
• Does (or will do) most of what SQL*Plus can do, and much more
• Main focus: making life easier for CLI users
• Minimal installation, minimal requirements
SQL Developer Command Line (SQLcl)
278
• Part of 12cR2 Database deployment
• current version: 17.3.0.271.1943, September 29, 2017
• New version comes out every couple of months
• Adding support for existing SQL*Plus commands/syntax
• Adding new commands and functionality
• The team is accepting bug reports and enhancement requests
from the public
• Active community on OTN forums!
Current Status (November 2017)
279
• Very small footprint: 19 MB
• Tool is Java based so it can run on Windows, Linux, and OS/X
• Java 7/8 JRE (runtime environment - no need for JDK)
• No need for installer or setup
• No need for any other additional software or special license
• No need for an Oracle Client
Prerequisites
280
• Download from: SQL Developer Command Line OTN Page
• Unzip the file
• Run it
Installing
281
Running SQLcl
What Can It Do?
283
• When no Oracle Client - using thin connection:
EZConnect connect style out of the box
connect host:port/service
• Support TNS, Thick and LDAP connection when Oracle home
detected
• Auto-complete connection strings from last connections AND
tnsnames.ora
Connecting to the Database
284
• Use the tab key to complete commands
• Can be used to list tables, views or other queriable objects
• Can be used to replace the * with actual column names
• Use the arrow keys to move around the command
• Use CTRL+W and CTRL+S to jump to the beginning/end of commands
Object Completion and Easy Edit
285
• 100 command history buffer
• Commands are persistent between sessions (watch out for security!)
• Use UP and DOWN arrow keys to access old commands
• Usage:
history
history usage
History script
history full
History clear [session?]
• Load from history into command buffer:
history <number>
Command History
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance
PL/SQL New and Advanced Features for Extreme Performance

More Related Content

What's hot

Exploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic FunctionsExploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic FunctionsZohar Elkayam
 
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAsOracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAsZohar Elkayam
 
SQLcl the next generation of SQLPlus?
SQLcl the next generation of SQLPlus?SQLcl the next generation of SQLPlus?
SQLcl the next generation of SQLPlus?Zohar Elkayam
 
Oracle Database In-Memory Option for ILOUG
Oracle Database In-Memory Option for ILOUGOracle Database In-Memory Option for ILOUG
Oracle Database In-Memory Option for ILOUGZohar Elkayam
 
MySQL 5.7 New Features for Developers
MySQL 5.7 New Features for DevelopersMySQL 5.7 New Features for Developers
MySQL 5.7 New Features for DevelopersZohar Elkayam
 
Exploring Oracle Multitenant in Oracle Database 12c
Exploring Oracle Multitenant in Oracle Database 12cExploring Oracle Multitenant in Oracle Database 12c
Exploring Oracle Multitenant in Oracle Database 12cZohar Elkayam
 
Adding real time reporting to your database oracle db in memory
Adding real time reporting to your database oracle db in memoryAdding real time reporting to your database oracle db in memory
Adding real time reporting to your database oracle db in memoryZohar Elkayam
 
MySQL Performance Tips & Best Practices
MySQL Performance Tips & Best PracticesMySQL Performance Tips & Best Practices
MySQL Performance Tips & Best PracticesIsaac Mosquera
 
Ordina Oracle Open World
Ordina Oracle Open WorldOrdina Oracle Open World
Ordina Oracle Open WorldMarco Gralike
 
Things Every Oracle DBA Needs to Know about the Hadoop Ecosystem
Things Every Oracle DBA Needs to Know about the Hadoop EcosystemThings Every Oracle DBA Needs to Know about the Hadoop Ecosystem
Things Every Oracle DBA Needs to Know about the Hadoop EcosystemZohar Elkayam
 
An AMIS Overview of Oracle database 12c (12.1)
An AMIS Overview of Oracle database 12c (12.1)An AMIS Overview of Oracle database 12c (12.1)
An AMIS Overview of Oracle database 12c (12.1)Marco Gralike
 
Oracle Database 12c - New Features for Developers and DBAs
Oracle Database 12c  - New Features for Developers and DBAsOracle Database 12c  - New Features for Developers and DBAs
Oracle Database 12c - New Features for Developers and DBAsAlex Zaballa
 
Confoo 2021 - MySQL Indexes & Histograms
Confoo 2021 - MySQL Indexes & HistogramsConfoo 2021 - MySQL Indexes & Histograms
Confoo 2021 - MySQL Indexes & HistogramsDave Stokes
 
PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...
PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...
PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...Dave Stokes
 
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)Hemant Kumar Singh
 
Indexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuningIndexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuningOSSCube
 
An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3
An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3
An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3Marco Gralike
 
Design Concepts For Xml Applications That Will Perform
Design Concepts For Xml Applications That Will PerformDesign Concepts For Xml Applications That Will Perform
Design Concepts For Xml Applications That Will PerformMarco Gralike
 

What's hot (19)

Exploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic FunctionsExploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic Functions
 
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAsOracle Database Performance Tuning Advanced Features and Best Practices for DBAs
Oracle Database Performance Tuning Advanced Features and Best Practices for DBAs
 
SQLcl the next generation of SQLPlus?
SQLcl the next generation of SQLPlus?SQLcl the next generation of SQLPlus?
SQLcl the next generation of SQLPlus?
 
Oracle Database In-Memory Option for ILOUG
Oracle Database In-Memory Option for ILOUGOracle Database In-Memory Option for ILOUG
Oracle Database In-Memory Option for ILOUG
 
MySQL 5.7 New Features for Developers
MySQL 5.7 New Features for DevelopersMySQL 5.7 New Features for Developers
MySQL 5.7 New Features for Developers
 
Exploring Oracle Multitenant in Oracle Database 12c
Exploring Oracle Multitenant in Oracle Database 12cExploring Oracle Multitenant in Oracle Database 12c
Exploring Oracle Multitenant in Oracle Database 12c
 
Adding real time reporting to your database oracle db in memory
Adding real time reporting to your database oracle db in memoryAdding real time reporting to your database oracle db in memory
Adding real time reporting to your database oracle db in memory
 
MySQL Performance Tips & Best Practices
MySQL Performance Tips & Best PracticesMySQL Performance Tips & Best Practices
MySQL Performance Tips & Best Practices
 
Ordina Oracle Open World
Ordina Oracle Open WorldOrdina Oracle Open World
Ordina Oracle Open World
 
Things Every Oracle DBA Needs to Know about the Hadoop Ecosystem
Things Every Oracle DBA Needs to Know about the Hadoop EcosystemThings Every Oracle DBA Needs to Know about the Hadoop Ecosystem
Things Every Oracle DBA Needs to Know about the Hadoop Ecosystem
 
An AMIS Overview of Oracle database 12c (12.1)
An AMIS Overview of Oracle database 12c (12.1)An AMIS Overview of Oracle database 12c (12.1)
An AMIS Overview of Oracle database 12c (12.1)
 
Oracle 12c Architecture
Oracle 12c ArchitectureOracle 12c Architecture
Oracle 12c Architecture
 
Oracle Database 12c - New Features for Developers and DBAs
Oracle Database 12c  - New Features for Developers and DBAsOracle Database 12c  - New Features for Developers and DBAs
Oracle Database 12c - New Features for Developers and DBAs
 
Confoo 2021 - MySQL Indexes & Histograms
Confoo 2021 - MySQL Indexes & HistogramsConfoo 2021 - MySQL Indexes & Histograms
Confoo 2021 - MySQL Indexes & Histograms
 
PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...
PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...
PHP UK 2020 Tutorial: MySQL Indexes, Histograms And other ways To Speed Up Yo...
 
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)MySQL Indexing : Improving Query Performance Using Index (Covering Index)
MySQL Indexing : Improving Query Performance Using Index (Covering Index)
 
Indexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuningIndexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuning
 
An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3
An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3
An introduction into Oracle Enterprise Manager Cloud Control 12c Release 3
 
Design Concepts For Xml Applications That Will Perform
Design Concepts For Xml Applications That Will PerformDesign Concepts For Xml Applications That Will Perform
Design Concepts For Xml Applications That Will Perform
 

Similar to PL/SQL New and Advanced Features for Extreme Performance

Bye bye $GLOBALS['TYPO3_DB']
Bye bye $GLOBALS['TYPO3_DB']Bye bye $GLOBALS['TYPO3_DB']
Bye bye $GLOBALS['TYPO3_DB']Jan Helke
 
3 CityNetConf - sql+c#=u-sql
3 CityNetConf - sql+c#=u-sql3 CityNetConf - sql+c#=u-sql
3 CityNetConf - sql+c#=u-sqlŁukasz Grala
 
Dan Hotka's Top 10 Oracle 12c New Features
Dan Hotka's Top 10 Oracle 12c New FeaturesDan Hotka's Top 10 Oracle 12c New Features
Dan Hotka's Top 10 Oracle 12c New FeaturesEmbarcadero Technologies
 
ADBMS ASSIGNMENT
ADBMS ASSIGNMENTADBMS ASSIGNMENT
ADBMS ASSIGNMENTLori Moore
 
Tips & Tricks SQL in the City Seattle 2014
Tips & Tricks SQL in the City Seattle 2014Tips & Tricks SQL in the City Seattle 2014
Tips & Tricks SQL in the City Seattle 2014Ike Ellis
 
In-memory ColumnStore Index
In-memory ColumnStore IndexIn-memory ColumnStore Index
In-memory ColumnStore IndexSolidQ
 
Less07 schema
Less07 schemaLess07 schema
Less07 schemaImran Ali
 
Kevin Bengtson Portfolio
Kevin Bengtson PortfolioKevin Bengtson Portfolio
Kevin Bengtson PortfolioKbengt521
 
Understanding DB2 Optimizer
Understanding DB2 OptimizerUnderstanding DB2 Optimizer
Understanding DB2 Optimizerterraborealis
 
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)Dave Stokes
 
TSQL in SQL Server 2012
TSQL in SQL Server 2012TSQL in SQL Server 2012
TSQL in SQL Server 2012Eduardo Castro
 
PostgreSQL Database Slides
PostgreSQL Database SlidesPostgreSQL Database Slides
PostgreSQL Database Slidesmetsarin
 
Relational Database Design Bootcamp
Relational Database Design BootcampRelational Database Design Bootcamp
Relational Database Design BootcampMark Niebergall
 

Similar to PL/SQL New and Advanced Features for Extreme Performance (20)

Bye bye $GLOBALS['TYPO3_DB']
Bye bye $GLOBALS['TYPO3_DB']Bye bye $GLOBALS['TYPO3_DB']
Bye bye $GLOBALS['TYPO3_DB']
 
Sql server T-sql basics ppt-3
Sql server T-sql basics  ppt-3Sql server T-sql basics  ppt-3
Sql server T-sql basics ppt-3
 
Rdbms day3
Rdbms day3Rdbms day3
Rdbms day3
 
Overview of Oracle database12c for developers
Overview of Oracle database12c for developersOverview of Oracle database12c for developers
Overview of Oracle database12c for developers
 
3 CityNetConf - sql+c#=u-sql
3 CityNetConf - sql+c#=u-sql3 CityNetConf - sql+c#=u-sql
3 CityNetConf - sql+c#=u-sql
 
Dan Hotka's Top 10 Oracle 12c New Features
Dan Hotka's Top 10 Oracle 12c New FeaturesDan Hotka's Top 10 Oracle 12c New Features
Dan Hotka's Top 10 Oracle 12c New Features
 
Physical Design and Development
Physical Design and DevelopmentPhysical Design and Development
Physical Design and Development
 
ADBMS ASSIGNMENT
ADBMS ASSIGNMENTADBMS ASSIGNMENT
ADBMS ASSIGNMENT
 
Tips & Tricks SQL in the City Seattle 2014
Tips & Tricks SQL in the City Seattle 2014Tips & Tricks SQL in the City Seattle 2014
Tips & Tricks SQL in the City Seattle 2014
 
In-memory ColumnStore Index
In-memory ColumnStore IndexIn-memory ColumnStore Index
In-memory ColumnStore Index
 
Less07 schema
Less07 schemaLess07 schema
Less07 schema
 
Kevin Bengtson Portfolio
Kevin Bengtson PortfolioKevin Bengtson Portfolio
Kevin Bengtson Portfolio
 
DataBase Management System Lab File
DataBase Management System Lab FileDataBase Management System Lab File
DataBase Management System Lab File
 
Understanding DB2 Optimizer
Understanding DB2 OptimizerUnderstanding DB2 Optimizer
Understanding DB2 Optimizer
 
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
MySQL 8 -- A new beginning : Sunshine PHP/PHP UK (updated)
 
TSQL in SQL Server 2012
TSQL in SQL Server 2012TSQL in SQL Server 2012
TSQL in SQL Server 2012
 
Linq to sql
Linq to sqlLinq to sql
Linq to sql
 
PostgreSQL Database Slides
PostgreSQL Database SlidesPostgreSQL Database Slides
PostgreSQL Database Slides
 
Relational Database Design Bootcamp
Relational Database Design BootcampRelational Database Design Bootcamp
Relational Database Design Bootcamp
 
Angular
AngularAngular
Angular
 

More from Zohar Elkayam

Docker Concepts for Oracle/MySQL DBAs and DevOps
Docker Concepts for Oracle/MySQL DBAs and DevOpsDocker Concepts for Oracle/MySQL DBAs and DevOps
Docker Concepts for Oracle/MySQL DBAs and DevOpsZohar Elkayam
 
Oracle Advanced SQL and Analytic Functions
Oracle Advanced SQL and Analytic FunctionsOracle Advanced SQL and Analytic Functions
Oracle Advanced SQL and Analytic FunctionsZohar Elkayam
 
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527Zohar Elkayam
 
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)Zohar Elkayam
 
Introduction to Oracle Data Guard Broker
Introduction to Oracle Data Guard BrokerIntroduction to Oracle Data Guard Broker
Introduction to Oracle Data Guard BrokerZohar Elkayam
 
Things Every Oracle DBA Needs To Know About The Hadoop Ecosystem
Things Every Oracle DBA Needs To Know About The Hadoop EcosystemThings Every Oracle DBA Needs To Know About The Hadoop Ecosystem
Things Every Oracle DBA Needs To Know About The Hadoop EcosystemZohar Elkayam
 
Rapid Cluster Computing with Apache Spark 2016
Rapid Cluster Computing with Apache Spark 2016Rapid Cluster Computing with Apache Spark 2016
Rapid Cluster Computing with Apache Spark 2016Zohar Elkayam
 
Exploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic FunctionsExploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic FunctionsZohar Elkayam
 
The Hadoop Ecosystem for Developers
The Hadoop Ecosystem for DevelopersThe Hadoop Ecosystem for Developers
The Hadoop Ecosystem for DevelopersZohar Elkayam
 
Big data for cio 2015
Big data for cio 2015Big data for cio 2015
Big data for cio 2015Zohar Elkayam
 
Oracle Data Guard A to Z
Oracle Data Guard A to ZOracle Data Guard A to Z
Oracle Data Guard A to ZZohar Elkayam
 
Oracle Data Guard Broker Webinar
Oracle Data Guard Broker WebinarOracle Data Guard Broker Webinar
Oracle Data Guard Broker WebinarZohar Elkayam
 

More from Zohar Elkayam (13)

Docker Concepts for Oracle/MySQL DBAs and DevOps
Docker Concepts for Oracle/MySQL DBAs and DevOpsDocker Concepts for Oracle/MySQL DBAs and DevOps
Docker Concepts for Oracle/MySQL DBAs and DevOps
 
Oracle Advanced SQL and Analytic Functions
Oracle Advanced SQL and Analytic FunctionsOracle Advanced SQL and Analytic Functions
Oracle Advanced SQL and Analytic Functions
 
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem 20170527
 
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)
Things Every Oracle DBA Needs to Know About the Hadoop Ecosystem (c17lv version)
 
Introduction to Oracle Data Guard Broker
Introduction to Oracle Data Guard BrokerIntroduction to Oracle Data Guard Broker
Introduction to Oracle Data Guard Broker
 
Things Every Oracle DBA Needs To Know About The Hadoop Ecosystem
Things Every Oracle DBA Needs To Know About The Hadoop EcosystemThings Every Oracle DBA Needs To Know About The Hadoop Ecosystem
Things Every Oracle DBA Needs To Know About The Hadoop Ecosystem
 
Rapid Cluster Computing with Apache Spark 2016
Rapid Cluster Computing with Apache Spark 2016Rapid Cluster Computing with Apache Spark 2016
Rapid Cluster Computing with Apache Spark 2016
 
Exploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic FunctionsExploring Advanced SQL Techniques Using Analytic Functions
Exploring Advanced SQL Techniques Using Analytic Functions
 
The Hadoop Ecosystem for Developers
The Hadoop Ecosystem for DevelopersThe Hadoop Ecosystem for Developers
The Hadoop Ecosystem for Developers
 
Big data for cio 2015
Big data for cio 2015Big data for cio 2015
Big data for cio 2015
 
Intro to Big Data
Intro to Big DataIntro to Big Data
Intro to Big Data
 
Oracle Data Guard A to Z
Oracle Data Guard A to ZOracle Data Guard A to Z
Oracle Data Guard A to Z
 
Oracle Data Guard Broker Webinar
Oracle Data Guard Broker WebinarOracle Data Guard Broker Webinar
Oracle Data Guard Broker Webinar
 

Recently uploaded

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 

Recently uploaded (20)

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 

PL/SQL New and Advanced Features for Extreme Performance

  • 1. PL/SQL New and Advanced Features for Extreme Performance Zohar Elkayam CTO, Brillix Zohar@Brillix.co.il www.realdbamagic.com Twitter: @realmgic
  • 2. 2 • Zohar Elkayam, CTO at Brillix • Programmer, DBA, team leader, database trainer, public speaker, and a senior consultant for over 19 years • Oracle ACE Since 2014 • ilOUG Board Member – Israel Oracle User Group • Blogger – www.realdbamagic.com and www.ilDBA.co.il Who am I?
  • 3. 3 About Brillix • We offer complete, integrated end-to-end solutions based on best-of- breed innovations in database, security and big data technologies • We provide complete end-to-end 24x7 expert remote database services • We offer professional customized on-site trainings, delivered by our top-notch world recognized instructors
  • 4. 4 Some of Our Customers
  • 5. 5 • Founded in 1999, over 7000 members at its peak • Divided into Technologies (Databases) and Applications groups • Free Bi-monthly meetups for DBAs and Developers at Oracle Israel offices • Yearly conference with guests speakers from all over the world: • January 22-23, 2018 • Over 30 Speakers from all over the world: Ask TOM team, Oracle product mangers and Oracle ACEs from 9 different countries! • You can join our community: meetup group, facebook group or follow us on twitter (@ilOUG_org)! • Our website: www.ilOUG.org ilOUG – Israel Oracle User Group
  • 6. 6 • Developing PL/SQL: • Composite datatypes, advanced cursors, dynamic SQL, tracing, and more… • Compiling PL/SQL: • dependencies, optimization levels, and DBMS_WARNING • Tuning PL/SQL: • GTT, Result cache and Memory handling • Oracle 11g, 12c and 18c cool, new and useful features • SQLcl – New replacement tool for SQL*Plus (if we have time) Agenda
  • 7. 7 • Learning new and old PL/SQL techniques • We will not expert everything • Getting to know new features (12cR1 and 12cR2) • Hear about Oracle 18c • This is a starting point – don’t be afraid to try Our Goal Today
  • 8. 8 •‫דעתכם‬ ‫חוות‬ ‫את‬ ‫לקבל‬ ‫ונשמח‬ ‫משוב‬ ‫טופס‬ ‫יחולק‬ ‫הסמינר‬ ‫יום‬ ‫בסיום‬. •‫חשובה‬ ‫דעתכם‬:‫יותר‬ ‫טובים‬ ‫הסמינרים‬ ‫את‬ ‫לעשות‬ ‫לנו‬ ‫המאפשרת‬ ‫זו‬ ‫היא‬! Our REAL Agenda 10:30-10:45‫הפסקה‬ 12:30-13:30‫משתתפ‬ ‫לכל‬ ‫צהריים‬ ‫ארוחת‬‫המלון‬ ‫בגן‬ ‫הכנס‬ ‫י‬ 15:00-15:15‫הפנים‬ ‫קבלת‬ ‫במתחם‬ ‫מתוקה‬ ‫הפסקה‬ 16:30‫הביתה‬ ‫הולכים‬
  • 9. 9 Oracle LiveSQL • Oracle provides free "live" 12.2 SQL tool • Includes available code library • Ability to save scripts and share • Online database design including Sample Schemas • https://livesql.oracle.com • A short demo before we start…
  • 11. 11 • Composite datatypes • Advanced Cursors and Bulk operations • Dynamic SQL and SQL Injection • Autonomous Transactions • 11g mentionable features • 12cR1 new development features • 12cR2 new features • Oracle 18c Developing PL/SQL
  • 13. 13 • Collections • Nested table, varray • Associative arrays/PLSQL tables • Use collections methods • Manipulate collections • Distinguish between the different types of collections and when to use them Composite Datatypes
  • 14. 14 • A collection is a group of elements, all of the same type. • Collections work like arrays. • Collections can store instances of an object type and, conversely, can be attributes of an object type. • Types of collections in PL/SQL: • Associative arrays • String-indexed collections • INDEX BY pls_integer or BINARY_INTEGER • Nested tables • Varrays Understanding Collections
  • 15. 15 Collection Types Nested table Varray Associative array 1 2 3 4 5 6 a f i o t w Index by PLS_INTEGER Index by VARCHAR2
  • 16. 17 Associative arrays: • That are indexed by strings can improve performance • Are pure memory structures that are much faster than schema-level tables • Provide significant additional flexibility Using Associative Arrays Associative arrays 1 2 3 4 5 6 a f i o t w Index by PLS_INTEGER Index by VARCHAR2
  • 17. 19 Associative array in PL/SQL (string-indexed): Creating the Array TYPE type_name IS TABLE OF element_type INDEX BY VARCHAR2(size) CREATE OR REPLACE PROCEDURE report_credit (p_last_name customers.cust_last_name%TYPE, p_credit_limit customers.credit_limit%TYPE) IS TYPE typ_name IS TABLE OF customers%ROWTYPE INDEX BY customers.cust_email%TYPE; v_by_cust_email typ_name; i VARCHAR2(30); PROCEDURE load_arrays IS BEGIN FOR rec IN (SELECT * FROM customers WHERE cust_email IS NOT NULL) LOOP -- Load up the array in single pass to database table. v_by_cust_email (rec.cust_email) := rec; END LOOP; END; ... Create the string-indexed associative array type. Create the string-indexed associative array variable. Populate the string-indexed associative array variable.
  • 18. 20 Traversing the Array ... BEGIN load_arrays; i:= v_by_cust_email.FIRST; dbms_output.put_line ('For credit amount of: ' || p_credit_limit); WHILE i IS NOT NULL LOOP IF v_by_cust_email(i).cust_last_name = p_last_name AND v_by_cust_email(i).credit_limit > p_credit_limit THEN dbms_output.put_line ( 'Customer '|| v_by_cust_email(i).cust_last_name || ': ' || v_by_cust_email(i).cust_email || ' has credit limit of: ' || v_by_cust_email(i).credit_limit); END IF; i := v_by_cust_email.NEXT(i); END LOOP; END report_credit; / EXECUTE report_credit('Walken', 1200) For credit amount of: 1200 Customer Walken: Emmet.Walken@LIMPKIN.COM has credit limit of: 3600 Customer Walken: Prem.Walken@BRANT.COM has credit limit of: 3700
  • 19. 22 Nested table characteristics: • A table within a table • Unbounded • Available in both SQL and PL/SQL as well as the database • Array-like access to individual rows Using Nested Tables Nested table:
  • 20. 23 pOrder nested table: • Nested tables are stored out-of-line in storage tables. Nested Table Storage Storage table: ORDID SUPPLIER REQUESTER ORDERED ITEMS 500 50 5000 30-OCT-07 800 80 8000 31-OCT-07 NESTED_TABLE_ID PRODID PRICE 55 555 56 566 57 577 NESTED_TABLE_ID PRODID PRICE 88 888
  • 21. 24 To create a nested table in the database: To create a nested table in PL/SQL: Creating Nested Tables CREATE [OR REPLACE] TYPE type_name AS TABLE OF Element_datatype [NOT NULL]; TYPE type_name IS TABLE OF element_datatype [NOT NULL];
  • 22. 25 • First, define an object type: • Second, declare a column of that collection type: Declaring Collections: Nested Table CREATE TYPE typ_item AS OBJECT --create object (prodid NUMBER(5), price NUMBER(7,2) ) / CREATE TYPE typ_item_nst -- define nested table type AS TABLE OF typ_item / CREATE TABLE pOrder ( -- create database table ordid NUMBER(5), supplier NUMBER(5), requester NUMBER(4), ordered DATE, items typ_item_nst) NESTED TABLE items STORE AS item_stor_tab / 1 2 3
  • 23. 26 Using Nested Tables Add data to the nested table: INSERT INTO pOrder VALUES (500, 50, 5000, sysdate, typ_item_nst( typ_item(55, 555), typ_item(56, 566), typ_item(57, 577))); INSERT INTO pOrder VALUES (800, 80, 8000, sysdate, typ_item_nst (typ_item (88, 888))); ORDID SUPPLIER REQUESTER ORDERED ITEMS 500 50 5000 30-OCT-07 800 80 8000 31-OCT-07 PRODID PRICE 55 555 56 566 57 577 PRODID PRICE 88 888 1 2 1 2 pOrder nested table
  • 24. 27 • Querying the results: • Querying the results with the TABLE function: Using Nested Tables SELECT * FROM porder; ORDID SUPPLIER REQUESTER ORDERED ---------- ---------- ---------- --------- ITEMS(PRODID, PRICE) ----------------------------------------------------------------- 500 50 5000 31-OCT-07 TYP_ITEM_NST(TYP_ITEM(55, 555), TYP_ITEM(56, 566), TYP_ITEM(57, 577)) 800 80 8000 31-OCT-07 TYP_ITEM_NST(TYP_ITEM(88, 888)) SELECT p2.ordid, p1.* FROM porder p2, TABLE(p2.items) p1; ORDID PRODID PRICE ---------- ---------- ---------- 800 88 888 500 57 577 500 55 555 500 56 566
  • 25. 28 Use the collection name and a subscript to reference a collection element: • Syntax: • Example: • To reference a field in a collection: Referencing Collection Elements collection_name(subscript) v_with_discount(i) p_new_items(i).prodid
  • 26. 29 Using Nested Tables in PL/SQL CREATE OR REPLACE PROCEDURE add_order_items (p_ordid NUMBER, p_new_items typ_item_nst) IS v_num_items NUMBER; v_with_discount typ_item_nst; BEGIN v_num_items := p_new_items.COUNT; v_with_discount := p_new_items; IF v_num_items > 2 THEN --ordering more than 2 items gives a 5% discount FOR i IN 1..v_num_items LOOP v_with_discount(i) := typ_item(p_new_items(i).prodid, p_new_items(i).price*.95); END LOOP; END IF; UPDATE pOrder SET items = v_with_discount WHERE ordid = p_ordid; END;
  • 27. 30 Using Nested Tables in PL/SQL -- caller pgm: DECLARE v_form_items typ_item_nst:= typ_item_nst(); BEGIN -- let's say the form holds 4 items v_form_items.EXTEND(4); v_form_items(1) := typ_item(1804, 65); v_form_items(2) := typ_item(3172, 42); v_form_items(3) := typ_item(3337, 800); v_form_items(4) := typ_item(2144, 14); add_order_items(800, v_form_items); END; PRODID PRICE 1804 65 3172 42 3337 800 2144 14 v_form_items variable ORDID SUPPLIER REQUESTER ORDERED ITEMS 500 50 5000 30-OCT-07 800 80 8000 31-OCT-07 Resulting data in the pOrder nested table PRODID PRICE 1804 61.75 3172 39.9 3337 760 2144 13.3 The prices are added after discounts.
  • 28. 31 • To create a varray in the database: • To create a varray in PL/SQL: Understanding Varrays Varray: CREATE [OR REPLACE] TYPE type_name AS VARRAY (max_elements) OF element_datatype [NOT NULL]; TYPE type_name IS VARRAY (max_elements) OF element_datatype [NOT NULL];
  • 29. 32 CREATE TABLE department ( -- create database table dept_id NUMBER(2), name VARCHAR2(25), budget NUMBER(12,2), projects typ_ProjectList) -- declare varray as column / • First, define a collection type: • Second, declare a collection of that type: Declaring Collections: Varray CREATE TYPE typ_Project AS OBJECT( --create object project_no NUMBER(4), title VARCHAR2(35), cost NUMBER(12,2)) / CREATE TYPE typ_ProjectList AS VARRAY (50) OF typ_Project -- define VARRAY type / 1 2 3
  • 30. 33 Add data to the table containing a varray column: Using Varrays INSERT INTO department VALUES (10, 'Exec Admn', 30000000, typ_ProjectList( typ_Project(1001, 'Travel Monitor', 400000), typ_Project(1002, 'Open World', 10000000))); INSERT INTO department VALUES (20, 'IT', 5000000, typ_ProjectList( typ_Project(2001, 'DB11gR2', 900000))); 1 2 DEPT_ID NAME BUDGET PROJECTS PROJECT_NO TITLE COSTS 10 Exec Admn 30000000 1001 Travel Monitor 400000 1002 Open World 10000000 20 IT 5000000 2001 DB11gR2 900000 1 2 DEPARTMENT table
  • 31. 34 • Querying the results: • Querying the results with the TABLE function: Using Varrays SELECT * FROM department; DEPT_ID NAME BUDGET ---------- ------------------------- ---------- PROJECTS(PROJECT_NO, TITLE, COST) ----------------------------------------------------------------- 10 Executive Administration 30000000 TYP_PROJECTLIST(TYP_PROJECT(1001, 'Travel Monitor', 400000), TYP_PROJECT(1002, 'Open World', 10000000)) 20 Information Technology 5000000 TYP_PROJECTLIST(TYP_PROJECT(2001, 'DB11gR2', 900000)) SELECT d2.dept_id, d2.name, d1.* FROM department d2, TABLE(d2.projects) d1; DEPT_ID NAME PROJECT_NO TITLE COST ------- ------------------------ ---------- -------------- -------- 10 Executive Administration 1001 Travel Monitor 400000 10 Executive Administration 1002 Open World 10000000 20 Information Technology 2001 DB11gR2 900000
  • 32. 35 • You can declare collections as the formal parameters of procedures and functions. • You can specify a collection type in the RETURN clause of a function specification. • Collections follow the usual scoping and instantiation rules. Working with Collections in PL/SQL CREATE OR REPLACE PACKAGE manage_dept_proj AS PROCEDURE allocate_new_proj_list (p_dept_id NUMBER, p_name VARCHAR2, p_budget NUMBER); FUNCTION get_dept_project (p_dept_id NUMBER) RETURN typ_projectlist; PROCEDURE update_a_project (p_deptno NUMBER, p_new_project typ_Project, p_position NUMBER); FUNCTION manipulate_project (p_dept_id NUMBER) RETURN typ_projectlist; FUNCTION check_costs (p_project_list typ_projectlist) RETURN boolean; END manage_dept_proj;
  • 33. 38 Three ways to initialize: • Use a constructor. • Fetch from the database. • Assign another collection variable directly. Initializing Collections PROCEDURE allocate_new_proj_list (p_dept_id NUMBER, p_name VARCHAR2, p_budget NUMBER) IS v_accounting_project typ_projectlist; BEGIN -- this example uses a constructor v_accounting_project := typ_ProjectList (typ_Project (1, 'Dsgn New Expense Rpt', 3250), typ_Project (2, 'Outsource Payroll', 12350), typ_Project (3, 'Audit Accounts Payable',1425)); INSERT INTO department VALUES(p_dept_id, p_name, p_budget, v_accounting_project); END allocate_new_proj_list;
  • 34. 39 FUNCTION get_dept_project (p_dept_id NUMBER) RETURN typ_projectlist IS v_accounting_project typ_projectlist; BEGIN -- this example uses a fetch from the database SELECT projects INTO v_accounting_project FROM department WHERE dept_id = p_dept_id; RETURN v_accounting_project; END get_dept_project; Initializing Collections FUNCTION manipulate_project (p_dept_id NUMBER) RETURN typ_projectlist IS v_accounting_project typ_projectlist; v_changed_list typ_projectlist; BEGIN SELECT projects INTO v_accounting_project FROM department WHERE dept_id = p_dept_id; -- this example assigns one collection to another v_changed_list := v_accounting_project; RETURN v_changed_list; END manipulate_project; 1 2
  • 35. 40 Referencing Collection Elements -- sample caller program to the manipulate_project function DECLARE v_result_list typ_projectlist; BEGIN v_result_list := manage_dept_proj.manipulate_project(10); FOR i IN 1..v_result_list.COUNT LOOP dbms_output.put_line('Project #: ' ||v_result_list(i).project_no); dbms_output.put_line('Title: '||v_result_list(i).title); dbms_output.put_line('Cost: ' ||v_result_list(i).cost); END LOOP; END; Project #: 1001 Title: Travel Monitor Cost: 400000 Project #: 1002 Title: Open World Cost: 10000000
  • 36. 41 • EXISTS • COUNT • LIMIT • FIRST and LAST • PRIOR and NEXT • EXTEND • TRIM • DELETE Using Collection Methods collection_name.method_name [(parameters)]
  • 37. 43 FUNCTION check_costs (p_project_list typ_projectlist) RETURN boolean IS c_max_allowed NUMBER := 10000000; i INTEGER; v_flag BOOLEAN := FALSE; BEGIN i := p_project_list.FIRST ; WHILE i IS NOT NULL LOOP IF p_project_list(i).cost > c_max_allowed then v_flag := TRUE; dbms_output.put_line (p_project_list(i).title || ' exceeded allowable budget.'); RETURN TRUE; END IF; i := p_project_list.NEXT(i); END LOOP; RETURN null; END check_costs; Traverse collections with the following methods: Using Collection Methods
  • 38. 44 Using Collection Methods -- sample caller program to check_costs set serverout on DECLARE v_project_list typ_projectlist; BEGIN v_project_list := typ_ProjectList( typ_Project (1,'Dsgn New Expense Rpt', 3250), typ_Project (2, 'Outsource Payroll', 120000), typ_Project (3, 'Audit Accounts Payable',14250000)); IF manage_dept_proj.check_costs(v_project_list) THEN dbms_output.put_line('Project rejected: overbudget'); ELSE dbms_output.put_line('Project accepted, fill out forms.'); END IF; END; Audit Accounts Payable exceeded allowable budget. Project rejected: overbudget PROJECT_NO TITLE COSTS 1 Dsgn New Expense Rpt 3250 2 Outsource Payroll 120000 3 Audit Accounts Payable 14250000 V_PROJECT_LIST variable:
  • 39. 45 PROCEDURE update_a_project (p_deptno NUMBER, p_new_project typ_Project, p_position NUMBER) IS v_my_projects typ_ProjectList; BEGIN v_my_projects := get_dept_project (p_deptno); v_my_projects.EXTEND; --make room for new project /* Move varray elements forward */ FOR i IN REVERSE p_position..v_my_projects.LAST - 1 LOOP v_my_projects(i + 1) := v_my_projects(i); END LOOP; v_my_projects(p_position) := p_new_project; -- insert new one UPDATE department SET projects = v_my_projects WHERE dept_id = p_deptno; END update_a_project; Manipulating Individual Elements
  • 40. 46 Manipulating Individual Elements -- check the table prior to the update: SELECT d2.dept_id, d2.name, d1.* FROM department d2, TABLE(d2.projects) d1; DEPT_ID NAME PROJECT_NO TITLE COST ------- ------------------------- ---------- ----------------------------- -- 10 Executive Administration 1001 Travel Monitor 400000 10 Executive Administration 1002 Open World 10000000 20 Information Technology 2001 DB11gR2 900000 -- caller program to update_a_project BEGIN manage_dept_proj.update_a_project(20, typ_Project(2002, 'AQM', 80000), 2); END; DEPT_ID NAME PROJECT_NO TITLE COST ------- ------------------------- ---------- ----------------------------- -- 10 Executive Administration 1001 Travel Monitor 400000 10 Executive Administration 1002 Open World 10000000 20 Information Technology 2001 DB11gR2 900000 20 Information Technology 2002 AQM 80000 -- check the table after the update: SELECT d2.dept_id, d2.name, d1.* FROM department d2, TABLE(d2.projects) d1;
  • 41. 47 Listing Characteristics for Collections PL/SQL Nested Tables DB Nested Tables PL/SQL Varrays DB Varrays PL/SQL Associative Arrays Maximum size No No Yes Yes Dynamic Sparsity Can be No Dense Dense Yes Storage N/A Stored out-of- line N/A Stored inline (if < 4,000 bytes) N/A Ordering Does not retain ordering and subscripts Does not retain ordering and subscripts Retains ordering and subscripts Retains ordering and subscripts Retains ordering and subscripts
  • 42. 48 • Varrays involve fewer disk accesses and are more efficient. • Use nested tables for storing large amounts of data. • Use varrays to preserve the order of elements in the collection column. • If you do not have a requirement to delete elements in the middle of a collection, favor varrays. • Varrays do not allow piecewise updates. • After deleting the elements, release the unused memory with DBMS_SESSION.FREE_UNUSED_USER_MEMORY Guidelines for Using Collections Effectively
  • 44. 50 • Fetch into a record when fetching from a cursor. • Benefit • No individual variables declaration is needed. • You can automatically use the structure of the SELECT column list. Cursor Design: Use Records DECLARE CURSOR cur_cust IS SELECT customer_id, cust_last_name, cust_email FROM customers WHERE credit_limit = 1200; v_cust_record cur_cust%ROWTYPE; BEGIN OPEN cur_cust; LOOP FETCH cur_cust INTO v_cust_record; ...
  • 45. 51 • Reference implicit cursor attributes immediately after the SQL statement executes. • Benefit • Doing so ensures that you are dealing with the result of the correct SQL statement. Guidelines for Good Cursor Design BEGIN UPDATE customers SET credit_limit = p_credit_limit WHERE customer_id = p_cust_id; get_avg_order(p_cust_id); -- procedure call IF SQL%NOTFOUND THEN ... ``
  • 46. 52 • Create cursors with parameters. • Benefit • Parameters increase the cursor’s flexibility and reusability. • Parameters help avoid scoping problems. Use Cursor Parameters CURSOR cur_cust (p_crd_limit NUMBER, p_acct_mgr NUMBER) IS SELECT customer_id, cust_last_name, cust_email FROM customers WHERE credit_limit = p_crd_limit AND account_mgr_id = p_acct_mgr; BEGIN OPEN cur_cust(p_crd_limit_in, p_acct_mgr_in); ... CLOSE cur_cust; ... OPEN cur_cust(v_credit_limit, 145); ... END;
  • 47. 53 • Simplify coding with cursor FOR loops. • Benefit • Reduces the volume of code • Automatically handles the open, fetch, and close operations, and defines a record type that matches the cursor definition Using the Cursor For Loop CREATE OR REPLACE PROCEDURE cust_pack (p_crd_limit_in NUMBER, p_acct_mgr_in NUMBER) IS v_credit_limit NUMBER := 1500; CURSOR cur_cust (p_crd_limit NUMBER, p_acct_mgr NUMBER) IS SELECT customer_id, cust_last_name, cust_email FROM customers WHERE credit_limit = p_crd_limit AND account_mgr_id = p_acct_mgr; BEGIN FOR cur_rec IN cur_cust (p_crd_limit_in, p_acct_mgr_in) LOOP -- implicit open and fetch ... END LOOP; -- implicit close ... END;
  • 48. 54 CREATE OR REPLACE PROCEDURE cust_list IS CURSOR cur_cust IS SELECT customer_id, cust_last_name, credit_limit*1.1 FROM customers; cust_record cur_cust%ROWTYPE; BEGIN OPEN cur_cust; LOOP FETCH cur_cust INTO cust_record; DBMS_OUTPUT.PUT_LINE('Customer ' || cust_record.cust_last_name || ' wants credit ' || cust_record.(credit_limit * 1.1)); EXIT WHEN cur_cust%NOTFOUND; END LOOP; ... • Make a DBA happy: Close a cursor when it is no longer needed. • Use column aliases in cursors for calculated columns fetched into records declared with %ROWTYPE. More Guidelines for Good Cursor Design Use col. alias
  • 49. 55 • A Ref Cursor is a Cursor variable • It hold a pointer to the result set of a previously opened cursor • The actual SQL statement of the cursor is dynamic and determined at execution time • A single Ref Cursor can point to different result sets at different times Returning Result Sets From PL/SQL
  • 50. 56 Memory Cursor Variables: Overview 1 Southlake, Texas 1400 2 San Francisco 1500 3 New Jersey 1600 4 Seattle, Washington 1700 5 Toronto 1800 REF CURSOR memory locator
  • 51. 57 Working with Cursor Variables Define and declare the cursor variable. Open the cursor variable. Fetch rows from the result set. Close the cursor variable. 1 2 3 4
  • 52. 58 • Strong REF CURSOR: • Is restrictive • Specifies a RETURN type • Associates only with type-compatible queries • Is less error prone • Weak REF CURSOR: • Is nonrestrictive • Associates with any query • Is very flexible Strong Versus Weak REF CURSOR Variables
  • 53. 59 DECLARE TYPE rt_cust IS REF CURSOR RETURN customers%ROWTYPE; ... Define a REF CURSOR type: • ref_type_name is a type specified in subsequent declarations. • return_type represents a record type. • RETURN keyword indicates a strong cursor. Step 1: Defining a REF CURSOR Type TYPE ref_type_name IS REF CURSOR [RETURN return_type];
  • 54. 60 Declare a cursor variable of a cursor type: • cursor_variable_name is the name of the cursor variable. • ref_type_name is the name of a REF CURSOR type. Step 1: Declaring a Cursor Variable DECLARE TYPE rt_cust IS REF CURSOR RETURN customers%ROWTYPE; cv_cust rt_cust; cursor_variable_name ref_type_name;
  • 55. 61 Options: • Use %TYPE and %ROWTYPE. • Specify a user-defined record in the RETURN clause. • Declare the cursor variable as the formal parameter of a stored procedure or function. Step 1: Declaring a REF CURSOR Return Type
  • 56. 62 • Associate a cursor variable with a multiple-row SELECT statement. • Execute the query. • Identify the result set: • cursor_variable_name is the name of the cursor variable. • select_statement is the SQL SELECT statement. Step 2: Opening a Cursor Variable OPEN cursor_variable_name FOR select_statement;
  • 57. 64 • Retrieve rows from the result set one at a time. • The return type of the cursor variable must be compatible with the variables named in the INTO clause of the FETCH statement. Step 3: Fetching from a Cursor Variable FETCH cursor_variable_name INTO variable_name1 [,variable_name2,. . .] | record_name;
  • 58. 65 • Disable a cursor variable. • The result set is undefined. • Accessing the cursor variable after it is closed raises the INVALID_CURSOR predefined exception. Step 4: Closing a Cursor Variable CLOSE cursor_variable_name;
  • 59. 66 You can pass query result sets among PL/SQL-stored subprograms and various clients. Passing Cursor Variables as Arguments Access by a host variable on the client side Pointer to the result set
  • 61. 69 Using the SYS_REFCURSOR Predefined Type CREATE OR REPLACE PROCEDURE REFCUR (p_num IN NUMBER) IS refcur sys_refcursor; empno emp.empno%TYPE; ename emp.ename%TYPE; BEGIN IF p_num = 1 THEN OPEN refcur FOR SELECT empno, ename FROM emp; DBMS_OUTPUT.PUT_LINE('Employee# Name'); DBMS_OUTPUT.PUT_LINE('----- -------'); LOOP FETCH refcur INTO empno, ename; EXIT WHEN refcur%NOTFOUND; DBMS_OUTPUT.PUT_LINE(empno || ' ' || ename); END LOOP; ELSE .... SYS_REFCURSOR is a built-in REF CURSOR type that allows any result set to be associated with it.
  • 62. 71 • You cannot use cursor variables with remote subprograms on another server. • You cannot use comparison operators to test cursor variables. • You cannot assign a null value to cursor variables. • You cannot use REF CURSOR types in CREATE TABLE or VIEW statements. • Cursors and cursor variables are not interoperable. Rules for Cursor Variables
  • 63. 72 Cursor variables have the following benefits: • Are dynamic and ensure more flexibility • Are not tied to a single SELECT statement • Hold the value of a pointer • Can reduce network traffic • Give access to query work areas after a block completes Comparing Cursor Variables with Static Cursors
  • 65. 74 • Use explicit locking to deny access to other sessions for the duration of a transaction • Lock the rows before the update or delete • Syntax: Using the For Update Clause SELECT ... FROM ... FOR UPDATE [OF column_reference][NOWAIT | WAIT n];
  • 66. 75 • Select for Update default is to wait for locked rows • We can set the wait time to be limited with a time frame or fail if rows are already locked • We can also ask the query to skip the locked rows and return the unlocked rows: Handling Locked Rows SELECT ... FROM ... FOR UPDATE SKIP LOCKED;
  • 67. 76 • When using cursor with FOR UPDATE clause, we might want to change that same record • We can use the WHERE CURRENT OF cursor to get a fast ROWID access to that row Using WHERE CURRENT OF Clause UPDATE employees SET salary = 12000 WHERE CURRENT OF emp_cursor;
  • 68. 77 • Include the RETURNING clause with an INSERT, UPDATE, and DELETE to return column values. • Benefit: • Eliminates the need to SELECT the row after DML • Fewer network round trips • Less server CPU time • Fewer cursors • Less server memory is required Using the RETURNING Clause
  • 69. 78 Using RETURNING Clause Example DECLARE v_emp_sal employees.salary%type; BEGIN UPDATE employees e set salary = salary * 1.2 WHERE e.employee_id = 202 RETURNING e.salary into v_emp_sal; dbms_output.put_line('The new salary is ' || v_emp_sal); END; / The new salary is 7200
  • 70. 79 Use bulk binds to reduce context switches between the PL/SQL engine and the SQL engine. Using Bulk Binding SQL enginePL/SQL run-time engine PL/SQL block FORALL j IN 1..1000 INSERT … (OrderId(j), OrderDate(j), …); SQL statement executor Procedural statement executor
  • 71. 80 Bind whole arrays of values simultaneously, rather than looping to perform fetch, insert, update, and delete on multiple rows. • Instead of: • Use: Using Bulk Binding ... FOR i IN 1 .. 50000 LOOP INSERT INTO bulk_bind_example_tbl VALUES(...); END LOOP; ... ... FORALL i IN 1 .. 50000 INSERT INTO bulk_bind_example_tbl VALUES(...); ...
  • 72. 82 Use BULK COLLECT to improve performance: Using Bulk Binding CREATE OR REPLACE PROCEDURE process_customers (p_account_mgr customers.account_mgr_id%TYPE) IS TYPE typ_numtab IS TABLE OF customers.customer_id%TYPE; TYPE typ_chartab IS TABLE OF customers.cust_last_name%TYPE; TYPE typ_emailtab IS TABLE OF customers.cust_email%TYPE; v_custnos typ_numtab; v_last_names typ_chartab; v_emails typ_emailtab; BEGIN SELECT customer_id, cust_last_name, cust_email BULK COLLECT INTO v_custnos, v_last_names, v_emails FROM customers WHERE account_mgr_id = p_account_mgr; ... END process_customers;
  • 73. 83 Use the RETURNING clause to retrieve information about the rows that are being modified: Using Bulk Binding DECLARE TYPE typ_replist IS VARRAY(100) OF NUMBER; TYPE typ_numlist IS TABLE OF orders.order_total%TYPE; repids typ_replist := typ_replist(153, 155, 156, 161); totlist typ_numlist; c_big_total CONSTANT NUMBER := 60000; BEGIN FORALL i IN repids.FIRST..repids.LAST UPDATE orders SET order_total = .95 * order_total WHERE sales_rep_id = repids(i) AND order_total > c_big_total RETURNING order_total BULK COLLECT INTO Totlist; END;
  • 74. 85 • You can use the SAVE EXCEPTIONS keyword in your FORALL statements: • Exceptions raised during execution are saved in the %BULK_EXCEPTIONS cursor attribute. • The attribute is a collection of records with two fields: • Note that the values always refer to the most recently executed FORALL statement. Using SAVE EXCEPTIONS FORALL index IN lower_bound..upper_bound SAVE EXCEPTIONS {insert_stmt | update_stmt | delete_stmt} Field Definition ERROR_INDEX Holds the iteration of the FORALL statement where the exception was raised ERROR_CODE Holds the corresponding Oracle error code
  • 75. 86 Handling FORALL Exceptions DECLARE TYPE NumList IS TABLE OF NUMBER; num_tab NumList := NumList(100,0,110,300,0,199,200,0,400); bulk_errors EXCEPTION; PRAGMA EXCEPTION_INIT (bulk_errors, -24381 ); BEGIN FORALL i IN num_tab.FIRST..num_tab.LAST SAVE EXCEPTIONS DELETE FROM orders WHERE order_total < 500000/num_tab(i); EXCEPTION WHEN bulk_errors THEN DBMS_OUTPUT.PUT_LINE('Number of errors is: ' || SQL%BULK_EXCEPTIONS.COUNT); FOR j in 1..SQL%BULK_EXCEPTIONS.COUNT LOOP DBMS_OUTPUT.PUT_LINE ( TO_CHAR(SQL%BULK_EXCEPTIONS(j).error_index) || ' / ' || SQLERRM(-SQL%BULK_EXCEPTIONS(j).error_code) ); END LOOP; END; /
  • 76. Dynamic SQL and SQL Injection
  • 77. 88 • Used for two main reasons: • Modify commands dynamically to retrieve or filter columns based on input • Run DDL and DCL commands from PL/SQL • PLEASE don’t use it for running DMLs! • Two main ways to run dynamic commands: • EXECUTE IMMDIATE • DBMS_SQL Dynamic SQL
  • 78. 89 • Easy syntax: • Accepts all command types • Accept bind variables with the USING clause • Allows dynamic PL/SQL creation Advantages of Native Dynamic SQL EXECUTE_IMMEDIATE dynamic_string { INTO { define_variable [, define_variable ...] | record_name } | BULK COLLECT INTO { collection_name [, collection_name ...] | :host_array_name } } [ USING [ IN | OUT | IN OUT ] bind_argument [, [ IN | OUT | IN OUT ] bind_argument] ... ] [ returning_clause ] ;
  • 79. 90 • DBMS_SQL supports statements with unknown number of inputs or outputs • We can use DESCRIBE_COLUMNS procedure in the DBMS_SQL package to describe columns for a cursor opened/parsed through DBMS_SQL • DBMS_SQL Supports SQL statements larger than 32 KB • DBMS_SQL Lets you reuse SQL statements Advantages of DBMS_SQL
  • 80. 91 Using Execute Immediate CREATE OR REPLACE PROCEDURE del_rows (p_condition varchar2, p_rows_deld out number) IS BEGIN EXECUTE IMMEDIATE 'DELETE FROM employees ' || p_condition; p_rows_deld:=sql%ROWCOUNT; END; / DECLARE cnt number; BEGIN del_rows(‘where employee_id = 201’, cnt); END; /
  • 81. 92 Using DBMS_SQL CREATE OR REPLACE PROCEDURE del_rows (p_condition in varchar2, p_rows_del out number) is cursor_id integer; BEGIN cursor_id := dbms_sql.open_cursor; dbms_sql.parse (cursor_id,'DELETE FROM employees ‘ ||p_condition, dbms_sql.native); p_rows_del := dbms_sql.execute (cursor_id); dbms_sql.close_cursor (cursor_id); END; /
  • 82. 93 • Starting Oracle 11g, we can transform a DBMS_SQL cursor into a PL/SQL REF CURSOR and vice versa Transforming DBMS_SQL Cursor into a REF CURSOR DBMS_SQL.TO_REFCURSOR (cursor_number IN INTEGER) RETURN SYS_REFCURSOR; DBMS_SQL.TO_CURSOR_NUMBER (rc IN OUT SYS_REFCURSOR) RETURN INTEGER;
  • 83. 94 • Dynamic SQL is not checked until runtime • Syntax • Structure validity • Permissions • Dynamic SQL can be used as SQL injection entry point Disadvantages of Dynamic SQL
  • 84. 95 SQL injection is a technique for maliciously exploiting applications that use client-supplied data in SQL statements. • Attackers trick the SQL engine into executing unintended commands. • SQL injection techniques may differ, but they all exploit a single vulnerability in the application. • To immunize your code against SQL injection attacks, use bind arguments or validate and sanitize all input concatenated to dynamic SQL. Understanding SQL Injection
  • 85. 96 SQL Injection: Example -- First order attack CREATE OR REPLACE PROCEDURE GET_EMAIL (p_last_name VARCHAR2 DEFAULT NULL) AS TYPE cv_custtyp IS REF CURSOR; cv cv_custtyp; v_email customers.cust_email%TYPE; v_stmt VARCHAR2(400); BEGIN v_stmt := 'SELECT cust_email FROM customers WHERE cust_last_name = '''|| p_last_name || ''''; DBMS_OUTPUT.PUT_LINE('SQL statement: ' || v_stmt); OPEN cv FOR v_stmt; LOOP FETCH cv INTO v_email; EXIT WHEN cv%NOTFOUND; DBMS_OUTPUT.PUT_LINE('Email: '||v_email); END LOOP; CLOSE cv; EXCEPTION WHEN OTHERS THEN dbms_output.PUT_LINE(sqlerrm); dbms_output.PUT_LINE('SQL statement: ' || v_stmt); END; String literals that are incorrectly validated or not validated are concatenated into a dynamic SQL statement, and interpreted as code by the SQL engine.
  • 86. 97 Assessing Vulnerability Code Uses bind arguments for all dynamic components Vulnerable Safe Contains dynamic SQL? Filters input correctly? No No No Yes Yes YesLateral injection vulnerability No
  • 87. 98 Use the following strategies to reduce attack surface: • Use invoker’s rights. • Reduce arbitrary inputs. • Use Bind arguments. • The Filter pitfall. Reducing the Attack Surface
  • 88. 99 • Give out privileges appropriately. • Run code with invoker’s rights when possible. • Ensure that the database privilege model is upheld when using definer’s rights. Avoiding Privilege Escalation Invoker’s rights Definer’s rights
  • 89. 100 • Using invoker’s rights: • Helps to limit the privileges • Helps to minimize the security exposure. • The following example does not use invoker's rights: Using Invoker’s Rights CREATE OR REPLACE PROCEDURE change_password(p_username VARCHAR2 DEFAULT NULL, p_new_password VARCHAR2 DEFAULT NULL) IS v_sql_stmt VARCHAR2(500); BEGIN v_sql_stmt := 'ALTER USER '||p_username ||' IDENTIFIED BY ' || p_new_password; EXECUTE IMMEDIATE v_sql_stmt; END change_password; GRANT EXECUTE ON change_password to OE, HR, SH; 1 2 Note the use of dynamic SQL with concatenated input values.
  • 90. 101 • OE is successful at changing the SYS password, because, by default, CHANGE_PASSWORD executes with SYS privileges: • Add the AUTHID to change the privileges to the invokers: Using Invoker’s Rights EXECUTE sys.change_password ('SYS', 'mine') CREATE OR REPLACE PROCEDURE change_password(p_username VARCHAR2 DEFAULT NULL, p_new_password VARCHAR2 DEFAULT NULL) AUTHID CURRENT_USER IS v_sql_stmt VARCHAR2(500); BEGIN v_sql_stmt := 'ALTER USER '||p_username ||' IDENTIFIED BY ' || p_new_password; EXECUTE IMMEDIATE v_sql_stmt; END change_password;
  • 91. 102 • Reduce the end-user interfaces to only those that are actually needed. • In a Web application, restrict users to accessing specified Web pages. • In a PL/SQL API, expose only those routines that are intended for customer use. • Where user input is required, make use of language features to ensure that only data of the intended type can be specified. • Do not specify a VARCHAR2 parameter when it will be used as a number. • Do not use numbers if you need only positive integers; use natural instead. Reducing Arbitrary Inputs
  • 92. 103 DBMS_ASSERT functions: Understanding DBMS_ASSERT Function Description ENQUOTE_LITERAL Encloses string literal in single quotes SIMPLE_SQL_NAME Verifies that the string is a simple SQL name
  • 93. 104 • Example 1: The object name used as an identifier: • Example 2: The object name used as a literal: • Example 3: The object name used as a quoted (normal format) identifier: • The "orders" table referenced in example 3 is a different table compared to the orders table in examples 1 and 2. • It is vulnerable to SQL injection. SELECT num_rows FROM user_tables WHERE table_name = 'ORDERS'; SELECT count(*) records FROM orders; Formatting Oracle Identifiers SELECT count(*) records FROM "orders";
  • 94. 105 • For your identifiers, determine: 1. Where will the input come from: user or data dictionary? 2. What verification is required? 3. How will the result be used, as an identifier or a literal value? • These three factors affect: • What preprocessing is required (if any) prior to calling the verification functions • Which DBMS_ASSERT verification function is required • What post-processing is required before the identifier can actually be used Working with Identifiers in Dynamic SQL
  • 95. 106 Avoiding Injection by Using DBMS_ASSERT.ENQUOTE_LITERAL CREATE OR REPLACE PROCEDURE Count_Rows(w in varchar2) authid definer as Quote constant varchar2(1) := ''''; Quote_Quote constant varchar2(2) := Quote||Quote; Safe_Literal varchar2(32767) := Quote||replace(w,Quote,Quote_Quote)||Quote; Stmt constant varchar2(32767) := 'SELECT count(*) FROM t WHERE a='|| DBMS_ASSERT.ENQUOTE_LITERAL(Safe_Literal); Row_Count number; BEGIN EXECUTE IMMEDIATE Stmt INTO Row_Count; DBMS_OUTPUT.PUT_LINE(Row_Count||' rows'); END; / Verify whether the literal is well-formed.
  • 96. 109 Avoiding Injection by Using DBMS_ASSERT.SIMPLE_SQL_NAME CREATE OR REPLACE PROCEDURE show_col2 (p_colname varchar2, p_tablename varchar2) AS type t is varray(200) of varchar2(25); Results t; Stmt CONSTANT VARCHAR2(4000) := 'SELECT '||dbms_assert.simple_sql_name( p_colname ) || ' FROM '|| dbms_assert.simple_sql_name( p_tablename ) ; BEGIN DBMS_Output.Put_Line ('SQL Stmt: ' || Stmt); EXECUTE IMMEDIATE Stmt bulk collect into Results; for j in 1..Results.Count() loop DBMS_Output.Put_Line(Results(j)); end loop; END show_col2; Verify that the input string conforms to the basic characteristics of a simple SQL name.
  • 97. 111 • Most common vulnerability: • Dynamic SQL with string concatenation • Your code design must: • Avoid input string concatenation in dynamic SQL • Use bind arguments, whether automatically via static SQL or explicitly via dynamic SQL statements Using Bind Arguments
  • 98. 112 • Filter parameter: • P_WHERE_CLAUSE is a filter. • It is difficult to protect against SQL injection. • Prevention methods: • Do not specify APIs that allow arbitrary query parameters to be exposed. • Any existing APIs with this type of functionality must be deprecated and replaced with safe alternatives. Beware of Filter Parameters stmt := 'SELECT session_id FROM sessions WHERE' || p_where_clause;
  • 99. 113 • An Autonomous Transaction is an independent Transaction started by another transaction. • The main transaction will hold for the AT and wait until it is completed • Uses PRAGMA compiler directive • Allowed in individual routines • Commonly used for loggers, progress bars, and concurrent operations Autonomous Transactions
  • 100. 114 AT Example: Main Transaction DECLARE tmp NUMBER; BEGIN FOR i IN 1..10 LOOP tmp := i; INSERT INTO t VALUES (TRUNC(i/2)); END LOOP; EXCEPTION WHEN DUP_VAL_ON_INDEX THEN logger('Failed on ' || TO_CHAR(tmp)); ROLLBACK; RAISE; END; /
  • 101. 115 AT Example: Logger (Autonomous) PROCEDURE logger (message IN VARCHAR2) IS PRAGMA AUTONOMOUS_TRANSACTION BEGIN INSERT INTO logger VALUES (sysdate, message); COMMIT; END; /
  • 102. Cool, New and Useful Features for Developers 11gR2, 12cR1, 12cR2 and what’s coming for 18c?
  • 104. 118 • For a specified measure, LISTAGG orders data within each group specified in the ORDER BY clause and then concatenates the values of the measure column • Limited to 4000 chars (in 11g, see 12cR2 enhancement!) Using the LISTAGG Function LISTAGG(measure_expr [, 'delimiter']) WITHIN GROUP (order_by_clause) [OVER query_partition_clause]
  • 105. 119 Using LISTAGG: Example SELECT department_id "Dept", hire_date "Date", last_name "Name", LISTAGG(last_name, ', ') WITHIN GROUP (ORDER BY hire_date, last_name) OVER (PARTITION BY department_id) as "Emp_list" FROM hr.employees WHERE hire_date < '01-SEP-2003' ORDER BY "Dept", "Date", "Name";
  • 106. 120 • Returns the N-th values in an ordered set of values • Different default window: RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW The NTH_VALUE Analytic Function NTH_VALUE (measure_expr, n) [ FROM { FIRST | LAST } ][ { RESPECT | IGNORE } NULLS ] OVER (analytic_clause)
  • 107. 121 Using NTH_VALUE: Example SELECT prod_id, channel_id, MIN(amount_sold), NTH_VALUE ( MIN(amount_sold), 2) OVER (PARTITION BY prod_id ORDER BY channel_id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) nv FROM sh.sales WHERE prod_id BETWEEN 13 and 16 GROUP BY prod_id, channel_id;
  • 108. 122 • Virtual columns are dynamic (not stored) columns of a table (no views required) • Virtual columns obtain their value be evaluating as expression: • Columns from the same table • Constraints • Function Calls (user defined) • Might be used for • Eliminate views • Control table partitioning • Manage “Binary” XMLType data • Index values (function based index) Virtual Columns
  • 109. 123 Virtual Columns Example column_name [datatype] [GENERATED ALWAYS] AS (expression) [VIRTUAL] CREATE TABLE employees ( id NUMBER, first_name VARCHAR2(10), last_name VARCHAR2(10), salary NUMBER(9,2), comm1 NUMBER(3), comm2 NUMBER(3), salary1 AS (ROUND(salary*(1+comm1/100),2)), salary2 NUMBER GENERATED ALWAYS AS (ROUND(salary*(1+comm2/100),2)) VIRTUAL, CONSTRAINT employees_pk PRIMARY KEY (id) );
  • 111. 125 • A single trigger on a table that allows you to specify actions for each of the following four timing points: • Before the firing statement • Before each row that the firing statement affects • After each row that the firing statement affects • After the firing statement What Is a Compound Trigger?
  • 112. 126 • The compound trigger body supports a common PL/SQL state that the code for each timing point can access. • The compound trigger common state is: • Established when the triggering statement starts • Destroyed when the triggering statement completes • A compound trigger has a declaration section and a section for each of its timing points. Working with Compound Triggers
  • 113. 127 • You can use compound triggers to: • Program an approach where you want the actions you implement for the various timing points to share common data. • Accumulate rows destined for a second table so that you can periodically bulk-insert them • Avoid the mutating-table error (ORA-04091)by allowing rows destined for a second table to accumulate and then bulk-inserting them The Benefits of Using a Compound Trigger
  • 114. 128 • A compound trigger defined on a table has one or more of the following timing-point sections. Timing-point sections must appear in the order shown in the table. Timing-Point Sections of a Table Compound Trigger Timing Point Compound Trigger Section Before the triggering statement executes BEFORE statement After the triggering statement executes AFTER statement Before each row that the triggering statement affects BEFORE EACH ROW After each row that the triggering statement affects AFTER EACH ROW
  • 115. 129 Compound Trigger Structure for Tables CREATE OR REPLACE TRIGGER schema.trigger FOR dml_event_clause ON schema.table COMPOUND TRIGGER -- Initial section -- Declarations -- Subprograms -- Optional section BEFORE STATEMENT IS ...; -- Optional section BEFORE EACH ROW IS ...; -- Optional section AFTER EACH ROW IS ...; -- Optional section AFTER STATEMENT IS ...; 1 2
  • 116. 130 • A mutating table is: • A table that is being modified by an UPDATE, DELETE, or INSERT statement, or • A table that might be updated by the effects of a DELETE CASCADE constraint • The session that issued the triggering statement cannot query or modify a mutating table. • This restriction prevents a trigger from seeing an inconsistent set of data. • This restriction applies to all triggers that use the FOR EACH ROW clause. • Views being modified in the INSTEAD OF triggers are not considered mutating. Trigger Restrictions on Mutating Tables
  • 117. 131 Using a Compound Trigger to Resolve the Mutating Table Error CREATE OR REPLACE TRIGGER check_salary FOR INSERT OR UPDATE OF salary, job_id ON employees WHEN (NEW.job_id <> 'AD_PRES') COMPOUND TRIGGER TYPE salaries_t IS TABLE OF employees.salary%TYPE; min_salaries salaries_t; max_salaries salaries_t; TYPE department_ids_t IS TABLE OF employees.department_id%TYPE; department_ids department_ids_t; TYPE department_salaries_t IS TABLE OF employees.salary%TYPE INDEX BY VARCHAR2(80); department_min_salaries department_salaries_t; department_max_salaries department_salaries_t; -- example continues on next slide
  • 118. 132 Using a Compound Trigger to Resolve the Mutating Table Error . . . BEFORE STATEMENT IS BEGIN SELECT MIN(salary), MAX(salary), NVL(department_id, -1) BULK COLLECT INTO min_Salaries, max_salaries, department_ids FROM employees GROUP BY department_id; FOR j IN 1..department_ids.COUNT() LOOP department_min_salaries(department_ids(j)) := min_salaries(j); department_max_salaries(department_ids(j)) := max_salaries(j); END LOOP; END BEFORE STATEMENT; AFTER EACH ROW IS BEGIN IF :NEW.salary < department_min_salaries(:NEW.department_id) OR :NEW.salary > department_max_salaries(:NEW.department_id) THEN RAISE_APPLICATION_ERROR(-20505,'New Salary is out of acceptable range'); END IF; END AFTER EACH ROW; END check_salary;
  • 119. 133 • A compound trigger must be a DML trigger and defined on either a table or a view • An exception that occurs in one section must be handled in that section. It cannot transfer control to another section • :OLD and :NEW cannot appear in the declaration, BEFORE STATEMENT, or the AFTER STATEMENT sections • Only the BEFORE EACH ROW section can change the value of :NEW • The firing order of compound triggers is not guaranteed unless you use the FOLLOWS clause Compound Trigger Restrictions
  • 120. 134 • To ensure that a trigger fires after certain other triggers on the same object, use the FOLLOWS clause • Lets you order the executions of multiple triggers relative to each other • Applies to both compound and simple triggers • Applies only to the section of the compound trigger with the same timing point as the simple trigger FOLLOWS Clause
  • 121. 135 • Consider two AFTER ROW ... FOR UPDATE triggers defined on the same table. One trigger needs to reference the :OLD value and the other trigger needs to change the :OLD value. • In this case, you can use the FOLLOWS clause to order the firing sequence FOLLOWS Clause Example CREATE OR REPLACE TRIGGER change_product AFTER UPDATE of product_id ON order_items FOR EACH ROW FOLLOWS oe1.compute_total BEGIN dbms_output.put_line ('Do processing here…'); END;
  • 122. Pivot and Unpivot Turning things around!
  • 123. 137 • You can use the PIVOT operator of the SELECT statement to write cross-tabulation queries that rotate the column values into new columns, aggregating data in the process. • You can use the UNPIVOT operator of the SELECT statement to rotate columns into values of a column. PIVOT and UNPIVOT PIVOT UNPIVOT
  • 124. 138 Pivoting on the QUARTER Column: Conceptual Example 30,000 40,000 60,000 30,000 40,000 20,000 AMOUNT_ SOLD 2,500Q1IUSAKids Jeans 2,000Q2CJapanKids Jeans 2,000Q3SUSAShorts I P C CHANNEL Kids Jeans Shorts Shorts PRODUCT 1,000Q2Germany 1,500Q4USA Q2 QUARTER 2,500Poland QUANTITY_ SOLD COUNTRY 2,000 Q3 Kids Jeans Shorts PRODUCT 3,500 2,000 Q2 1,5002,500 Q4Q1
  • 125. 139 • Pivoting the data before 11g was a complex query which required the use of the CASE or DECODE functions Pivoting Before Oracle 11g select product, sum(case when quarter = 'Q1' then amount_sold else null end) Q1, sum(case when quarter = 'Q2' then amount_sold else null end) Q2, sum(case when quarter = 'Q3' then amount_sold else null end) Q3, sum(case when quarter = 'Q4' then amount_sold else null end) Q4 from sales group by product;
  • 126. 140 PIVOT Clause Syntax table_reference PIVOT [ XML ] ( aggregate_function ( expr ) [[AS] alias ] [, aggregate_function ( expr ) [[AS] alias ] ]... pivot_for_clause pivot_in_clause ) -- Specify the column(s) to pivot whose values are to -- be pivoted into columns. pivot_for_clause = FOR { column |( column [, column]... ) } -- Specify the pivot column values from the columns you -- specified in the pivot_for_clause. pivot_in_clause = IN ( { { { expr | ( expr [, expr]... ) } [ [ AS] alias] }... | subquery | { ANY | ANY [, ANY]...} } )
  • 127. 142 Creating a New View: Example CREATE OR REPLACE VIEW sales_view AS SELECT prod_name AS product, country_name AS country, channel_id AS channel, SUBSTR(calendar_quarter_desc, 6,2) AS quarter, SUM(amount_sold) AS amount_sold, SUM(quantity_sold) AS quantity_sold FROM sales, times, customers, countries, products WHERE sales.time_id = times.time_id AND sales.prod_id = products.prod_id AND sales.cust_id = customers.cust_id AND customers.country_id = countries.country_id GROUP BY prod_name, country_name, channel_id, SUBSTR(calendar_quarter_desc, 6, 2);
  • 128. 144 Selecting the SALES VIEW Data SELECT product, country, channel, quarter, quantity_sold FROM sales_view; PRODUCT COUNTRY CHANNEL QUARTER QUANTITY_SOLD ------------ ------------ ---------- -------- ------------- Y Box Italy 4 01 21 Y Box Italy 4 02 17 Y Box Italy 4 03 20 . . . Y Box Japan 2 01 35 Y Box Japan 2 02 39 Y Box Japan 2 03 36 Y Box Japan 2 04 46 Y Box Japan 3 01 65 . . . Bounce Italy 2 01 34 Bounce Italy 2 02 43 . . . 9502 rows selected.
  • 129. 145 Pivoting the QUARTER Column in the SH Schema: Example SELECT * FROM (SELECT product, quarter, quantity_sold FROM sales_view) PIVOT (sum(quantity_sold) FOR quarter IN ('01', '02', '03', '04')) ORDER BY product DESC; . . .
  • 130. 147 Unpivoting the QUARTER Column: Conceptual Example 2,000 Q3 Kids Jeans Shorts PRODUCT 3,500 2,000 Q2 1,5002,500 Q4Q1 2,500Q1Kids Jeans 2,000Q2Kids Jeans 3,500Q2Shorts 1,500Q4Kids Jeans Q3 QUARTER 2,000Shorts SUM_OF_QUANTITYPRODUCT
  • 131. 148 • Univoting the data before 11g requires multiple queries on the table using the UNION ALL operator Unpivoting Before Oracle 11g SELECT * FROM ( SELECT product, '01' AS quarter, Q1_value FROM sales UNION ALL SELECT product, '02' AS quarter, Q2_value FROM sales UNION ALL SELECT product, '03' AS quarter, Q3_value FROM sales UNION ALL SELECT product, '04' AS quarter, Q4_value FROM sales );
  • 132. 149 • An UNPIVOT operation does not reverse a PIVOT operation; instead, it rotates data found in multiple columns of a single row into multiple rows of a single column. • If you are working with pivoted data, UNPIVOT cannot reverse any aggregations that have been made by PIVOT or any other means. Using the UNPIVOT Operator UNPIVOT
  • 133. 150 • The UNPIVOT clause rotates columns from a previously pivoted table or a regular table into rows. You specify: • The measure column or columns to be unpivoted • The name or names for the columns that result from the UNPIVOT operation • The columns that are unpivoted back into values of the column specified in pivot_for_clause • You can use an alias to map the column name to another value. Using the UNPIVOT Clause
  • 134. 151 UNPIVOT Clause Syntax table_reference UNPIVOT [{INCLUDE|EXCLUDE} NULLS] -- specify the measure column(s) to be unpivoted. ( { column | ( column [, column]... ) } unpivot_for_clause unpivot_in_clause ) -- Specify one or more names for the columns that will -- result from the unpivot operation. unpivot_for_clause = FOR { column | ( column [, column]... ) } -- Specify the columns that will be unpivoted into values of -- the column specified in the unpivot_for_clause. unpivot_in_clause = ( { column | ( column [, column]... ) } [ AS { constant | ( constant [, constant]... ) } ] [, { column | ( column [, column]... ) } [ AS { constant | ( constant [, constant]...) } ] ]...)
  • 135. 152 Creating a New Pivot Table: Example . . . CREATE TABLE pivotedtable AS SELECT * FROM (SELECT product, quarter, quantity_sold FROM sales_view) PIVOT (sum(quantity_sold) FOR quarter IN ('01' AS Q1, '02' AS Q2, '03' AS Q3, '04' AS Q4)); SELECT * FROM pivotedtable ORDER BY product DESC;
  • 136. 153 • Unpivoting the QUARTER Column in the SH Schema: Unpivoting the QUARTER Column : Example SELECT * FROM pivotedtable UNPIVOT (quantity_sold For Quarter IN (Q1, Q2, Q3, Q4)) ORDER BY product DESC, quarter; . . .
  • 137. 154 • More information and examples could be found on my Blog: https://www.realdbamagic.com/he/pivot-a-table/ More Examples…
  • 139. 156 • Oracle 12c allows SQL VARCHAR2 to be the same size as PL/SQL VARCHAR2 • This is not the default behavior and needs to be turned on: • Create table with 32k varchar2: • See https://www.realdbamagic.com/he/varchar2-size-change-oracle12c/ for more details 32K VARCHAR2/NVARCHAR2 ALTER SYSTEM set MAX_STRING_SIZE = EXTENDED scope = SPFILE; CREATE TABLE Applicants (id NUMBER GENERATED AS IDENTITY, first_name varchar2(30), last_name varchar2(30), application date, CV varchar2(32767) );
  • 140. 157 • Columns can be marked as “invisible” • The invisible column will not be available for users unless explicitly mentioned in the query • This is very useful when doing application migration for example • The *_TAB_COLUMNS views see all of the columns (even invisible and unused) Invisible Columns
  • 141. 158 Invisible Column Example CREATE TABLE tab1 ( id NUMBER, description VARCHAR2(50) INVISIBLE ); INSERT INTO tab1 VALUES (1); SELECT * FROM tab1; ID ---------- 1 INSERT INTO tab1 (id, description) VALUES (2, 'TWO'); COMMIT; SELECT id, description FROM tab1; ID DESCRIPTION ---------- ---------------------------------------------- 1 2 TWO
  • 142. 159 • In previous releases, there was no direct equivalent of the AutoNumber or Identity functionality of other database engines • This behavior had to be implemented using a combination of sequences and trigger • Oracle 12c introduces the ability to define an identity clause against a table column defined using a numeric type • User should have the create sequence privilege • Identity columns are always not null Identity Column Type
  • 143. 160 • ALWAYS • Forces the use of the identity. If an insert statement references the identity column, an error is produced • BY DEFAULT • Allows using the identity if the column isn't referenced in the insert statement. If the column is referenced, the specified value will be used in place of the identity • BY DEFAULT ON NULL • Allows the identity to be used if the identity column is referenced, but a value of NULL is specified Identity Column Type – Options
  • 144. 161 • You can specify only one identity column per table • When specifying identity clause, you must specify a numeric data type for datatype in the column definition clause • When specifying identity clause, you cannot specify the DEFAULT clause in the column definition clause • When specifying identity clause, the NOT NULL constraint is implicitly specified • CREATE TABLE AS SELECT will not inherit the identity property on a column Identity Column Type – Restrictions
  • 145. 162 • You can specify CURRVAL and NEXTVAL as default values for a column • Default value is used when the column is not referenced by the insert or when the DEFAULT keyword is used • Gives you the ability to auto-populate master-detail relationships • Only makes sense if you can guarantee the inserts into the detail table would always immediately follow the insert into the master table Default Value Using a Sequence
  • 146. 163 • In an insert statement, when the column is explicitly referenced, even when using the value NULL, the default value is not used • Oracle database 12c allows you to modify this behavior using the ON NULL clause in the default definition Default Value on Explicit Nulls
  • 147. 164 • You can define PL/SQL functions and procedures in the WITH clause of a subquery and then use them as you would any other built-in or user-defined function • The “;” does not work as a terminator to the SQL statement when the PL/SQL declaration is included in the WITH clause • Functions defined in the PL/SQL declaration section of the WITH clause take precedence over objects with the same name defined at the schema level • Provides better performance as compared with schema level functions Calling PL/SQL from SQL
  • 148. 165 Functions in the WITH Clause (12.1) with function sumascii (str in varchar2) return number is x number := 0; begin for i in 1..length (str) loop x := x + ascii (substr (str, i, 1)) ; end loop; return x; end; select /*+ WITH_PLSQL */ h.EMPLOYEE_ID, h.last_name, sumascii (h.last_name) from hr.employees h
  • 149. Top-N and Paging Queries In Oracle 12c
  • 150. 167 • A Top-N query is used to retrieve the top or bottom N rows from an ordered set • Combining two Top-N queries gives you the ability to page through an ordered set • Oracle 12c has introduced the row limiting clause to simplify Top-N queries Top-N Queries
  • 151. 168 • This is ANSI syntax • The default offset is 0 • Null values in offset, rowcount or percent will return no rows Top-N in 12cR1 [ OFFSET offset { ROW | ROWS } ] [ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ] { ROW | ROWS } { ONLY | WITH TIES } ]
  • 152. 169 Top-N Examples SELECT last_name, salary FROM hr.employees ORDER BY salary FETCH FIRST 4 ROWS ONLY; SELECT last_name, salary FROM hr.employees ORDER BY salary FETCH FIRST 4 ROWS WITH TIES; SELECT last_name, salary FROM hr.employees ORDER BY salary DESC FETCH FIRST 10 PERCENT ROWS ONLY;
  • 153. 170 • Before 12c we had to use the rownum pseudo column to filter out rows • That will require sorting the entire rowset Paging Before 12c SELECT val FROM (SELECT val, rownum AS rnum FROM (SELECT val FROM rownum_order_test ORDER BY val) WHERE rownum <= 10) WHERE rnum >= 5;
  • 154. 171 • After 12c we have a syntax improvement for paging using the Top-N queries • This will use ROW_NUMBER and RANK in the background – there is no real optimization improvements Paging in Oracle 12c SELECT val FROM rownum_order_test ORDER BY val OFFSET 4 ROWS FETCH NEXT 5 ROWS ONLY;
  • 155. 172 • More information and examples could be found on my blog: https://www.realdbamagic.com/he/12c-top-n-query/ More Examples
  • 157. 174 • Identify and group rows with consecutive values • Consecutive in this regards – row after row • Uses regular expression like syntax to find patterns What is Pattern Matching
  • 158. 175 • Finding sequences of events in security applications • Locating dropped calls in a CDR listing • Financial price behaviors (V-shape, W-shape U-shape, etc.) • Fraud detection and sensor data analysis Common Business Challenges
  • 159. 176 MATCH_RECOGNIZE Syntax SELECT FROM [row pattern input table] MATCH_RECOGNIZE ( [ PARTITION BY <cols> ] [ ORDER BY <cols> ] [ MEASURES <cols> ] [ ONE ROW PER MATCH | ALL ROWS PER MATCH ] [ SKIP_TO_option] PATTERN ( <row pattern> ) DEFINE <definition list> )
  • 160. 177 • Our goal: find groups of users with sequences IDs • This can be useful for detecting missing employees in a table, or to locate “gaps” in a group Example: Sequential Employee IDs FIRSTEMP LASTEMP ---------- ---------- 7371 7498 7500 7520 7522 7565 7567 7653 7655 7697 7699 7781 7783 7787 7789 7838
  • 161. 178 Pattern Matching Example SELECT * FROM Emps MATCH_RECOGNIZE ( ORDER BY emp_id PATTERN (STRT B*) DEFINE B AS emp_id = PREV(emp_id)+1 ONE ROW PER MATCH MEASURES STRT.emp_id firstemp, LAST(emp_id) lastemp AFTER MATCH SKIP PAST LAST ROW ); 1. Define input 2. Pattern Matching 3. Order input 4. Process pattern 5. Using defined conditions 6. Output: rows per match 7. Output: columns per row 8. Where to go after match? Original concept by Stew Ashton
  • 162. 179 Pattern Matching Example SELECT * FROM Emps MATCH_RECOGNIZE ( ORDER BY emp_id MEASURES STRT.emp_id firstemp, LAST(emp_id) lastemp ONE ROW PER MATCH AFTER MATCH SKIP PAST LAST ROW PATTERN (STRT B*) DEFINE B AS emp_id = PREV(emp_id)+1 ); 1. Define input 2. Pattern Matching 3. Order input 4. Process pattern 5. Using defined conditions 6. Output: rows per match 7. Output: columns per row 8. Where to go after match? Original concept by Stew Ashton
  • 163. 180 Oracle 11g Analytic Function Solution select firstemp, lastemp From (select nvl (lag (r) over (order by r), minr) firstemp, q lastemp from (select emp_id r, lag (emp_id) over (order by emp_id) q, min (emp_id) over () minr, max (emp_id) over () maxr from emps e1) where r != q + 1 -- groups including lower end union select q, nvl (lead (r) over (order by r), maxr) from ( select emp_id r, lead (emp_id) over (order by emp_id) q, min (emp_id) over () minr, max (emp_id) over () maxr from emps e1) where r + 1 != q -- groups including higher end );
  • 164. 181 Supported Regular Expression Patterns • Concatenation: No operator between elements. • Quantifiers: • * 0 or more matches. • + 1 or more matches • ? 0 or 1 match. • {n} Exactly n matches. • {n,} n or more matches. • {n, m} Between n and m (inclusive) matches. • {, m} Between 0 an m (inclusive) matches. • Alternation: | • Grouping: ()
  • 165. 182 • Test all cases: pattern matching can be very tricky • Don’t forget to test your data with no matches • There is no LISTAGG and no DISTINCT when using match recognition • Pattern variables cannot be used as bind variables Few Last Tips
  • 166. 183 • Session-specific sequence • Truncate CASCADE command • Temporal Validity • Temporary Undo • Online DML Operations • And tons of new features for DBAs too! More 12cR1 Developers’ Features…
  • 167. 184 • More information and examples could be found on my Blog: https://www.realdbamagic.com/he/pivot-a-table/ https://www.realdbamagic.com/he/12c-top-n-query/ https://www.realdbamagic.com/he/with-pl-sql-oracle-12c/ https://www.realdbamagic.com/he/session-level-sequence-12c/ More Examples…
  • 169. 186 • Up to Oracle 12cR2, objects name length (tables, columns, indexes, constraints etc.) were limited to 30 chars • Starting Oracle 12cR2, length is now limited to 128 bytes Object Names Length create table with_a_really_really_really_really_really_long_name ( and_lots_and_lots_and_lots_and_lots_and_lots_of int, really_really_really_really_really_long_columns int );
  • 170. 187 LISTAGG in Oracle 12c • Limited to output of 4000 chars or 32000 with extended column sizes • Oracle 12cR2 provides overflow handling: • Example: listagg ( measure_expr, ',' [ on overflow (truncate|error) ] [ text ] [ (with|without) count ] ) within group (order by cols) select listagg(table_name, ',' on overflow truncate) within group (order by table_name) table_names from dba_tables
  • 171. 188 Verify Data Type Conversions (12.2) • If we try to validate using regular conversion we might hit an error: ORA-01858: a non-numeric character was found where a numeric was expected • Use validate_conversion to validate the data without an error select t.* from dodgy_dates t where validate_conversion(is_this_a_date as date) = 1; select t.* from dodgy_dates t where validate_conversion(is_this_a_date as date, 'yyyymmdd') = 1;
  • 172. 189 • Let’s say we convert the value of a column using cast. What happens if some of the values doesn’t fit? • The cast function can now handle conversion errors: Handle Casting Conversion Errors (12.2) select cast ( 'not a date' as date default date'0001-01-01' on conversion error ) dt from dual;
  • 173. 190 • JSON in 12cR1 used to work with JSON documents stored in the database • 12cR2 brought the ability to create and modify JSON: • JSON_object • JSON_objectagg • JSON_array • JSON_arrayagg JSON in 12.2.0.1
  • 174. 191 • 12.2.0.1 also introduced PL/SQL object to handle JSON. The key object types are: • json_element_t – a supertype for json docs and arrays • json_document_t – for working with JSON documents • json_array_t – for working with JSON arrays • The treat function casts elements to the right type Handling JSON Documents from PL/SQL emps := treat(doc.get('employees') as json_array_t); for i in 0 .. emps.get_size - 1 loop emp := treat(emps.get(i) as json_object_t); emp.put('title', ''); emp.put('name', upper(emp.get_String('name'))); end loop;
  • 175. 192 • Approximate Query Enhancements • PL/SQL Code Coverage using new DBMS package: dbms_plsql_code_coverage • Partitions enhancements • List partition major changes: Auto-list, multi-column • Read only partitions • More… More 12c Developers’ Features…
  • 177. 194 • Oracle is changing the way they number products • Products will be release more often • Version names will be based on last two digits of the year and a subversion • There is no more Release 1-Release 2 for major versions, we can’t tell when we jumped to the next major version and when for the next minor • Examples: • 12.2.0.1 will be followed by 18.1 (and not 12.2.0.2) • SQL Developer 4.2.1 was followed by 17.3 • Read more at the updated MOS Note 742060.1 – Release Schedule of Current Database Releases Wait! 18c?! What happened to 13c?
  • 178. 195 • Improved JSON support • Private Temporary Tables (more on that later!) • Machine Learning Algorithms in the database • “Autonomous Database” 18c Developers’ Features (preview)
  • 180. 197 • Native and Interpreted Compilation • Deprecating Functions (12cR2) • Code inlining • Fine-grain Dependency management Compiling PL/SQL
  • 181. 198 Two compilation methods: • Interpreted compilation • Default compilation method • Interpreted at run time • Native compilation • Compiles into native code • Stored in the SYSTEM tablespace Native and Interpreted Compilation
  • 182. 199 • Use the interpreted mode when (typically during development): • You are using a debugging tool, such as SQL Developer • You need the code compiled quickly • Use the native mode when (typically post development): • Your code is heavily PL/SQL based • You are looking for increased performance in production Deciding on a Compilation Method Native Interpreted
  • 183. 200 • PLSQL_CODE_TYPE: Specifies the compilation mode for the PL/SQL library units • PLSQL_OPTIMIZE_LEVEL: Specifies the optimization level to be used to compile the PL/SQL library units • In general, for fastest performance, use the following setting: Setting the Compilation Method PLSQL_CODE_TYPE = { INTERPRETED | NATIVE } PLSQL_OPTIMIZE_LEVEL = { 0 | 1 | 2 | 3} PLSQL_CODE_TYPE = NATIVE PLSQL_OPTIMIZE_LEVEL = 2
  • 184. 202 • Use the USER|ALL|DBA_PLSQL_OBJECT_SETTINGS data dictionary views to display the settings for a PL/SQL object: Viewing the Compilation Settings DESCRIBE ALL_PLSQL_OBJECT_SETTINGS Name Null? Type ------------------------- -------- -------------------- OWNER NOT NULL VARCHAR2(30) NAME NOT NULL VARCHAR2(30) TYPE VARCHAR2(12) PLSQL_OPTIMIZE_LEVEL NUMBER PLSQL_CODE_TYPE VARCHAR2(4000) PLSQL_DEBUG VARCHAR2(4000) PLSQL_WARNINGS VARCHAR2(4000) NLS_LENGTH_SEMANTICS VARCHAR2(4000) PLSQL_CCFLAGS VARCHAR2(4000) PLSCOPE_SETTINGS VARCHAR2(4000)
  • 185. 203 Viewing the Compilation Settings SELECT name, plsql_code_type, plsql_optimize_level FROM user_plsql_object_settings; NAME PLSQL_CODE_TYP PLSQL_OPTIMIZE_LEVEL -------------------- -------------- -------------------- ACTIONS_T INTERPRETED 2 ACTION_T INTERPRETED 2 ACTION_V INTERPRETED 2 ADD_ORDER_ITEMS INTERPRETED 2 CATALOG_TYP INTERPRETED 2 CATALOG_TYP INTERPRETED 2 CATALOG_TYP INTERPRETED 2 CATEGORY_TYP INTERPRETED 2 CATEGORY_TYP INTERPRETED 2 COMPOSITE_CATEGORY_TYP INTERPRETED 2 ...
  • 186. 204 • This requires DBA privileges. • The PLSQL_CODE_TYPE compilation parameter must be set to NATIVE. • The benefits apply to all the built-in PL/SQL packages that are used for many database operations. Setting Up a Database for Native Compilation ALTER SYSTEM SET PLSQL_CODE_TYPE = NATIVE;
  • 187. 205 Compiling a Program Unit for Native Compilation SELECT name, plsql_code_type, plsql_optimize_level FROM user_plsql_object_settings WHERE name = 'ADD_ORDER_ITEMS'; NAME PLSQL_CODE_T PLSQL_OPTIMIZE_LEVEL ---------------------- ------------ -------------------- ADD_ORDER_ITEMS INTERPRETED 2 ALTER SESSION SET PLSQL_CODE_TYPE = 'NATIVE'; ALTER PROCEDURE add_order_items COMPILE; SELECT name, plsql_code_type, plsql_optimize_level FROM user_plsql_object_settings WHERE name = 'ADD_ORDER_ITEMS'; NAME PLSQL_CODE_T PLSQL_OPTIMIZE_LEVEL ---------------------- ------------ -------------------- ADD_ORDER_ITEMS NATIVE 2 1 2 3 4
  • 188. 206 • We can turn on checking for certain warning conditions • Warning messages can be issued during compilation of PL/SQL subprograms (not for anonymous blocks ) • Use the SQL*Plus SHOW ERRORS command or query the USER_ERRORS data dictionary view, to see any warnings generated during compilation • PL/SQL warning messages use the prefix PLW • Use PLSQL_WARNINGS initialization parameter, or the DBMS_WARNING package PL/SQL Compile-Time Warnings
  • 189. 207 • SEVERE: Messages for conditions that might cause unexpected behavior or wrong results, such as aliasing problems with parameters • PERFORMANCE: Messages for conditions that might cause performance problems, such as passing a VARCHAR2 value to a NUMBER column in an INSERT statement. • INFORMATIONAL: Messages for conditions that do not have an effect on performance or correctness, but that you might want to change to make the code more maintainable, such as unreachable code that can never be executed. • All: refer to all warning messages PL/SQL Warning Categories
  • 190. 208 • Can be set at • System level • Session level • Single compilation level PLSQL_WARNINGS Parameter ALTER SYSTEM SET PLSQL_WARNINGS='ENABLE:PERFORMANCE'; ALTER SESSION SET PLSQL_WARNINGS='DISABLE:ALL'; ALTER SESSION SET PLSQL_WARNINGS='ENABLE:SEVERE', 'DISABLE:PERFORMANCE', 'ERROR:07204'; ALTER PROCEDURE query_emp COMPILE PLSQL_WARNINGS='ENABLE:ALL';
  • 191. 209 • This warning means that the OTHERS handler of PL/SQL subroutine can exit without executing some form of RAISE or a call to the standard RAISE_APPLICATION_ERROR procedure. • Good programming practices suggest that the OTHERS handler should pass an exception upward to avoid the risk of having exceptions go unnoticed PLW-06009 Warning Message
  • 192. 210 • Mark a function as deprecated Pragma Deprecate (12.2) alter session set plsql_warnings = 'enable:(6019,6020,6021,6022)'; create or replace procedure your_old_code is pragma deprecate ( your_old_code, 'This is deprecated. Use new_code instead!' ); begin -- old code here null; end your_old_code; / show error Warning(2,3): PLW-06019: entity YOUR_OLD_CODE is deprecated
  • 193. 211 • Errors will show when compiling calling code: Pragma Deprecate (cont.) alter session set plsql_warnings = 'error:6020'; create or replace procedure calling_old_code is begin your_old_code(); end calling_old_code; / SQL> show error Errors for PROCEDURE CALLING_OLD_CODE: LINE/COL ERROR -------- --------------------------------------------------------------- 4/3 PLS-06020: reference to a deprecated entity: YOUR_OLD_CODE declared in unit YOUR_OLD_CODE[1,11]. This is deprecated. Use new_code instead!
  • 195. 213 • Definition: • Inlining is defined as the replacement of a call to subroutine with a copy of the body of the subroutine that is called. • The copied procedure generally runs faster than the original. • The PL/SQL compiler can automatically find the calls that should be inlined. • Benefits: • Inlining can provide large performance gains when applied judiciously by a factor of 2–10 times. Intra Unit Inlining
  • 196. 214 • Influence implementing inlining via two methods: • Oracle parameter PLSQL_OPTIMIZE_LEVEL • PRAGMA INLINE • Recommend that you: • Inline small programs • Inline programs that are frequently executed • Use performance tools to identify hot spots suitable for inline applications: • plstimer Use of Inlining
  • 197. 215 • Noninlined program: Inlining Concepts CREATE OR REPLACE PROCEDURE small_pgm IS a NUMBER; b NUMBER; PROCEDURE touch(x IN OUT NUMBER, y NUMBER) IS BEGIN IF y > 0 THEN x := x*x; END IF; END; BEGIN a := b; FOR I IN 1..10 LOOP touch(a, -17); a := a*b; END LOOP; END small_pgm;
  • 198. 216 • Examine the loop after inlining: Inlining Concepts ... BEGIN a := b; FOR i IN 1..10 LOOP IF –17 > 0 THEN a := a*a; END IF; a := a*b; END LOOP; END small_pgm; ...
  • 199. 217 • The loop is transformed in several steps: Inlining Concepts a := b; FOR i IN 1..10 LOOP ... IF false THEN a := a*a; END IF; a := a*b; END LOOP; a := b; FOR i IN 1..10 LOOP ... a := a*b; END LOOP; a := b; a := a*b; FOR i IN 1..10 LOOP ... END LOOP; a := b*b; FOR i IN 1..10 LOOP ... END LOOP;
  • 200. 218 • Set the PLSQL_OPTIMIZE_LEVEL session-level parameter to a value of 2 or 3: • Setting it to 2 means no automatic inlining is attempted. • Setting it to 3 means automatic inlining is attempted and no pragmas are necessary. • Within a PL/SQL subroutine, use PRAGMAINLINE • NO means no inlining occurs regardless of the level and regardless of the YES pragmas. • YES means inline at level 2 of a particular call and increase the priority of inlining at level 3 for the call. Inlining: Example ALTER PROCEDURE small_pgm COMPILE PLSQL_OPTIMIZE_LEVEL = 3 REUSE SETTINGS;
  • 201. 219 • After setting the PLSQL_OPTIMIZE_LEVEL parameter, use a pragma: Inlining: Example CREATE OR REPLACE PROCEDURE small_pgm IS a PLS_INTEGER; FUNCTION add_it(a PLS_INTEGER, b PLS_INTEGER) RETURN PLS_INTEGER IS BEGIN RETURN a + b; END; BEGIN pragma INLINE (small_pgm, 'YES'); a := add_it(3, 4) + 6; END small_pgm;
  • 202. 220 • Pragmas apply only to calls in the next statement following the pragma. • Programs that make use of smaller helper subroutines are good candidates for inlining. • Only local subroutines can be inlined. • You cannot inline an external subroutine. • Cursor functions should not be inlined. • Inlining can increase the size of a unit. • Be careful about suggesting to inline functions that are deterministic. Inlining: Guidelines
  • 204. 222 • Procedure A is a direct dependent of View B. View B is a direct dependent of Table C. Procedure A is an indirect dependent of Table C. • Direct dependents are invalidated only by changes to the referenced object that affect them. • Indirect dependents can be invalidated by changes to the reference object that do not affect them. Invalidation of Dependent Objects View B Table CProcedure A
  • 205. 223 • Before 11g, adding column D to table T invalidated the dependent objects. • Oracle Database 11g records additional, finer-grained dependency management: • Adding column D to table T does not impact view V and does not invalidate the dependent objects More Precise Dependency Metadata Procedure P Function FView V Columns: A,B Table T Columns: A,B Add column D
  • 206. 224 • In Oracle Database 11g, dependencies are now tracked at the level of element within unit. • Element-based dependency tracking covers the following: • Dependency of a single-table view on its base table • Dependency of a PL/SQL program unit (package specification, package body, or subprogram) on the following: • Other PL/SQL program units • Tables • Views Fine-Grained Dependency Management
  • 207. 225 Fine-Grained Dependency Management: Example 1 CREATE TABLE t2 (col_a NUMBER, col_b NUMBER, col_c NUMBER); CREATE VIEW v AS SELECT col_a, col_b FROM t2; ALTER TABLE t2 ADD (col_d VARCHAR2(20)); SELECT ud.name, ud.type, ud.referenced_name, ud.referenced_type, uo.status FROM user_dependencies ud, user_objects uo WHERE ud.name = uo.object_name AND ud.name = 'V'; SELECT ud.name, ud.type, ud.referenced_name, ud.referenced_type, uo.status FROM user_dependencies ud, user_objects uo WHERE ud.name = uo.object_name AND ud.name = 'V';
  • 208. 226 Fine-Grained Dependency Management: Example 1 ALTER TABLE t2 MODIFY (col_a VARCHAR2(20)); SELECT ud.name, ud.referenced_name, ud.referenced_type, uo.status FROM user_dependencies ud, user_objects uo WHERE ud.name = uo.object_name AND ud.name = 'V';
  • 209. 227 Fine-Grained Dependency Management: Example 2 CREATE PACKAGE pkg IS PROCEDURE proc_1; END pkg; / CREATE OR REPLACE PROCEDURE p IS BEGIN pkg.proc_1(); END p; / CREATE OR REPLACE PACKAGE pkg IS PROCEDURE proc_1; PROCEDURE unheard_of; END pkg; /
  • 210. 228 • To reduce invalidation of dependent objects: Guidelines for Reducing Invalidation Add new items to the end of the package Reference each table through a view
  • 211. 229 • An object that is not valid when it is referenced must be validated before it can be used. • Validation occurs automatically when an object is referenced; it does not require explicit user action. • If an object is not valid, its status is either COMPILED WITH ERRORS, UNAUTHORIZED, or INVALID. Object Revalidation
  • 213. 231 • Memory handing in PL/SQL • Global Temporary Tables (GTT) • PL/SQL result cache • Tips and Tricks Tuning PL/SQL
  • 214. 232 • Create packages that contain logically related program units • Reserve space for large allocations: • Set the SHARED_POOL_RESERVED_SIZE initialization parameter • Prevent large or frequently used objects from being aged out: • Use the DBMS_SHARED_POOL package Packages: Memory Issues ORA-04031: unable to allocate 4160 bytes of shared memory..
  • 215. 233 • Use dbms_shared_pool package: • Flags: • P – Package, Procedure or Function • T – Type • R – Trigger • Q – Sequence Pinning Objects DBMS_SHARED_POOL.KEEP(object_name, flag) DBMS_SHARED_POOL.UNKEEP(object_name, flag)
  • 216. 234 • Memory is used more efficiently for scalability (more users consume more memory) • Package global memory is kept in the SGA (instead of the UGA) and is reused for different users • Package global memory is only used within a unit of work (a client- server call or a server to different server call) • Memory can be released and reused by another user Reusing Package Memory Pragma SERIALLY_REUSABLE
  • 217. 235 SERIALLY_REUSABLE - Example CREATE OR REPLACE PACKAGE maintain_state IS pragma serially_reusable; num1 number:= 0; END maintain_state; / CREATE OR REPLACE PACKAGE regular_state IS num1 number:= 0; END regular_state; /
  • 218. 236 SERIALLY_REUSABLE - Example BEGIN dbms_output.put_line(chr(10) || 'THE MAINTAIN PACKAGE'); dbms_output.put_line('Original Value: ' || maintain_state.num1); maintain_state.num1 := maintain_state.num1 + 10; dbms_output.put_line('New Value: ' || maintain_state.num1 || chr(10)); dbms_output.put_line('THE REGULAR PACKAGE'); dbms_output.put_line('Original Value: ' || regular_state.num1); regular_state.num1 := regular_state.num1 + 10; dbms_output.put_line('New Value: ' || regular_state.num1 || chr(10)); dbms_output.put_line(chr(10)||chr(10)); dbms_output.put_line('THE MAINTAIN PACKAGE'); dbms_output.put_line('Original Value: ' || maintain_state.num1); maintain_state.num1 := maintain_state.num1 + 10; dbms_output.put_line('New Value: ' || maintain_state.num1 || chr(10)); dbms_output.put_line('THE REGULAR PACKAGE'); dbms_output.put_line('Original Value: ' || regular_state.num1); regular_state.num1 := regular_state.num1 + 10; dbms_output.put_line('New Value: ' || regular_state.num1 || chr(10)); END; /
  • 219. 237 SERIALLY_REUSABLE - Example First Run Second Run 237 THE MAINTAIN PACKAGE Original Value: 0 New Value: 10 THE REGULAR PACKAGE Original Value: 0 New Value: 10 THE MAINTAIN PACKAGE Original Value: 10 New Value: 20 THE REGULAR PACKAGE Original Value: 10 New Value: 20 THE MAINTAIN PACKAGE Original Value: 0 New Value: 10 THE REGULAR PACKAGE Original Value: 20 New Value: 30 THE MAINTAIN PACKAGE Original Value: 10 New Value: 20 THE REGULAR PACKAGE Original Value: 30 New Value: 40
  • 220. 238 • Since we’re giving up state managing, we can now avoid ORA-4068 when compiling • For more information, visit my blog: https://www.realdbamagic.com/he/solving-ora-04068/ SERIALLY_REUSABLE – Side Effect
  • 221. 239 • The flexibility built into PL/SQL enables you to pass: • Simple scalar variables • Complex data structures • You can use the NOCOPY hint to improve performance with the IN OUT parameters. Passing Data Between PL/SQL Programs
  • 222. 240 • The hint enables the PL/SQL compiler to pass OUT and IN OUT parameters by reference, as opposed to passing by value • Enhances performance by reducing overhead when passing parameters since less memory is being used • The Compiler will ignore the hint if it is not possible to reference the original structure (type conversion, constraints, for loop variable, etc.) NOCOPY Hint
  • 223. 241 NOCOPY - Example CREATE OR REPLACE PACKAGE show_emp_pkg IS TYPE EmpTabTyp IS TABLE OF emp%ROWTYPE INDEX BY BINARY_INTEGER; PROCEDURE show_emp (p_Deptno IN NUMBER, p_EmpTab OUT NOCOPY EmpTabTyp); END; /
  • 224. 242 • Can be used in functions as an optimization hint • Indicates that a function can be used in a parallelized query or parallelized DML statement Using the PARALLEL_ENABLE Hint CREATE OR REPLACE FUNCTION f2 (p_p1 NUMBER) RETURN NUMBER PARALLEL_ENABLE IS BEGIN RETURN p_p1 * 2; END f2;
  • 225. 243 • Large result sets can be stored in Table Variables or Temporary Tables • Temporary tables can be created to hold session-private data that exists only for the duration of a transaction or session. • Each session sees its own separate set of rows • DML locks are not acquired on the data • We can create indexes, views, and triggers on temporary tables • Using temporary tables instead of program variables for large • record sets, can reduce memory consumption Global Temporary Tables CREATE GLOBAL TEMPORARY TABLE hr.employees_temp ON COMMIT PRSERVE ROWS;
  • 226. 244 • Temporary objects you can create, use and then they disappear automatically • Like Global Temporary Tables, they can hold temporary data for the duration of the transaction or session • Unlike GTT – the structure itself is temporary and might be limited for the transaction or session • Each session sees only their own PTTs Private Temporary Tables (18c)
  • 228. 246 • The result cache allows SQL query and PL/SQL function results to be stored in cache memory. • Subsequent executions of the same query or function can be served directly out of the cache, improving response times. • This technique can be especially effective for SQL queries and PL/SQL functions that are executed frequently. • Cached query results become invalid when the database data accessed by the query is modified. What Is Result Caching? Data dictionary cache Library cache SGA Result cache Shared pool
  • 229. 247 • You can increase the small, default result cache memory size by using the RESULT_CACHE_MAX_SIZE initialization parameter. Increasing Result Cache Memory Size SGA Default result cache Shared pool Increased result cache
  • 230. 248 • Set Result_Cache_Max_Size from the command line or in an initialization file created by a DBA. • The cache size is dynamic and can be changed either permanently or until the instance is restarted. Setting Result_Cache_Max_Size SQL> ALTER SYSTEM SET result_cache_max_size = 2M SCOPE = MEMORY; System altered. SQL> SELECT name, value 2 FROM v$parameter 3 WHERE name = 'result_cache_max_size'; NAME VALUE ---------------------------------------- ------------------ result_cache_max_size 2097152 1 row selected.
  • 231. 249 • Use the RESULT_CACHE_MODE initialization parameter in the database initialization parameter file. • RESULT_CACHE_MODE can be set to: • MANUAL (default): You must add the RESULT_CACHE hint to your queries for the results to be cached. • FORCE: Results are always stored in the result cache memory, if possible. Enabling Query Result Cache
  • 232. 250 • Definition: • Cache the results of the current query or query fragment in memory, and then use the cached results in future executions of the query or query fragments. • Cached results reside in the result cache memory portion of the SGA. • Benefits: • Improved performance SQL Query Result Cache
  • 233. 251 • Scenario: • You need to find the greatest average value of credit limit grouped by state over the whole population. • The query returns a large number of rows being analyzed to yield a few or one row. • In your query, the data changes fairly slowly (say every hour) but the query is repeated fairly often (say every second). • Solution: • Use the new optimizer hint /*+ result_cache */ in your query: SQL Query Result Cache SELECT /*+ result_cache */ AVG(cust_credit_limit), cust_state_province FROM sh.customers GROUP BY cust_state_province;
  • 234. 252 Clearing the Shared Pool and Result Cache --- flush.sql --- Start with a clean slate. Flush the cache and shared pool. --- Verify that memory was released. SET ECHO ON SET FEEDBACK 1 SET SERVEROUTPUT ON execute dbms_result_cache.flush alter system flush shared_pool /
  • 235. 253 • Definition: • Enables data that is stored in cache to be shared across sessions • Stores the function result cache in an SGA, making it available to any session that runs your application • Benefits: • Improved performance • Improved scalability PL/SQL Function Result Cache
  • 236. 254 • Scenario: • You need a PL/SQL function that derives a complex metric. • The data that your function calculates changes slowly, but the function is frequently called. • Solution: • Use the new RESULT_CACHE clause in your function definition. • You can also have the cache purged when a dependent table experiences a DML operation, by using the RELIES_ON clause. Marking PL/SQL Function Results to Be Cached
  • 237. 255 CREATE OR REPLACE FUNCTION ORD_COUNT(cust_no number) RETURN NUMBER RESULT_CACHE RELIES_ON (orders) IS V_COUNT NUMBER; BEGIN SELECT COUNT(*) INTO V_COUNT FROM orders WHERE customer_id = cust_no; return v_count; end; • Include the RESULT_CACHE option in the function definition. • Optionally, include the RELIES_ON clause. Creating a PL/SQL Function Using the RESULT_CACHE Clause Specifies that the result should be cached Specifies the table upon which the function relies (not needed in 11.2+)
  • 238. 256 • Specify DETERMINISTIC to indicate that the function returns the same result value whenever it is called with the same values for its arguments. • This helps the optimizer avoid redundant function calls. • If a function was called previously with the same arguments, the optimizer can elect to use the previous result. • Do not specify DETERMINISTIC for a function whose result depends on the state of session variables or schema objects. Using the DETERMINISTIC Clause with Functions
  • 239. 257 Calling the PL/SQL Function Inside a Query select cust_last_name, ord_count(customer_id) no_of_orders from customers where cust_last_name = 'MacGraw'
  • 240. 258 Verifying Memory Allocation --- Establish the cache content set serveroutput on execute dbms_result_cache.memory_report
  • 241. 259 Viewing Cache Results Created col name format a55 select * from v$result_cache_statistics /
  • 242. 260 Calling the PL/SQL Function Again select cust_last_name, ord_count(customer_id) no_of_orders from customers where cust_last_name = 'MacGraw'
  • 243. 261 Viewing Cache Results Found col name format a55 select * from v$result_cache_statistics /
  • 244. 262 Confirming That the Cached Result Was Used select type, namespace,status, scan_count,name from v$result_cache_objects /
  • 245. 263 • Beware of result caching of timed actions: DBMS_LOCK.SLEEP will also be cached overriding the sleep • Cannot be used with invoker's rights or in an anonymous block • Cannot be used with pipelined table function • Cannot be used with OUT or IN OUT parameters. PL/SQL Result Cache Pitfall
  • 247. 265 You can tune your PL/SQL code by: • Identifying the data type and constraint issues • Data type conversion • The NOT NULL constraint • PLS_INTEGER • SIMPLE_INTEGER • Writing smaller executable sections of code • Comparing SQL with PL/SQL • Rephrasing conditional statements Tuning PL/SQL Code
  • 248. 266 DECLARE n NUMBER; BEGIN n := n + 15; -- converted n := n + 15.0; -- not converted ... END; • PL/SQL performs implicit conversions between structurally different data types. • Example: When assigning a PLS_INTEGER variable to a NUMBER variable Avoiding Implicit Data Type Conversion strings dates numbers
  • 249. 267 Understanding the NOT NULL Constraint PROCEDURE calc_m IS m NUMBER; --no constraint ... BEGIN m := a + b; IF m IS NULL THEN -- raise error END IF; END; PROCEDURE calc_m IS m NUMBER NOT NULL:=0; a NUMBER; b NUMBER; BEGIN m := a + b; END; The value of the expression a + b is assigned to a temporary variable, which is then tested for nullity. A better way to check nullity; no performance overhead
  • 250. 268 Use PLS_INTEGER when dealing with integer data. • It is an efficient data type for integer variables. • It requires less storage than INTEGER or NUMBER. • Its operations use machine arithmetic, which is faster than library arithmetic. Using the PLS_INTEGER Data Type for Integers
  • 251. 269 • Definition: • Is a predefined subtype • Has the range –2147483648 .. 2147483648 • Does not include a null value • Is allowed anywhere in PL/SQL where the PLS_INTEGER data type is allowed • Benefits: • Eliminates the overhead of overflow checking • Is estimated to be 2–10 times faster when compared with the PLS_INTEGER type with native PL/SQL compilation Using the SIMPLE_INTEGER Data Type
  • 252. 270 Each has its own benefits: • SQL: • Accesses data in the database • Treats data as sets • PL/SQL: • Provides procedural capabilities • Has more flexibility built into the language Comparing SQL with PL/SQL
  • 253. 271 • Some simple set processing is markedly faster than the equivalent PL/SQL. • Avoid using procedural code when it may be better to use SQL. Comparing SQL with PL/SQL ...FOR I IN 1..5600 LOOP counter := counter + 1; SELECT product_id, warehouse_id INTO v_p_id, v_wh_id FROM big_inventories WHERE v_p_id = counter; INSERT INTO inventories2 VALUES(v_p_id, v_wh_id); END LOOP;... BEGIN INSERT INTO inventories2 SELECT product_id, warehouse_id FROM main_inventories; END;
  • 254. 272 If your business logic results in one condition being true, use the ELSIF syntax for mutually exclusive clauses: Rephrasing Conditional Control Statements IF v_acct_mgr = 145 THEN process_acct_145; END IF; IF v_acct_mgr = 147 THEN process_acct_147; END IF; IF v_acct_mgr = 148 THEN process_acct_148; END IF; IF v_acct_mgr = 149 THEN process_acct_149; END IF; IF v_acct_mgr = 145 THEN process_acct_145; ELSIF v_acct_mgr = 147 THEN process_acct_147; ELSIF v_acct_mgr = 148 THEN process_acct_148; ELSIF v_acct_mgr = 149 THEN process_acct_149; END IF;
  • 255. SQL Developer Command Line (SQLcl) The Next Generation of SQL*Plus?
  • 256. 274 • Introduced in Oracle 5 (1985) • Looks very simple but has tight integration with other Oracle infrastructure and tools • Very good for reporting, scripting, and automation • Replaced old CLI tool called … UFI (“User Friendly Interface”) SQL*Plus
  • 257. 275 • Nothing really wrong with SQL*Plus – it is being updated constantly but it is missing a lot of functionality • SQL*Plus forces us to use GUI tools to complete some basic tasks • Easy to understand, a bit hard to use • Not easy for new users or developers What’s Wrong With SQL*Plus?
  • 258. 276 • SQL Developer is a free GUI tool to handle common database operations • Comes with Oracle client installation starting Oracle 11g • Good for development and management of databases • Developer mode • DBA mode • Modeling mode • Has a Command Line interface (SDCLI) – but it’s not interactive Using SQL Developer
  • 259. 277 • The SQL Developer Command Line (SQLcl, priv. SDSQL) is a new command line interface (CLI) for SQL developers, report users, and DBAs • It is part of the SQL Developer suite – developed by the same team: Oracle Database Development Tools Team • Does (or will do) most of what SQL*Plus can do, and much more • Main focus: making life easier for CLI users • Minimal installation, minimal requirements SQL Developer Command Line (SQLcl)
  • 260. 278 • Part of 12cR2 Database deployment • current version: 17.3.0.271.1943, September 29, 2017 • New version comes out every couple of months • Adding support for existing SQL*Plus commands/syntax • Adding new commands and functionality • The team is accepting bug reports and enhancement requests from the public • Active community on OTN forums! Current Status (November 2017)
  • 261. 279 • Very small footprint: 19 MB • Tool is Java based so it can run on Windows, Linux, and OS/X • Java 7/8 JRE (runtime environment - no need for JDK) • No need for installer or setup • No need for any other additional software or special license • No need for an Oracle Client Prerequisites
  • 262. 280 • Download from: SQL Developer Command Line OTN Page • Unzip the file • Run it Installing
  • 264. What Can It Do?
  • 265. 283 • When no Oracle Client - using thin connection: EZConnect connect style out of the box connect host:port/service • Support TNS, Thick and LDAP connection when Oracle home detected • Auto-complete connection strings from last connections AND tnsnames.ora Connecting to the Database
  • 266. 284 • Use the tab key to complete commands • Can be used to list tables, views or other queriable objects • Can be used to replace the * with actual column names • Use the arrow keys to move around the command • Use CTRL+W and CTRL+S to jump to the beginning/end of commands Object Completion and Easy Edit
  • 267. 285 • 100 command history buffer • Commands are persistent between sessions (watch out for security!) • Use UP and DOWN arrow keys to access old commands • Usage: history history usage History script history full History clear [session?] • Load from history into command buffer: history <number> Command History