<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JOOQ Archives - Philipp Salvisberg&#039;s Blog</title>
	<atom:link href="https://www.salvis.com/blog/tag/jooq/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.salvis.com/blog/tag/jooq/</link>
	<description>Database-centric development</description>
	<lastBuildDate>Sun, 09 Feb 2025 09:08:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</url>
	<title>JOOQ Archives - Philipp Salvisberg&#039;s Blog</title>
	<link>https://www.salvis.com/blog/tag/jooq/</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/>
<atom:link rel="hub" href="https://websubhub.com/hub"/>
<atom:link rel="self" href="https://www.salvis.com/blog/tag/jooq/feed/"/>
	<item>
		<title>View-API for JOOQ Application</title>
		<link>https://www.salvis.com/blog/2018/08/05/view-api-jooq-application/</link>
					<comments>https://www.salvis.com/blog/2018/08/05/view-api-jooq-application/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 05 Aug 2018 20:34:07 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JOOQ]]></category>
		<category><![CDATA[oddgen]]></category>
		<category><![CDATA[PinkDB]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=8722</guid>

					<description><![CDATA[<p>In this blog post, I show how to build a read-only view-API for Oracle&#8217;s HR sample schema. And I will use this view-API in a JOOQ application. This application will fully comply with the Pink Database Paradigm (PinkDB). This means the application executes set-based SQL and retrieves data with as few network roundtrips as possible.<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2018/08/05/view-api-jooq-application/">View-API for JOOQ Application</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In this blog post, I show how to build a read-only view-API for Oracle&#8217;s <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/comsc/introduction-to-sample-schemas.html#GUID-4DE9844F-0B28-4713-9AFC-CCD8D6249D76">HR sample schema</a>. And I will use this view-API in a <a href="https://www.jooq.org/">JOOQ</a> application. This application will fully comply with the <a href="https://www.salvis.com/blog/2018/07/18/the-pink-database-paradigm-pinkdb/">Pink Database Paradigm (PinkDB)</a>. This means the application executes set-based SQL and retrieves data with as few network roundtrips as possible.</p>



<p>The following topics are covered:</p>



<ol class="wp-block-list">
<li><a href="#install_sample_schemas">Install Sample Schemas</a></li>



<li><a href="#build_view_api">Build the View-API</a></li>



<li><a href="#create_role">Create the View-API Database Role</a></li>



<li><a href="#create_connect_user">Create the Connect User</a></li>



<li><a href="#install_jooq">Install JOOQ</a></li>



<li><a href="#teach_jooq_view_api">Teach JOOQ the View-API</a></li>



<li><a href="#run_simple_query">Run a Simple Query</a></li>



<li><a href="#using_joins">Using Joins &amp; Aggregations</a></li>



<li><a href="#using_binds">Using Bind Variables</a></li>



<li><a href="#run_top_n_query">Run a Top N Query</a></li>



<li><a href="#using_row_pattern_matching">Using Row Pattern Matching</a></li>



<li><a href="#conclusion">Conclusion</a></li>
</ol>



<p>This is not meant to be a tutorial. However, you should be able to build the application based on the information in this blog post and the referenced links.</p>



<p>It&#8217;s the first time I&#8217;ve done anything with JOOQ. I read about it and understood the high-level concepts, but I have never used JOOQ before. This is one reason why this blog post became a bit more verbose. I hope it is helpful.</p>



<h2 class="wp-block-heading"><a name="install_sample_schemas"></a>1. Install Sample Schemas</h2>



<p>See the&nbsp;<a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/comsc/installing-sample-schemas.html#GUID-1E645D09-F91F-4BA6-A286-57C5EC66321D">Oracle documentation</a>.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Starting with Oracle Database 12c Release 2, the latest version of the sample schema scripts are available on GitHub at&nbsp;<a class="new-window" href="https://github.com/oracle/db-sample-schemas/releases/latest" target="_blank" rel="noopener noreferrer">https://github.com/oracle/db-sample-schemas/releases/latest</a>. (&#8230;)</p>
</blockquote>



<h2 class="wp-block-heading"><a name="build_view_api"></a>2. Build the View-API</h2>



<h3 class="wp-block-heading">1:1 Views</h3>



<p>When building a view API I start with a 1:1 mapping to the table. There are usually some discussions on different topics.</p>



<h3 class="wp-block-heading">Expose Surrogate Keys</h3>



<p>One topic is to include surrogate keys or just business keys in the view API. Nowadays, I tend to expose surrogate keys. The main reason is to avoid joins when business key columns are stored in related (parent) tables. Forcing the application to join views via such business key columns is a bad idea from a performance point of view.</p>



<h3 class="wp-block-heading">Convenience Views &#8211; Not a Replacement for 1:1 Views</h3>



<p>Another topic is the simplification of the model. For example, provide data from various tables to simplify the usage. Simplification means here sparing the consuming application to use joins. This is sometimes a good idea, but it does not replace the 1:1 views, which are the key to the optimal path to the data. I know about join elimination, but in reality, they often do not work. One reason is that unnecessary columns are queried as well. Another problem is, to force the view to apply selective predicates as early as possible. Sometimes it is necessary to introduce an application context, just for that purpose, making the usage of the view not that simple anymore.</p>



<h3 class="wp-block-heading">Value of a 1:1 View-API</h3>



<p>The logical next question is this: Why do we need a view layer when it just provides data the same way as the underlying tables? That&#8217;s an excellent question. I strongly recommend introducing a layer only, when it provides more value than the additional effort. So, what is the value of a 1:1 view layer? Most products evolve during their life cycle. Hence, the data model will most probably change as well. When we have a view layer, we have the option to change the physical data model and keep the existing view layer the same for the consuming applications. From that point on, the views are not a 1:1 representation of tables, at least not in every case.</p>



<p>As long as we keep the interface to the application unchanged, we do not have to coordinate changes with the consuming applications. This gives us effective room for refactoring and simplifies going-live scenarios of new releases. Providing additional data and functionality is usually not a problem. However, adapting applications to new interfaces needs time. A view-API, especially if it implements some versioning concept, provides an excellent value in this area.</p>



<h3 class="wp-block-heading">View-API of HR Schema</h3>



<p>I&#8217;ve generated the initial version of the 1:1 view layer with <a href="https://www.oddgen.org/">oddgen</a>&#8216;s 1:1 View generator.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">View-API</span><span role="button" tabindex="0" data-code="ALTER SESSION SET current_schema=hr;

CREATE OR REPLACE VIEW COUNTRIES_V AS
   SELECT COUNTRY_ID,
          COUNTRY_NAME,
          REGION_ID
     FROM COUNTRIES;

CREATE OR REPLACE VIEW DEPARTMENTS_V AS
   SELECT DEPARTMENT_ID,
          DEPARTMENT_NAME,
          MANAGER_ID,
          LOCATION_ID
     FROM DEPARTMENTS;

CREATE OR REPLACE VIEW EMPLOYEES_V AS
   SELECT EMPLOYEE_ID,
          FIRST_NAME,
          LAST_NAME,
          EMAIL,
          PHONE_NUMBER,
          HIRE_DATE,
          JOB_ID,
          SALARY,
          COMMISSION_PCT,
          MANAGER_ID,
          DEPARTMENT_ID
     FROM EMPLOYEES;

CREATE OR REPLACE VIEW JOB_HISTORY_V AS
   SELECT EMPLOYEE_ID,
          START_DATE,
          END_DATE,
          JOB_ID,
          DEPARTMENT_ID
     FROM JOB_HISTORY;

CREATE OR REPLACE VIEW JOBS_V AS
   SELECT JOB_ID,
          JOB_TITLE,
          MIN_SALARY,
          MAX_SALARY
     FROM JOBS;

CREATE OR REPLACE VIEW LOCATIONS_V AS
   SELECT LOCATION_ID,
          STREET_ADDRESS,
          POSTAL_CODE,
          CITY,
          STATE_PROVINCE,
          COUNTRY_ID
     FROM LOCATIONS;

CREATE OR REPLACE VIEW REGIONS_V AS
   SELECT REGION_ID,
          REGION_NAME
     FROM REGIONS;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">SESSION</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">SET</span><span style="color: #D4D4D4"> current_schema=hr;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">COUNTRIES_V</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> COUNTRY_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          COUNTRY_NAME,</span></span>
<span class="line"><span style="color: #D4D4D4">          REGION_ID</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> COUNTRIES;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">DEPARTMENTS_V</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> DEPARTMENT_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          DEPARTMENT_NAME,</span></span>
<span class="line"><span style="color: #D4D4D4">          MANAGER_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          LOCATION_ID</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> DEPARTMENTS;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">EMPLOYEES_V</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> EMPLOYEE_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          FIRST_NAME,</span></span>
<span class="line"><span style="color: #D4D4D4">          LAST_NAME,</span></span>
<span class="line"><span style="color: #D4D4D4">          EMAIL,</span></span>
<span class="line"><span style="color: #D4D4D4">          PHONE_NUMBER,</span></span>
<span class="line"><span style="color: #D4D4D4">          HIRE_DATE,</span></span>
<span class="line"><span style="color: #D4D4D4">          JOB_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          SALARY,</span></span>
<span class="line"><span style="color: #D4D4D4">          COMMISSION_PCT,</span></span>
<span class="line"><span style="color: #D4D4D4">          MANAGER_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          DEPARTMENT_ID</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> EMPLOYEES;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">JOB_HISTORY_V</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> EMPLOYEE_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">START_DATE</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">          END_DATE,</span></span>
<span class="line"><span style="color: #D4D4D4">          JOB_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          DEPARTMENT_ID</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> JOB_HISTORY;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">JOBS_V</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> JOB_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          JOB_TITLE,</span></span>
<span class="line"><span style="color: #D4D4D4">          MIN_SALARY,</span></span>
<span class="line"><span style="color: #D4D4D4">          MAX_SALARY</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> JOBS;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">LOCATIONS_V</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> LOCATION_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          STREET_ADDRESS,</span></span>
<span class="line"><span style="color: #D4D4D4">          POSTAL_CODE,</span></span>
<span class="line"><span style="color: #D4D4D4">          CITY,</span></span>
<span class="line"><span style="color: #D4D4D4">          STATE_PROVINCE,</span></span>
<span class="line"><span style="color: #D4D4D4">          COUNTRY_ID</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> LOCATIONS;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">REGIONS_V</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> REGION_ID,</span></span>
<span class="line"><span style="color: #D4D4D4">          REGION_NAME</span></span>
<span class="line"><span style="color: #D4D4D4">     </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> REGIONS;</span></span></code></pre></div>



<h3 class="wp-block-heading">View Constraints</h3>



<p>When building a view-API it is a good idea to also define primary key, foreign key and unique constraints for these views. They will not be enforced by the Oracle database, but they are an excellent documentation. Furthermore, they will be used by JOOQ as we see later.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">View Constraints</span><span role="button" tabindex="0" data-code="ALTER SESSION SET current_schema=hr;

-- primary key and unique constraints
ALTER VIEW countries_v   ADD PRIMARY KEY (country_id)              DISABLE NOVALIDATE;
ALTER VIEW departments_v ADD PRIMARY KEY (department_id)           DISABLE NOVALIDATE;
ALTER VIEW employees_v   ADD PRIMARY KEY (employee_id)             DISABLE NOVALIDATE;
ALTER VIEW employees_v   ADD UNIQUE      (email)                   DISABLE NOVALIDATE;
ALTER VIEW job_history_v ADD PRIMARY KEY (employee_id, start_date) DISABLE NOVALIDATE;
ALTER VIEW jobs_v        ADD PRIMARY KEY (job_id)                  DISABLE NOVALIDATE;
ALTER VIEW locations_v   ADD PRIMARY KEY (location_id)             DISABLE NOVALIDATE;
ALTER VIEW regions_v     ADD PRIMARY KEY (region_id)               DISABLE NOVALIDATE;

-- foreign key constraints
ALTER VIEW countries_v   ADD FOREIGN KEY (region_id)     REFERENCES hr.regions_v     DISABLE NOVALIDATE;
ALTER VIEW departments_v ADD FOREIGN KEY (location_id)   REFERENCES hr.locations_v   DISABLE NOVALIDATE;
ALTER VIEW departments_v ADD FOREIGN KEY (manager_id)    REFERENCES hr.employees_v   DISABLE NOVALIDATE;
ALTER VIEW employees_v   ADD FOREIGN KEY (department_id) REFERENCES hr.departments_v DISABLE NOVALIDATE;
ALTER VIEW employees_v   ADD FOREIGN KEY (job_id)        REFERENCES hr.jobs_v        DISABLE NOVALIDATE;
ALTER VIEW employees_v   ADD FOREIGN KEY (manager_id)    REFERENCES hr.employees_v   DISABLE NOVALIDATE;
ALTER VIEW job_history_v ADD FOREIGN KEY (department_id) REFERENCES hr.departments_v DISABLE NOVALIDATE;
ALTER VIEW job_history_v ADD FOREIGN KEY (employee_id)   REFERENCES hr.employees_v   DISABLE NOVALIDATE;
ALTER VIEW job_history_v ADD FOREIGN KEY (job_id)        REFERENCES hr.jobs_v        DISABLE NOVALIDATE;
ALTER VIEW locations_v   ADD FOREIGN KEY (country_id)    REFERENCES hr.countries_v   DISABLE NOVALIDATE;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">SESSION</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">SET</span><span style="color: #D4D4D4"> current_schema=hr;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">-- primary key and unique constraints</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> countries_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (country_id)              </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> departments_v </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (department_id)           </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> employees_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (employee_id)             </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> employees_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">UNIQUE</span><span style="color: #D4D4D4">      (email)                   </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> job_history_v </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (employee_id, </span><span style="color: #569CD6">start_date</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> jobs_v        </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (job_id)                  </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> locations_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (location_id)             </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> regions_v     </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PRIMARY KEY</span><span style="color: #D4D4D4"> (region_id)               </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">-- foreign key constraints</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> countries_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (region_id)     </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.regions_v     </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> departments_v </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (location_id)   </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.locations_v   </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> departments_v </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (manager_id)    </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.employees_v   </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> employees_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (department_id) </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.departments_v </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> employees_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (job_id)        </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.jobs_v        </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> employees_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (manager_id)    </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.employees_v   </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> job_history_v </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (department_id) </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.departments_v </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> job_history_v </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (employee_id)   </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.employees_v   </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> job_history_v </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (job_id)        </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.jobs_v        </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span>
<span class="line"><span style="color: #569CD6">ALTER</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">VIEW</span><span style="color: #D4D4D4"> locations_v   </span><span style="color: #569CD6">ADD</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">FOREIGN KEY</span><span style="color: #D4D4D4"> (country_id)    </span><span style="color: #569CD6">REFERENCES</span><span style="color: #D4D4D4"> hr.countries_v   </span><span style="color: #569CD6">DISABLE</span><span style="color: #D4D4D4"> NOVALIDATE;</span></span></code></pre></div>



<h3 class="wp-block-heading">View-API Model</h3>



<p>I created the following relational model with Oracle&#8217;s SQL Developer.&nbsp;SQL Developer automatically took into account all constraints defined on these 7 views. Most of the work was to rearrange the view boxes on the diagram,&nbsp;but with only 7 views it was no big deal.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API.png"><img fetchpriority="high" decoding="async" width="949" height="657" src="https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API.png" alt="HR View-API" class="wp-image-8745" srcset="https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API.png 949w, https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API-300x208.png 300w, https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API-768x532.png 768w, https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API-211x146.png 211w, https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API-50x35.png 50w, https://www.salvis.com/blog/wp-content/uploads/2018/08/HR-View-API-108x75.png 108w" sizes="(max-width:767px) 480px, (max-width:949px) 100vw, 949px" /></a></figure>



<h2 class="wp-block-heading"><a name="create_role"></a>3. Create the View-API Database Role</h2>



<p>We grant read access to all views as part of the API to the database role <code>HR_API_ROLE</code>. This is easier to maintain, especially when access to more than one connect user is granted.</p>



<p>Please note that just <code>READ</code> access is granted on the views. We do not grant <code>SELECT</code> access to ensure that data can&#8217;t be locked by the connect users via <code>SELECT FOR UPDATE</code>.&nbsp; The <code>READ</code> privilege was introduced in Oracle Database 12c.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">HR_API_ROLE</span><span role="button" tabindex="0" data-code="CREATE ROLE hr_api_role;

GRANT READ ON hr.countries_v   TO hr_api_role;
GRANT READ ON hr.departments_v TO hr_api_role;
GRANT READ ON hr.employees_v   TO hr_api_role;
GRANT READ ON hr.job_history_v TO hr_api_role;
GRANT READ ON hr.jobs_v        TO hr_api_role;
GRANT READ ON hr.locations_v   TO hr_api_role;
GRANT READ ON hr.regions_v     TO hr_api_role;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ROLE</span><span style="color: #D4D4D4"> hr_api_role;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> hr.countries_v   </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> hr_api_role;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> hr.departments_v </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> hr_api_role;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> hr.employees_v   </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> hr_api_role;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> hr.job_history_v </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> hr_api_role;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> hr.jobs_v        </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> hr_api_role;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> hr.locations_v   </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> hr_api_role;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">READ</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> hr.regions_v     </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> hr_api_role;</span></span></code></pre></div>



<p>In this case, it does not make sense to define more than one role. But for larger projects, it might be helpful to create more roles. For example to distinguish between read and write roles or to manage access to sensitive data explicitly.</p>



<h2 class="wp-block-heading"><a name="create_connect_user"></a>4. Create the Connect User</h2>



<p>Now we create a connect user named <code>JOOQ</code>. It will have the right to connect, access the view-API and execute the procedures in the <code>SYS.DBMS_MONITOR</code> package. The access to <code>DBMS_MONITOR</code> is given only to enable SQL Trace for some analysis on the database server.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Create Connect User JOOQ</span><span role="button" tabindex="0" data-code="CREATE USER jooq IDENTIFIED BY jooq;
GRANT connect, hr_api_role TO jooq;
GRANT EXECUTE ON sys.dbms_monitor TO jooq;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">USER</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">jooq</span><span style="color: #D4D4D4"> IDENTIFIED </span><span style="color: #569CD6">BY</span><span style="color: #D4D4D4"> jooq;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">connect</span><span style="color: #D4D4D4">, hr_api_role </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> jooq;</span></span>
<span class="line"><span style="color: #569CD6">GRANT</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">EXECUTE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> sys.dbms_monitor </span><span style="color: #569CD6">TO</span><span style="color: #D4D4D4"> jooq;</span></span></code></pre></div>



<h2 class="wp-block-heading"><a name="install_jooq"></a>5. Install JOOQ</h2>



<p><a href="https://www.jooq.org/download/">Download</a> the trial version of JOOQ Professional for free. The trial period is 30 days. Registration is not required.</p>



<p>JOOQ comes with an excellent documentation. In fact, I kept the PDF version open during all my tests and found everything I needed using the search function. After extracting the downloaded ZIP file, I run the following commands on my macOS system:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Install JOOQ in Local Maven Repository</span><span role="button" tabindex="0" data-code="chmod +x maven-deploy.sh
./maven-deploy.sh -u file:///Users/phs/.m2/repository" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">chmod</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">+x</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">maven-deploy.sh</span></span>
<span class="line"><span style="color: #DCDCAA">./maven-deploy.sh</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-u</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">file:///Users/phs/.m2/repository</span></span></code></pre></div>



<p>This deployed JOOQ in my local Maven repository. Run <code>./maven-deploy.sh -h</code> for command line options, e.g. when you want to deploy it on your Sonatype Nexus repository.</p>



<h2 class="wp-block-heading"><a name="teach_jooq_view_api"></a>6. Teach JOOQ the View-API</h2>



<p>JOOQ allows to build SQL and execute SQL statements in a typesafe manner. It&#8217;s similar to SQL within PL/SQL. You avoid to build SQL using string concatenation. Instead, you use the JOOQ domain-specific language (DSL) that knows about SQL and can learn about your database model. For example, JOOQ must learn that <code>JOBS_V</code> is a view and <code>JOB_ID</code> is its primary key column.</p>



<p>Technically JOOQ reads the data dictionary and generates a set of Java classes for you. You may call the generator via command line using a XML configuration file or use the JOOQ Maven plugin to configure the generator directly in your <code>pom.xml</code>. You may also generate these classes via Ant or Gradle. I&#8217;ve used the Maven plugin to include the code generation process in my project build.</p>



<p>On lines 36-38, we define the JDBC driver.</p>



<p>On lines 43-46, we configure the JDBC URL and the credentials of the connect user.</p>



<p>Line 50 tells JOOQ to use the Oracle meta-model and line 51 is a regular expression to define the generation scope. In our case the visible objects in the <code>HR</code> schema and the PL/SQL package <code>SYS.DBMS_MONITOR</code>. Using the default would generate Java code for all public objects.</p>



<p>Finally, on lines 54-55, we define the target directory for the generated Java classes and their Java package name.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">XML</span><span role="button" tabindex="0" data-code="<project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
   xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
   <modelVersion&gt;4.0.0</modelVersion&gt;
   <groupId&gt;com.trivadis.pinkdb.jooq</groupId&gt;
   <artifactId&gt;jooq-pinkdb</artifactId&gt;
   <version&gt;0.0.1-SNAPSHOT</version&gt;
   <properties&gt;
      <project.build.sourceEncoding&gt;UTF-8</project.build.sourceEncoding&gt;
      <jdk.version&gt;1.8</jdk.version&gt;
      <xtend.version&gt;2.12.0</xtend.version&gt;
   </properties&gt;
   <build&gt;
      <plugins&gt;
         <plugin&gt;
            <groupId&gt;org.apache.maven.plugins</groupId&gt;
            <version&gt;3.8.0</version&gt;
            <artifactId&gt;maven-compiler-plugin</artifactId&gt;
            <configuration&gt;
               <source&gt;${jdk.version}</source&gt;
               <target&gt;${jdk.version}</target&gt;
            </configuration&gt;
         </plugin&gt;
         <plugin&gt;
            <groupId&gt;org.jooq.trial</groupId&gt;
            <artifactId&gt;jooq-codegen-maven</artifactId&gt;
            <version&gt;3.11.3</version&gt;
            <executions&gt;
               <execution&gt;
                  <goals&gt;
                     <goal&gt;generate</goal&gt;
                  </goals&gt;
               </execution&gt;
            </executions&gt;
            <dependencies&gt;
               <dependency&gt;
                  <groupId&gt;oracle</groupId&gt;
                  <artifactId&gt;ojdbc8</artifactId&gt;
                  <version&gt;12.2.0.1.0</version&gt;
               </dependency&gt;
            </dependencies&gt;
            <configuration&gt;
               <jdbc&gt;
                  <driver&gt;oracle.jdbc.OracleDriver</driver&gt;
                  <url&gt;jdbc:oracle:thin:@localhost:1521/odb.docker</url&gt;
                  <user&gt;jooq</user&gt;
                  <password&gt;jooq</password&gt;
               </jdbc&gt;
               <generator&gt;
                  <database&gt;
                     <name&gt;org.jooq.meta.oracle.OracleDatabase</name&gt;
                     <includes&gt;HR\..*|SYS\.DBMS_MONITOR</includes&gt;
                  </database&gt;
                  <target&gt;
                     <packageName&gt;com.trivadis.jooq.pinkdb.model.generated</packageName&gt;
                     <directory&gt;src/main/java</directory&gt;
                  </target&gt;
               </generator&gt;
            </configuration&gt;
         </plugin&gt;
      </plugins&gt;
   </build&gt;
   <dependencies&gt;
      <dependency&gt;
         <groupId&gt;org.jooq.trial</groupId&gt;
         <artifactId&gt;jooq</artifactId&gt;
         <version&gt;3.11.3</version&gt;
      </dependency&gt;
      <dependency&gt;
         <groupId&gt;oracle</groupId&gt;
         <artifactId&gt;ojdbc8</artifactId&gt;
         <version&gt;12.2.0.1.0</version&gt;
      </dependency&gt;
   </dependencies&gt;
</project&gt;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #808080">&lt;</span><span style="color: #569CD6">project</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">xmlns</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;http://maven.apache.org/POM/4.0.0&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">xmlns:xsi</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #9CDCFE">xsi:schemaLocation</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">modelVersion</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">4.0.0</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">modelVersion</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">com.trivadis.pinkdb.jooq</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">jooq-pinkdb</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">0.0.1-SNAPSHOT</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">properties</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">project.build.sourceEncoding</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">UTF-8</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">project.build.sourceEncoding</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">jdk.version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">1.8</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">jdk.version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">xtend.version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">2.12.0</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">xtend.version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">properties</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">build</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">plugins</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">plugin</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">org.apache.maven.plugins</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">3.8.0</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">maven-compiler-plugin</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">configuration</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">source</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">${jdk.version}</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">source</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">target</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">${jdk.version}</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">target</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">configuration</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">plugin</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">plugin</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">org.jooq.trial</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">jooq-codegen-maven</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">3.11.3</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">executions</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">execution</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">goals</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                     </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">goal</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">generate</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">goal</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">goals</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">execution</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">executions</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">dependencies</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">dependency</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">oracle</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">ojdbc8</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">12.2.0.1.0</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">dependency</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">dependencies</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">configuration</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">jdbc</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">driver</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">oracle.jdbc.OracleDriver</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">driver</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">url</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">jdbc:oracle:thin:@localhost:1521/odb.docker</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">url</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">user</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">jooq</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">user</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">password</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">jooq</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">password</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">jdbc</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">generator</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">database</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                     </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">name</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">org.jooq.meta.oracle.OracleDatabase</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">name</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                     </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">includes</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">HR\..*|SYS\.DBMS_MONITOR</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">includes</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">database</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">target</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                     </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">packageName</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">com.trivadis.jooq.pinkdb.model.generated</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">packageName</span><span style="color: #808080">&gt;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                     </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">directory</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">src/main/java</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">directory</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">target</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">generator</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">configuration</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">plugin</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">plugins</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">build</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">dependencies</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">dependency</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">org.jooq.trial</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">jooq</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">3.11.3</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">dependency</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">dependency</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">oracle</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">groupId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">ojdbc8</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">artifactId</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">12.2.0.1.0</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">version</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">dependency</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">dependencies</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #808080">&lt;/</span><span style="color: #569CD6">project</span><span style="color: #808080">&gt;</span></span></code></pre></div>



<p>Here&#8217;s the excerpt of the console output (of <code>mvn package</code>) regarding the generation run:</p>


<div class="accordion"><div class="mfn-acc accordion_wrapper "><br />
<div class="question"><div class="title"><i class="icon-plus acc-icon-plus" aria-hidden="true"></i><i class="icon-minus acc-icon-minus" aria-hidden="true"></i>JOOQ generator output</div><div class="answer"></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">JOOQ Generator Output</span><span role="button" tabindex="0" data-code="&#091;INFO&#093; --- jooq-codegen-maven:3.11.3:generate (default) @ jooq-pinkdb ---
&#091;INFO&#093; No &lt;inputCatalog/&gt; was provided. Generating ALL available catalogs instead.
&#091;INFO&#093; No &lt;inputSchema/&gt; was provided. Generating ALL available schemata instead.
&#091;INFO&#093; License parameters       
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093;   Thank you for using jOOQ and jOOQ's code generator
&#091;INFO&#093;                          
&#091;INFO&#093; Database parameters      
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093;   dialect                : ORACLE
&#091;INFO&#093;   URL                    : jdbc:oracle:thin:@localhost:1521/odb.docker
&#091;INFO&#093;   target dir             : /Users/phs/git/JooqPinkDB/src/main/java
&#091;INFO&#093;   target package         : com.trivadis.jooq.pinkdb.model.generated
&#091;INFO&#093;   includes               : &#091;HR\..*|SYS\.DBMS_MONITOR&#093;
&#091;INFO&#093;   excludes               : &#091;&#093;
&#091;INFO&#093;   includeExcludeColumns  : false
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093;                          
&#091;INFO&#093; JavaGenerator parameters 
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093;   annotations (generated): true
&#091;INFO&#093;   annotations (JPA: any) : false
&#091;INFO&#093;   annotations (JPA: version): 
&#091;INFO&#093;   annotations (validation): false
&#091;INFO&#093;   comments               : true
&#091;INFO&#093;   comments on attributes : true
&#091;INFO&#093;   comments on catalogs   : true
&#091;INFO&#093;   comments on columns    : true
&#091;INFO&#093;   comments on keys       : true
&#091;INFO&#093;   comments on links      : true
&#091;INFO&#093;   comments on packages   : true
&#091;INFO&#093;   comments on parameters : true
&#091;INFO&#093;   comments on queues     : true
&#091;INFO&#093;   comments on routines   : true
&#091;INFO&#093;   comments on schemas    : true
&#091;INFO&#093;   comments on sequences  : true
&#091;INFO&#093;   comments on tables     : true
&#091;INFO&#093;   comments on udts       : true
&#091;INFO&#093;   daos                   : false
&#091;INFO&#093;   deprecated code        : true
&#091;INFO&#093;   global references (any): true
&#091;INFO&#093;   global references (catalogs): true
&#091;INFO&#093;   global references (keys): true
&#091;INFO&#093;   global references (links): true
&#091;INFO&#093;   global references (queues): true
&#091;INFO&#093;   global references (routines): true
&#091;INFO&#093;   global references (schemas): true
&#091;INFO&#093;   global references (sequences): true
&#091;INFO&#093;   global references (tables): true
&#091;INFO&#093;   global references (udts): true
&#091;INFO&#093;   indexes                : true
&#091;INFO&#093;   instance fields        : true
&#091;INFO&#093;   interfaces             : false
&#091;INFO&#093;   interfaces (immutable) : false
&#091;INFO&#093;   javadoc                : true
&#091;INFO&#093;   keys                   : true
&#091;INFO&#093;   links                  : true
&#091;INFO&#093;   pojos                  : false
&#091;INFO&#093;   pojos (immutable)      : false
&#091;INFO&#093;   queues                 : true
&#091;INFO&#093;   records                : true
&#091;INFO&#093;   routines               : true
&#091;INFO&#093;   sequences              : true
&#091;INFO&#093;   table-valued functions : false
&#091;INFO&#093;   tables                 : true
&#091;INFO&#093;   udts                   : true
&#091;INFO&#093;   relations              : true
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093;                          
&#091;INFO&#093; Generation remarks       
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093;                          
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093; Generating catalogs      : Total: 1
&#091;INFO&#093; 
                                      
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@  @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@        @@@@@@@@@@
@@@@@@@@@@@@@@@@  @@  @@    @@@@@@@@@@
@@@@@@@@@@  @@@@  @@  @@    @@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@
@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@
@@@@@@@@@@        @@  @  @  @@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  Thank you for using the 30 day free jOOQ 3.11.3 trial edition
                                      
&#091;INFO&#093; Packages fetched         : 517 (1 included, 516 excluded)
&#091;INFO&#093; Applying synonym         : &quot;PUBLIC&quot;.&quot;KU$_LOGENTRY&quot; is synonym for &quot;SYS&quot;.&quot;KU$_LOGENTRY1010&quot;
&#091;INFO&#093; Applying synonym         : &quot;PUBLIC&quot;.&quot;XMLTYPE&quot; is synonym for &quot;SYS&quot;.&quot;XMLTYPE&quot;
&#091;INFO&#093; ARRAYs fetched           : 641 (0 included, 641 excluded)
&#091;INFO&#093; Enums fetched            : 0 (0 included, 0 excluded)
&#091;INFO&#093; No schema version is applied for catalog . Regenerating.
&#091;INFO&#093;                          
&#091;INFO&#093; Generating catalog       : DefaultCatalog.java
&#091;INFO&#093; ==========================================================
&#091;INFO&#093; Routines fetched         : 312 (0 included, 312 excluded)
&#091;INFO&#093; Tables fetched           : 2347 (7 included, 2340 excluded)
&#091;INFO&#093; UDTs fetched             : 1287 (0 included, 1287 excluded)
&#091;INFO&#093; Generating schemata      : Total: 63
&#091;INFO&#093; No schema version is applied for schema SYS. Regenerating.
&#091;INFO&#093; Generating schema        : Sys.java
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093; Sequences fetched        : 12 (0 included, 12 excluded)
&#091;INFO&#093; Domains fetched          : 0 (0 included, 0 excluded)
&#091;INFO&#093; Generating packages      
&#091;INFO&#093; Generating package       : SYS.DBMS_MONITOR
&#091;INFO&#093; Generating routine       : ClientIdStatDisable.java
&#091;INFO&#093; Generating routine       : ClientIdStatEnable.java
&#091;INFO&#093; Generating routine       : ClientIdTraceDisable.java
&#091;INFO&#093; Generating routine       : ClientIdTraceEnable.java
&#091;INFO&#093; Generating routine       : DatabaseTraceDisable.java
&#091;INFO&#093; Generating routine       : DatabaseTraceEnable.java
&#091;INFO&#093; Generating routine       : ServModActStatDisable.java
&#091;INFO&#093; Generating routine       : ServModActStatEnable.java
&#091;INFO&#093; Generating routine       : ServModActTraceDisable.java
&#091;INFO&#093; Generating routine       : ServModActTraceEnable.java
&#091;INFO&#093; Generating routine       : SessionTraceDisable.java
&#091;INFO&#093; Generating routine       : SessionTraceEnable.java
&#091;INFO&#093; Packages generated       : Total: 7.009s
&#091;INFO&#093; UDT not supported or not in input schemata: SYS.SCHEDULER$_EVENT_INFO
&#091;INFO&#093; UDT not supported or not in input schemata: SYS.SCHEDULER_FILEWATCHER_RESULT
&#091;INFO&#093; Queues fetched           : 0 (0 included, 0 excluded)
&#091;INFO&#093; Links fetched            : 0 (0 included, 0 excluded)
&#091;INFO&#093; Generation finished: SYS : Total: 7.482s, +473.374ms
&#091;INFO&#093;                          
&#091;INFO&#093; Excluding empty schema   : AUDSYS
&#091;INFO&#093; Excluding empty schema   : SYSTEM
&#091;INFO&#093; Excluding empty schema   : SYSBACKUP
&#091;INFO&#093; Excluding empty schema   : SYSDG
&#091;INFO&#093; Excluding empty schema   : SYSKM
&#091;INFO&#093; Excluding empty schema   : SYSRAC
&#091;INFO&#093; Excluding empty schema   : OUTLN
&#091;INFO&#093; Excluding empty schema   : XS$NULL
&#091;INFO&#093; Excluding empty schema   : GSMADMIN_INTERNAL
&#091;INFO&#093; Excluding empty schema   : GSMUSER
&#091;INFO&#093; Excluding empty schema   : DIP
&#091;INFO&#093; Excluding empty schema   : REMOTE_SCHEDULER_AGENT
&#091;INFO&#093; Excluding empty schema   : DBSFWUSER
&#091;INFO&#093; Excluding empty schema   : ORACLE_OCM
&#091;INFO&#093; Excluding empty schema   : SYS$UMF
&#091;INFO&#093; Excluding empty schema   : DBSNMP
&#091;INFO&#093; Excluding empty schema   : APPQOSSYS
&#091;INFO&#093; Excluding empty schema   : GSMCATUSER
&#091;INFO&#093; Excluding empty schema   : GGSYS
&#091;INFO&#093; Excluding empty schema   : XDB
&#091;INFO&#093; Excluding empty schema   : ANONYMOUS
&#091;INFO&#093; Excluding empty schema   : WMSYS
&#091;INFO&#093; Excluding empty schema   : DVF
&#091;INFO&#093; Excluding empty schema   : OJVMSYS
&#091;INFO&#093; Excluding empty schema   : CTXSYS
&#091;INFO&#093; Excluding empty schema   : ORDSYS
&#091;INFO&#093; Excluding empty schema   : ORDDATA
&#091;INFO&#093; Excluding empty schema   : ORDPLUGINS
&#091;INFO&#093; Excluding empty schema   : SI_INFORMTN_SCHEMA
&#091;INFO&#093; Excluding empty schema   : MDSYS
&#091;INFO&#093; Excluding empty schema   : OLAPSYS
&#091;INFO&#093; Excluding empty schema   : MDDATA
&#091;INFO&#093; Excluding empty schema   : LBACSYS
&#091;INFO&#093; Excluding empty schema   : DVSYS
&#091;INFO&#093; Excluding empty schema   : FLOWS_FILES
&#091;INFO&#093; Excluding empty schema   : APEX_PUBLIC_USER
&#091;INFO&#093; Excluding empty schema   : APEX_180100
&#091;INFO&#093; Excluding empty schema   : APEX_INSTANCE_ADMIN_USER
&#091;INFO&#093; Excluding empty schema   : APEX_LISTENER
&#091;INFO&#093; Excluding empty schema   : APEX_REST_PUBLIC_USER
&#091;INFO&#093; Excluding empty schema   : ORDS_METADATA
&#091;INFO&#093; Excluding empty schema   : ORDS_PUBLIC_USER
&#091;INFO&#093; Excluding empty schema   : SCOTT
&#091;INFO&#093; No schema version is applied for schema HR. Regenerating.
&#091;INFO&#093; Generating schema        : Hr.java
&#091;INFO&#093; ----------------------------------------------------------
&#091;INFO&#093; Generating tables        
&#091;INFO&#093; Adding foreign key       : SYS_C0012240 (HR.COUNTRIES_V.REGION_ID) referencing SYS_C0012239
&#091;INFO&#093; Adding foreign key       : SYS_C0012241 (HR.DEPARTMENTS_V.LOCATION_ID) referencing SYS_C0012238
&#091;INFO&#093; Adding foreign key       : SYS_C0012242 (HR.DEPARTMENTS_V.MANAGER_ID) referencing SYS_C0012235
&#091;INFO&#093; Adding foreign key       : SYS_C0012244 (HR.EMPLOYEES_V.DEPARTMENT_ID) referencing SYS_C0012234
&#091;INFO&#093; Adding foreign key       : SYS_C0012245 (HR.EMPLOYEES_V.JOB_ID) referencing SYS_C0012237
&#091;INFO&#093; Adding foreign key       : SYS_C0012246 (HR.EMPLOYEES_V.MANAGER_ID) referencing SYS_C0012235
&#091;INFO&#093; Adding foreign key       : SYS_C0012247 (HR.JOB_HISTORY_V.DEPARTMENT_ID) referencing SYS_C0012234
&#091;INFO&#093; Adding foreign key       : SYS_C0012248 (HR.JOB_HISTORY_V.EMPLOYEE_ID) referencing SYS_C0012235
&#091;INFO&#093; Adding foreign key       : SYS_C0012249 (HR.JOB_HISTORY_V.JOB_ID) referencing SYS_C0012237
&#091;INFO&#093; Adding foreign key       : SYS_C0012250 (HR.LOCATIONS_V.COUNTRY_ID) referencing SYS_C0012233
&#091;INFO&#093; Synthetic primary keys   : 0 (0 included, 0 excluded)
&#091;INFO&#093; Overriding primary keys  : 8 (0 included, 8 excluded)
&#091;INFO&#093; Generating table         : CountriesV.java &#091;input=COUNTRIES_V, output=COUNTRIES_V, pk=SYS_C0012233&#093;
&#091;INFO&#093; Indexes fetched          : 0 (0 included, 0 excluded)
&#091;INFO&#093; Generating table         : DepartmentsV.java &#091;input=DEPARTMENTS_V, output=DEPARTMENTS_V, pk=SYS_C0012234&#093;
&#091;INFO&#093; Generating table         : EmployeesV.java &#091;input=EMPLOYEES_V, output=EMPLOYEES_V, pk=SYS_C0012235&#093;
&#091;INFO&#093; Generating table         : JobsV.java &#091;input=JOBS_V, output=JOBS_V, pk=SYS_C0012237&#093;
&#091;INFO&#093; Generating table         : JobHistoryV.java &#091;input=JOB_HISTORY_V, output=JOB_HISTORY_V, pk=SYS_C0012236&#093;
&#091;INFO&#093; Generating table         : LocationsV.java &#091;input=LOCATIONS_V, output=LOCATIONS_V, pk=SYS_C0012238&#093;
&#091;INFO&#093; Generating table         : RegionsV.java &#091;input=REGIONS_V, output=REGIONS_V, pk=SYS_C0012239&#093;
&#091;INFO&#093; Tables generated         : Total: 13.888s, +6.405s
&#091;INFO&#093; Generating table references
&#091;INFO&#093; Table refs generated     : Total: 13.889s, +1.9ms
&#091;INFO&#093; Generating Keys          
&#091;INFO&#093; Keys generated           : Total: 13.9s, +10.228ms
&#091;INFO&#093; Generating Indexes       
&#091;INFO&#093; Skipping empty indexes   
&#091;INFO&#093; Generating table records 
&#091;INFO&#093; Generating record        : CountriesVRecord.java
&#091;INFO&#093; Generating record        : DepartmentsVRecord.java
&#091;INFO&#093; Generating record        : EmployeesVRecord.java
&#091;INFO&#093; Generating record        : JobsVRecord.java
&#091;INFO&#093; Generating record        : JobHistoryVRecord.java
&#091;INFO&#093; Generating record        : LocationsVRecord.java
&#091;INFO&#093; Generating record        : RegionsVRecord.java
&#091;INFO&#093; Table records generated  : Total: 13.939s, +39.368ms
&#091;INFO&#093; Generation finished: HR  : Total: 13.939s, +0.14ms
&#091;INFO&#093;                          
&#091;INFO&#093; Excluding empty schema   : OE
&#091;INFO&#093; Excluding empty schema   : PM
&#091;INFO&#093; Excluding empty schema   : IX
&#091;INFO&#093; Excluding empty schema   : SH
&#091;INFO&#093; Excluding empty schema   : BI
&#091;INFO&#093; Excluding empty schema   : FTLDB
&#091;INFO&#093; Excluding empty schema   : TEPLSQL
&#091;INFO&#093; Excluding empty schema   : ODDGEN
&#091;INFO&#093; Excluding empty schema   : OGDEMO
&#091;INFO&#093; Excluding empty schema   : AQDEMO
&#091;INFO&#093; Excluding empty schema   : AX
&#091;INFO&#093; Excluding empty schema   : EMPTRACKER
&#091;INFO&#093; Excluding empty schema   : UT3
&#091;INFO&#093; Excluding empty schema   : PLSCOPE
&#091;INFO&#093; Excluding empty schema   : SONAR
&#091;INFO&#093; Excluding empty schema   : TVDCA
&#091;INFO&#093; Excluding empty schema   : DEMO
&#091;INFO&#093; Excluding empty schema   : JOOQ
&#091;INFO&#093; Removing excess files" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">[INFO] --- jooq-codegen-maven:3.11.3:generate (default) @ jooq-pinkdb ---</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] No &lt;inputCatalog/&gt; was provided. Generating ALL available catalogs instead.</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] No &lt;inputSchema/&gt; was provided. Generating ALL available schemata instead.</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] License parameters       </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   Thank you for using jOOQ and jOOQ&#39;s code generator</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]                          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Database parameters      </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   dialect                : ORACLE</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   URL                    : jdbc:oracle:thin:@localhost:1521/odb.docker</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   target dir             : /Users/phs/git/JooqPinkDB/src/main/java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   target package         : com.trivadis.jooq.pinkdb.model.generated</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   includes               : [HR\..*|SYS\.DBMS_MONITOR]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   excludes               : []</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   includeExcludeColumns  : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]                          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] JavaGenerator parameters </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   annotations (generated): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   annotations (JPA: any) : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   annotations (JPA: version): </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   annotations (validation): false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments               : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on attributes : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on catalogs   : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on columns    : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on keys       : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on links      : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on packages   : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on parameters : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on queues     : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on routines   : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on schemas    : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on sequences  : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on tables     : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   comments on udts       : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   daos                   : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   deprecated code        : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (any): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (catalogs): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (keys): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (links): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (queues): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (routines): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (schemas): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (sequences): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (tables): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   global references (udts): true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   indexes                : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   instance fields        : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   interfaces             : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   interfaces (immutable) : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   javadoc                : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   keys                   : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   links                  : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   pojos                  : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   pojos (immutable)      : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   queues                 : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   records                : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   routines               : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   sequences              : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   table-valued functions : false</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   tables                 : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   udts                   : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]   relations              : true</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]                          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generation remarks       </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]                          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating catalogs      : Total: 1</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] </span></span>
<span class="line"><span style="color: #D4D4D4">                                      </span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@  @@        @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@        @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@  @@  @@    @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@  @@@@  @@  @@    @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@        @@        @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@        @@        @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@        @@  @  @  @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@        @@        @@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</span></span>
<span class="line"><span style="color: #D4D4D4">@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  Thank you for using the 30 day free jOOQ 3.11.3 trial edition</span></span>
<span class="line"><span style="color: #D4D4D4">                                      </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Packages fetched         : 517 (1 included, 516 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Applying synonym         : &quot;PUBLIC&quot;.&quot;KU$_LOGENTRY&quot; is synonym for &quot;SYS&quot;.&quot;KU$_LOGENTRY1010&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Applying synonym         : &quot;PUBLIC&quot;.&quot;XMLTYPE&quot; is synonym for &quot;SYS&quot;.&quot;XMLTYPE&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ARRAYs fetched           : 641 (0 included, 641 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Enums fetched            : 0 (0 included, 0 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] No schema version is applied for catalog . Regenerating.</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]                          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating catalog       : DefaultCatalog.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ==========================================================</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Routines fetched         : 312 (0 included, 312 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Tables fetched           : 2347 (7 included, 2340 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] UDTs fetched             : 1287 (0 included, 1287 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating schemata      : Total: 63</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] No schema version is applied for schema SYS. Regenerating.</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating schema        : Sys.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Sequences fetched        : 12 (0 included, 12 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Domains fetched          : 0 (0 included, 0 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating packages      </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating package       : SYS.DBMS_MONITOR</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ClientIdStatDisable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ClientIdStatEnable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ClientIdTraceDisable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ClientIdTraceEnable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : DatabaseTraceDisable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : DatabaseTraceEnable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ServModActStatDisable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ServModActStatEnable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ServModActTraceDisable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : ServModActTraceEnable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : SessionTraceDisable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating routine       : SessionTraceEnable.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Packages generated       : Total: 7.009s</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] UDT not supported or not in input schemata: SYS.SCHEDULER$_EVENT_INFO</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] UDT not supported or not in input schemata: SYS.SCHEDULER_FILEWATCHER_RESULT</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Queues fetched           : 0 (0 included, 0 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Links fetched            : 0 (0 included, 0 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generation finished: SYS : Total: 7.482s, +473.374ms</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]                          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : AUDSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SYSTEM</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SYSBACKUP</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SYSDG</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SYSKM</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SYSRAC</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : OUTLN</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : XS$NULL</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : GSMADMIN_INTERNAL</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : GSMUSER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : DIP</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : REMOTE_SCHEDULER_AGENT</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : DBSFWUSER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ORACLE_OCM</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SYS$UMF</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : DBSNMP</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : APPQOSSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : GSMCATUSER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : GGSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : XDB</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ANONYMOUS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : WMSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : DVF</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : OJVMSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : CTXSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ORDSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ORDDATA</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ORDPLUGINS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SI_INFORMTN_SCHEMA</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : MDSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : OLAPSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : MDDATA</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : LBACSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : DVSYS</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : FLOWS_FILES</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : APEX_PUBLIC_USER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : APEX_180100</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : APEX_INSTANCE_ADMIN_USER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : APEX_LISTENER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : APEX_REST_PUBLIC_USER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ORDS_METADATA</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ORDS_PUBLIC_USER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SCOTT</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] No schema version is applied for schema HR. Regenerating.</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating schema        : Hr.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] ----------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating tables        </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012240 (HR.COUNTRIES_V.REGION_ID) referencing SYS_C0012239</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012241 (HR.DEPARTMENTS_V.LOCATION_ID) referencing SYS_C0012238</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012242 (HR.DEPARTMENTS_V.MANAGER_ID) referencing SYS_C0012235</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012244 (HR.EMPLOYEES_V.DEPARTMENT_ID) referencing SYS_C0012234</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012245 (HR.EMPLOYEES_V.JOB_ID) referencing SYS_C0012237</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012246 (HR.EMPLOYEES_V.MANAGER_ID) referencing SYS_C0012235</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012247 (HR.JOB_HISTORY_V.DEPARTMENT_ID) referencing SYS_C0012234</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012248 (HR.JOB_HISTORY_V.EMPLOYEE_ID) referencing SYS_C0012235</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012249 (HR.JOB_HISTORY_V.JOB_ID) referencing SYS_C0012237</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Adding foreign key       : SYS_C0012250 (HR.LOCATIONS_V.COUNTRY_ID) referencing SYS_C0012233</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Synthetic primary keys   : 0 (0 included, 0 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Overriding primary keys  : 8 (0 included, 8 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table         : CountriesV.java [input=COUNTRIES_V, output=COUNTRIES_V, pk=SYS_C0012233]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Indexes fetched          : 0 (0 included, 0 excluded)</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table         : DepartmentsV.java [input=DEPARTMENTS_V, output=DEPARTMENTS_V, pk=SYS_C0012234]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table         : EmployeesV.java [input=EMPLOYEES_V, output=EMPLOYEES_V, pk=SYS_C0012235]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table         : JobsV.java [input=JOBS_V, output=JOBS_V, pk=SYS_C0012237]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table         : JobHistoryV.java [input=JOB_HISTORY_V, output=JOB_HISTORY_V, pk=SYS_C0012236]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table         : LocationsV.java [input=LOCATIONS_V, output=LOCATIONS_V, pk=SYS_C0012238]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table         : RegionsV.java [input=REGIONS_V, output=REGIONS_V, pk=SYS_C0012239]</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Tables generated         : Total: 13.888s, +6.405s</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table references</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Table refs generated     : Total: 13.889s, +1.9ms</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating Keys          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Keys generated           : Total: 13.9s, +10.228ms</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating Indexes       </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Skipping empty indexes   </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating table records </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating record        : CountriesVRecord.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating record        : DepartmentsVRecord.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating record        : EmployeesVRecord.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating record        : JobsVRecord.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating record        : JobHistoryVRecord.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating record        : LocationsVRecord.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generating record        : RegionsVRecord.java</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Table records generated  : Total: 13.939s, +39.368ms</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Generation finished: HR  : Total: 13.939s, +0.14ms</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO]                          </span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : OE</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : PM</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : IX</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SH</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : BI</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : FTLDB</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : TEPLSQL</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : ODDGEN</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : OGDEMO</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : AQDEMO</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : AX</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : EMPTRACKER</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : UT3</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : PLSCOPE</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : SONAR</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : TVDCA</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : DEMO</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Excluding empty schema   : JOOQ</span></span>
<span class="line"><span style="color: #D4D4D4">[INFO] Removing excess files</span></span></code></pre></div>


<p></div></div>
<br />
</div></div>




<h2 class="wp-block-heading"><a name="run_simple_query"></a>7. Run a Simple Query</h2>



<p>The following code is a complete Java program. It contains a bit more than the simple query because I will need these parts in the next chapters and would like to focus on the JOOQ query only.</p>



<h3 class="wp-block-heading">Java Program (JOOQ Query)</h3>



<p>On line 3 the view-API is imported statically. This allows to reference the view <code>JOBS_V</code> instead of&nbsp; <code>JobsV.JOBS_V</code> or <code>Hr.JOBS_V</code>. It&#8217;s just convenience, but it makes the code much more readable.</p>



<p>The next static import on line 4 allows for example to use SQL functions such as <code>count()</code>, <code>sum()</code>, etc. without the <code>DSL.</code> prefix. Again, it&#8217;s just convenience, but makes to code shorter and improves readability.</p>



<p>On lines 27-28, the DSL context is initialized.  The context holds the connection to the database and some configuration. In this case I&#8217;ve configured JOOQ to produce formatted SQL statements and fetch data with an array size of 30 from the database. The JDBC default is 10, which is not bad, but 30 is in our case better, since it reduces the network roundtrips to 1 for all SQL query results.</p>



<p>On lines 64-67, we build the SQL statement using the JOOQ DSL. The statement is equivalent to <code>SELECT * FROM hr.jobs_v ORDER BY job_id</code>.</p>



<p>Finally, on line 68 the function <code>fetchAndPrint</code> is called. This function prints the query produced by JOOQ, all used bind variables and the query result. See lines 51, 59 and 60.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Simple Query &#8211; Java Program</span><span role="button" tabindex="0" data-code="package com.trivadis.jooq.pinkdb;

import static com.trivadis.jooq.pinkdb.model.generated.hr.Tables.*;
import static org.jooq.impl.DSL.*;

import com.trivadis.jooq.pinkdb.model.generated.sys.packages.DbmsMonitor;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

import org.jooq.DSLContext;
import org.jooq.Result;
import org.jooq.ResultQuery;
import org.jooq.SQLDialect;
import org.jooq.conf.Settings;
import org.jooq.impl.DSL;

public class Main {
   private static DSLContext ctx;
   private static boolean sqlTrace = false;
   
   private static void initCtx(boolean withSqlTrace) throws SQLException {
      final Connection conn = DriverManager.getConnection(
            &quot;jdbc:oracle:thin:@localhost:1521/odb.docker&quot;, &quot;jooq&quot;, &quot;jooq&quot;);
      ctx = DSL.using(conn, SQLDialect.ORACLE12C, 
            new Settings().withRenderFormatted(true).withFetchSize(30));
      sqlTrace = withSqlTrace;
      enableSqlTrace();
   }
   
   private static void closeCtx() throws SQLException {
      disableSqlTrace();
      ctx.close();
   }
   
   private static void enableSqlTrace() throws SQLException {
      if (sqlTrace) {
         DbmsMonitor.sessionTraceEnable(ctx.configuration(), null, null, true, true, &quot;all_executions&quot;);
      }
   }

   private static void disableSqlTrace() throws SQLException {
      if (sqlTrace) {
         DbmsMonitor.sessionTraceDisable(ctx.configuration(), null, null);
      }
   }
   
   private static void fetchAndPrint(String name, ResultQuery<?&gt; query) {
      System.out.println(name + &quot;: \n\n&quot; + query.getSQL());
      final List<Object&gt; binds = query.getBindValues();
      if (binds.size() &gt; 0) {
         System.out.println(&quot;\n&quot; + name + &quot; binds:&quot;);
         for (int i=0; i<binds.size(); i++) {
            System.out.println(&quot;   &quot; + &quot;:&quot; + (i+1) + &quot; = &quot; + binds.get(i));
         }
      }
      final Result<?&gt; result = query.fetch();
      System.out.println(&quot;\n&quot; + name + &quot; result (&quot; + result.size() + &quot; rows): \n\n&quot; + result.format());            
   }
   
   private static void queryJobs() {
      final ResultQuery<?&gt; query = ctx
            .select()
            .from(JOBS_V)
            .orderBy(JOBS_V.JOB_ID);
      fetchAndPrint(&quot;Jobs&quot;, query);
   }
   
   public static void main(String[] args) throws SQLException {
      initCtx(true);
      queryJobs();
      closeCtx();
   }
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">package</span><span style="color: #D4D4D4"> com.trivadis.jooq.pinkdb;</span></span>
<span class="line"></span>
<span class="line cbp-line-highlight"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> com.trivadis.jooq.pinkdb.model.generated.hr.Tables.*;</span></span>
<span class="line cbp-line-highlight"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> org.jooq.impl.DSL.*;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> com.trivadis.jooq.pinkdb.model.generated.sys.packages.DbmsMonitor;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.Connection;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.DriverManager;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.sql.SQLException;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> java.util.List;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> org.jooq.DSLContext;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> org.jooq.Result;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> org.jooq.ResultQuery;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> org.jooq.SQLDialect;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> org.jooq.conf.Settings;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> org.jooq.impl.DSL;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Main</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">DSLContext</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">ctx</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">boolean</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sqlTrace</span><span style="color: #D4D4D4"> = </span><span style="color: #569CD6">false</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">initCtx</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">boolean</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">withSqlTrace</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">final</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Connection</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">conn</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">DriverManager</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getConnection</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #CE9178">&quot;jdbc:oracle:thin:@localhost:1521/odb.docker&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;jooq&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;jooq&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      ctx = </span><span style="color: #9CDCFE">DSL</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">using</span><span style="color: #D4D4D4">(conn, </span><span style="color: #9CDCFE">SQLDialect</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">ORACLE12C</span><span style="color: #D4D4D4">, </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Settings</span><span style="color: #D4D4D4">().</span><span style="color: #DCDCAA">withRenderFormatted</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">withFetchSize</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">));</span></span>
<span class="line"><span style="color: #D4D4D4">      sqlTrace = withSqlTrace;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">enableSqlTrace</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">closeCtx</span><span style="color: #D4D4D4">() </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">disableSqlTrace</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">ctx</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">close</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">enableSqlTrace</span><span style="color: #D4D4D4">() </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (sqlTrace) {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">DbmsMonitor</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">sessionTraceEnable</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">ctx</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">configuration</span><span style="color: #D4D4D4">(), </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;all_executions&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">disableSqlTrace</span><span style="color: #D4D4D4">() </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (sqlTrace) {</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">DbmsMonitor</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">sessionTraceDisable</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">ctx</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">configuration</span><span style="color: #D4D4D4">(), </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">fetchAndPrint</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">name</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">ResultQuery</span><span style="color: #D4D4D4">&lt;</span><span style="color: #569CD6">?</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4">) {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(name + </span><span style="color: #CE9178">&quot;: </span><span style="color: #D7BA7D">\n\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> + </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getSQL</span><span style="color: #D4D4D4">());</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">final</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">List</span><span style="color: #D4D4D4">&lt;</span><span style="color: #4EC9B0">Object</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">binds</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getBindValues</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">binds</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">size</span><span style="color: #D4D4D4">() &gt; </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> + name + </span><span style="color: #CE9178">&quot; binds:&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> (</span><span style="color: #4EC9B0">int</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">i</span><span style="color: #D4D4D4">=</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">; i&lt;</span><span style="color: #9CDCFE">binds</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">size</span><span style="color: #D4D4D4">(); i++) {</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;   &quot;</span><span style="color: #D4D4D4"> + </span><span style="color: #CE9178">&quot;:&quot;</span><span style="color: #D4D4D4"> + (i+</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">) + </span><span style="color: #CE9178">&quot; = &quot;</span><span style="color: #D4D4D4"> + </span><span style="color: #9CDCFE">binds</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">get</span><span style="color: #D4D4D4">(i));</span></span>
<span class="line"><span style="color: #D4D4D4">         }</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">final</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Result</span><span style="color: #D4D4D4">&lt;</span><span style="color: #569CD6">?</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">result</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">fetch</span><span style="color: #D4D4D4">();</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> + name + </span><span style="color: #CE9178">&quot; result (&quot;</span><span style="color: #D4D4D4"> + </span><span style="color: #9CDCFE">result</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">size</span><span style="color: #D4D4D4">() + </span><span style="color: #CE9178">&quot; rows): </span><span style="color: #D7BA7D">\n\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> + </span><span style="color: #9CDCFE">result</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">format</span><span style="color: #D4D4D4">());            </span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">queryJobs</span><span style="color: #D4D4D4">() {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">final</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">ResultQuery</span><span style="color: #D4D4D4">&lt;</span><span style="color: #569CD6">?</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4"> = ctx</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">select</span><span style="color: #D4D4D4">()</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">from</span><span style="color: #D4D4D4">(JOBS_V)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">orderBy</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">JOBS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">JOB_ID</span><span style="color: #D4D4D4">);</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">fetchAndPrint</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Jobs&quot;</span><span style="color: #D4D4D4">, query);</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">main</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4">[] </span><span style="color: #9CDCFE">args</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">initCtx</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">);</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">queryJobs</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">closeCtx</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<h3 class="wp-block-heading">Java Program Output (SQL Query &amp; Result)</h3>



<p>The program produces this output:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Simple Query &#8211; SQL Query &amp; Result</span><span role="button" tabindex="0" data-code="Jobs: 

select 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;
from &quot;HR&quot;.&quot;JOBS_V&quot;
order by &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;

Jobs result (19 rows): 

+----------+-------------------------------+----------+----------+
|JOB_ID    |JOB_TITLE                      |MIN_SALARY|MAX_SALARY|
+----------+-------------------------------+----------+----------+
|AC_ACCOUNT|Public Accountant              |      4200|      9000|
|AC_MGR    |Accounting Manager             |      8200|     16000|
|AD_ASST   |Administration Assistant       |      3000|      6000|
|AD_PRES   |President                      |     20080|     40000|
|AD_VP     |Administration Vice President  |     15000|     30000|
|FI_ACCOUNT|Accountant                     |      4200|      9000|
|FI_MGR    |Finance Manager                |      8200|     16000|
|HR_REP    |Human Resources Representative |      4000|      9000|
|IT_PROG   |Programmer                     |      4000|     10000|
|MK_MAN    |Marketing Manager              |      9000|     15000|
|MK_REP    |Marketing Representative       |      4000|      9000|
|PR_REP    |Public Relations Representative|      4500|     10500|
|PU_CLERK  |Purchasing Clerk               |      2500|      5500|
|PU_MAN    |Purchasing Manager             |      8000|     15000|
|SA_MAN    |Sales Manager                  |     10000|     20080|
|SA_REP    |Sales Representative           |      6000|     12008|
|SH_CLERK  |Shipping Clerk                 |      2500|      5500|
|ST_CLERK  |Stock Clerk                    |      2008|      5000|
|ST_MAN    |Stock Manager                  |      5500|      8500|
+----------+-------------------------------+----------+----------+" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Jobs: </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">select </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">from &quot;HR&quot;.&quot;JOBS_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">order by &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Jobs result (19 rows): </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">+----------+-------------------------------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|JOB_ID    |JOB_TITLE                      |MIN_SALARY|MAX_SALARY|</span></span>
<span class="line"><span style="color: #D4D4D4">+----------+-------------------------------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|AC_ACCOUNT|Public Accountant              |      4200|      9000|</span></span>
<span class="line"><span style="color: #D4D4D4">|AC_MGR    |Accounting Manager             |      8200|     16000|</span></span>
<span class="line"><span style="color: #D4D4D4">|AD_ASST   |Administration Assistant       |      3000|      6000|</span></span>
<span class="line"><span style="color: #D4D4D4">|AD_PRES   |President                      |     20080|     40000|</span></span>
<span class="line"><span style="color: #D4D4D4">|AD_VP     |Administration Vice President  |     15000|     30000|</span></span>
<span class="line"><span style="color: #D4D4D4">|FI_ACCOUNT|Accountant                     |      4200|      9000|</span></span>
<span class="line"><span style="color: #D4D4D4">|FI_MGR    |Finance Manager                |      8200|     16000|</span></span>
<span class="line"><span style="color: #D4D4D4">|HR_REP    |Human Resources Representative |      4000|      9000|</span></span>
<span class="line"><span style="color: #D4D4D4">|IT_PROG   |Programmer                     |      4000|     10000|</span></span>
<span class="line"><span style="color: #D4D4D4">|MK_MAN    |Marketing Manager              |      9000|     15000|</span></span>
<span class="line"><span style="color: #D4D4D4">|MK_REP    |Marketing Representative       |      4000|      9000|</span></span>
<span class="line"><span style="color: #D4D4D4">|PR_REP    |Public Relations Representative|      4500|     10500|</span></span>
<span class="line"><span style="color: #D4D4D4">|PU_CLERK  |Purchasing Clerk               |      2500|      5500|</span></span>
<span class="line"><span style="color: #D4D4D4">|PU_MAN    |Purchasing Manager             |      8000|     15000|</span></span>
<span class="line"><span style="color: #D4D4D4">|SA_MAN    |Sales Manager                  |     10000|     20080|</span></span>
<span class="line"><span style="color: #D4D4D4">|SA_REP    |Sales Representative           |      6000|     12008|</span></span>
<span class="line"><span style="color: #D4D4D4">|SH_CLERK  |Shipping Clerk                 |      2500|      5500|</span></span>
<span class="line"><span style="color: #D4D4D4">|ST_CLERK  |Stock Clerk                    |      2008|      5000|</span></span>
<span class="line"><span style="color: #D4D4D4">|ST_MAN    |Stock Manager                  |      5500|      8500|</span></span>
<span class="line"><span style="color: #D4D4D4">+----------+-------------------------------+----------+----------+</span></span></code></pre></div>



<p>Two things are interesting.</p>



<p>First, the generated <code>SELECT</code> statement lists all columns, even if no column was defined in the query on program line 65.</p>



<p>Second, the output is formatted nicely. Where did this happen? On line 59 the query is executed and the result is saved in the local variable named <code>result</code>. This is a result set and contains all rows. For example, you may get the number of rows via <code>result.size()</code>, as on line 60. I may also loop through the result set and do whatever I want. In this case, I just used a convenience function <code>format</code> to format the result set as text. There are other convenience functions such as <code>formatCSV</code>, <code>formatHTML</code>, <code>formatJSON</code> or <code>formatXML</code>.  You may guess by the name what they are doing. Nice!</p>



<h3 class="wp-block-heading">SQL Trace Output</h3>



<p>The Java program produces a SQL Trace file by default. See program line 40. Here&#8217;s the relevant <code>tkprof</code> excerpt:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Simple Query &#8211; TKPROF excerpt</span><span role="button" tabindex="0" data-code="call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.03       0.18          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0          2          0          19
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.03       0.18          0          2          0          19

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 133  
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
        19         19         19  TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=45 us starts=1 cost=2 size=627 card=19)
        19         19         19   INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=18 us starts=1 cost=1 size=0 card=19)(object id 78619)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       1        0.00          0.00
  SQL*Net message from client                     1        0.10          0.10" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">call     count       cpu    elapsed       disk      query    current        rows</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">Parse        1      0.03       0.18          0          0          0           0</span></span>
<span class="line"><span style="color: #D4D4D4">Execute      1      0.00       0.00          0          0          0           0</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Fetch        1      0.00       0.00          0          2          0          19</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">total        3      0.03       0.18          0          2          0          19</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Misses in library cache during parse: 1</span></span>
<span class="line"><span style="color: #D4D4D4">Optimizer mode: ALL_ROWS</span></span>
<span class="line"><span style="color: #D4D4D4">Parsing user id: 133  </span></span>
<span class="line"><span style="color: #D4D4D4">Number of plan statistics captured: 1</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Rows (1st) Rows (avg) Rows (max)  Row Source Operation</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- ----------  ---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19  TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=45 us starts=1 cost=2 size=627 card=19)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19   INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=18 us starts=1 cost=1 size=0 card=19)(object id 78619)</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed times include waiting on following events:</span></span>
<span class="line"><span style="color: #D4D4D4">  Event waited on                             Times   Max. Wait  Total Waited</span></span>
<span class="line"><span style="color: #D4D4D4">  ----------------------------------------   Waited  ----------  ------------</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message to client                       1        0.00          0.00</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message from client                     1        0.10          0.10</span></span></code></pre></div>



<p>Interesting is line 5 of the output. There was just one fetch to retrieve 19 rows. A default configuration of the JDBC driver would have caused two fetches. Our configuration on program line 28 worked. All data fetched in a single network roundtrip.</p>



<h2 class="wp-block-heading"><a name="using_joins"></a>8. Using Joins &amp; Aggregations</h2>



<p>In the next example we query the salaries per location. The idea is to look at a JOOQ query with joins and aggregations.</p>



<h3 class="wp-block-heading">JOOQ Query</h3>



<p>On lines 6-8, you see how aggregate functions are used in JOOQ and how to define an alias for the resulting column.</p>



<p>Line 10 is interesting. It defines the join using the <code>onKey</code> function. This function requires a parameter when multiple join paths are possible. In this case <code>EMPLOYEE_V</code> and <code>DEPARTMENTS_V</code> may be joined either via <code>DEPARTMENTS_V.MANAGER_ID</code> or via <code>EMPLOYEES_V.DEPARTMENT_ID</code>. In this case we defined the latter.</p>



<p>On line 11 the <code>onKey</code> function has no parameters, since only one join path exists to <code>LOCATIONS</code>. This clearly shows how JOOQ uses our referential integrity constraints on the view-API to build the query. The idea is similar to a <code>NATURAL JOIN</code>, but the implementation is better since it relies on constraints and not naming conventions. I already miss this feature in SQL.</p>



<p>The use of the functions <code>groupBy</code> and <code>orderBy</code> on line 14 and 15 should be self-explanatory.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Joins &amp; Aggregations &#8211; JOOQ Query</span><span role="button" tabindex="0" data-code="   private static void querySalariesPerLocation() {
      final ResultQuery<?&gt; query = ctx
            .select(REGIONS_V.REGION_NAME,
                  COUNTRIES_V.COUNTRY_NAME,
                  LOCATIONS_V.CITY,
                  count().as(&quot;employees&quot;),
                  sum(EMPLOYEES_V.SALARY).as(&quot;sum_salaray&quot;),
                  max(EMPLOYEES_V.SALARY).as(&quot;max_salary&quot;))
            .from(EMPLOYEES_V)
            .join(DEPARTMENTS_V).onKey(EMPLOYEES_V.DEPARTMENT_ID)
            .join(LOCATIONS_V).onKey()
            .join(COUNTRIES_V).onKey()
            .join(REGIONS_V).onKey()
            .groupBy(REGIONS_V.REGION_NAME, COUNTRIES_V.COUNTRY_NAME, LOCATIONS_V.CITY)
            .orderBy(REGIONS_V.REGION_NAME, COUNTRIES_V.COUNTRY_NAME, LOCATIONS_V.CITY);
      fetchAndPrint(&quot;Salaries Per Location&quot;, query);
   }" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">querySalariesPerLocation</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">final</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">ResultQuery</span><span style="color: #D4D4D4">&lt;</span><span style="color: #569CD6">?</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4"> = ctx</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">select</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">REGIONS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">REGION_NAME</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">COUNTRIES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">COUNTRY_NAME</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">LOCATIONS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">CITY</span><span style="color: #D4D4D4">,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">().</span><span style="color: #DCDCAA">as</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;employees&quot;</span><span style="color: #D4D4D4">),</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">as</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;sum_salaray&quot;</span><span style="color: #D4D4D4">),</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #DCDCAA">max</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">as</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;max_salary&quot;</span><span style="color: #D4D4D4">))</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">from</span><span style="color: #D4D4D4">(EMPLOYEES_V)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">join</span><span style="color: #D4D4D4">(DEPARTMENTS_V).</span><span style="color: #DCDCAA">onKey</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">DEPARTMENT_ID</span><span style="color: #D4D4D4">)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">join</span><span style="color: #D4D4D4">(LOCATIONS_V).</span><span style="color: #DCDCAA">onKey</span><span style="color: #D4D4D4">()</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">join</span><span style="color: #D4D4D4">(COUNTRIES_V).</span><span style="color: #DCDCAA">onKey</span><span style="color: #D4D4D4">()</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">join</span><span style="color: #D4D4D4">(REGIONS_V).</span><span style="color: #DCDCAA">onKey</span><span style="color: #D4D4D4">()</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">groupBy</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">REGIONS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">REGION_NAME</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">COUNTRIES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">COUNTRY_NAME</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">LOCATIONS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">CITY</span><span style="color: #D4D4D4">)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">orderBy</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">REGIONS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">REGION_NAME</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">COUNTRIES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">COUNTRY_NAME</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">LOCATIONS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">CITY</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">fetchAndPrint</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Salaries Per Location&quot;</span><span style="color: #D4D4D4">, query);</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Query &amp; Result</h3>



<p>No surprises. The query looks as expected.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Joins &amp; Aggregations &#8211; SQL Query &amp; Result</span><span role="button" tabindex="0" data-code="Salaries Per Location: 

select 
  &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_NAME&quot;, 
  &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_NAME&quot;, 
  &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;CITY&quot;, 
  count(*) &quot;employees&quot;, 
  sum(&quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;) &quot;sum_salaray&quot;, 
  max(&quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;) &quot;max_salary&quot;
from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;
  join &quot;HR&quot;.&quot;DEPARTMENTS_V&quot;
  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;DEPARTMENT_ID&quot; = &quot;HR&quot;.&quot;DEPARTMENTS_V&quot;.&quot;DEPARTMENT_ID&quot;
  join &quot;HR&quot;.&quot;LOCATIONS_V&quot;
  on &quot;HR&quot;.&quot;DEPARTMENTS_V&quot;.&quot;LOCATION_ID&quot; = &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;LOCATION_ID&quot;
  join &quot;HR&quot;.&quot;COUNTRIES_V&quot;
  on &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;COUNTRY_ID&quot; = &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_ID&quot;
  join &quot;HR&quot;.&quot;REGIONS_V&quot;
  on &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;REGION_ID&quot; = &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_ID&quot;
group by 
  &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_NAME&quot;, 
  &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_NAME&quot;, 
  &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;CITY&quot;
order by 
  &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_NAME&quot;, 
  &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_NAME&quot;, 
  &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;CITY&quot;


Salaries Per Location result (7 rows): 

+-----------+------------------------+-------------------+---------+-----------+----------+
|REGION_NAME|COUNTRY_NAME            |CITY               |employees|sum_salaray|max_salary|
+-----------+------------------------+-------------------+---------+-----------+----------+
|Americas   |Canada                  |Toronto            |        2|      19000|     13000|
|Americas   |United States of America|Seattle            |       18|     159216|     24000|
|Americas   |United States of America|South San Francisco|       45|     156400|      8200|
|Americas   |United States of America|Southlake          |        5|      28800|      9000|
|Europe     |Germany                 |Munich             |        1|      10000|     10000|
|Europe     |United Kingdom          |London             |        1|       6500|      6500|
|Europe     |United Kingdom          |Oxford             |       34|     304500|     14000|
+-----------+------------------------+-------------------+---------+-----------+----------+" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Salaries Per Location: </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">select </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;CITY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  count(*) &quot;employees&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  sum(&quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;) &quot;sum_salaray&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  max(&quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;) &quot;max_salary&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  join &quot;HR&quot;.&quot;DEPARTMENTS_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;DEPARTMENT_ID&quot; = &quot;HR&quot;.&quot;DEPARTMENTS_V&quot;.&quot;DEPARTMENT_ID&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  join &quot;HR&quot;.&quot;LOCATIONS_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  on &quot;HR&quot;.&quot;DEPARTMENTS_V&quot;.&quot;LOCATION_ID&quot; = &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;LOCATION_ID&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  join &quot;HR&quot;.&quot;COUNTRIES_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  on &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;COUNTRY_ID&quot; = &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_ID&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  join &quot;HR&quot;.&quot;REGIONS_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  on &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;REGION_ID&quot; = &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_ID&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">group by </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;CITY&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">order by </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;REGIONS_V&quot;.&quot;REGION_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;COUNTRIES_V&quot;.&quot;COUNTRY_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;LOCATIONS_V&quot;.&quot;CITY&quot;</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Salaries Per Location result (7 rows): </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">+-----------+------------------------+-------------------+---------+-----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|REGION_NAME|COUNTRY_NAME            |CITY               |employees|sum_salaray|max_salary|</span></span>
<span class="line"><span style="color: #D4D4D4">+-----------+------------------------+-------------------+---------+-----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|Americas   |Canada                  |Toronto            |        2|      19000|     13000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Americas   |United States of America|Seattle            |       18|     159216|     24000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Americas   |United States of America|South San Francisco|       45|     156400|      8200|</span></span>
<span class="line"><span style="color: #D4D4D4">|Americas   |United States of America|Southlake          |        5|      28800|      9000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Europe     |Germany                 |Munich             |        1|      10000|     10000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Europe     |United Kingdom          |London             |        1|       6500|      6500|</span></span>
<span class="line"><span style="color: #D4D4D4">|Europe     |United Kingdom          |Oxford             |       34|     304500|     14000|</span></span>
<span class="line"><span style="color: #D4D4D4">+-----------+------------------------+-------------------+---------+-----------+----------+</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Trace Output</h3>



<p>In the <code>tkprof</code> output we see that parsing took more than a second. This is a bit too long for this kind of query. However, that is not a problem of JOOQ. Beside that, the output looks good. Single network roundtrip as expected.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Joins &amp; Aggregations &#8211; TKPROF excerpt</span><span role="button" tabindex="0" data-code="call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.24       1.09          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0         22          0           7
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.25       1.09          0         22          0           7

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 133  
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         7          7          7  SORT GROUP BY (cr=24 pr=0 pw=0 time=8817 us starts=1 cost=12 size=5512 card=106)
       106        106        106   HASH JOIN  (cr=24 pr=0 pw=0 time=8745 us starts=1 cost=11 size=5512 card=106)
        27         27         27    MERGE JOIN  (cr=16 pr=0 pw=0 time=294 us starts=1 cost=8 size=1215 card=27)
         3          3          3     TABLE ACCESS BY INDEX ROWID REGIONS (cr=2 pr=0 pw=0 time=43 us starts=1 cost=2 size=56 card=4)
         3          3          3      INDEX FULL SCAN REG_ID_PK (cr=1 pr=0 pw=0 time=11 us starts=1 cost=1 size=0 card=4)(object id 78609)
        27         27         27     SORT JOIN (cr=14 pr=0 pw=0 time=251 us starts=3 cost=6 size=837 card=27)
        27         27         27      VIEW  VW_GBF_23 (cr=14 pr=0 pw=0 time=328 us starts=1 cost=5 size=837 card=27)
        27         27         27       NESTED LOOPS  (cr=14 pr=0 pw=0 time=325 us starts=1 cost=5 size=999 card=27)
        27         27         27        MERGE JOIN  (cr=10 pr=0 pw=0 time=238 us starts=1 cost=5 size=594 card=27)
        19         19         19         TABLE ACCESS BY INDEX ROWID LOCATIONS (cr=2 pr=0 pw=0 time=32 us starts=1 cost=2 size=345 card=23)
        19         19         19          INDEX FULL SCAN LOC_ID_PK (cr=1 pr=0 pw=0 time=26 us starts=1 cost=1 size=0 card=23)(object id 78613)
        27         27         27         SORT JOIN (cr=8 pr=0 pw=0 time=189 us starts=19 cost=3 size=189 card=27)
        27         27         27          VIEW  index$_join$_013 (cr=8 pr=0 pw=0 time=163 us starts=1 cost=2 size=189 card=27)
        27         27         27           HASH JOIN  (cr=8 pr=0 pw=0 time=162 us starts=1)
        27         27         27            INDEX FAST FULL SCAN DEPT_ID_PK (cr=4 pr=0 pw=0 time=35 us starts=1 cost=1 size=189 card=27)(object id 78616)
        27         27         27            INDEX FAST FULL SCAN DEPT_LOCATION_IX (cr=4 pr=0 pw=0 time=15 us starts=1 cost=1 size=189 card=27)(object id 78631)
        27         27         27        INDEX UNIQUE SCAN COUNTRY_C_ID_PK (cr=4 pr=0 pw=0 time=20 us starts=27 cost=0 size=15 card=1)(object id 78611)
       107        107        107    TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=35 us starts=1 cost=3 size=749 card=107)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       1        0.00          0.00
  PGA memory operation                            1        0.00          0.00
  SQL*Net message from client                     1        0.01          0.01" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">call     count       cpu    elapsed       disk      query    current        rows</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Parse        1      0.24       1.09          0          0          0           0</span></span>
<span class="line"><span style="color: #D4D4D4">Execute      1      0.00       0.00          0          0          0           0</span></span>
<span class="line"><span style="color: #D4D4D4">Fetch        1      0.00       0.00          0         22          0           7</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">total        3      0.25       1.09          0         22          0           7</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Misses in library cache during parse: 1</span></span>
<span class="line"><span style="color: #D4D4D4">Optimizer mode: ALL_ROWS</span></span>
<span class="line"><span style="color: #D4D4D4">Parsing user id: 133  </span></span>
<span class="line"><span style="color: #D4D4D4">Number of plan statistics captured: 1</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Rows (1st) Rows (avg) Rows (max)  Row Source Operation</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- ----------  ---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">         7          7          7  SORT GROUP BY (cr=24 pr=0 pw=0 time=8817 us starts=1 cost=12 size=5512 card=106)</span></span>
<span class="line"><span style="color: #D4D4D4">       106        106        106   HASH JOIN  (cr=24 pr=0 pw=0 time=8745 us starts=1 cost=11 size=5512 card=106)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27    MERGE JOIN  (cr=16 pr=0 pw=0 time=294 us starts=1 cost=8 size=1215 card=27)</span></span>
<span class="line"><span style="color: #D4D4D4">         3          3          3     TABLE ACCESS BY INDEX ROWID REGIONS (cr=2 pr=0 pw=0 time=43 us starts=1 cost=2 size=56 card=4)</span></span>
<span class="line"><span style="color: #D4D4D4">         3          3          3      INDEX FULL SCAN REG_ID_PK (cr=1 pr=0 pw=0 time=11 us starts=1 cost=1 size=0 card=4)(object id 78609)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27     SORT JOIN (cr=14 pr=0 pw=0 time=251 us starts=3 cost=6 size=837 card=27)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27      VIEW  VW_GBF_23 (cr=14 pr=0 pw=0 time=328 us starts=1 cost=5 size=837 card=27)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27       NESTED LOOPS  (cr=14 pr=0 pw=0 time=325 us starts=1 cost=5 size=999 card=27)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27        MERGE JOIN  (cr=10 pr=0 pw=0 time=238 us starts=1 cost=5 size=594 card=27)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19         TABLE ACCESS BY INDEX ROWID LOCATIONS (cr=2 pr=0 pw=0 time=32 us starts=1 cost=2 size=345 card=23)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19          INDEX FULL SCAN LOC_ID_PK (cr=1 pr=0 pw=0 time=26 us starts=1 cost=1 size=0 card=23)(object id 78613)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27         SORT JOIN (cr=8 pr=0 pw=0 time=189 us starts=19 cost=3 size=189 card=27)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27          VIEW  index$_join$_013 (cr=8 pr=0 pw=0 time=163 us starts=1 cost=2 size=189 card=27)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27           HASH JOIN  (cr=8 pr=0 pw=0 time=162 us starts=1)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27            INDEX FAST FULL SCAN DEPT_ID_PK (cr=4 pr=0 pw=0 time=35 us starts=1 cost=1 size=189 card=27)(object id 78616)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27            INDEX FAST FULL SCAN DEPT_LOCATION_IX (cr=4 pr=0 pw=0 time=15 us starts=1 cost=1 size=189 card=27)(object id 78631)</span></span>
<span class="line"><span style="color: #D4D4D4">        27         27         27        INDEX UNIQUE SCAN COUNTRY_C_ID_PK (cr=4 pr=0 pw=0 time=20 us starts=27 cost=0 size=15 card=1)(object id 78611)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107    TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=35 us starts=1 cost=3 size=749 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed times include waiting on following events:</span></span>
<span class="line"><span style="color: #D4D4D4">  Event waited on                             Times   Max. Wait  Total Waited</span></span>
<span class="line"><span style="color: #D4D4D4">  ----------------------------------------   Waited  ----------  ------------</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message to client                       1        0.00          0.00</span></span>
<span class="line"><span style="color: #D4D4D4">  PGA memory operation                            1        0.00          0.00</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message from client                     1        0.01          0.01</span></span></code></pre></div>



<h2 class="wp-block-heading"><a name="using_binds"></a>9. Using Bind Variables</h2>



<p>Parsing can be costly, as we have seen in the previous example. Using bind variables can reduce parsing. In this case I&#8217;d like to see how I can avoid hard- and soft-parsing. See <a href="http://www.orafaq.com/wiki/Parsing">Oracle FAQs</a> for good parsing definitions.</p>



<h3 class="wp-block-heading">JOOQ Query</h3>



<p>JOOQ automatically creates bind variables for the usages of <code>fromSalary</code> and <code>toSalary</code> on line 23. This means that JOOQ eliminates unnecessary hard parses by design. To eliminate unnecessary soft-parses we have to ensure that the Java statement behind the scenes is not closed. JOOQ provides the <code>keepStatement</code> function for that purpose as used on line 25. When using this function we are responsible to close the statement. We do so on line 7.</p>



<p>We call the query twice. See lines 36 and 37. On the first call, the bind variables are set automatically by JOOQ when building the <code>preparedQuery</code>. On subsequent calls the <code>preparedQuery</code> is reused and its bind variable values are changed. See line 27 and 28. Fetching and printing works as for the other JOOQ queries. The only difference is, that the statement is not closed after the last row is fetched.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Bind Variables &#8211; JOOQ Query</span><span role="button" tabindex="0" data-code="public class Main {
   private static ResultQuery<?&gt; preparedQuery;
   (...)
   private static void closeCtx() throws SQLException {
      disableSqlTrace();
      if (preparedQuery != null) {
         preparedQuery.close();
      }
      ctx.close();
   }
   (...)
   private static void queryEmployeesInSalaryRange(BigDecimal fromSalary, BigDecimal toSalary) {
      if (preparedQuery == null) {
         preparedQuery = ctx
               .select(JOBS_V.JOB_TITLE,
                     EMPLOYEES_V.LAST_NAME,
                     EMPLOYEES_V.FIRST_NAME,
                     EMPLOYEES_V.SALARY,
                     JOBS_V.MIN_SALARY,
                     JOBS_V.MAX_SALARY)
               .from(EMPLOYEES_V)
               .join(JOBS_V).onKey()
               .where(EMPLOYEES_V.SALARY.between(fromSalary, toSalary))
               .orderBy(EMPLOYEES_V.SALARY.desc())
               .keepStatement(true);
      } else {
         preparedQuery.bind(1, fromSalary);
         preparedQuery.bind(2, toSalary);
      }
      fetchAndPrint(&quot;Employees in Salary Range&quot;, preparedQuery);
   }
   (...)
   public static void main(String[] args) throws SQLException {
      initCtx(true);
      (...)
      queryEmployeesInSalaryRange(BigDecimal.valueOf(13000), BigDecimal.valueOf(100000));
      queryEmployeesInSalaryRange(BigDecimal.valueOf(10000), BigDecimal.valueOf(13000));
      closeCtx();
   }
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">class</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">Main</span><span style="color: #D4D4D4"> {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">ResultQuery</span><span style="color: #D4D4D4">&lt;</span><span style="color: #569CD6">?</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">preparedQuery</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   (...)</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">closeCtx</span><span style="color: #D4D4D4">() </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">disableSqlTrace</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (preparedQuery != </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">) {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">preparedQuery</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">close</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">ctx</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">close</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   (...)</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">queryEmployeesInSalaryRange</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">BigDecimal</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">fromSalary</span><span style="color: #D4D4D4">, </span><span style="color: #4EC9B0">BigDecimal</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">toSalary</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (preparedQuery == </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">         preparedQuery = ctx</span></span>
<span class="line"><span style="color: #D4D4D4">               .</span><span style="color: #DCDCAA">select</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">JOBS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">JOB_TITLE</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                     </span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">LAST_NAME</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                     </span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">FIRST_NAME</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                     </span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                     </span><span style="color: #9CDCFE">JOBS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">MIN_SALARY</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                     </span><span style="color: #9CDCFE">JOBS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">MAX_SALARY</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">               .</span><span style="color: #DCDCAA">from</span><span style="color: #D4D4D4">(EMPLOYEES_V)</span></span>
<span class="line"><span style="color: #D4D4D4">               .</span><span style="color: #DCDCAA">join</span><span style="color: #D4D4D4">(JOBS_V).</span><span style="color: #DCDCAA">onKey</span><span style="color: #D4D4D4">()</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">               .</span><span style="color: #DCDCAA">where</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">between</span><span style="color: #D4D4D4">(fromSalary, toSalary))</span></span>
<span class="line"><span style="color: #D4D4D4">               .</span><span style="color: #DCDCAA">orderBy</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">desc</span><span style="color: #D4D4D4">())</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">               .</span><span style="color: #DCDCAA">keepStatement</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      } </span><span style="color: #C586C0">else</span><span style="color: #D4D4D4"> {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">preparedQuery</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">bind</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, fromSalary);</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         </span><span style="color: #9CDCFE">preparedQuery</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">bind</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, toSalary);</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">fetchAndPrint</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Employees in Salary Range&quot;</span><span style="color: #D4D4D4">, preparedQuery);</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">   (...)</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">public</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">main</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4">[] </span><span style="color: #9CDCFE">args</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">throws</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">SQLException</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">initCtx</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      (...)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">queryEmployeesInSalaryRange</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">BigDecimal</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">valueOf</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">13000</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">BigDecimal</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">valueOf</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">100000</span><span style="color: #D4D4D4">));</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">queryEmployeesInSalaryRange</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">BigDecimal</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">valueOf</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">10000</span><span style="color: #D4D4D4">), </span><span style="color: #9CDCFE">BigDecimal</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">valueOf</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">13000</span><span style="color: #D4D4D4">));</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">closeCtx</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Query &amp; Result</h3>



<p>We are executing the query twice. Hence we see two output sets.</p>



<p>On lines 13/45, you see the bind variable placeholders (?).</p>



<p>On lines 17-18/49-50, you see the values of the bind variables.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Plaintext</span><span role="button" tabindex="0" data-code="Employees in Salary Range: 

select 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;LAST_NAME&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;FIRST_NAME&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;
from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;
  join &quot;HR&quot;.&quot;JOBS_V&quot;
  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot; = &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;
where &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; between ? and ?
order by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; desc

Employees in Salary Range binds:
   :1 = 13000
   :2 = 100000

Employees in Salary Range result (6 rows): 

+-----------------------------+---------+----------+------+----------+----------+
|JOB_TITLE                    |LAST_NAME|FIRST_NAME|SALARY|MIN_SALARY|MAX_SALARY|
+-----------------------------+---------+----------+------+----------+----------+
|President                    |King     |Steven    | 24000|     20080|     40000|
|Administration Vice President|Kochhar  |Neena     | 17000|     15000|     30000|
|Administration Vice President|De Haan  |Lex       | 17000|     15000|     30000|
|Sales Manager                |Russell  |John      | 14000|     10000|     20080|
|Sales Manager                |Partners |Karen     | 13500|     10000|     20080|
|Marketing Manager            |Hartstein|Michael   | 13000|      9000|     15000|
+-----------------------------+---------+----------+------+----------+----------+

Employees in Salary Range: 

select 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;LAST_NAME&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;FIRST_NAME&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;
from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;
  join &quot;HR&quot;.&quot;JOBS_V&quot;
  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot; = &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;
where &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; between ? and ?
order by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; desc

Employees in Salary Range binds:
   :1 = 10000
   :2 = 13000

Employees in Salary Range result (14 rows): 

+-------------------------------+---------+----------+------+----------+----------+
|JOB_TITLE                      |LAST_NAME|FIRST_NAME|SALARY|MIN_SALARY|MAX_SALARY|
+-------------------------------+---------+----------+------+----------+----------+
|Marketing Manager              |Hartstein|Michael   | 13000|      9000|     15000|
|Finance Manager                |Greenberg|Nancy     | 12008|      8200|     16000|
|Accounting Manager             |Higgins  |Shelley   | 12008|      8200|     16000|
|Sales Manager                  |Errazuriz|Alberto   | 12000|     10000|     20080|
|Sales Representative           |Ozer     |Lisa      | 11500|      6000|     12008|
|Purchasing Manager             |Raphaely |Den       | 11000|      8000|     15000|
|Sales Manager                  |Cambrault|Gerald    | 11000|     10000|     20080|
|Sales Representative           |Abel     |Ellen     | 11000|      6000|     12008|
|Sales Representative           |Vishney  |Clara     | 10500|      6000|     12008|
|Sales Manager                  |Zlotkey  |Eleni     | 10500|     10000|     20080|
|Sales Representative           |Tucker   |Peter     | 10000|      6000|     12008|
|Sales Representative           |Bloom    |Harrison  | 10000|      6000|     12008|
|Public Relations Representative|Baer     |Hermann   | 10000|      4500|     10500|
|Sales Representative           |King     |Janette   | 10000|      6000|     12008|
+-------------------------------+---------+----------+------+----------+----------+" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Employees in Salary Range: </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">select </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;LAST_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;FIRST_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  join &quot;HR&quot;.&quot;JOBS_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot; = &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">where &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; between ? and ?</span></span>
<span class="line"><span style="color: #D4D4D4">order by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; desc</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Employees in Salary Range binds:</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   :1 = 13000</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   :2 = 100000</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Employees in Salary Range result (6 rows): </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">+-----------------------------+---------+----------+------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|JOB_TITLE                    |LAST_NAME|FIRST_NAME|SALARY|MIN_SALARY|MAX_SALARY|</span></span>
<span class="line"><span style="color: #D4D4D4">+-----------------------------+---------+----------+------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|President                    |King     |Steven    | 24000|     20080|     40000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Administration Vice President|Kochhar  |Neena     | 17000|     15000|     30000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Administration Vice President|De Haan  |Lex       | 17000|     15000|     30000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Manager                |Russell  |John      | 14000|     10000|     20080|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Manager                |Partners |Karen     | 13500|     10000|     20080|</span></span>
<span class="line"><span style="color: #D4D4D4">|Marketing Manager            |Hartstein|Michael   | 13000|      9000|     15000|</span></span>
<span class="line"><span style="color: #D4D4D4">+-----------------------------+---------+----------+------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Employees in Salary Range: </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">select </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;LAST_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;FIRST_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  join &quot;HR&quot;.&quot;JOBS_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot; = &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">where &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; between ? and ?</span></span>
<span class="line"><span style="color: #D4D4D4">order by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot; desc</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Employees in Salary Range binds:</span></span>
<span class="line"><span style="color: #D4D4D4">   :1 = 10000</span></span>
<span class="line"><span style="color: #D4D4D4">   :2 = 13000</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Employees in Salary Range result (14 rows): </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">+-------------------------------+---------+----------+------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|JOB_TITLE                      |LAST_NAME|FIRST_NAME|SALARY|MIN_SALARY|MAX_SALARY|</span></span>
<span class="line"><span style="color: #D4D4D4">+-------------------------------+---------+----------+------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|Marketing Manager              |Hartstein|Michael   | 13000|      9000|     15000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Finance Manager                |Greenberg|Nancy     | 12008|      8200|     16000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Accounting Manager             |Higgins  |Shelley   | 12008|      8200|     16000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Manager                  |Errazuriz|Alberto   | 12000|     10000|     20080|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |Ozer     |Lisa      | 11500|      6000|     12008|</span></span>
<span class="line"><span style="color: #D4D4D4">|Purchasing Manager             |Raphaely |Den       | 11000|      8000|     15000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Manager                  |Cambrault|Gerald    | 11000|     10000|     20080|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |Abel     |Ellen     | 11000|      6000|     12008|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |Vishney  |Clara     | 10500|      6000|     12008|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Manager                  |Zlotkey  |Eleni     | 10500|     10000|     20080|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |Tucker   |Peter     | 10000|      6000|     12008|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |Bloom    |Harrison  | 10000|      6000|     12008|</span></span>
<span class="line"><span style="color: #D4D4D4">|Public Relations Representative|Baer     |Hermann   | 10000|      4500|     10500|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |King     |Janette   | 10000|      6000|     12008|</span></span>
<span class="line"><span style="color: #D4D4D4">+-------------------------------+---------+----------+------+----------+----------+</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Trace Output</h3>



<p>The <code>tkprof</code> excerpt on line 4 shows that the query is executed twice. Line 3 reveals that the query is parsed only once. The total of 20 rows are read in two network roundtrips. That&#8217;s perfect.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Bind Variables &#8211; TKPROF excerpt</span><span role="button" tabindex="0" data-code="call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      2      0.01       0.05          0          0          0           0
Fetch        2      0.00       0.00          0         16          0          20
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        5      0.01       0.05          0         16          0          20

Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 133  
Number of plan statistics captured: 2

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         6         10         14  SORT ORDER BY (cr=8 pr=0 pw=0 time=160 us starts=1 cost=7 size=366 card=6)
         6         10         14   FILTER  (cr=8 pr=0 pw=0 time=156 us starts=1)
         6         10         14    MERGE JOIN  (cr=8 pr=0 pw=0 time=153 us starts=1 cost=6 size=366 card=6)
        16         16         17     TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=38 us starts=1 cost=2 size=627 card=19)
        16         16         17      INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=20 us starts=1 cost=1 size=0 card=19)(object id 78619)
         6         10         14     SORT JOIN (cr=6 pr=0 pw=0 time=94 us starts=16 cost=4 size=168 card=6)
         6         10         14      TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=68 us starts=1 cost=3 size=168 card=6)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       2        0.00          0.00
  SQL*Net message from client                     2        0.00          0.00" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">call     count       cpu    elapsed       disk      query    current        rows</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Parse        1      0.00       0.00          0          0          0           0</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Execute      2      0.01       0.05          0          0          0           0</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Fetch        2      0.00       0.00          0         16          0          20</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">total        5      0.01       0.05          0         16          0          20</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Misses in library cache during parse: 1</span></span>
