Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Rajeshwaran.

Asked: September 01, 2015 - 11:59 pm UTC

Last updated: September 18, 2015 - 3:32 am UTC

Version: 11.2.0.4

Viewed 1000+ times

You Asked

Tom,

I was reading about in-memory parallel execution here
https://docs.oracle.com/cd/E11882_01/server.112/e25523/parallel002.htm#BEICFFGB

but i am not able to suceed with a sample test script to demonstrate this feature.
can you help me with a test script to show how this works? Thanks.

looked around the web, but no luck.
http://www.rittmanmead.com/2010/01/in-memory-parallel-execution-in-oracle-database-11gr2/
https://blogs.oracle.com/datawarehousing/entry/in-memory_parallel_execution_i
http://www.databaseskill.com/954958/

and Connor said...


Some internal notes on this feature are as below:


In-Memory Parallel Execution (In-Memory PX) introduced in Oracle Database 11g Release 2,takes advantage of this large database buffer cache and ensures that cache content are not trshed.

With In-Memory PX, when a SQL statement is issued in parallel, a check is conducted to determine if the objects accessed by the statement should be cached in the aggregated buffer cache of the system; an object can either be a table, an index, or in the case of partitioned objects one or multiple partitions.

The decision to use the aggregated buffer cache is based on an advanced set of heuristics that include; the size of an object, the frequency at which the object changes and is accessed, and the size of the aggregated buffer cache.

[snip]

To leverage In-Memory PX initialization parameter PARALLEL_DEGREE_POLICY must be set to AUTO (default MANUAL). Once this is set, the database controls which objects are eligible to be read into the buffer cache and which object will reside there at any point in time. It is not possible to manual control the behavior for specific statements.


Having said that, we can attempt to see if we can influence the database as best we can with its decision.

So I've done this (on my laptop)

*.db_keep_cache_size=2500m
*.parallel_degree_policy=AUTO

And then loaded up a table into the KEEP pool to "convince" the database that the table will always be in the buffer cache for use.

Then I'll load a table, make it "reasonably" sized to fill most of my KEEP pool, and then tell the optimizer is huge so it kicks in parallel query

SQL> drop table T purge;

Table dropped.

SQL> create table T as select * from dba_objects where 1=0;

Table created.

SQL> alter table T storage ( buffer_pool keep );

Table altered.

SQL> insert /*+ APPEND */ into T select * from dba_objects;

92125 rows created.

SQL> commit;

Commit complete.

SQL> insert /*+ APPEND */ into T select * from T;

92125 rows created.

SQL> commit;

Commit complete.

SQL> insert /*+ APPEND */ into T select * from T;

184250 rows created.

SQL> commit;

Commit complete.

SQL> insert /*+ APPEND */ into T select * from T;

368500 rows created.

SQL> commit;

Commit complete.

SQL> insert /*+ APPEND */ into T select * from T;

737000 rows created.

SQL> commit;

SQL> insert /*+ APPEND */ into T select * from T;

1474000 rows created.

SQL> commit;

Commit complete.

SQL> insert /*+ APPEND */ into T select * from T;

2948000 rows created.

SQL> commit;

Commit complete.

SQL> exec dbms_stats.gather_table_Stats('','T');

PL/SQL procedure successfully completed.

SQL> select blocks from user_tables where table_name = 'T';

    BLOCKS
----------
     99472

1 row selected.

SQL> begin
  2    dbms_stats.set_table_stats(
  3      ownname=>'',
  4      tabname=>'t',
  5      numrows=>100000000,
  6      numblks=>3932160,
  7      no_invalidate=>false,
  8      force=>true);
  9  end;
 10  /

PL/SQL procedure successfully completed.

SQL> alter table T parallel;

Table altered.

SQL> set autotrace traceonly explain
SQL> select owner, max(object_name)
  2  from T
  3  group by owner;


