SlideShare a Scribd company logo
Copyright © 2017, Oracle and/or its affiliates. All rights reserved. |
Your PL/SQL Office Hours session will begin
soon…
Polymorphic Table Functions!
with
Chris Saxon, @ChrisRSaxon & @SQLDaily
https://www.youtube.com/c/TheMagicofSQL
https://blogs.oracle.com/sql
Steven Feuerstein, @sfonplsql
http://www.youtube.com/c/PracticallyPerfectPLSQL
http://stevenfeuersteinonplsql.blogspot.com/
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
Polymorphic
Table Functions
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
Added in Oracle Database 18c, Polymorphic Table Functions
(PTFs) allow you do dynamically manipulate a result set at
runtime.
This means you can add or remove columns from a table,
based on input parameters
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
Why would
I want to do
this?!
Ryan McGuire / Gratisography
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
C,S,V =>
Dynamic
Customer Total Orders
Best customer 1,422
2nd best customer 1,000
All other customers 6,502
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
PTF Use Cases
CSV to Column conversion
Inspect CSV files and automatically split
the fields into columns
Dynamic Pivot
Generate pivoted column names based
on a row source
Top-N+
Like a standard Top-N query, but with an
extra row, summarizing all remaining data
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
To build a PTF, you need two things
A package
The package is the engine of the PTF. This must include a describe function. This tells
the database which columns are in the output
To assign values for each row to the new columns, you use a fetch_rows procedure
The function itself
You can create the PTF itself within the package
Or as a standalone function
Defining PTFs
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
create or replace package add_cols_pkg as
function describe (
tab in out dbms_tf.table_t,
cols dbms_tf.columns_t
) return dbms_tf.describe_t;
procedure fetch_rows ;
end add_cols_pkg;
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
Assign values
(optional)
Define new s
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
create or replace function add_columns (
tab table,
cols columns
) return
table pipelined
table polymorphic
using add_cols_pkg;
/
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
create or replace function add_columns (
tab table,
cols columns
) return
table pipelined
table polymorphic
using add_cols_pkg;
/
PTFs introduce two new "data types":
table
The input table for the PTF
Every PTF must have one of these
columns pseudo operator
A list of identifiers. These could be
existing columns in the table, or new
columns you want to add
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
create or replace function add_columns (
tab table,
cols columns
) return
table pipelined
table polymorphic
using add_cols_pkg;
/
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
In the polymorphic clause you
define it as using row or table
semantics.
With row semantics, the input is a
single row.
With table semantics, the input is a set
of rows. This allows you to sort the
input
The using clause states which package
contains the implementation of the PTF
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
describe function
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
You must have one of one of these in your package
This tells the database which columns will be in the result set
The following describe body adds columns to the output
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
begin
for i in 1 .. cols.count loop
new_cols(i) := dbms_tf.column_metadata_t (
name => cols(i),
type => dbms_tf.type_number
);
end loop;
return dbms_tf.describe_t ( new_columns => new_cols );
end;
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
This builds up an array of definitions for the new columns
dbms_tf.column_metadata_t defines their properties
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
begin
for i in 1 .. cols.count loop
new_cols(i) := dbms_tf.column_metadata_t (
name => cols(i),
type => dbms_tf.type_number
);
end loop;
return dbms_tf.describe_t ( new_columns => new_cols );
end;
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
To add the new columns to the results, you must return them
using dbms_tf.describe_t
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
select * from add_columns (
dual, columns ( c1 )
);
DUMMY C1
X <null>
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
select * from add_columns (
dual, columns ( c1, c2 )
);
DUMMY C1 C2
X <null> <null>
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
fetch_rows procedure
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
To assign values to each row for the new columns you need a
fetch_rows procedure
The following fetch_rows body sets the value of new
columns to
row# * column#
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
begin
env := dbms_tf.get_env();
for clmn in 1 .. env.ref_put_col.count loop
for rw in 1 .. env.row_count loop
col ( rw ) := rw * clmn;
end loop;
dbms_tf.put_col ( clmn, col );
end loop;
end fetch_rows;
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
dbms_tf.get_env captures the
current execution state
This includes details of all the
rows and columns processed in
this iteration of fetch_rows
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
begin
env := dbms_tf.get_env();
for clmn in 1 .. env.ref_put_col.count loop
for rw in 1 .. env.row_count loop
col ( rw ) := rw * clmn;
end loop;
dbms_tf.put_col ( clmn, col );
end loop;
end fetch_rows;
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
col is an array of row values
for a column
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
begin
env := dbms_tf.get_env();
for clmn in 1 .. env.ref_put_col.count loop
for rw in 1 .. env.row_count loop
col ( rw ) := rw * clmn;
end loop;
dbms_tf.put_col ( clmn, col );
end loop;
end fetch_rows;
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
To return the row values to the
client, you must call
dbms_tf.put_col
This assigns the array of row
values to the put column at
position CLMN
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
select * from add_columns (
tab,
columns ( c1, c2 )
);
X C1 C2
1 1 2
2 2 4
3 3 6
4 4 8
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
tab is a four-row table with the
column x
The PTF assigns incrementing
values to the columns added
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
select * from add_columns (
tab,
columns ( c1, c2 )
);
X C1 C2
1 1 2
2 2 4
3 3 6
4 4 8
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
select * from add_columns (
tab order by x desc,
columns ( c1, c2 )
);
X C1 C2
4 1 2
3 2 4
2 3 6
1 4 8
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
This PTF uses table semantics
So you can sort the input with
an order by clause after the
table name
This has a descending sort, so as
X decreases, C1 increases
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
select * from add_columns (
tab partition by y order by x desc,
columns ( c1, c2 )
);
X Y C1 C2
4 0 1 2
2 0 2 4
3 1 1 2
1 1 2 4
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
This PTF uses table semantics
So you can also split the input
into groups with an partition by
clause after the table name
The database calls the
fetch_rows procedure at least
once for each distinct value in
the partition by
Y = mod (X, 2); so odd and even
values of X have separate
counters
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
X Y C1 C2
1021 1 1021 2042
1022 0 1022 2044
1023 1 1023 2046
1024 0 1024 2048
1025 1 1 2
1026 0 2 4
1027 1 3 6
1028 0 4 8
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
PTFs process rows in batches
Empirical testing shows this as
units of 1,024 rows (whether
this is a hard limit is TBC)
After fetching this many rows,
the PTF calls fetch_rows again
So this resets the counter
If you write PTFs which have
running counters or
aggregations, you'll need to
save the execution state
You can do this with
dbms_tf.xstore procedures
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
for clmn in 1 .. env.ref_put_col.count loop
dbms_tf.xstore_get('col' || clmn, last_row);
for rw in 1 .. env.row_count loop
col ( rw ) := ( rw + last_row ) * clmn;
end loop;
dbms_tf.put_col ( clmn, col );
dbms_tf.xstore_set (
'col' || clmn, last_row + env.row_count
);
end loop;
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
The xstore holds key-
value pairs
If you get a non-
existent key, the input
value is unchanged
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
How do
I debug it?
Gratisography
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
dbms_tf.trace (
env => dbms_tf.get_env()
);
dbms_tf.trace (
msg => 'Your text here'
);
blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
The dbms_tf.trace procedure
has several overloads which
allow you to view the current
execution state
In my experience, the most
useful are:
• env; this displays the whole
execution state
• msg; which allows you to
add your own text
Like dbms_output, tracing
displays the results on screen,
not in a database table or view
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
Now it's over to you!
Where canYou can find many PTF examples on https://livesql.oracle.com
Copyright © 2019, Oracle and/or its affiliates. All rights reserved. |
asktom.oracle.com
#AskTOMOfficeHours
Ryan McGuire / Gratisography

