Successfully reported this slideshow.
Your SlideShare is downloading. ×

Polymorphic Table Functions in SQL

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Postgresql
Postgresql
Loading in …3
×

Check these out next

1 of 28 Ad

Polymorphic Table Functions in SQL

Download to read offline

Added in Oracle Database 18c, Polymorphic Table Functions (PTFs) allow you to change the shape of a result set at runtime. So you can add or remove columns from your results based on input parameters.

This presentation gives an overview of the why & how of PTFs.

Added in Oracle Database 18c, Polymorphic Table Functions (PTFs) allow you to change the shape of a result set at runtime. So you can add or remove columns from your results based on input parameters.

This presentation gives an overview of the why & how of PTFs.

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Similar to Polymorphic Table Functions in SQL (20)

Advertisement

Recently uploaded (20)

Advertisement

Polymorphic Table Functions in SQL

  1. 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. 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. 3. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | Why would I want to do this?! Ryan McGuire / Gratisography
  4. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 25. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | How do I debug it? Gratisography
  26. 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. 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. 28. Copyright © 2019, Oracle and/or its affiliates. All rights reserved. | asktom.oracle.com #AskTOMOfficeHours Ryan McGuire / Gratisography

×