------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |          |    33 |  1023 |   148K  (1)| 00:00:06 |        |      |            |
|   1 |  PX COORDINATOR          |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)    | :TQ10001 |    33 |  1023 |   148K  (1)| 00:00:06 |  Q1,01 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY         |          |    33 |  1023 |   148K  (1)| 00:00:06 |  Q1,01 | PCWP |            |
|   4 |     PX RECEIVE           |          |    33 |  1023 |   148K  (1)| 00:00:06 |  Q1,01 | PCWP |            |
|   5 |      PX SEND HASH        | :TQ10000 |    33 |  1023 |   148K  (1)| 00:00:06 |  Q1,00 | P->P | HASH       |
|   6 |       HASH GROUP BY      |          |    33 |  1023 |   148K  (1)| 00:00:06 |  Q1,00 | PCWP |            |
|   7 |        PX BLOCK ITERATOR |          |   100M|  2956M|   147K  (1)| 00:00:06 |  Q1,00 | PCWC |            |
|   8 |         TABLE ACCESS FULL| T        |   100M|  2956M|   147K  (1)| 00:00:06 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------------------

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 8 because of degree limit

19 rows selected.


Now with a fresh session, we'll do a parallel query and see if any direct reads were done.

SQL> connect asktom/asktom
Connected.

SQL> set autotrace off
SQL> select owner, max(object_name)
  2  from T
  3  group by owner;

[snip]

SQL> @mystat
Enter value for statname: direct

NAME                                                    VALUE
-------------------------------------------------- ----------
db block gets direct                                        0
consistent gets direct                                      0
physical reads direct                                       0
physical writes direct                                      0
physical reads direct temporary tablespace                  0
physical writes direct temporary tablespace                 0
physical reads direct (lob)                                 0
physical writes direct (lob)                                0
[snip]

19 rows selected.

SQL>


Similarly, a look at consistent gets shows a marked jump

SQL> @mystat
Enter value for statname: consistent

NAME                                                    VALUE
-------------------------------------------------- ----------
consistent gets                                        101178
consistent gets from cache                             101178
consistent gets pin                                    101135
consistent gets pin (fastpath)                         101135



Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Keep pool mandatory ?

Rajeshwaran Jeyabal, September 05, 2015 - 11:48 am UTC

I am on 11.2.0.4 with automated memory management set to 452M

Questions,

#1 Is it mandatory to have the segments on KEEP pool to have this in-memory parallel execution to kick in? I was able to achieve the same by without KEEP pool.

#2 - After the query execution, I don't see any Physical IO (from v$sesstat) - so that confirms the In-memory parallel execution in-place. if that is correct, why does the autotrace statistics reports physical reads as "7587" ? autotrace shows physical IO but v$sesstat report no physical IO? why so. please clarify.

rajesh@ORA11G>
rajesh@ORA11G> show parameter pga

NAME                                          TYPE        VALUE
--------------------------------------------- ----------- ----------
pga_aggregate_target                          big integer 0
rajesh@ORA11G> show parameter memory

NAME                                          TYPE        VALUE
--------------------------------------------- ----------- ----------
hi_shared_memory_address                      integer     0
memory_max_target                             big integer 452M
memory_target                                 big integer 452M
shared_memory_address                         integer     0
rajesh@ORA11G>

drop table t purge;

create table t 
parallel as
select *
from big_table
where rownum <=500000;

begin
 dbms_stats.set_table_stats
 (ownname=>user, 
  tabname=>'T',
  numblks=>100000000,
  numrows=>100000000) ;
end;
/

rajesh@ORA11G> conn rajesh/oracle@ora11g
Connected.
rajesh@ORA11G> set timing off
rajesh@ORA11G> alter session set parallel_degree_policy=auto;

Session altered.

rajesh@ORA11G> @mystat direct

NAME                                                    VALUE
-------------------------------------------------- ----------
db block gets direct                                        0
securefile direct write ops                                 0
physical reads direct                                       0
physical writes direct                                      0
physical reads direct temporary tablespace                  0
physical writes direct temporary tablespace                 0
physical reads direct (lob)                                 0
physical writes direct (lob)                                0
flashback direct read optimizations for block new           0
redo size for direct writes                                 0
cell physical IO bytes sent directly to DB node to          0
 balance CPU

table scans (direct read)                                   0
index fast full scans (direct read)                         0
securefile direct read bytes                                0
securefile direct write bytes                               0
securefile direct read ops                                  0
consistent gets direct                                      0

17 rows selected.