<span class="line"><span style="color: #D4D4D4">Misses in library cache during execute: 1</span></span>
<span class="line"><span style="color: #D4D4D4">Optimizer mode: ALL_ROWS</span></span>
<span class="line"><span style="color: #D4D4D4">Parsing user id: 133  </span></span>
<span class="line"><span style="color: #D4D4D4">Number of plan statistics captured: 2</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Rows (1st) Rows (avg) Rows (max)  Row Source Operation</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- ----------  ---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">         6         10         14  SORT ORDER BY (cr=8 pr=0 pw=0 time=160 us starts=1 cost=7 size=366 card=6)</span></span>
<span class="line"><span style="color: #D4D4D4">         6         10         14   FILTER  (cr=8 pr=0 pw=0 time=156 us starts=1)</span></span>
<span class="line"><span style="color: #D4D4D4">         6         10         14    MERGE JOIN  (cr=8 pr=0 pw=0 time=153 us starts=1 cost=6 size=366 card=6)</span></span>
<span class="line"><span style="color: #D4D4D4">        16         16         17     TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=38 us starts=1 cost=2 size=627 card=19)</span></span>
<span class="line"><span style="color: #D4D4D4">        16         16         17      INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=20 us starts=1 cost=1 size=0 card=19)(object id 78619)</span></span>
<span class="line"><span style="color: #D4D4D4">         6         10         14     SORT JOIN (cr=6 pr=0 pw=0 time=94 us starts=16 cost=4 size=168 card=6)</span></span>
<span class="line"><span style="color: #D4D4D4">         6         10         14      TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=68 us starts=1 cost=3 size=168 card=6)</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed times include waiting on following events:</span></span>
<span class="line"><span style="color: #D4D4D4">  Event waited on                             Times   Max. Wait  Total Waited</span></span>
<span class="line"><span style="color: #D4D4D4">  ----------------------------------------   Waited  ----------  ------------</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message to client                       2        0.00          0.00</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message from client                     2        0.00          0.00</span></span></code></pre></div>