More Related Content

PPTX
PostgreSQL Database Slides
PDF
Polymorphic Table Functions in 18c
PDF
Chasing the optimizer
PDF
Harnessing the Power of Optimizer Hints
PPTX
Oracle sql high performance tuning
PDF
Backup and recovery in oracle
PPT
10 Creating Triggers
PPTX
Explain the explain_plan
PostgreSQL Database Slides
Polymorphic Table Functions in 18c
Chasing the optimizer
Harnessing the Power of Optimizer Hints
Oracle sql high performance tuning
Backup and recovery in oracle
10 Creating Triggers
Explain the explain_plan

What's hot (20)

DOCX
Oracle architecture
PDF
All About PL/SQL Collections
PDF
SQL Macros - Game Changing Feature for SQL Developers?
PPTX
Oracle database performance tuning
PPTX
Sql Constraints
PPTX
Adapting and adopting spm v04
PPT
04 Handling Exceptions
PDF
Mysql Explain Explained
PPT
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...
PDF
Oracle Database SQL Tuning Concept
PDF
Introduction to MariaDB
PPTX
Oracle Unified Directory. Lessons learnt. Is it ready for a move from OID? (O...
PDF
Oracle Performance Tuning Fundamentals
PPTX
PL/SQL Fundamentals I
PDF
How to Analyze and Tune MySQL Queries for Better Performance
PDF
Active dataguard
PDF
Mastering PostgreSQL Administration
 
PDF
Exploring Oracle Database Performance Tuning Best Practices for DBAs and Deve...
PPT
Sql – Structured Query Language
Oracle architecture
All About PL/SQL Collections
SQL Macros - Game Changing Feature for SQL Developers?
Oracle database performance tuning
Sql Constraints
Adapting and adopting spm v04
04 Handling Exceptions
Mysql Explain Explained
03 Writing Control Structures, Writing with Compatible Data Types Using Expli...
Oracle Database SQL Tuning Concept
Introduction to MariaDB
Oracle Unified Directory. Lessons learnt. Is it ready for a move from OID? (O...
Oracle Performance Tuning Fundamentals
PL/SQL Fundamentals I
How to Analyze and Tune MySQL Queries for Better Performance
Active dataguard
Mastering PostgreSQL Administration
 
Exploring Oracle Database Performance Tuning Best Practices for DBAs and Deve...
Sql – Structured Query Language
Ad

Similar to Polymorphic Table Functions in SQL (20)

PDF
18(ish) Things You'll Love About Oracle Database 18c
PPTX
12 things about Oracle 12c
PDF
OG Yatra - upgrading to the new 12c+ optimizer
PPTX
The Five Best Things To Happen To SQL
PPT
ORACLE PL SQL
PPT
PDF
Advanced database lab oracle structure query language
PPTX
Oracle Database features every developer should know about
PPT
DDL. data defination language for creating database
PPT
Creating and Managing Tables -Oracle Data base
PDF
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
PPTX
Melbourne Groundbreakers Tour - Upgrading without risk
PPTX
Sangam 18 - The New Optimizer in Oracle 12c
PDF
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
PDF
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
PPTX
Wellington APAC Groundbreakers tour - Upgrading to the 12c Optimizer
PDF
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
TXT
Oracle 9i notes(kamal.love@gmail.com)
PPTX
429cf300-0dc7-4c2e-9280-d918d69e3cb4.pptx
PDF
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
18(ish) Things You'll Love About Oracle Database 18c
12 things about Oracle 12c
OG Yatra - upgrading to the new 12c+ optimizer
The Five Best Things To Happen To SQL
ORACLE PL SQL
Advanced database lab oracle structure query language
Oracle Database features every developer should know about
DDL. data defination language for creating database
Creating and Managing Tables -Oracle Data base
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
Melbourne Groundbreakers Tour - Upgrading without risk
Sangam 18 - The New Optimizer in Oracle 12c
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
Wellington APAC Groundbreakers tour - Upgrading to the 12c Optimizer
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
Oracle 9i notes(kamal.love@gmail.com)
429cf300-0dc7-4c2e-9280-d918d69e3cb4.pptx
Oracle 10g Database Administrator Implementation and Administration 2nd Editi...
Ad

More from Chris Saxon (7)

PDF
Game of Fraud Detection with SQL and Machine Learning
PDF
Agile Database Development with JSON
PDF
Using Edition-Based Redefinition for Zero Downtime PL/SQL Changes
PDF
Why Isn't My Query Using an Index? An Introduction to SQL Performance
PDF
12 Things Developers Will Love About Oracle Database 12c Release 2
PDF
How to Hack Your App Using SQL Injection
PDF
How to Find Patterns in Your Data with SQL
Game of Fraud Detection with SQL and Machine Learning
Agile Database Development with JSON
Using Edition-Based Redefinition for Zero Downtime PL/SQL Changes
Why Isn't My Query Using an Index? An Introduction to SQL Performance
12 Things Developers Will Love About Oracle Database 12c Release 2
How to Hack Your App Using SQL Injection
How to Find Patterns in Your Data with SQL

Recently uploaded (20)

PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Approach and Philosophy of On baking technology
PDF
Unlocking AI with Model Context Protocol (MCP)
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Review of recent advances in non-invasive hemoglobin estimation
PPTX
Spectroscopy.pptx food analysis technology
PDF
Machine learning based COVID-19 study performance prediction
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
cuic standard and advanced reporting.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Empathic Computing: Creating Shared Understanding
PDF
Network Security Unit 5.pdf for BCA BBA.
Chapter 3 Spatial Domain Image Processing.pdf
Approach and Philosophy of On baking technology
Unlocking AI with Model Context Protocol (MCP)
The AUB Centre for AI in Media Proposal.docx
Spectral efficient network and resource selection model in 5G networks
Review of recent advances in non-invasive hemoglobin estimation
Spectroscopy.pptx food analysis technology
Machine learning based COVID-19 study performance prediction
Programs and apps: productivity, graphics, security and other tools
cuic standard and advanced reporting.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Encapsulation_ Review paper, used for researhc scholars
Advanced methodologies resolving dimensionality complications for autism neur...
Per capita expenditure prediction using model stacking based on satellite ima...
sap open course for s4hana steps from ECC to s4
Diabetes mellitus diagnosis method based random forest with bat algorithm
“AI and Expert System Decision Support & Business Intelligence Systems”
Digital-Transformation-Roadmap-for-Companies.pptx
Empathic Computing: Creating Shared Understanding
Network Security Unit 5.pdf for BCA BBA.

Polymorphic Table Functions in SQL

  • 1. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | Your PL/SQL Office Hours session will begin soon… Polymorphic Table Functions! with Chris Saxon, @ChrisRSaxon & @SQLDaily https://www.youtube.com/c/TheMagicofSQL https://blogs.oracle.com/sql Steven Feuerstein, @sfonplsql http://www.youtube.com/c/PracticallyPerfectPLSQL http://stevenfeuersteinonplsql.blogspot.com/
  • 2. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | Polymorphic Table Functions blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon Added in Oracle Database 18c, Polymorphic Table Functions (PTFs) allow you do dynamically manipulate a result set at runtime. This means you can add or remove columns from a table, based on input parameters
  • 3. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | Why would I want to do this?! Ryan McGuire / Gratisography
  • 4. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | C,S,V => Dynamic Customer Total Orders Best customer 1,422 2nd best customer 1,000 All other customers 6,502 blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon PTF Use Cases CSV to Column conversion Inspect CSV files and automatically split the fields into columns Dynamic Pivot Generate pivoted column names based on a row source Top-N+ Like a standard Top-N query, but with an extra row, summarizing all remaining data
  • 5. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon To build a PTF, you need two things A package The package is the engine of the PTF. This must include a describe function. This tells the database which columns are in the output To assign values for each row to the new columns, you use a fetch_rows procedure The function itself You can create the PTF itself within the package Or as a standalone function Defining PTFs
  • 6. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | create or replace package add_cols_pkg as function describe ( tab in out dbms_tf.table_t, cols dbms_tf.columns_t ) return dbms_tf.describe_t; procedure fetch_rows ; end add_cols_pkg; blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon Assign values (optional) Define new s
  • 7. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon create or replace function add_columns ( tab table, cols columns ) return table pipelined table polymorphic using add_cols_pkg; /
  • 8. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon create or replace function add_columns ( tab table, cols columns ) return table pipelined table polymorphic using add_cols_pkg; / PTFs introduce two new "data types": table The input table for the PTF Every PTF must have one of these columns pseudo operator A list of identifiers. These could be existing columns in the table, or new columns you want to add
  • 9. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | create or replace function add_columns ( tab table, cols columns ) return table pipelined table polymorphic using add_cols_pkg; / blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon In the polymorphic clause you define it as using row or table semantics. With row semantics, the input is a single row. With table semantics, the input is a set of rows. This allows you to sort the input The using clause states which package contains the implementation of the PTF
  • 10. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | describe function blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon You must have one of one of these in your package This tells the database which columns will be in the result set The following describe body adds columns to the output
  • 11. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | begin for i in 1 .. cols.count loop new_cols(i) := dbms_tf.column_metadata_t ( name => cols(i), type => dbms_tf.type_number ); end loop; return dbms_tf.describe_t ( new_columns => new_cols ); end; blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon This builds up an array of definitions for the new columns dbms_tf.column_metadata_t defines their properties
  • 12. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | begin for i in 1 .. cols.count loop new_cols(i) := dbms_tf.column_metadata_t ( name => cols(i), type => dbms_tf.type_number ); end loop; return dbms_tf.describe_t ( new_columns => new_cols ); end; blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon To add the new columns to the results, you must return them using dbms_tf.describe_t
  • 13. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | select * from add_columns ( dual, columns ( c1 ) ); DUMMY C1 X <null> blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
  • 14. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | select * from add_columns ( dual, columns ( c1, c2 ) ); DUMMY C1 C2 X <null> <null> blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
  • 15. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | fetch_rows procedure blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon To assign values to each row for the new columns you need a fetch_rows procedure The following fetch_rows body sets the value of new columns to row# * column#
  • 16. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | begin env := dbms_tf.get_env(); for clmn in 1 .. env.ref_put_col.count loop for rw in 1 .. env.row_count loop col ( rw ) := rw * clmn; end loop; dbms_tf.put_col ( clmn, col ); end loop; end fetch_rows; blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon dbms_tf.get_env captures the current execution state This includes details of all the rows and columns processed in this iteration of fetch_rows
  • 17. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | begin env := dbms_tf.get_env(); for clmn in 1 .. env.ref_put_col.count loop for rw in 1 .. env.row_count loop col ( rw ) := rw * clmn; end loop; dbms_tf.put_col ( clmn, col ); end loop; end fetch_rows; blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon col is an array of row values for a column
  • 18. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | begin env := dbms_tf.get_env(); for clmn in 1 .. env.ref_put_col.count loop for rw in 1 .. env.row_count loop col ( rw ) := rw * clmn; end loop; dbms_tf.put_col ( clmn, col ); end loop; end fetch_rows; blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon To return the row values to the client, you must call dbms_tf.put_col This assigns the array of row values to the put column at position CLMN
  • 19. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | select * from add_columns ( tab, columns ( c1, c2 ) ); X C1 C2 1 1 2 2 2 4 3 3 6 4 4 8 blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon tab is a four-row table with the column x The PTF assigns incrementing values to the columns added
  • 20. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | select * from add_columns ( tab, columns ( c1, c2 ) ); X C1 C2 1 1 2 2 2 4 3 3 6 4 4 8 blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon
  • 21. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | select * from add_columns ( tab order by x desc, columns ( c1, c2 ) ); X C1 C2 4 1 2 3 2 4 2 3 6 1 4 8 blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon This PTF uses table semantics So you can sort the input with an order by clause after the table name This has a descending sort, so as X decreases, C1 increases
  • 22. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | select * from add_columns ( tab partition by y order by x desc, columns ( c1, c2 ) ); X Y C1 C2 4 0 1 2 2 0 2 4 3 1 1 2 1 1 2 4 blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon This PTF uses table semantics So you can also split the input into groups with an partition by clause after the table name The database calls the fetch_rows procedure at least once for each distinct value in the partition by Y = mod (X, 2); so odd and even values of X have separate counters
  • 23. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | X Y C1 C2 1021 1 1021 2042 1022 0 1022 2044 1023 1 1023 2046 1024 0 1024 2048 1025 1 1 2 1026 0 2 4 1027 1 3 6 1028 0 4 8 blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon PTFs process rows in batches Empirical testing shows this as units of 1,024 rows (whether this is a hard limit is TBC) After fetching this many rows, the PTF calls fetch_rows again So this resets the counter If you write PTFs which have running counters or aggregations, you'll need to save the execution state You can do this with dbms_tf.xstore procedures
  • 24. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | for clmn in 1 .. env.ref_put_col.count loop dbms_tf.xstore_get('col' || clmn, last_row); for rw in 1 .. env.row_count loop col ( rw ) := ( rw + last_row ) * clmn; end loop; dbms_tf.put_col ( clmn, col ); dbms_tf.xstore_set ( 'col' || clmn, last_row + env.row_count ); end loop; blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon The xstore holds key- value pairs If you get a non- existent key, the input value is unchanged
  • 25. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | How do I debug it? Gratisography
  • 26. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | dbms_tf.trace ( env => dbms_tf.get_env() ); dbms_tf.trace ( msg => 'Your text here' ); blogs.oracle.com/sql www.youtube.com/c/TheMagicOfSQL @ChrisRSaxon The dbms_tf.trace procedure has several overloads which allow you to view the current execution state In my experience, the most useful are: • env; this displays the whole execution state • msg; which allows you to add your own text Like dbms_output, tracing displays the results on screen, not in a database table or view
  • 27. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | Now it's over to you! Where canYou can find many PTF examples on https://livesql.oracle.com
  • 28. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | asktom.oracle.com #AskTOMOfficeHours Ryan McGuire / Gratisography