rajesh@ORA11G> @mystat consistent

NAME                                                    VALUE
-------------------------------------------------- ----------
consistent gets from cache                                 66
consistent gets                                            66
consistent gets from cache (fastpath)                      43
no work - consistent read gets                             36
consistent gets - examination                              22
cleanouts only - consistent read gets                       0
rollbacks only - consistent read gets                       0
data blocks consistent reads - undo records applie          0
d

transaction tables consistent read rollbacks                0
cleanouts and rollbacks - consistent read gets              0
consistent changes                                          0
consistent gets direct                                      0
transaction tables consistent reads - undo records          0
 applied


13 rows selected.

rajesh@ORA11G> set autotrace traceonly explain statistics
rajesh@ORA11G> select owner,count(*) from t
  2  group by owner ;

31 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 129087698

------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |          |   100M|  1621M|  3762K  (1)| 00:11:57 |        |      |            |
|   1 |  PX COORDINATOR          |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)    | :TQ10001 |   100M|  1621M|  3762K  (1)| 00:11:57 |  Q1,01 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY         |          |   100M|  1621M|  3762K  (1)| 00:11:57 |  Q1,01 | PCWP |            |
|   4 |     PX RECEIVE           |          |   100M|  1621M|  3762K  (1)| 00:11:57 |  Q1,01 | PCWP |            |
|   5 |      PX SEND HASH        | :TQ10000 |   100M|  1621M|  3762K  (1)| 00:11:57 |  Q1,00 | P->P | HASH       |
|   6 |       HASH GROUP BY      |          |   100M|  1621M|  3762K  (1)| 00:11:57 |  Q1,00 | PCWP |            |
|   7 |        PX BLOCK ITERATOR |          |   100M|  1621M|  3761K  (1)| 00:11:57 |  Q1,00 | PCWC |            |
|   8 |         TABLE ACCESS FULL| T        |   100M|  1621M|  3761K  (1)| 00:11:57 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------------------

Note
-----
   - automatic DOP: Computed Degree of Parallelism is 8 because of degree limit


Statistics
----------------------------------------------------------
         54  recursive calls
          0  db block gets
       9667  consistent gets
       7587  physical reads
          0  redo size
       1125  bytes sent via SQL*Net to client
        500  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         31  rows processed

rajesh@ORA11G> set autotrace off
rajesh@ORA11G>
rajesh@ORA11G> @mystat direct

NAME                                                    VALUE
-------------------------------------------------- ----------
db block gets direct                                        0
securefile direct write ops                                 0
physical reads direct                                       0
physical writes direct                                      0
physical reads direct temporary tablespace                  0
physical writes direct temporary tablespace                 0
physical reads direct (lob)                                 0
physical writes direct (lob)                                0
flashback direct read optimizations for block new           0
redo size for direct writes                                 0
cell physical IO bytes sent directly to DB node to          0
 balance CPU

table scans (direct read)                                   0
index fast full scans (direct read)                         0
securefile direct read bytes                                0
securefile direct write bytes                               0
securefile direct read ops                                  0
consistent gets direct                                      0

17 rows selected.

rajesh@ORA11G> @mystat consistent

NAME                                                    VALUE
-------------------------------------------------- ----------
consistent gets                                          9796
consistent gets from cache                               9796
consistent gets from cache (fastpath)                    9439
no work - consistent read gets                           7640
consistent changes                                         41
consistent gets - examination                              29
rollbacks only - consistent read gets                       0
cleanouts only - consistent read gets                       0
data blocks consistent reads - undo records applie          0
d

transaction tables consistent read rollbacks                0
cleanouts and rollbacks - consistent read gets              0
consistent gets direct                                      0
transaction tables consistent reads - undo records          0
 applied


13 rows selected.

rajesh@ORA11G>

Any addtional details required?

Rajeshwaran, Jeyabal, September 10, 2015 - 10:44 am UTC

Any additional details required, to answer the above followup?
Connor McDonald
September 14, 2015 - 3:11 am UTC

The KEEP pool is not mandatory - I included it to gain some more control over what was in memory to ensure the inmem para query (IMPQ) was invoked.