<h2 class="wp-block-heading"><a name="run_top_n_query"></a>10. Run a Top N Query</h2>



<p>In the next example we query the 4 employees with the lowest salary along with some general salary information. It&#8217;ll be interesting to see if JOOQ uses Oracle&#8217;s native top-n query syntax.</p>



<h3 class="wp-block-heading">JOOQ Query</h3>



<p>On line 8 we see that JOOQ has no problems dealing with analytic functions.</p>



<p>On line 14 the top n query is defined. Limit the result to 4 rows with ties, this means rows with the same order by values are considered as well.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Top N Query &#8211; JOOQ Query</span><span role="button" tabindex="0" data-code="   private static void queryTopBadEarners() {
       final ResultQuery<?&gt; query = ctx
            .select(JOBS_V.JOB_TITLE,
                  EMPLOYEES_V.LAST_NAME,
                  EMPLOYEES_V.FIRST_NAME,
                  EMPLOYEES_V.HIRE_DATE,
                  EMPLOYEES_V.SALARY,
                  avg(EMPLOYEES_V.SALARY).over().partitionBy(EMPLOYEES_V.JOB_ID).as(&quot;avg_salary&quot;),
                  JOBS_V.MIN_SALARY,
                  JOBS_V.MAX_SALARY)
            .from(EMPLOYEES_V)
            .join(JOBS_V).onKey()
            .orderBy(EMPLOYEES_V.SALARY)
            .limit(4).withTies();
      fetchAndPrint(&quot;Top 4 Bad Earners&quot;, query);
   }" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">queryTopBadEarners</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">final</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">ResultQuery</span><span style="color: #D4D4D4">&lt;</span><span style="color: #569CD6">?</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4"> = ctx</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">select</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">JOBS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">JOB_TITLE</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">LAST_NAME</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">FIRST_NAME</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">HIRE_DATE</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #DCDCAA">avg</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">over</span><span style="color: #D4D4D4">().</span><span style="color: #DCDCAA">partitionBy</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">JOB_ID</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">as</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;avg_salary&quot;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">JOBS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">MIN_SALARY</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #9CDCFE">JOBS_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">MAX_SALARY</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">from</span><span style="color: #D4D4D4">(EMPLOYEES_V)</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">join</span><span style="color: #D4D4D4">(JOBS_V).</span><span style="color: #DCDCAA">onKey</span><span style="color: #D4D4D4">()</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">orderBy</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">EMPLOYEES_V</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">SALARY</span><span style="color: #D4D4D4">)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">limit</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">).</span><span style="color: #DCDCAA">withTies</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">fetchAndPrint</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Top 4 Bad Earners&quot;</span><span style="color: #D4D4D4">, query);</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Query &amp; Result</h3>



