{
  "date": "2014-12-15T13:50:00",
  "slug": "oracle-lateral-inline-view-cursor-expression-and-12c-implicit-statement-result",
  "link": "https://www.dbi-services.com/blog/oracle-lateral-inline-view-cursor-expression-and-12c-implicit-statement-result/",
  "title": {
    "rendered": "Oracle lateral inline view, cursor expression and 12c implicit statement result"
  },
  "content": {
    "rendered": "<h2>By Franck Pachot</h2>\n<p>.<br />\nI&#8217;ll present here 3 ways to run a query for each result of another query. Let&#8217;s take an exemple: get all executions plan (select from dbms_xplan.display_cursor) for each of my queries (identified from v$sql). The 90&#8217;s way was to run the first query, which generates the second queries into a spool file, and execute that file. Here are easier ways, some of them coming from 12c new features lateral join and implicit statement result.</p>\n<h3>Test case</h3>\n<p>I&#8217;m running 2 queries and will identify them from their module (APPINFO from sqlplus) and user:</p>\n<pre><code>SQL&gt; connect scott/tiger\nConnected.\n\nSQL&gt; set appinfo DEMO\n\nSQL&gt; select * from DEPT;\nSQL&gt; select * from EMP;\n</code></pre>\n<p>I don&#8217;t show the result &#8211; you know it &#8211; but here is how I identify the queries:</p>\n<pre><code>SQL&gt; select sql_id,child_number,sql_text from v$sql where plan_hash_value&gt;0 and module='DEMO' and parsing_schema_name='SCOTT';\n\nSQL_ID        CHILD_NUMBER SQL_TEXT\n------------- ------------ ------------------------------\n5aht0fch310ca            0 select * from EMP\n18wrqtcj3ksap            0 select * from DEPT\n</code></pre>\n<p>And I want to run dbms_xplan.display_cursor(sql_id,child_number) for each of them. Here are 3 ways to do it</p>\n<h3>Cursor expression</h3>\n<p>Do you know cursor expressions? In your SELECT expressions, you can have a query. Your client will retrieve it as a cursor and have to run it. sqlplus and sqldeveloper does that. Here is an example:</p>\n<pre><code>SQL&gt; select\n  cursor (select * from table(dbms_xplan.display_cursor(sql_id,child_number,format=&gt;'TYPICAL'))) PLAN\n  from\n  (select * from v$sql where plan_hash_value&gt;0 and module='DEMO' and parsing_schema_name='SCOTT')\n /\n\n</code></pre>\n<p>which gives the following result:</p>\n<pre><code>PLAN\n--------------------\nCURSOR STATEMENT : 1\n\nPLAN_TABLE_OUTPUT\n------------------------------------------------------------------------------------------\nSQL_ID  5aht0fch310ca, child number 0\n-------------------------------------\nselect * from EMP\n\nPlan hash value: 3956160932\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\n13 rows selected.\n\nCURSOR STATEMENT : 1\n\nPLAN_TABLE_OUTPUT\n------------------------------------------------------------------------------------------\nSQL_ID  18wrqtcj3ksap, child number 0\n-------------------------------------\nselect * from DEPT\n\nPlan hash value: 3383998547\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| DEPT |     4 |    80 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\n13 rows selected.\n\n</code></pre>\n<p>This is possible on all versions, and the output can change depending on the tool you use. sqlplus handles it as above, running each cursor.</p>\n<h3>implicit statement result</h3>\n<p>You want to do it from pl/sql? That&#8217;s possible. But you have to format the output yourself with dbms_output.</p>\n<p>Except if you are in 12c and use the &#8216;implicit statement result&#8217; new feature:</p>\n<pre><code>SQL&gt; declare\n  r sys_refcursor;\n begin\n  for c in\n  (select * from v$sql where plan_hash_value&gt;0 and module='DEMO' and parsing_schema_name='SCOTT')\n  loop\n   open r for select * from table(dbms_xplan.display_cursor(c.sql_id,c.child_number));\n   dbms_sql.return_result(r);\n  end loop;\n end;\n /\nPL/SQL procedure successfully completed.\n</code></pre>\n<p>which gives the following result:</p>\n<pre><code>ResultSet #1\n\nPLAN_TABLE_OUTPUT\n------------------------------------------------------------------------------------------\nSQL_ID  5aht0fch310ca, child number 0\n-------------------------------------\nselect * from EMP\n\nPlan hash value: 3956160932\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\n13 rows selected.\n\nResultSet #2\n\nPLAN_TABLE_OUTPUT\n------------------------------------------------------------------------------------------\nSQL_ID  18wrqtcj3ksap, child number 0\n-------------------------------------\nselect * from DEPT\n\nPlan hash value: 3383998547\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| DEPT |     4 |    80 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\n13 rows selected.\n\n</code></pre>\n<p>This is similar to the previous approach in the way that the client has to manage the result.</p>\n<h3>Lateral inline view</h3>\n<p>This is my preferred way which is only SQL and do not depend on the client formatting. A lateral inline view is a subquery that you put in the FROM clause, using the LATERAL keyword, and which can use data from the other tables on the left of it in the FROM clause:</p>\n<pre><code>SQL&gt; select plan_table_output from\n  (select * from v$sql where plan_hash_value&gt;0 and module='DEMO' and parsing_schema_name='SCOTT'),\n  lateral (select * from table(dbms_xplan.display_cursor(sql_id,child_number)))\n ;\n</code></pre>\n<p>which gives the following result:</p>\n<pre><code>PLAN_TABLE_OUTPUT\n------------------------------------------------------------------------------------------\nSQL_ID  5aht0fch310ca, child number 0\n-------------------------------------\nselect * from EMP\n\nPlan hash value: 3956160932\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\nSQL_ID  18wrqtcj3ksap, child number 0\n-------------------------------------\nselect * from DEPT\n\nPlan hash value: 3383998547\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| DEPT |     4 |    80 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\n</code></pre>\n<p>This is a 12c new feature. It existed on previous versions but not enabled by default and not documented, but you can set it with the following event:</p>\n<pre><code>SQL&gt; host oerr ora 22829\n\nSQL&gt; alter session set events '22829 trace name context forever';\n</code></pre>\n<p>12c came with a lot of nice improvement in SQL and PL/SQL and they are available in all editions.</p>\n<h3>Update</h3>\n<p>What is very cool about twitter is that sometimes I have to update my blog post as soon as it is published. In that case it seems that I ignored the simplest way to do that since 9i:</p>\n<blockquote lang=\"en\"><p><a href=\"https://twitter.com/FranckPachot\">@FranckPachot</a> Why not just &#8220;from v$sql, table(dbms_xplan.display_cursor(&#8230;))&#8221;? Left correlation is official and it works since 9i</p>\n<p>— Vladimir Sitnikov (@VladimirSitnikv) <a href=\"https://twitter.com/VladimirSitnikv/status/544177719458934784\">December 14, 2014</a></p></blockquote>\n<p>So here it is:</p>\n<pre><code>SQL&gt; select plan_table_output from\n  2   v$sql,\n  3   table(dbms_xplan.display_cursor(sql_id,child_number))\n  4  where plan_hash_value&gt;0 and module='DEMO' and parsing_schema_name='SCOTT'\n  5  ;\n\nPLAN_TABLE_OUTPUT\n------------------------------------------------------------------------------------------\nSQL_ID  5aht0fch310ca, child number 0\n-------------------------------------\nselect * from EMP\n\nPlan hash value: 3956160932\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| EMP  |    14 |   532 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\nSQL_ID  18wrqtcj3ksap, child number 0\n-------------------------------------\nselect * from DEPT\n\nPlan hash value: 3383998547\n\n--------------------------------------------------------------------------\n| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |\n--------------------------------------------------------------------------\n|   0 | SELECT STATEMENT  |      |       |       |     3 (100)|          |\n|   1 |  TABLE ACCESS FULL| DEPT |     4 |    80 |     3   (0)| 00:00:01 |\n--------------------------------------------------------------------------\n\n\n26 rows selected.\n\n</code></pre>\n<p>That does not invalidate this blog post because I wanted to show those 3 features. It&#8217;s just my example which was badly chosen because dbms_xplan returns a table expression and left correlation can be used for it.</p>\n<p>Thanks to Vladimir Sitnikov, I learned a 9i feature while blogging about 12c new feature 🙂</p>\n",
    "protected": false
  }
}