Here's another example (on a 200 meg buffer cache). You'll see that IMPQ is invoked for the second pair of executions, once we adjust parallel_degree_policy

SQL> drop table t purge;

Table dropped.

Elapsed: 00:00:00.08
SQL> create table t(a number, b varchar2(100)) pctfree 99 pctused 1;

Table created.

Elapsed: 00:00:00.02
SQL> insert into t  values (1,lpad('x',100));

1 row created.

Elapsed: 00:00:00.01
SQL> commit;

Commit complete.

Elapsed: 00:00:00.00
SQL> alter table t minimize records_per_block;

Table altered.

Elapsed: 00:00:00.01
SQL> insert into t select rownum,lpad('x',100) from dual connect by level<10000;

9999 rows created.

Elapsed: 00:00:01.22
SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
SQL> exec dbms_stats.gather_table_stats(user,'T');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.27
SQL> 
SQL> select sum(bytes)/1024/1024 sizemb from user_segments where segment_name='T';

    SIZEMB                                                                                                                                                                                              
----------                                                                                                                                                                                              
84.4453125                                                                                                                                                                                              

Elapsed: 00:00:00.02
SQL> select value/1024/1024 buffer_cache from v$sga where name='Database Buffers';

BUFFER_CACHE                                                                                                                                                                                            
------------                                                                                                                                                                                            
         200                                                                                                                                                                                            

Elapsed: 00:00:00.00
SQL> alter system flush buffer_cache;

System altered.

Elapsed: 00:00:01.57
SQL> 
SQL> alter session set parallel_degree_policy=manual;

Session altered.

Elapsed: 00:00:00.00
SQL> set autot trace
SQL> select /*+ parallel(2) */ count(*) from t;

Elapsed: 00:00:00.10

Execution Plan
----------------------------------------------------------                                                                                                                                              
Plan hash value: 3126468333                                                                                                                                                                             
                                                                                                                                                                                                        
--------------------------------------------------------------------------------------------------------                                                                                                
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
|   0 | SELECT STATEMENT       |          |     1 |  1507   (1)| 00:00:01 |        |      |            |                                                                                                
|   1 |  SORT AGGREGATE        |          |     1 |            |          |        |      |            |                                                                                                
|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |                                                                                                
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |                                                                                                
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |                                                                                                
|   5 |      PX BLOCK ITERATOR |          | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWC |            |                                                                                                
|   6 |       TABLE ACCESS FULL| T        | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWP |            |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - Degree of Parallelism is 2 because of hint                                                                                                                                                         


Statistics
----------------------------------------------------------                                                                                                                                              
          7  recursive calls                                                                                                                                                                            
          0  db block gets                                                                                                                                                                              
      10062  consistent gets                                                                                                                                                                            
      10004  physical reads                                                                                                                                                                             
          0  redo size                                                                                                                                                                                  
        542  bytes sent via SQL*Net to client                                                                                                                                                           
        552  bytes received via SQL*Net from client                                                                                                                                                     
          2  SQL*Net roundtrips to/from client                                                                                                                                                          
          0  sorts (memory)                                                                                                                                                                             
          0  sorts (disk)                                                                                                                                                                               
          1  rows processed                                                                                                                                                                             

SQL> select /*+ parallel(2) */ count(*) from t;

Elapsed: 00:00:00.11

Execution Plan
----------------------------------------------------------                                                                                                                                              
Plan hash value: 3126468333                                                                                                                                                                             
                                                                                                                                                                                                        
--------------------------------------------------------------------------------------------------------                                                                                                
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
|   0 | SELECT STATEMENT       |          |     1 |  1507   (1)| 00:00:01 |        |      |            |                                                                                                
|   1 |  SORT AGGREGATE        |          |     1 |            |          |        |      |            |                                                                                                
|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |                                                                                                
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |                                                                                                
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |                                                                                                
|   5 |      PX BLOCK ITERATOR |          | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWC |            |                                                                                                
|   6 |       TABLE ACCESS FULL| T        | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWP |            |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - Degree of Parallelism is 2 because of hint                                                                                                                                                         