<p>The query crafted by JOOQ is a native Oracle top n query. See line 16. Very good.</p>



<p>Interesting is, that JOOQ also creates a bind variable for the literal 4. This could be good or bad. If you want to use a literal instead of a bind variable, you can simply use <code>inline(4)</code>&nbsp; instead of <code>4</code>. The default behaviour of JOOQ reminds a little of <code>CURSOR_SHARING=FORCE</code>. But since you may control the behaviour on statement level, I think it is a good and sensible default.</p>



<p>We got a result of 5 rows, because Landry and Gee both have a salary of 2400. That&#8217;s the result of <code>WITH TIES</code>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Top N Query &#8211; SQL Query &amp; Result</span><span role="button" tabindex="0" data-code="Top 4 Bad Earners: 

select 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;LAST_NAME&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;FIRST_NAME&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;HIRE_DATE&quot;, 
  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;, 
  avg(&quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;) over (partition by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot;) &quot;avg_salary&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, 
  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;
from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;
  join &quot;HR&quot;.&quot;JOBS_V&quot;
  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot; = &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;
order by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;
fetch next ? rows with ties

Top 4 Bad Earners binds:
   :1 = 4

Top 4 Bad Earners result (5 rows): 

+-----------+----------+----------+----------+------+----------+----------+----------+
|JOB_TITLE  |LAST_NAME |FIRST_NAME|HIRE_DATE |SALARY|avg_salary|MIN_SALARY|MAX_SALARY|
+-----------+----------+----------+----------+------+----------+----------+----------+
|Stock Clerk|Olson     |TJ        |2007-04-10|  2100|      2785|      2008|      5000|
|Stock Clerk|Markle    |Steven    |2008-03-08|  2200|      2785|      2008|      5000|
|Stock Clerk|Philtanker|Hazel     |2008-02-06|  2200|      2785|      2008|      5000|
|Stock Clerk|Landry    |James     |2007-01-14|  2400|      2785|      2008|      5000|
|Stock Clerk|Gee       |Ki        |2007-12-12|  2400|      2785|      2008|      5000|
+-----------+----------+----------+----------+------+----------+----------+----------+" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Top 4 Bad Earners: </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">select </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_TITLE&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;LAST_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;FIRST_NAME&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;HIRE_DATE&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  avg(&quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;) over (partition by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot;) &quot;avg_salary&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MIN_SALARY&quot;, </span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;MAX_SALARY&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">from &quot;HR&quot;.&quot;EMPLOYEES_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  join &quot;HR&quot;.&quot;JOBS_V&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  on &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;JOB_ID&quot; = &quot;HR&quot;.&quot;JOBS_V&quot;.&quot;JOB_ID&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">order by &quot;HR&quot;.&quot;EMPLOYEES_V&quot;.&quot;SALARY&quot;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">fetch next ? rows with ties</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Top 4 Bad Earners binds:</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   :1 = 4</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Top 4 Bad Earners result (5 rows): </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">+-----------+----------+----------+----------+------+----------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|JOB_TITLE  |LAST_NAME |FIRST_NAME|HIRE_DATE |SALARY|avg_salary|MIN_SALARY|MAX_SALARY|</span></span>
<span class="line"><span style="color: #D4D4D4">+-----------+----------+----------+----------+------+----------+----------+----------+</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Clerk|Olson     |TJ        |2007-04-10|  2100|      2785|      2008|      5000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Clerk|Markle    |Steven    |2008-03-08|  2200|      2785|      2008|      5000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Clerk|Philtanker|Hazel     |2008-02-06|  2200|      2785|      2008|      5000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Clerk|Landry    |James     |2007-01-14|  2400|      2785|      2008|      5000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Clerk|Gee       |Ki        |2007-12-12|  2400|      2785|      2008|      5000|</span></span>
<span class="line"><span style="color: #D4D4D4">+-----------+----------+----------+----------+------+----------+----------+----------+</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Trace Output</h3>



