{"id":1556,"date":"2020-10-06T23:32:36","date_gmt":"2020-10-06T21:32:36","guid":{"rendered":"https:\/\/blog.sqlora.com\/en\/?p=1556"},"modified":"2020-10-07T08:52:52","modified_gmt":"2020-10-07T06:52:52","slug":"using-subqueries-with-ptf-or-sql-macros","status":"publish","type":"post","link":"https:\/\/blog.sqlora.com\/en\/using-subqueries-with-ptf-or-sql-macros\/","title":{"rendered":"Using Subqueries and Views with PTF or SQL macros"},"content":{"rendered":"\n<p>In the last post about <a rel=\"noreferrer noopener\" aria-label=\"SQL macros in 19c (opens in a new tab)\" href=\"https:\/\/blog.sqlora.com\/en\/sql-macros-in-oracle-19c\/\" target=\"_blank\">SQL macros in 19c<\/a> I tried to use a subquery as an input for the function. And when I had some DATE calculations in a query, I got  <code>ORA-62558: Unsupported data types (DATE)<\/code> The result looked somewhat confusing at first, but if you think about it, it is logical and maybe not a bug at all. You should just be very explicit while using subqueries and views(!) in this scenario. And because this behavior is not documented, it is worth sharing, I think.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Let&#8217;s see again what happened. Just selecting a date field <code><strong>HIREDATE<\/strong><\/code> is fine. But also using <code><strong>SYSDATE<\/strong><\/code> as a value for new (generated) column <code><strong>EXTRACTION_DT<\/strong><\/code> is not working.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; -- this works\nSQL&gt; with subq as (select empno, ename, hiredate \n  2                from empv \n  3                fetch first 5 rows only)\n  4  select * from get_csv(subq);\n \nCSV_ROW                                           \n--------------------------------------------------\n&quot;EMPNO&quot;,&quot;ENAME&quot;,&quot;HIREDATE&quot;\n7654,&quot;MARTIN&quot;,1981-09-28\n7521,&quot;WARD&quot;,1981-02-22\n7566,&quot;JONES&quot;,1981-04-02\n7369,&quot;SMITH&quot;,1980-12-17\n7499,&quot;ALLEN&quot;,1981-02-20\n \n6 rows selected. \n \nSQL&gt; \nSQL&gt; -- doesn&#039;t work\nSQL&gt; with subq as (select empno, ename, hiredate, sysdate as extraction_dt \n  2                from empv\n  3                fetch first 5 rows only)\n  4  select * from get_csv(subq);\n \nError at Command Line : 235 Column : 15\nError report -\nSQL Error: ORA-62558: Unsupported data types (DATE) for polymorphic table function\n62558. 00000 -  &quot;Unsupported data types (%s) for polymorphic table function&quot;\n*Cause:    Non-scalar data types were used in polymorphic table function.\n           Only scalar data types are supported.\n*Action:   Use only scalar data types in polymorphic table function.\nSQL&gt; \n<\/pre><\/div>\n\n\n<p>Please note that you will also have the same error using regular views which define some date calculations:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; create or replace view test_view as\n  2  select empno, ename, hiredate\n  3       , sysdate as extraction_dt \n  4  from   empv\n  5  fetch first 5 rows only;\n\nView TEST_VIEW created.\n\nSQL&gt; \nSQL&gt; select * from get_csv(test_view);\n\nError at Command Line : 450 Column : 15\nError report -\nSQL Error: ORA-62558: Unsupported data types (DATE) for polymorphic table function\n...\n<\/pre><\/div>\n\n\n<p>The reason for this is that, in Oracle,  DATE is not equal DATE. There is internal proprietary DATE format used for stored dates and an external one used for computations like <code><strong>SYSDATE, TO_DATE<\/strong><\/code>, etc. See <a rel=\"noreferrer noopener\" aria-label=\"How does Oracle store the DATE datatype internally? (Doc ID 69028.1) (opens in a new tab)\" href=\"https:\/\/support.oracle.com\/epmos\/faces\/DocumentDisplay?_afrLoop=200491536501162&amp;id=69028.1\" target=\"_blank\">How does Oracle store the DATE datatype internally? (Doc ID 69028.1)<\/a> for details. Consider the following listing. Selecting a date from EMP shows Typ=12 (7 bit), but using <code><strong>SYSDATE<\/strong><\/code>, we got Typ=13 (8 bit)<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; select dump(hiredate) dh, dump(sysdate) ds\n  2  from  scott.emp\n  3  fetch first 1 row only;\n\nDH                                  DS                                 \n----------------------------------- -----------------------------------\nTyp=12 Len=7: 119,180,12,17,1,1,1   Typ=13 Len=8: 228,7,10,6,20,29,48,0\n<\/pre><\/div>\n\n\n<p>Now, what is supported with PTF or SQL macros? Since we use <code><strong>DBMS_TF.TABLE_T<\/strong><\/code> as parameter type, we should look inside <code><strong>DBMS_TF<\/strong><\/code> package, simply because the documentation only mentions the data type DATE, without further explanation. Here, we only see the type 12<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\ncreate or replace NONEDITIONABLE PACKAGE DBMS_TF AS\n\n   \/*\n    Package: DBMS_TF\n\n     DBMS_TF is the PL\/SQL package that provides various utility API&#039;s to\n     support POLYMORPHIC TABLE functions(ptf).\n\n   *\/\n\n  \/* Type Codes for supported types *\/\n  TYPE_VARCHAR2            CONSTANT PLS_INTEGER :=   1;\n  TYPE_NUMBER              CONSTANT PLS_INTEGER :=   2;\n  TYPE_DATE                CONSTANT PLS_INTEGER :=  12;\n  TYPE_RAW                 CONSTANT PLS_INTEGER :=  23;\n  TYPE_ROWID               CONSTANT PLS_INTEGER :=  69;\n  TYPE_CHAR                CONSTANT PLS_INTEGER :=  96;\n  TYPE_BINARY_FLOAT        CONSTANT PLS_INTEGER := 100;\n  TYPE_BINARY_DOUBLE       CONSTANT PLS_INTEGER := 101;\n  TYPE_CLOB                CONSTANT PLS_INTEGER := 112;\n  TYPE_BLOB                CONSTANT PLS_INTEGER := 113;\n  TYPE_TIMESTAMP           CONSTANT PLS_INTEGER := 180;\n  TYPE_TIMESTAMP_TZ        CONSTANT PLS_INTEGER := 181;\n  TYPE_INTERVAL_YM         CONSTANT PLS_INTEGER := 182;\n  TYPE_INTERVAL_DS         CONSTANT PLS_INTEGER := 183;\n\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Workaround<\/h2>\n\n\n\n<p>Is there a simple workaround? Just <code><strong>CAST SYSDATE<\/strong><\/code> explicitly as <code><strong>DATE<\/strong><\/code> and the output will be internal DATE (Typ=12)! <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; select dump(sysdate) ds, dump(cast (sysdate as date)) dcs\n  2  from  scott.emp\n  3  fetch first 1 row only;\n\nDS                                  DCS                                \n----------------------------------- -----------------------------------\nTyp=13 Len=8: 228,7,10,6,20,33,29,0 Typ=12 Len=7: 120,120,10,6,21,34,30\n<\/pre><\/div>\n\n\n<p>Now we can test our subquery again and it is just working fine:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; -- works after casting to date\nSQL&gt; with subq as (select empno, ename, hiredate\n  2                     , cast(sysdate as date) as extraction_dt \n  3                from empv\n  4                fetch first 5 rows only)\n  5  select * from get_csv(subq);\n\nCSV_ROW                                                                                      \n----------------------------------------------------------\n&quot;EMPNO&quot;,&quot;ENAME&quot;,&quot;HIREDATE&quot;,&quot;EXTRACTION_DT&quot;\n7654,&quot;MARTIN&quot;,1981-09-28,2020-10-06\n7521,&quot;WARD&quot;,1981-02-22,2020-10-06\n7566,&quot;JONES&quot;,1981-04-02,2020-10-06\n7369,&quot;SMITH&quot;,1980-12-17,2020-10-06\n7499,&quot;ALLEN&quot;,1981-02-20,2020-10-06\n\n6 rows selected. \n<\/pre><\/div>\n\n\n<p>Why had I mentioned polymorphic table functions in the title? Well, using subqueries with PTF works just the same way using <code><strong>DBMS_TF.TABLE_T<\/strong><\/code> and thus, we can expect the same behavior. Just a quick test with a PTF <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/18\/arpls\/DBMS_TF.html#GUID-47E8026F-B66B-4F8D-A2E2-D4324AAB2CED\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"NOOP from Oracle documentation (opens in a new tab)\">NOOP from Oracle documentation<\/a>, which actually does nothing:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nSQL&gt; with subq as (select empno, ename, hiredate\n  2                     , sysdate as extraction_dt \n  3                from scott.emp\n  4                fetch first 5 rows only)\n  5  select * from noop(subq);\n\nError at Command Line : 433 Column : 15\nError report -\nSQL Error: ORA-62558: Unsupported data types (DATE) for polymorphic table function\n62558. 00000 -  &quot;Unsupported data types (%s) for polymorphic table function&quot;\n*Cause:    Non-scalar data types were used in polymorphic table function.\n           Only scalar data types are supported.\n*Action:   Use only scalar data types in polymorphic table function.\nSQL&gt; \nSQL&gt; \nSQL&gt; -- works after casting to date\nSQL&gt; with subq as (select empno, ename, hiredate\n  2                     , cast(sysdate as date) as extraction_dt \n  3                from scott.emp\n  4                fetch first 5 rows only)\n  5  select * from noop(subq);\n\n     EMPNO ENAME      HIREDATE            EXTRACTION_DT      \n---------- ---------- ------------------- -------------------\n      7369 SMITH      17.12.1980 00:00:00 06.10.2020 21:17:00\n      7499 ALLEN      20.02.1981 00:00:00 06.10.2020 21:17:00\n      7521 WARD       22.02.1981 00:00:00 06.10.2020 21:17:00\n      7566 JONES      02.04.1981 00:00:00 06.10.2020 21:17:00\n      7654 MARTIN     28.09.1981 00:00:00 06.10.2020 21:17:00\n<\/pre><\/div>\n\n\n<p>There is the same problem with other data types like TIMESTAMP or INTERVAL too. So be careful when using subqueries and also regular views in this scenario. Now you know what the error messages really mean.<\/p>\n\n\n<script async src=\"\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js?client=ca-pub-2925154690547867\" crossorigin=\"anonymous\"><\/script><ins class=\"adsbygoogle\" style=\"display:block; text-align:center;\" data-ad-client=\"ca-pub-2925154690547867\" \ndata-ad-slot=\"2727403138\" \ndata-ad-layout=\"in-article\"\ndata-ad-format=\"fluid\"><\/ins>\n<script> \n(adsbygoogle = window.adsbygoogle || []).push({}); \n<\/script>\n\n\n<div class=\"crp-list-container\"><h3 class=\"crp-list-title\">Related Posts<\/h3><ul class=\"crp-list\"><li class=\"crp-list-item crp-list-item-image-none\"><div class=\"crp-list-item-title\"><a href=\"https:\/\/blog.sqlora.com\/en\/polymorphic-table-functions-ptf-part-4-table-semantic-ptf\/\" target=\"_blank\">Polymorphic Table Functions (PTF), Part 4 &#8211; Table Semantic PTF<\/a><\/div><\/li><li class=\"crp-list-item crp-list-item-image-none\"><div class=\"crp-list-item-title\"><a href=\"https:\/\/blog.sqlora.com\/en\/sql-macros-in-oracle-19c\/\" target=\"_blank\">SQL macros in Oracle 19c<\/a><\/div><\/li><\/ul><\/div>","protected":false},"excerpt":{"rendered":"<p>When using a subquery or a view  as input for PTF or SQL macro, be careful with data types or you get ORA-62558<\/p>\n","protected":false},"author":1,"featured_media":1566,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[99,1,2,3,100],"tags":[110,103,13],"class_list":["post-1556","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-20c","category-general","category-oracle","category-sql","category-sql-macros","tag-ora-62558","tag-sql-macros","tag-subquery"],"_links":{"self":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts\/1556","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/comments?post=1556"}],"version-history":[{"count":14,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts\/1556\/revisions"}],"predecessor-version":[{"id":1574,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts\/1556\/revisions\/1574"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/media\/1566"}],"wp:attachment":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/media?parent=1556"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/categories?post=1556"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/tags?post=1556"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}