Statistics
----------------------------------------------------------                                                                                                                                              
          6  recursive calls                                                                                                                                                                            
          0  db block gets                                                                                                                                                                              
      10062  consistent gets                                                                                                                                                                            
      10003  physical reads                                                                                                                                                                             
       8220  redo size                                                                                                                                                                                  
        542  bytes sent via SQL*Net to client                                                                                                                                                           
        552  bytes received via SQL*Net from client                                                                                                                                                     
          2  SQL*Net roundtrips to/from client                                                                                                                                                          
          0  sorts (memory)                                                                                                                                                                             
          0  sorts (disk)                                                                                                                                                                               
          1  rows processed                                                                                                                                                                             

SQL> 
SQL> alter session set parallel_degree_policy=auto;

Session altered.

Elapsed: 00:00:00.00
SQL> select /*+ parallel(2) */ count(*) from t;

Elapsed: 00:00:00.18

Execution Plan
----------------------------------------------------------                                                                                                                                              
Plan hash value: 3126468333                                                                                                                                                                             
                                                                                                                                                                                                        
--------------------------------------------------------------------------------------------------------                                                                                                
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
|   0 | SELECT STATEMENT       |          |     1 |  1507   (1)| 00:00:01 |        |      |            |                                                                                                
|   1 |  SORT AGGREGATE        |          |     1 |            |          |        |      |            |                                                                                                
|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |                                                                                                
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |                                                                                                
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |                                                                                                
|   5 |      PX BLOCK ITERATOR |          | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWC |            |                                                                                                
|   6 |       TABLE ACCESS FULL| T        | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWP |            |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - Degree of Parallelism is 2 because of hint                                                                                                                                                         


Statistics
----------------------------------------------------------                                                                                                                                              
          7  recursive calls                                                                                                                                                                            
          0  db block gets                                                                                                                                                                              
      10116  consistent gets                                                                                                                                                                            
      10003  physical reads                                                                                                                                                                             
          0  redo size                                                                                                                                                                                  
        542  bytes sent via SQL*Net to client                                                                                                                                                           
        552  bytes received via SQL*Net from client                                                                                                                                                     
          2  SQL*Net roundtrips to/from client                                                                                                                                                          
          0  sorts (memory)                                                                                                                                                                             
          0  sorts (disk)                                                                                                                                                                               
          1  rows processed                                                                                                                                                                             

SQL> select /*+ parallel(2) */ count(*) from t;

Elapsed: 00:00:00.07

Execution Plan
----------------------------------------------------------                                                                                                                                              
Plan hash value: 3126468333                                                                                                                                                                             
                                                                                                                                                                                                        
--------------------------------------------------------------------------------------------------------                                                                                                
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
|   0 | SELECT STATEMENT       |          |     1 |  1507   (1)| 00:00:01 |        |      |            |                                                                                                
|   1 |  SORT AGGREGATE        |          |     1 |            |          |        |      |            |                                                                                                
|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |                                                                                                
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |                                                                                                
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |                                                                                                
|   5 |      PX BLOCK ITERATOR |          | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWC |            |                                                                                                
|   6 |       TABLE ACCESS FULL| T        | 10000 |  1507   (1)| 00:00:01 |  Q1,00 | PCWP |            |                                                                                                
--------------------------------------------------------------------------------------------------------                                                                                                
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - Degree of Parallelism is 2 because of hint                                                                                                                                                         


Statistics
----------------------------------------------------------                                                                                                                                              
          6  recursive calls                                                                                                                                                                            
          0  db block gets                                                                                                                                                                              
      10116  consistent gets                                                                                                                                                                            
          0  physical reads                                                                                                                                                                             
          0  redo size                                                                                                                                                                                  
        542  bytes sent via SQL*Net to client                                                                                                                                                           
        552  bytes received via SQL*Net from client                                                                                                                                                     
          2  SQL*Net roundtrips to/from client                                                                                                                                                          
          0  sorts (memory)                                                                                                                                                                             
          0  sorts (disk)                                                                                                                                                                               
          1  rows processed                                                                                                                                                                             

SQL> 
SQL> set autot off
SQL> 
SQL> spo off



Thanks Connor.

Rajeshwaran Jeyabal, September 22, 2015 - 12:52 pm UTC

Thanks Connor. this helps.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library