<p>The <code>tkprof</code> excerpt looks good. Good performance, single network roundtrip.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Top N Query &#8211; TKPROF excerpt</span><span role="button" tabindex="0" data-code="call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0          8          0           5
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.00       0.01          0          8          0           5

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 133  
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         5          5          5  VIEW  (cr=8 pr=0 pw=0 time=335 us starts=1 cost=7 size=14124 card=107)
        11         11         11   WINDOW SORT PUSHED RANK (cr=8 pr=0 pw=0 time=326 us starts=1 cost=7 size=7383 card=107)
       107        107        107    WINDOW BUFFER (cr=8 pr=0 pw=0 time=260 us starts=1 cost=7 size=7383 card=107)
       107        107        107     MERGE JOIN  (cr=8 pr=0 pw=0 time=634 us starts=1 cost=6 size=7383 card=107)
        19         19         19      TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=42 us starts=1 cost=2 size=627 card=19)
        19         19         19       INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=30 us starts=1 cost=1 size=0 card=19)(object id 78619)
       107        107        107      SORT JOIN (cr=6 pr=0 pw=0 time=97 us starts=19 cost=4 size=3852 card=107)
       107        107        107       TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=28 us starts=1 cost=3 size=3852 card=107)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       1        0.00          0.00
  SQL*Net message from client                     1        0.01          0.01" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">call     count       cpu    elapsed       disk      query    current        rows</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">Parse        1      0.00       0.00          0          0          0           0</span></span>
<span class="line"><span style="color: #D4D4D4">Execute      1      0.00       0.00          0          0          0           0</span></span>
<span class="line"><span style="color: #D4D4D4">Fetch        1      0.00       0.00          0          8          0           5</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">total        3      0.00       0.01          0          8          0           5</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Misses in library cache during parse: 1</span></span>
<span class="line"><span style="color: #D4D4D4">Optimizer mode: ALL_ROWS</span></span>
<span class="line"><span style="color: #D4D4D4">Parsing user id: 133  </span></span>
<span class="line"><span style="color: #D4D4D4">Number of plan statistics captured: 1</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Rows (1st) Rows (avg) Rows (max)  Row Source Operation</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- ----------  ---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">         5          5          5  VIEW  (cr=8 pr=0 pw=0 time=335 us starts=1 cost=7 size=14124 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">        11         11         11   WINDOW SORT PUSHED RANK (cr=8 pr=0 pw=0 time=326 us starts=1 cost=7 size=7383 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107    WINDOW BUFFER (cr=8 pr=0 pw=0 time=260 us starts=1 cost=7 size=7383 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107     MERGE JOIN  (cr=8 pr=0 pw=0 time=634 us starts=1 cost=6 size=7383 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19      TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=42 us starts=1 cost=2 size=627 card=19)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19       INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=30 us starts=1 cost=1 size=0 card=19)(object id 78619)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107      SORT JOIN (cr=6 pr=0 pw=0 time=97 us starts=19 cost=4 size=3852 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107       TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=28 us starts=1 cost=3 size=3852 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed times include waiting on following events:</span></span>
<span class="line"><span style="color: #D4D4D4">  Event waited on                             Times   Max. Wait  Total Waited</span></span>
<span class="line"><span style="color: #D4D4D4">  ----------------------------------------   Waited  ----------  ------------</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message to client                       1        0.00          0.00</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message from client                     1        0.01          0.01</span></span></code></pre></div>



<h2 class="wp-block-heading"><a name="using_row_pattern_matching"></a>11. Using Row Pattern Matching</h2>



<p>What about <code>match_recognize</code>, does JOOQ support that? No, not currently. JOOQ has some limitations regarding SQL support. <code>match_recognize</code> is one and the <code>model_clause</code> is another. This is something to be expected, since the SQL grammar is still evolving. However, the question is, how do we deal with queries that must apply some SQL which cannot be created by JOOQ&#8217;s query builder? The solution is simple. We simply pass the pure SQL to JOOQ.</p>



<h3 class="wp-block-heading">&nbsp;JOOQ Query</h3>



<p>There are other ways to produce the same result without using <code>match_recognize</code>. However, if you would like to use JOOQ and <code>match_recognize</code> then you have to build the SQL yourself and pass it to JOOQ as on line 58.</p>



<p>It&#8217;s sad that Java still does not support multiline strings. The code is much simpler in other JVM languages that support multiline strings, such as Scala, Groovy, Kotlin or Xtend.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Row Pattern Matching &#8211; JOOQ Query</span><span role="button" tabindex="0" data-code="   private static void queryBestPayedNewEntries() {
      // using {{\\??\\}} instead of &quot;??&quot; to ensure JDBC does not interpret questions marks as a bind variable placeholders
      // see https://docs.oracle.com/en/database/oracle/oracle-database/18/jjdbc/JDBC-reference-information.html#GUID-3454411C-5F24-4D46-83A9-5DA0BA704F5D
      // documentation is wrong, escaping is required.
      StringBuffer sb = new StringBuffer();
      sb.append(&quot;WITH\n&quot;);
      sb.append(&quot;   base AS (\n&quot;);
      sb.append(&quot;      SELECT emp.employee_id,\n&quot;);
      sb.append(&quot;             emp.last_name,\n&quot;);
      sb.append(&quot;             emp.first_name,\n&quot;);
      sb.append(&quot;             job.job_title,\n&quot;);
      sb.append(&quot;             jhist.start_date,\n&quot;);
      sb.append(&quot;             emp.salary\n&quot;);
      sb.append(&quot;        FROM hr.employees_v emp\n&quot;);
      sb.append(&quot;        JOIN hr.job_history_v jhist\n&quot;);
      sb.append(&quot;          ON jhist.employee_id = emp.employee_id\n&quot;);
      sb.append(&quot;        JOIN hr.jobs_v job\n&quot;);
      sb.append(&quot;          ON job.job_id = jhist.job_id\n&quot;);
      sb.append(&quot;      UNION\n&quot;);
      sb.append(&quot;      SELECT emp.employee_id,\n&quot;);
      sb.append(&quot;             emp.last_name,\n&quot;);
      sb.append(&quot;             emp.first_name,\n&quot;);
      sb.append(&quot;             job.job_title,\n&quot;);
      sb.append(&quot;             emp.hire_date AS start_date,\n&quot;);
      sb.append(&quot;             emp.salary\n&quot;);
      sb.append(&quot;        FROM hr.employees_v emp\n&quot;);
      sb.append(&quot;        JOIN hr.jobs_v job\n&quot;);
      sb.append(&quot;          ON job.job_id = emp.job_id\n&quot;);
      sb.append(&quot;   ),\n&quot;);
      sb.append(&quot;   aggr AS (\n&quot;);
      sb.append(&quot;      SELECT employee_id,\n&quot;);
      sb.append(&quot;             last_name,\n&quot;);
      sb.append(&quot;             first_name,\n&quot;);
      sb.append(&quot;             job_title,\n&quot;);
      sb.append(&quot;             MAX(start_date) AS start_date,\n&quot;);
      sb.append(&quot;             salary,\n&quot;);
      sb.append(&quot;             MAX(salary) OVER (PARTITION BY job_title ORDER BY MAX(start_date)\n&quot;);
      sb.append(&quot;                ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS max_salary\n&quot;);
      sb.append(&quot;        FROM base\n&quot;);
      sb.append(&quot;       GROUP BY employee_id, last_name, first_name, job_title, salary\n&quot;);
      sb.append(&quot;   )\n&quot;);
      sb.append(&quot;SELECT job_title, start_date, last_name, first_name, salary\n&quot;);
      sb.append(&quot;  FROM aggr MATCH_RECOGNIZE (\n&quot;);
      sb.append(&quot;          PARTITION BY job_title\n&quot;);
      sb.append(&quot;          ORDER BY start_date\n&quot;);
      sb.append(&quot;          MEASURES LAST(employee_id) AS employee_id,\n&quot;);
      sb.append(&quot;                   LAST(last_name) AS last_name,\n&quot;);
      sb.append(&quot;                   LAST(first_name) AS first_name,\n&quot;);
      sb.append(&quot;                   LAST(start_date) AS start_date,\n&quot;);
      sb.append(&quot;                   LAST(salary) AS salary\n&quot;);
      sb.append(&quot;          ONE ROW PER MATCH\n&quot;);
      sb.append(&quot;          PATTERN((strt down*){{\\??\\}} up)\n&quot;);
      sb.append(&quot;          DEFINE strt AS salary = MAX(max_salary),\n&quot;);
      sb.append(&quot;                 down AS salary < MAX(max_salary),\n&quot;);
      sb.append(&quot;                 up AS salary = MAX(max_salary)\n&quot;);
      sb.append(&quot;       )\n&quot;);
      sb.append(&quot; ORDER BY job_title, start_date&quot;);
      final ResultQuery<Record&gt; query = ctx.resultQuery(sb.toString());
      fetchAndPrint(&quot;Best Payed New Entries&quot;, query);
   }" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">queryBestPayedNewEntries</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">// using {{\\??\\}} instead of &quot;??&quot; to ensure JDBC does not interpret questions marks as a bind variable placeholders</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">// see https://docs.oracle.com/en/database/oracle/oracle-database/18/jjdbc/JDBC-reference-information.html#GUID-3454411C-5F24-4D46-83A9-5DA0BA704F5D</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #6A9955">// documentation is wrong, escaping is required.</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #4EC9B0">StringBuffer</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4"> = </span><span style="color: #C586C0">new</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">StringBuffer</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;WITH</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;   base AS (</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;      SELECT emp.employee_id,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             emp.last_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             emp.first_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             job.job_title,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             jhist.start_date,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             emp.salary</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;        FROM hr.employees_v emp</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;        JOIN hr.job_history_v jhist</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          ON jhist.employee_id = emp.employee_id</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;        JOIN hr.jobs_v job</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          ON job.job_id = jhist.job_id</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;      UNION</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;      SELECT emp.employee_id,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             emp.last_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             emp.first_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             job.job_title,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             emp.hire_date AS start_date,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             emp.salary</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;        FROM hr.employees_v emp</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;        JOIN hr.jobs_v job</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          ON job.job_id = emp.job_id</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;   ),</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;   aggr AS (</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;      SELECT employee_id,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             last_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             first_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             job_title,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             MAX(start_date) AS start_date,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             salary,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;             MAX(salary) OVER (PARTITION BY job_title ORDER BY MAX(start_date)</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;                ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS max_salary</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;        FROM base</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;       GROUP BY employee_id, last_name, first_name, job_title, salary</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;   )</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;SELECT job_title, start_date, last_name, first_name, salary</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;  FROM aggr MATCH_RECOGNIZE (</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          PARTITION BY job_title</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          ORDER BY start_date</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          MEASURES LAST(employee_id) AS employee_id,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;                   LAST(last_name) AS last_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;                   LAST(first_name) AS first_name,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;                   LAST(start_date) AS start_date,</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;                   LAST(salary) AS salary</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          ONE ROW PER MATCH</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          PATTERN((strt down*){{</span><span style="color: #D7BA7D">\\</span><span style="color: #CE9178">??</span><span style="color: #D7BA7D">\\</span><span style="color: #CE9178">}} up)</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;          DEFINE strt AS salary = MAX(max_salary),</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;                 down AS salary &lt; MAX(max_salary),</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;                 up AS salary = MAX(max_salary)</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;       )</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">append</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot; ORDER BY job_title, start_date&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">final</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">ResultQuery</span><span style="color: #D4D4D4">&lt;</span><span style="color: #4EC9B0">Record</span><span style="color: #D4D4D4">&gt; </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">ctx</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">resultQuery</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">sb</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">toString</span><span style="color: #D4D4D4">());</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">fetchAndPrint</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;Best Payed New Entries&quot;</span><span style="color: #D4D4D4">, query);</span></span>
<span class="line"><span style="color: #D4D4D4">   }</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Query &amp; Result</h3>



<p>On line 49 you see that <code>{\??\}</code>&nbsp; is used instead of <code>??</code>. This is a necessity for the JDBC driver. Otherwise, the driver would expect bind variables for these question marks. All Java-based tools such as SQL Developer and SQLcl do have the same &#8220;problem&#8221;.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Row Pattern Matching &#8211; SQL Query &amp; Result</span><span role="button" tabindex="0" data-code="Best Payed New Entries: 

WITH
   base AS (
      SELECT emp.employee_id,
             emp.last_name,
             emp.first_name,
             job.job_title,
             jhist.start_date,
             emp.salary
        FROM hr.employees_v emp
        JOIN hr.job_history_v jhist
          ON jhist.employee_id = emp.employee_id
        JOIN hr.jobs_v job
          ON job.job_id = jhist.job_id
      UNION
      SELECT emp.employee_id,
             emp.last_name,
             emp.first_name,
             job.job_title,
             emp.hire_date AS start_date,
             emp.salary
        FROM hr.employees_v emp
        JOIN hr.jobs_v job
          ON job.job_id = emp.job_id
   ),
   aggr AS (
      SELECT employee_id,
             last_name,
             first_name,
             job_title,
             MAX(start_date) AS start_date,
             salary,
             MAX(salary) OVER (PARTITION BY job_title ORDER BY MAX(start_date)
                ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS max_salary
        FROM base
       GROUP BY employee_id, last_name, first_name, job_title, salary
   )
SELECT job_title, start_date, last_name, first_name, salary
  FROM aggr MATCH_RECOGNIZE (
          PARTITION BY job_title
          ORDER BY start_date
          MEASURES LAST(employee_id) AS employee_id,
                   LAST(last_name) AS last_name,
                   LAST(first_name) AS first_name,
                   LAST(start_date) AS start_date,
                   LAST(salary) AS salary
          ONE ROW PER MATCH
          PATTERN((strt down*){\??\} up)
          DEFINE strt AS salary = MAX(max_salary),
                 down AS salary < MAX(max_salary),
                 up AS salary = MAX(max_salary)
       )
 ORDER BY job_title, start_date

Best Payed New Entries result (25 rows): 

+-------------------------------+----------+---------+----------+------+
|JOB_TITLE                      |START_DATE|LAST_NAME|FIRST_NAME|SALARY|
+-------------------------------+----------+---------+----------+------+
|Accountant                     |2002-08-16|Faviet   |Daniel    |  9000|
|Accounting Manager             |2001-10-28|Kochhar  |Neena     | 17000|
|Administration Assistant       |2003-09-17|Whalen   |Jennifer  |  4400|
|Administration Vice President  |2001-01-13|De Haan  |Lex       | 17000|
|Administration Vice President  |2005-09-21|Kochhar  |Neena     | 17000|
|Finance Manager                |2002-08-17|Greenberg|Nancy     | 12008|
|Human Resources Representative |2002-06-07|Mavris   |Susan     |  6500|
|Marketing Manager              |2004-02-17|Hartstein|Michael   | 13000|
|Marketing Representative       |2004-02-17|Hartstein|Michael   | 13000|
|President                      |2003-06-17|King     |Steven    | 24000|
|Programmer                     |2001-01-13|De Haan  |Lex       | 17000|
|Public Accountant              |1997-09-21|Kochhar  |Neena     | 17000|
|Public Relations Representative|2002-06-07|Baer     |Hermann   | 10000|
|Purchasing Clerk               |2003-05-18|Khoo     |Alexander |  3100|
|Purchasing Manager             |2002-12-07|Raphaely |Den       | 11000|
|Sales Manager                  |2004-10-01|Russell  |John      | 14000|
|Sales Representative           |2004-01-30|King     |Janette   | 10000|
|Sales Representative           |2004-05-11|Abel     |Ellen     | 11000|
|Sales Representative           |2005-03-11|Ozer     |Lisa      | 11500|
|Shipping Clerk                 |2004-01-27|Sarchand |Nandita   |  4200|
|Stock Clerk                    |2003-07-14|Ladwig   |Renske    |  3600|
|Stock Clerk                    |2006-03-24|Raphaely |Den       | 11000|
|Stock Manager                  |2003-05-01|Kaufling |Payam     |  7900|
|Stock Manager                  |2004-07-18|Weiss    |Matthew   |  8000|
|Stock Manager                  |2005-04-10|Fripp    |Adam      |  8200|
+-------------------------------+----------+---------+----------+------+" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Best Payed New Entries: </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">WITH</span></span>
<span class="line"><span style="color: #D4D4D4">   base AS (</span></span>
<span class="line"><span style="color: #D4D4D4">      SELECT emp.employee_id,</span></span>
<span class="line"><span style="color: #D4D4D4">             emp.last_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             emp.first_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             job.job_title,</span></span>
<span class="line"><span style="color: #D4D4D4">             jhist.start_date,</span></span>
<span class="line"><span style="color: #D4D4D4">             emp.salary</span></span>
<span class="line"><span style="color: #D4D4D4">        FROM hr.employees_v emp</span></span>
<span class="line"><span style="color: #D4D4D4">        JOIN hr.job_history_v jhist</span></span>
<span class="line"><span style="color: #D4D4D4">          ON jhist.employee_id = emp.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">        JOIN hr.jobs_v job</span></span>
<span class="line"><span style="color: #D4D4D4">          ON job.job_id = jhist.job_id</span></span>
<span class="line"><span style="color: #D4D4D4">      UNION</span></span>
<span class="line"><span style="color: #D4D4D4">      SELECT emp.employee_id,</span></span>
<span class="line"><span style="color: #D4D4D4">             emp.last_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             emp.first_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             job.job_title,</span></span>
<span class="line"><span style="color: #D4D4D4">             emp.hire_date AS start_date,</span></span>
<span class="line"><span style="color: #D4D4D4">             emp.salary</span></span>
<span class="line"><span style="color: #D4D4D4">        FROM hr.employees_v emp</span></span>
<span class="line"><span style="color: #D4D4D4">        JOIN hr.jobs_v job</span></span>
<span class="line"><span style="color: #D4D4D4">          ON job.job_id = emp.job_id</span></span>
<span class="line"><span style="color: #D4D4D4">   ),</span></span>
<span class="line"><span style="color: #D4D4D4">   aggr AS (</span></span>
<span class="line"><span style="color: #D4D4D4">      SELECT employee_id,</span></span>
<span class="line"><span style="color: #D4D4D4">             last_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             first_name,</span></span>
<span class="line"><span style="color: #D4D4D4">             job_title,</span></span>
<span class="line"><span style="color: #D4D4D4">             MAX(start_date) AS start_date,</span></span>
<span class="line"><span style="color: #D4D4D4">             salary,</span></span>
<span class="line"><span style="color: #D4D4D4">             MAX(salary) OVER (PARTITION BY job_title ORDER BY MAX(start_date)</span></span>
<span class="line"><span style="color: #D4D4D4">                ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS max_salary</span></span>
<span class="line"><span style="color: #D4D4D4">        FROM base</span></span>
<span class="line"><span style="color: #D4D4D4">       GROUP BY employee_id, last_name, first_name, job_title, salary</span></span>
<span class="line"><span style="color: #D4D4D4">   )</span></span>
<span class="line"><span style="color: #D4D4D4">SELECT job_title, start_date, last_name, first_name, salary</span></span>
<span class="line"><span style="color: #D4D4D4">  FROM aggr MATCH_RECOGNIZE (</span></span>
<span class="line"><span style="color: #D4D4D4">          PARTITION BY job_title</span></span>
<span class="line"><span style="color: #D4D4D4">          ORDER BY start_date</span></span>
<span class="line"><span style="color: #D4D4D4">          MEASURES LAST(employee_id) AS employee_id,</span></span>
<span class="line"><span style="color: #D4D4D4">                   LAST(last_name) AS last_name,</span></span>
<span class="line"><span style="color: #D4D4D4">                   LAST(first_name) AS first_name,</span></span>
<span class="line"><span style="color: #D4D4D4">                   LAST(start_date) AS start_date,</span></span>
<span class="line"><span style="color: #D4D4D4">                   LAST(salary) AS salary</span></span>
<span class="line"><span style="color: #D4D4D4">          ONE ROW PER MATCH</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          PATTERN((strt down*){\??\} up)</span></span>
<span class="line"><span style="color: #D4D4D4">          DEFINE strt AS salary = MAX(max_salary),</span></span>
<span class="line"><span style="color: #D4D4D4">                 down AS salary &lt; MAX(max_salary),</span></span>
<span class="line"><span style="color: #D4D4D4">                 up AS salary = MAX(max_salary)</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> ORDER BY job_title, start_date</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Best Payed New Entries result (25 rows): </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">+-------------------------------+----------+---------+----------+------+</span></span>
<span class="line"><span style="color: #D4D4D4">|JOB_TITLE                      |START_DATE|LAST_NAME|FIRST_NAME|SALARY|</span></span>
<span class="line"><span style="color: #D4D4D4">+-------------------------------+----------+---------+----------+------+</span></span>
<span class="line"><span style="color: #D4D4D4">|Accountant                     |2002-08-16|Faviet   |Daniel    |  9000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Accounting Manager             |2001-10-28|Kochhar  |Neena     | 17000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Administration Assistant       |2003-09-17|Whalen   |Jennifer  |  4400|</span></span>
<span class="line"><span style="color: #D4D4D4">|Administration Vice President  |2001-01-13|De Haan  |Lex       | 17000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Administration Vice President  |2005-09-21|Kochhar  |Neena     | 17000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Finance Manager                |2002-08-17|Greenberg|Nancy     | 12008|</span></span>
<span class="line"><span style="color: #D4D4D4">|Human Resources Representative |2002-06-07|Mavris   |Susan     |  6500|</span></span>
<span class="line"><span style="color: #D4D4D4">|Marketing Manager              |2004-02-17|Hartstein|Michael   | 13000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Marketing Representative       |2004-02-17|Hartstein|Michael   | 13000|</span></span>
<span class="line"><span style="color: #D4D4D4">|President                      |2003-06-17|King     |Steven    | 24000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Programmer                     |2001-01-13|De Haan  |Lex       | 17000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Public Accountant              |1997-09-21|Kochhar  |Neena     | 17000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Public Relations Representative|2002-06-07|Baer     |Hermann   | 10000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Purchasing Clerk               |2003-05-18|Khoo     |Alexander |  3100|</span></span>
<span class="line"><span style="color: #D4D4D4">|Purchasing Manager             |2002-12-07|Raphaely |Den       | 11000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Manager                  |2004-10-01|Russell  |John      | 14000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |2004-01-30|King     |Janette   | 10000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |2004-05-11|Abel     |Ellen     | 11000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Sales Representative           |2005-03-11|Ozer     |Lisa      | 11500|</span></span>
<span class="line"><span style="color: #D4D4D4">|Shipping Clerk                 |2004-01-27|Sarchand |Nandita   |  4200|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Clerk                    |2003-07-14|Ladwig   |Renske    |  3600|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Clerk                    |2006-03-24|Raphaely |Den       | 11000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Manager                  |2003-05-01|Kaufling |Payam     |  7900|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Manager                  |2004-07-18|Weiss    |Matthew   |  8000|</span></span>
<span class="line"><span style="color: #D4D4D4">|Stock Manager                  |2005-04-10|Fripp    |Adam      |  8200|</span></span>
<span class="line"><span style="color: #D4D4D4">+-------------------------------+----------+---------+----------+------+</span></span></code></pre></div>



<h3 class="wp-block-heading">SQL Trace Output</h3>



<p>The <code>tkprof</code> excerpt shows that most of the time is spent parsing the query, but it is still fast. All 25 result rows are fetched in a single network roundtrip.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Row Pattern Matching &#8211; TKPROF excerpt</span><span role="button" tabindex="0" data-code="call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.20          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0         22          0          25
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.01       0.20          0         22          0          25

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 133  
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
        25         25         25  SORT ORDER BY (cr=22 pr=0 pw=0 time=1965 us starts=1 cost=22 size=7839 card=117)
        25         25         25   VIEW  (cr=22 pr=0 pw=0 time=2016 us starts=1 cost=21 size=7839 card=117)
        25         25         25    MATCH RECOGNIZE SORT (cr=22 pr=0 pw=0 time=2016 us starts=1 cost=21 size=9360 card=117)
       115        115        115     VIEW  (cr=22 pr=0 pw=0 time=1905 us starts=1 cost=20 size=9360 card=117)
       115        115        115      WINDOW SORT (cr=22 pr=0 pw=0 time=1904 us starts=1 cost=20 size=9360 card=117)
       115        115        115       HASH GROUP BY (cr=22 pr=0 pw=0 time=1718 us starts=1 cost=20 size=9360 card=117)
       116        116        116        VIEW  (cr=22 pr=0 pw=0 time=385 us starts=1 cost=18 size=9360 card=117)
       116        116        116         SORT UNIQUE (cr=22 pr=0 pw=0 time=384 us starts=1 cost=18 size=7879 card=117)
       117        117        117          UNION-ALL  (cr=22 pr=0 pw=0 time=213 us starts=1)
        10         10         10           HASH JOIN  (cr=14 pr=0 pw=0 time=210 us starts=1 cost=9 size=710 card=10)
        10         10         10            NESTED LOOPS  (cr=8 pr=0 pw=0 time=126 us starts=1 cost=9 size=710 card=10)
        10         10         10             NESTED LOOPS  (cr=8 pr=0 pw=0 time=116 us starts=1)
        10         10         10              STATISTICS COLLECTOR  (cr=8 pr=0 pw=0 time=115 us starts=1)
        10         10         10               MERGE JOIN  (cr=8 pr=0 pw=0 time=121 us starts=1 cost=6 size=480 card=10)
        10         10         10                TABLE ACCESS BY INDEX ROWID JOB_HISTORY (cr=2 pr=0 pw=0 time=34 us starts=1 cost=2 size=210 card=10)
        10         10         10                 INDEX FULL SCAN JHIST_JOB_IX (cr=1 pr=0 pw=0 time=24 us starts=1 cost=1 size=0 card=10)(object id 78632)
        10         10         10                SORT JOIN (cr=6 pr=0 pw=0 time=72 us starts=10 cost=4 size=513 card=19)
        19         19         19                 TABLE ACCESS FULL JOBS (cr=6 pr=0 pw=0 time=42 us starts=1 cost=3 size=513 card=19)
         0          0          0              INDEX UNIQUE SCAN EMP_EMP_ID_PK (cr=0 pr=0 pw=0 time=0 us starts=0)(object id 78622)
         0          0          0             TABLE ACCESS BY INDEX ROWID EMPLOYEES (cr=0 pr=0 pw=0 time=0 us starts=0 cost=3 size=23 card=1)
       107        107        107            TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=11 us starts=1 cost=3 size=2461 card=107)
       107        107        107           MERGE JOIN  (cr=8 pr=0 pw=0 time=366 us starts=1 cost=6 size=7169 card=107)
        19         19         19            TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=27 us starts=1 cost=2 size=513 card=19)
        19         19         19             INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=5 us starts=1 cost=1 size=0 card=19)(object id 78619)
       107        107        107            SORT JOIN (cr=6 pr=0 pw=0 time=67 us starts=19 cost=4 size=4280 card=107)
       107        107        107             TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=7 us starts=1 cost=3 size=4280 card=107)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       1        0.00          0.00
  PGA memory operation                            5        0.00          0.00
  SQL*Net message from client                     1        0.01          0.01" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">call     count       cpu    elapsed       disk      query    current        rows</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">Parse        1      0.01       0.20          0          0          0           0</span></span>
<span class="line"><span style="color: #D4D4D4">Execute      1      0.00       0.00          0          0          0           0</span></span>
<span class="line"><span style="color: #D4D4D4">Fetch        1      0.00       0.00          0         22          0          25</span></span>
<span class="line"><span style="color: #D4D4D4">------- ------  -------- ---------- ---------- ---------- ----------  ----------</span></span>
<span class="line"><span style="color: #D4D4D4">total        3      0.01       0.20          0         22          0          25</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Misses in library cache during parse: 1</span></span>
<span class="line"><span style="color: #D4D4D4">Optimizer mode: ALL_ROWS</span></span>
<span class="line"><span style="color: #D4D4D4">Parsing user id: 133  </span></span>
<span class="line"><span style="color: #D4D4D4">Number of plan statistics captured: 1</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Rows (1st) Rows (avg) Rows (max)  Row Source Operation</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- ----------  ---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">        25         25         25  SORT ORDER BY (cr=22 pr=0 pw=0 time=1965 us starts=1 cost=22 size=7839 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">        25         25         25   VIEW  (cr=22 pr=0 pw=0 time=2016 us starts=1 cost=21 size=7839 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">        25         25         25    MATCH RECOGNIZE SORT (cr=22 pr=0 pw=0 time=2016 us starts=1 cost=21 size=9360 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">       115        115        115     VIEW  (cr=22 pr=0 pw=0 time=1905 us starts=1 cost=20 size=9360 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">       115        115        115      WINDOW SORT (cr=22 pr=0 pw=0 time=1904 us starts=1 cost=20 size=9360 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">       115        115        115       HASH GROUP BY (cr=22 pr=0 pw=0 time=1718 us starts=1 cost=20 size=9360 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">       116        116        116        VIEW  (cr=22 pr=0 pw=0 time=385 us starts=1 cost=18 size=9360 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">       116        116        116         SORT UNIQUE (cr=22 pr=0 pw=0 time=384 us starts=1 cost=18 size=7879 card=117)</span></span>
<span class="line"><span style="color: #D4D4D4">       117        117        117          UNION-ALL  (cr=22 pr=0 pw=0 time=213 us starts=1)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10           HASH JOIN  (cr=14 pr=0 pw=0 time=210 us starts=1 cost=9 size=710 card=10)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10            NESTED LOOPS  (cr=8 pr=0 pw=0 time=126 us starts=1 cost=9 size=710 card=10)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10             NESTED LOOPS  (cr=8 pr=0 pw=0 time=116 us starts=1)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10              STATISTICS COLLECTOR  (cr=8 pr=0 pw=0 time=115 us starts=1)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10               MERGE JOIN  (cr=8 pr=0 pw=0 time=121 us starts=1 cost=6 size=480 card=10)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10                TABLE ACCESS BY INDEX ROWID JOB_HISTORY (cr=2 pr=0 pw=0 time=34 us starts=1 cost=2 size=210 card=10)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10                 INDEX FULL SCAN JHIST_JOB_IX (cr=1 pr=0 pw=0 time=24 us starts=1 cost=1 size=0 card=10)(object id 78632)</span></span>
<span class="line"><span style="color: #D4D4D4">        10         10         10                SORT JOIN (cr=6 pr=0 pw=0 time=72 us starts=10 cost=4 size=513 card=19)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19                 TABLE ACCESS FULL JOBS (cr=6 pr=0 pw=0 time=42 us starts=1 cost=3 size=513 card=19)</span></span>
<span class="line"><span style="color: #D4D4D4">         0          0          0              INDEX UNIQUE SCAN EMP_EMP_ID_PK (cr=0 pr=0 pw=0 time=0 us starts=0)(object id 78622)</span></span>
<span class="line"><span style="color: #D4D4D4">         0          0          0             TABLE ACCESS BY INDEX ROWID EMPLOYEES (cr=0 pr=0 pw=0 time=0 us starts=0 cost=3 size=23 card=1)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107            TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=11 us starts=1 cost=3 size=2461 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107           MERGE JOIN  (cr=8 pr=0 pw=0 time=366 us starts=1 cost=6 size=7169 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19            TABLE ACCESS BY INDEX ROWID JOBS (cr=2 pr=0 pw=0 time=27 us starts=1 cost=2 size=513 card=19)</span></span>
<span class="line"><span style="color: #D4D4D4">        19         19         19             INDEX FULL SCAN JOB_ID_PK (cr=1 pr=0 pw=0 time=5 us starts=1 cost=1 size=0 card=19)(object id 78619)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107            SORT JOIN (cr=6 pr=0 pw=0 time=67 us starts=19 cost=4 size=4280 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4">       107        107        107             TABLE ACCESS FULL EMPLOYEES (cr=6 pr=0 pw=0 time=7 us starts=1 cost=3 size=4280 card=107)</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed times include waiting on following events:</span></span>
<span class="line"><span style="color: #D4D4D4">  Event waited on                             Times   Max. Wait  Total Waited</span></span>
<span class="line"><span style="color: #D4D4D4">  ----------------------------------------   Waited  ----------  ------------</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message to client                       1        0.00          0.00</span></span>
<span class="line"><span style="color: #D4D4D4">  PGA memory operation                            5        0.00          0.00</span></span>
<span class="line"><span style="color: #D4D4D4">  SQL*Net message from client                     1        0.01          0.01</span></span></code></pre></div>



<h2 class="wp-block-heading"><a name="conclusion"></a>12. Conclusion</h2>



<p>A view-API has a value. You can change the physical data model and keep the existing view layer compatible for the consuming applications. This makes the database application independent, at least to a certain extent. That&#8217;s a great value when you think of testing interfaces or releasing new versions. Building an initial 1:1 view-API is no big deal, especially since it can be generated. The maintenance costs for such a view-API depend on many things. But I can&#8217;t imagine a scenario that isn&#8217;t worth it.</p>



<p>I was positively surprised by the feature richness and good usability of JOOQ. Things like the deep data model awareness including referential integrity constraints to make joins simpler and less error-prone are impressive. Ok, the DSL needs some getting used to, but the excellent documentation helps a lot. Although I have only scratched the surface of JOOQ, I am convinced that it is very well suited for developing high-performing PinkDB applications. Because JOOQ developers have control over the SQL statements sent to the database.</p>
<p>The post <a href="https://www.salvis.com/blog/2018/08/05/view-api-jooq-application/">View-API for JOOQ Application</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2018/08/05/view-api-jooq-application/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>The Pink Database Paradigm (PinkDB)</title>
		<link>https://www.salvis.com/blog/2018/07/18/the-pink-database-paradigm-pinkdb/</link>
					<comments>https://www.salvis.com/blog/2018/07/18/the-pink-database-paradigm-pinkdb/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Wed, 18 Jul 2018 17:53:22 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[JOOQ]]></category>
		<category><![CDATA[PinkDB]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SmartDB]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=8633</guid>

					<description><![CDATA[<p>1. Introduction The Pink Database paradigm (PinkDB) is an application architecture for database-centric applications. It focuses on relational database systems and is vendor-neutral. The principles are based on the ideas of SmartDB, with some adaptions that make PinkDB easier to apply in existing development environments. An important feature of a PinkDB application<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2018/07/18/the-pink-database-paradigm-pinkdb/">The Pink Database Paradigm (PinkDB)</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">1. Introduction</h2>



<p>The Pink Database paradigm (PinkDB) is an application architecture for database-centric applications. It focuses on relational database systems and is vendor-neutral. The principles are based on the ideas of SmartDB, with some adaptions that make PinkDB easier to apply in existing development environments. An important feature of a PinkDB application is that it uses set-based SQL to conserve resources and deliver the best performance.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB.png"><img decoding="async" width="618" height="618" src="https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB.png" alt="" class="wp-image-8650" srcset="https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB.png 618w, https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB-150x150.png 150w, https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB-300x300.png 300w, https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB-146x146.png 146w, https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB-50x50.png 50w, https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB-75x75.png 75w, https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB-85x85.png 85w, https://www.salvis.com/blog/wp-content/uploads/2018/07/PinkDB-80x80.png 80w" sizes="(max-width:767px) 480px, 618px" /></a></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%"><div class="quick_fact align_center animate-math"><h4 class="title heading_tag ">Connect User</h4><hr class="hr_narrow" /><div class="desc"></p>
<p>The connect user does not own objects. No tables. No views. No synonyms. No stored objects. It follows the <a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">principle of least privileges</a>.<br />
</div></div>



<div class="quick_fact align_center animate-math"><h4 class="title heading_tag ">API Schema</h4><hr class="hr_narrow" /><div class="desc"></p>
<p>The API schema owns the API to the data. Access is granted on the basis of the <a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">principle of least privileges</a>. The API consists of stored objects and views, but no tables.<br />
</div></div>



<div class="quick_fact align_center animate-math"><h4 class="title heading_tag ">Data</h4><hr class="hr_narrow" /><div class="desc"></p>
<p>The data is stored in a data model using the features of the underlying database system for <a href="https://en.wikipedia.org/wiki/Consistency_(database_systems)">consistency</a>. It is protected by the API and processed by set-based SQL for best performance.<br />
</div></div>

</div>
</div>



<h2 class="wp-block-heading">2. Features</h2>



<p>An application implementing PinkDB has the following features:</p>



<ol class="wp-block-list">
<li><a href="#feature_1">The connect user does not own database objects</a></li>



<li><a href="#feature_2">The connect user has access to API objects only</a></li>



<li><a href="#feature_3">The API consists of stored objects and views</a></li>



<li><a href="#feature_4">Data is processed by set-based operations</a></li>



<li><a href="#feature_5">Exceptions are documented</a></li>
</ol>



<h3 class="wp-block-heading"><a name="feature_1"></a>2.1.&nbsp;The connect user does not own database objects</h3>



<p>The connect user is used by application components outside of the database to interact with the database. It is configured for example in the connection pool of the middle-tier application.</p>



<p>The connect user must access only the APIs of the underlying database applications. It must not own database objects such as tables, views, synonyms or stored objects.</p>



<p>The <a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">principle of least privileges</a>&nbsp;is followed.</p>



<p>This is 100 percent identical to SmartDB.</p>



<h3 class="wp-block-heading"><a name="feature_2"></a>2.2. The connect user has access to API objects only</h3>



<p>Database tables are guarded behind an API. The connect user must not have privileges to access objects that are not part of the API, e.g. via <code>SELECT ANY TABLE</code> privileges or similar.</p>



<p>The <a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">principle of least privileges</a>&nbsp;is followed.</p>



<h3 class="wp-block-heading"><a name="feature_3"></a>2.3 The API consists of stored objects and views</h3>



<p>The API schema owns the API to the data. Access is granted on the basis of the <a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">principle of least privileges</a>. The API consists of stored objects and views, but no tables.</p>



<h3 class="wp-block-heading"><a name="feature_4"></a>2.4 Data is processed by set-based operations</h3>



<p>The data ist stored in a data model using the features of the underlying database system for&nbsp;<a href="https://en.wikipedia.org/wiki/Consistency_(database_systems)">consistency</a>. It is not necessary to store tables, indexes, etc. in a dedicated schema. But it is mandatory, that the data is protected by the API.</p>



<p>Set-based SQL ist the key to good performance. It means that you are using the database as a processing engine and not as a data store only. You should avoid row-by-row processing when set-based SQL is feasible and noticeably faster. This means that row-by-row processing is acceptable, e.g. to update a few rows via GUI, but not for batch processing where set-based operations are by factors faster. Using stored objects for batch processing simplifies the work. Set-based processing becomes natural.</p>



<p>You should make it a habit to minimize the total number of executed SQL statements to get a job done. Less loops, more set-based SQL. In the end, it is simpler. You tell the database what you want and the optimizer figures out how to do it efficiently.</p>



<h3 class="wp-block-heading"><a name="feature_5"></a>2.5 Exceptions are documented</h3>



<p>All these features are understood as recommendations. They should be followed. Without exceptions. However, in real projects, we have to deal with limitations and bugs and sometimes it is necessary to break rules. Document the reason for the exception and make sure that the exception does not become the rule.</p>



<h2 class="wp-block-heading">3. Differences to SmartDB</h2>



<p>SmartDB is targeting PL/SQL and therefore focusing on Oracle Databases. PinkDB is vendor agnostic and can be applied on SQL Server, Db2, Teradata, EnterpriseDB, PostgreSQL, MySQL, MariaDB, HSQL, etc. This does not mean that just a common superset of database features should be used, quite the contrary. Use the features of the underlying systems to get the best value, even if they are vendor-specific.</p>



<p>The API in SmartDB consists of PL/SQL units only. No exceptions. PinkDB allows views. In fact they are an excellent API for various use-cases. For example, reporting tools using SQL to access star schemas or using an MDX adapter to access logical cubes based on analytic views. APEX is another example. You develop efficiently with APEX when your reports and screens are based on views (or tables). Using stored objects only to access Oracle database sources is working against the tool. However, you have to be careful. Using views only can be dangerous and most probably will violate sooner or later the &#8220;<a href="#feature_4">data is processed by set-based operations</a>&#8221; feature, if you do not pay attention. Other examples are applications built with JOOQ. JOOQ makes static SQL possible within Java. The productivity is comparable to PL/SQL. It&#8217;s natural to write set-based SQL. These examples show that defining NoPlsql (NoStoredObjects) as the opposite of SmartDB is misleading since it describes something bad. NoPlsql is not bad per se. It really depends on how you use the database. If you use it as a processing engine then this cannot be bad. In fact, it is excellent. This is probably the biggest difference between SmartDB and PinkDB.</p>



<p>SmartDB has this weird requirement that all&nbsp;<code>SELECT</code>, <code>INSERT</code>, <code>UPDATE</code>, <code>DELETE</code> and <code>MERGE</code> statements must be written by human hand (within PL/SQL). No generators are allowed. PinkDB welcomes generators to increase the productivity and consistency of the result.</p>



<p>The last difference is transaction control statements. SmartDB enforces them to be part of the PL/SQL API. PinkDB allows the use of <code>COMMIT</code> and <code>ROLLBACK</code> outside of the database. However, if a stored object call is covering the complete transaction, it should take also responsibility for the final <code>COMMIT</code>.</p>



<p>SmartDB and PinkDB have the same ancestors. I see&nbsp;PinkDB as the understanding sister of her wise, but sometimes a bit stubborn brother SmartDB.</p>



<h2 class="wp-block-heading">4. Related Resources</h2>



<p>As I said, PinkDB and SmartDB are related. That&#8217;s why all SmartDB documents are also interesting for PinkDB. Steven Feuerstein is maintaining a <a href="http://stevenfeuersteinonplsql.blogspot.com/2018/05/the-smartdb-resource-center.html">SmartDB Resource Center</a>. You find a lot of useful information and links there. I highly recommend looking at Toon Koppelaar&#8217;s excellent <a href="https://www.youtube.com/watch?v=8jiJDflpw4Y">video</a>&nbsp;and&nbsp;<a href="https://drive.google.com/file/d/0B7jyeB8kxFPjcTRlQkZEVnNVRHc/view">slide deck.</a>&nbsp;Toon really knows what he is talking about. Would you like to know if your database application is SmartDB compliant? Then see my previous <a href="https://www.salvis.com/blog/2018/07/18/is-your-application-smartdb/">blog post</a>. There&#8217;s a script you can run to find out.</p>
<p>The post <a href="https://www.salvis.com/blog/2018/07/18/the-pink-database-paradigm-pinkdb/">The Pink Database Paradigm (PinkDB)</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2018/07/18/the-pink-database-paradigm-pinkdb/feed/</wfw:commentRss>
			<slash:comments>19</slash:comments>
		
		
			</item>
	</channel>
</rss>
