<?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>SQL Archives - Philipp Salvisberg&#039;s Blog</title>
	<atom:link href="https://www.salvis.com/blog/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.salvis.com/blog/tag/sql/</link>
	<description>Database-centric development</description>
	<lastBuildDate>Sat, 29 Aug 2026 07:52:43 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>

<image>
	<url>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</url>
	<title>SQL Archives - Philipp Salvisberg&#039;s Blog</title>
	<link>https://www.salvis.com/blog/tag/sql/</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/sql/feed/"/>
	<item>
		<title>Implicit Outer Joins in Join-to-One: Feature or Flaw?</title>
		<link>https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/</link>
					<comments>https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/#respond</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sat, 29 Aug 2026 07:52:40 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Oracle 26ai]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=23948</guid>

					<description><![CDATA[<p>Background As you probably know, I&#8217;m maintaining a parser for grammars used in SQL files for Oracle AI Database and PostgreSQL. As a result, I check for new statements and clauses in every version of those DBMSs. PostgreSQL typically adds new features only in major versions; this means yearly. Oracle, on the<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/">Implicit Outer Joins in Join-to-One: Feature or Flaw?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="background" class="wp-block-heading">Background</h2>



<p class="wp-block-paragraph">As you probably know, I&#8217;m maintaining a parser for grammars used in SQL files for Oracle AI Database and PostgreSQL. As a result, I check for new statements and clauses in every version of those DBMSs. PostgreSQL typically adds new features only in major versions; this means yearly. Oracle, on the other hand, documents new features in every new RU; this means quarterly. </p>



<p class="wp-block-paragraph">The RU for 26.2 was a bit delayed. So, on 1 May 2026, I went through the new features in 26.2 and discovered the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/adfns/building-queries-correct-joins-more-easily.html#GUID-FEB8218C-8FD5-47BC-BB14-4E43DDD32F35" target="_blank" rel="noreferrer noopener">join-to-one clause</a> while documenting the changes required for IslandSQL in a <a href="https://github.com/IslandSQL/IslandSQL/issues/315" data-type="link" data-id="https://github.com/IslandSQL/IslandSQL/issues/315" target="_blank" rel="noreferrer noopener">GitHub issue</a>. I tried the feature in an OCI instance and posted about it on Bluesky.</p>



<figure class="wp-block-image size-full"><a href="https://bsky.app/profile/salvis.com/post/3mkt4dj3ofc2c" target="_blank" rel=" noopener"><img fetchpriority="high" decoding="async" width="592" height="511" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky.png" alt="Join to one post on Bluesky" class="wp-image-23950" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky.png 592w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-300x259.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-87x75.png 87w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-480x414.png 480w" sizes="(max-width:767px) 480px, 592px" /></a></figure>



<p class="wp-block-paragraph">This led to some discussions in private channels. </p>



<p class="wp-block-paragraph">Back then, I hadn&#8217;t made up my mind regarding the usefulness of this feature, but the fact that a join uses outer-join semantics by default irritated me from the very first moment.</p>



<p class="wp-block-paragraph">In the meantime, I believe that this feature is useful for various use cases. I&#8217;m not going to talk about that in this blog post. However, the longer I thought about the implicit outer join in join-to-one, the more it irritated me.</p>



<h2 id="join-to-one-will-make-it-into-the-sql-standard" class="wp-block-heading">Join-To-One Will Make It Into the SQL Standard</h2>



<p class="wp-block-paragraph">According to <a href="https://peter.eisentraut.org/blog/2026/06/30/waiting-for-sql-202y-stockholm-meeting-report#join-to-one" target="_blank" rel="noreferrer noopener">Peter Eisentraut&#8217;s blog post</a>, this feature has been accepted into the next SQL standard and is now part of its working draft. I wonder whether they also discussed the default join behaviour of a join-to-one and what the consensus was. </p>



<p class="wp-block-paragraph">Anyway, since version 26.2, this feature is part of Oracle AI Database. Changing the behaviour at that stage is only feasible with a database parameter similar to <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/refrn/GROUP_BY_POSITION_ENABLED.html" data-type="link" data-id="https://docs.oracle.com/en/database/oracle/oracle-database/26/refrn/GROUP_BY_POSITION_ENABLED.html" target="_blank" rel="noreferrer noopener">group_by_position_enabled</a> to keep backward compatibility. I doubt that something like this will happen.</p>



<h2 id="what-is-the-problem" class="wp-block-heading">What Is the Problem?</h2>



<p class="wp-block-paragraph">It is the first time an outer join has become the default. For every other join variant since ANSI SQL-86, an inner join has been the default. We are used to that.</p>



<p class="wp-block-paragraph">Changing such a long-established convention is not necessarily a bad thing. However, there should be a convincing reason for doing so.</p>



<p class="wp-block-paragraph">The <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-9388EBCC-9ADE-4668-AAF4-D6193B8395F2" data-type="link" data-id="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-9388EBCC-9ADE-4668-AAF4-D6193B8395F2" target="_blank" rel="noreferrer noopener">SQL Language Reference</a> provides this reason:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">&#8220;The database chose this default because <code>INNER JOIN</code>s often filter rows unintentionally.&#8221;</p>
</blockquote>



<p class="wp-block-paragraph">So, the intention is to avoid accidental filtering. That sounds reasonable. But is silently preserving rows really better than silently filtering them?</p>



<p class="wp-block-paragraph">In both cases, the omitted join type affects the result. An implicit inner join may remove rows. An implicit outer join may introduce null values that have to be considered in subsequent expressions and predicates.</p>



<p class="wp-block-paragraph">In any case, the join-to-one clause relies on integrity constraints. These constraints are already used to derive the join condition. So why not consider them fully and choose an inner join for mandatory foreign keys and an outer join for optional foreign keys?</p>



<p class="wp-block-paragraph">Of course, this would make the join type depend on the schema definition. A change to the optionality of a foreign key could then change the semantics of an existing query. That would have been a very good reason not to choose a fixed default join type, right?</p>



<p class="wp-block-paragraph">However, while the optimiser could deal with a dynamically determined join type, the query would be more challenging to read and understand. We would need to check the current optionality of each foreign key involved to determine whether nulls need to be handled.</p>



<p class="wp-block-paragraph">Ouch. This would be cumbersome without implementing an additional concept that forces us to handle null values in SQL expressions and predicates (something similar to <a href="https://jspecify.dev/docs/user-guide/" data-type="link" data-id="https://jspecify.dev/docs/user-guide/" target="_blank" rel="noreferrer noopener">JSpecify</a>). Therefore, it&#8217;s probably better not to derive the join type automatically from a foreign key&#8217;s optionality. Being explicit has its value.</p>



<p class="wp-block-paragraph">Furthermore, an outer join limits the optimiser&#8217;s solution space and can affect performance, as Andrej Pashchenko demonstrated for join-to-one in <a href="https://blog.sqlora.com/en/oracle-26ai-an-even-closer-look-at-join-to-one/" data-type="link" data-id="https://blog.sqlora.com/en/oracle-26ai-an-even-closer-look-at-join-to-one/" target="_blank" rel="noreferrer noopener">this blog post</a>.</p>



<p class="wp-block-paragraph">These performance aspects may be addressed in upcoming versions. But the unfamiliar implicit default join strategy remains.</p>



<h2 id="an-example" class="wp-block-heading">An Example</h2>



<p class="wp-block-paragraph">Let&#8217;s compare the following two queries:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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;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">1) Implicit outer joins</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          departments d,
          jobs j,
          employees mgr on e.manager_id 
                       = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><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">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          departments d,</span></span>
<span class="line"><span style="color: #D4D4D4">          jobs j,</span></span>
<span class="line"><span style="color: #D4D4D4">          employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                       = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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;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">2) Explict inner and outer joins</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          outer join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><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">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>
</div>



<p class="wp-block-paragraph">The queries are based on the HR example schema and produce the same result.</p>



<p class="wp-block-paragraph">Which one is easier to read and understand?</p>



<p class="wp-block-paragraph">Which one reveals information that might be helpful when crafting or reviewing the WHERE clause?</p>



<p class="wp-block-paragraph">IMO, the second example. For both questions.</p>



<p class="wp-block-paragraph">The second example shows that: </p>



<ul class="wp-block-list">
<li>Employees do not necessarily belong to a department. Yes, the <code>department_id</code> column in the <code>employees</code> table is optional.</li>



<li>Not every employee has a manager.</li>



<li>Every employee has a job.</li>
</ul>



<p class="wp-block-paragraph">This information helps us filter data using the department or manager columns. We have to handle null values there.</p>



<p class="wp-block-paragraph">Based on that, we can see a flaw in the query. We can either use an inner join for managers because we are not interested in counting employees without a manager, or we have to address employees without a manager in the WHERE clause.</p>



<p class="wp-block-paragraph">So, we should change the query to something like the following:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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-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">2a) Excluding emps without mgr</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          inner join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><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">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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-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">2b) Including emps without mgr</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          outer join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary
    or mgr.employee_id is null;</textarea></pre><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">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> mgr.employee_id </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4">;</span></span></code></pre></div>
</div>
</div>



<p class="wp-block-paragraph">Query 2a produces the same result as queries 1 and 2, but the inner join on employees makes it clear that excluding employees without a manager was intended.</p>



<p class="wp-block-paragraph">Query 2b produces additional results for employees without a manager. The outer join on employees and the null handling in the WHERE clause make it clear that this was intentional.</p>



<h2 id="summary" class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">IMO, the implicit outer joins in the new join-to-one clause are clearly a flaw. You should always specify inner or outer joins explicitly in a join-to-one clause. This communicates the intended semantics and highlights where downstream null handling may be required.</p>



<p class="wp-block-paragraph">If you are using <a href="https://marketplace.visualstudio.com/items?itemName=Grisselbav.dblinter" target="_blank" rel="noreferrer noopener">dbLinter</a> &#8211; which you should &#8211; then you can enable the rule <a href="https://dblinter.app/ords/r/dblinter/dblinter-console/rules#P1000_SHOW_RULE=core%20g-3194" target="_blank" rel="noreferrer noopener">G-3194</a> to improve the maintainability of your join-to-one clauses.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/">Implicit Outer Joins in Join-to-One: Feature or Flaw?</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/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The Checkbox That Disables TLS</title>
		<link>https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/</link>
					<comments>https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/#respond</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 23 Aug 2026 21:20:28 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[APEXlang]]></category>
		<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[dbLinter]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=23591</guid>

					<description><![CDATA[<p>Introduction The dbLinter clients include a new setting named Allow Insecure TLS. It is disabled by default. As a result, all REST API calls verify the TLS certificate and hostname. The setting allows dbLinter to work in organisations that inspect TLS traffic using tools such as Zscaler. In larger organisations, arranging an<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/">The Checkbox That Disables TLS</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="introduction" class="wp-block-heading">Introduction</h2>



<p class="wp-block-paragraph">The dbLinter clients include a new setting named <code>Allow Insecure TLS</code>. It is disabled by default. As a result, all REST API calls verify the TLS certificate and hostname. </p>



<p class="wp-block-paragraph">The setting allows dbLinter to work in organisations that inspect TLS traffic using tools such as <a href="https://help.zscaler.com/zia/understanding-ssltls-inspection" target="_blank" rel="noreferrer noopener">Zscaler</a>.</p>



<p class="wp-block-paragraph">In larger organisations, arranging an inspection bypass can be cumbersome and is often too much effort for an ad-hoc trial of dbLinter. The checkbox provides a temporary workaround and should be enabled only on a trusted network.</p>



<p class="wp-block-paragraph">However, allowing insecure TLS on untrusted networks, such as open Wi-Fi without client isolation, can let an attacker redirect traffic through their own machine using techniques like <a href="https://en.wikipedia.org/wiki/ARP_spoofing" target="_blank" rel="noreferrer noopener">ARP spoofing</a>. The attacker can also operate the access point themselves, for example, by creating a rogue Wi-Fi hotspot.</p>



<p class="wp-block-paragraph">In this blog post, I demonstrate the effect of this checkbox.</p>



<h2 id="allow-insecure-tls" class="wp-block-heading">Allow Insecure TLS</h2>



<p class="wp-block-paragraph">The latest version of dbLinter for VS Code has a checkbox that disables certificate and hostname verification.</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox.png"><img decoding="async" width="1024" height="833" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1024x833.png" alt="Allow Insecure TLS Checkbox in VS Code" class="wp-image-23595" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1024x833.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-300x244.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-768x624.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1536x1249.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-2048x1665.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-92x75.png 92w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-480x390.png 480w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">dbLinter&#8217;s <code>allowInsecureTls</code> setting is nothing unusual. Many common tools offer a similar option, including curl (<code>--insecure</code>), wget (<code>--no-check-certificate</code>), and git (<code>--config http.sslVerify false</code>).</p>



<h2 id="installing-and-configuring-a-proxy" class="wp-block-heading">Installing and Configuring a Proxy</h2>



<p class="wp-block-paragraph">I run this demo on macOS 26.6.2.</p>



<p class="wp-block-paragraph">A simple proxy is <a href="https://www.mitmproxy.org/" data-type="link" data-id="https://www.mitmproxy.org/" target="_blank" rel="noreferrer noopener">mitmweb</a>. We can install and configure it as follows:</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:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>brew install mitmproxy
networksetup -setsecurewebproxy "Wi-Fi" 127.0.0.1 8090
mitmweb --listen-port 8090 --web-port 8091 --allow-hosts '^api\.dblinter\.app'</textarea></pre><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">brew</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">install</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">mitmproxy</span></span>
<span class="line"><span style="color: #DCDCAA">networksetup</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-setsecurewebproxy</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Wi-Fi&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">127.0</span><span style="color: #CE9178">.0.1</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8090</span></span>
<span class="line"><span style="color: #DCDCAA">mitmweb</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--listen-port</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8090</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--web-port</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8091</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--allow-hosts</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;^api\.dblinter\.app&#39;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;20:36:20.907&#93; HTTP(S) proxy listening at *:8090.
&#91;20:36:20.908&#93; Web server listening at http://127.0.0.1:8091/?token=f83b02032aaaccd282ad3925a484fcdb</textarea></pre><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">&#91;20:36:20.907&#93; HTTP(S) proxy listening at *:8090.</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:36:20.908&#93; Web server listening at http://127.0.0.1:8091/?token=f83b02032aaaccd282ad3925a484fcdb</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>mitmweb</code> command starts the proxy and listens on port 8090 for TLS traffic between localhost and <code>api.dblinter.app</code>. All other traffic is bypassed. </p>



<p class="wp-block-paragraph">The <code>mitmweb</code> proxy also opens the following web page:</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start.png"><img decoding="async" width="1024" height="201" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-1024x201.png" alt="mitmproxy after start up" class="wp-image-23617" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-1024x201.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-300x59.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-768x150.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-150x29.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-480x94.png 480w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start.png 1281w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<h2 id="intercepting-traffic" class="wp-block-heading">Intercepting Traffic</h2>



<p class="wp-block-paragraph">To generate traffic, we launch VS Code and open a SQL file. This produces the following in the output panel for dbLinter:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>2026-08-23 20:37:43.216 &#91;Info &#93; Starting dbLinter Language Server.
2026-08-23 20:37:43.539 &#91;Info &#93; connect.
2026-08-23 20:37:43.611 &#91;Info &#93; initialize VSCode 1.10.0.
2026-08-23 20:37:43.646 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.
2026-08-23 20:37:43.651 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.
2026-08-23 20:37:43.671 &#91;Warn &#93; TLS certificate and hostname verification are disabled for dbLinter repository API calls. Use this temporary workaround only when TLS interception cannot be bypassed.
2026-08-23 20:37:45.533 &#91;Info &#93; Configuration dbLinter of tenant Grisselbav loaded with 294 check methods.
2026-08-23 20:37:45.534 &#91;Info &#93; didChangeConfiguration.
2026-08-23 20:37:45.703 &#91;Info &#93; tests returned 43 tests.
2026-08-23 20:37:45.796 &#91;Info &#93; parseAndCheck file:///.../dbl_client_types.sql.
2026-08-23 20:37:45.910 &#91;Info &#93; hasFeature Config returned true.
2026-08-23 20:37:46.286 &#91;Info &#93; parseAndCheck completed in 0.489 sec including 0.052 sec for checks.
2026-08-23 20:37:46.289 &#91;Info &#93; diagnostics for file:///.../dbl_client_types.sql with 2 issues.</textarea></pre><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">2026-08-23 20:37:43.216 &#91;Info &#93; Starting dbLinter Language Server.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.539 &#91;Info &#93; connect.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.611 &#91;Info &#93; initialize VSCode 1.10.0.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.646 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.651 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">2026-08-23 20:37:43.671 &#91;Warn &#93; TLS certificate and hostname verification are disabled for dbLinter repository API calls. Use this temporary workaround only when TLS interception cannot be bypassed.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.533 &#91;Info &#93; Configuration dbLinter of tenant Grisselbav loaded with 294 check methods.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.534 &#91;Info &#93; didChangeConfiguration.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.703 &#91;Info &#93; tests returned 43 tests.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.796 &#91;Info &#93; parseAndCheck file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.910 &#91;Info &#93; hasFeature Config returned true.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:46.286 &#91;Info &#93; parseAndCheck completed in 0.489 sec including 0.052 sec for checks.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:46.289 &#91;Info &#93; diagnostics for file:///.../dbl_client_types.sql with 2 issues.</span></span></code></pre></div>



<p class="wp-block-paragraph">The log contains a warning that TLS certificate and hostname verification are disabled.</p>



<p class="wp-block-paragraph">dbLinter analyses SQL and APEXlang files locally. The captured traffic lets us verify what is sent to the dbLinter API. It contains the API key and session data, but not the contents of the analysed files. The source code therefore remains within the local network.</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-scaled.png"><img loading="lazy" decoding="async" width="1024" height="538" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1024x538.png" alt="mitmproxy request message" class="wp-image-23618" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1024x538.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-300x158.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-768x403.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1536x807.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-2048x1076.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-143x75.png 143w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-480x252.png 480w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">It goes without saying that it is not good to expose the API key in plain text.</p>



<p class="wp-block-paragraph">The proxy also shows the decrypted response:</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-scaled.png"><img loading="lazy" decoding="async" width="1024" height="292" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1024x292.png" alt="mitmproxy response message" class="wp-image-23619" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1024x292.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-300x85.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-768x219.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1536x438.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-2048x584.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-150x43.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-480x137.png 480w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">The session object in the response contains a signature. The client can therefore detect changes to the signed content, including the validators. This prevents the proxy from silently modifying the validators or injecting malicious code. However, the signature does not prevent the proxy from reading the request and response.</p>



<h2 id="enforce-tls-verification" class="wp-block-heading">Enforce TLS Verification</h2>



<p class="wp-block-paragraph">Now let&#8217;s uncheck the <code>Allow Insecure TLS</code> checkbox and execute the <code>Reload Window</code> command. </p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2.png"><img loading="lazy" decoding="async" width="1024" height="191" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-1024x191.png" alt="disallow insecure TLS in VS Code" class="wp-image-23613" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-1024x191.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-300x56.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-768x143.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-150x28.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-480x89.png 480w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2.png 1354w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">This produces the following in the output panel for dbLinter:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>2026-08-23 20:52:37.281 &#91;Info &#93; Starting dbLinter Language Server.
2026-08-23 20:52:37.550 &#91;Info &#93; connect.
2026-08-23 20:52:37.606 &#91;Info &#93; initialize VSCode 1.10.0.
2026-08-23 20:52:38.047 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.
2026-08-23 20:52:38.049 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.
2026-08-23 20:52:38.375 &#91;Error&#93; Failed to load configuration.

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://api.dblinter.app/api/client-session/open": (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</textarea></pre><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">2026-08-23 20:52:37.281 &#91;Info &#93; Starting dbLinter Language Server.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:37.550 &#91;Info &#93; connect.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:37.606 &#91;Info &#93; initialize VSCode 1.10.0.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:38.047 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:38.049 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">2026-08-23 20:52:38.375 &#91;Error&#93; Failed to load configuration.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">org.springframework.web.client.ResourceAccessException: I/O error on POST request for &quot;https://api.dblinter.app/api/client-session/open&quot;: (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</span></span></code></pre></div>



<p class="wp-block-paragraph">The proxy presented a certificate for <code>api.dblinter.app</code> which was not issued by a trusted certification authority.</p>



<p class="wp-block-paragraph">The proxy console therefore shows the following log entry:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;20:52:38.217&#93;&#91;127.0.0.1:60439&#93; server connect api.dblinter.app:443 (91.98.90.2:443)
&#91;20:52:38.360&#93;&#91;127.0.0.1:60441&#93; client connect
&#91;20:52:38.375&#93;&#91;127.0.0.1:60439&#93; Client TLS handshake failed. The client does not trust the proxy's certificate for api.dblinter.app (OpenSSL Error(&#91;('SSL routines', '', 'ssl/tls alert certificate unknown')&#93;))
&#91;20:52:38.377&#93;&#91;127.0.0.1:60439&#93; client disconnect
&#91;20:52:38.380&#93;&#91;127.0.0.1:60439&#93; server disconnect api.dblinter.app:443 (91.98.90.2:443)</textarea></pre><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">&#91;20:52:38.217&#93;&#91;127.0.0.1:60439&#93; server connect api.dblinter.app:443 (91.98.90.2:443)</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.360&#93;&#91;127.0.0.1:60441&#93; client connect</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">&#91;20:52:38.375&#93;&#91;127.0.0.1:60439&#93; Client TLS handshake failed. The client does not trust the proxy&#39;s certificate for api.dblinter.app (OpenSSL Error(&#91;(&#39;SSL routines&#39;, &#39;&#39;, &#39;ssl/tls alert certificate unknown&#39;)&#93;))</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.377&#93;&#91;127.0.0.1:60439&#93; client disconnect</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.380&#93;&#91;127.0.0.1:60439&#93; server disconnect api.dblinter.app:443 (91.98.90.2:443)</span></span></code></pre></div>



<p class="wp-block-paragraph">The REST API call failed before the proxy received the HTTP request. Therefore, the API key and other request data were not exposed.</p>



<h2 id="reset-network-configuration-and-unistall-proxy" class="wp-block-heading">Reset Network Configuration and Uninstall Proxy</h2>



<p class="wp-block-paragraph">Let&#8217;s stop the proxy by pressing Ctrl-C in the terminal window running it. Then run the following:</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:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>networksetup -setsecurewebproxystate "Wi-Fi" off
brew uninstall mitmproxy
rm -rf ~/.mitmproxy</textarea></pre><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">networksetup</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-setsecurewebproxystate</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Wi-Fi&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">off</span></span>
<span class="line"><span style="color: #DCDCAA">brew</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">uninstall</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">mitmproxy</span></span>
<span class="line"><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-rf</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">~/.mitmproxy</span></span></code></pre></div>



<h2 id="conclusion" class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph">The <code>Allow Insecure TLS</code> option solves a practical problem in environments where TLS inspection cannot easily be bypassed. However, it disables certificate and hostname verification. A proxy or an attacker controlling the network can then read requests, including the API key.</p>



<p class="wp-block-paragraph">The captured traffic also confirms that dbLinter analyses SQL and APEXlang files locally. Signed server responses protect the downloaded configuration from manipulation, but they do not protect confidential request data.</p>



<p class="wp-block-paragraph">Therefore, enable this option only as a temporary workaround on a trusted network. The preferred solution is to configure a TLS inspection bypass. Disable the option again as soon as possible.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/">The Checkbox That Disables TLS</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/2026/08/23/the-checkbox-that-disables-tls/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using SQL Assertions to Enforce Temporal Data Integrity</title>
		<link>https://www.salvis.com/blog/2026/03/09/using-sql-assertions-to-enforce-temporal-data-integrity/</link>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Mon, 09 Mar 2026 14:45:31 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Oracle 26ai]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Assertions]]></category>
		<category><![CDATA[Temporal Database]]></category>
		<category><![CDATA[Valid Time]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=16264</guid>

					<description><![CDATA[<p>Introduction More than twelve years ago, I described the multi-temporal features of Oracle Database in this blog post. In the conclusion, I wrote that I missed a temporal DML API, temporal integrity constraints, temporal joins, and temporal aggregations. These features are still missing today. However, in the latest version of Oracle AI<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/03/09/using-sql-assertions-to-enforce-temporal-data-integrity/">Using SQL Assertions to Enforce Temporal Data Integrity</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" id="introduction">Introduction</h2>



<p class="wp-block-paragraph">More than twelve years ago, I described the multi-temporal features of Oracle Database in this <a href="https://www.salvis.com/blog/2014/01/04/multi-temporal-database-features-in-oracle-12c/" type="post" id="1009" target="_blank" rel="noreferrer noopener">blog post</a>. In the conclusion, I wrote that I missed a temporal DML API, temporal integrity constraints, temporal joins, and temporal aggregations. These features are still missing today.</p>



<p class="wp-block-paragraph">However, in the latest version of Oracle AI Database (23.26.1), SQL assertions make it possible to define temporal integrity constraints manually. In this post, I demonstrate how.</p>



<h2 class="wp-block-heading" id="data-model">Data Model</h2>



<p class="wp-block-paragraph">There are various ways to model temporal data. In this post, I use the well-known non-temporal DEPT-EMP model as a basis and add a history table for each non-temporal table with a valid-time <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/CREATE-TABLE.html#GUID-F9CE0CC3-13AE-4744-A43C-EAC7A71AAAB6__CJADHJHB" target="_blank" rel="noreferrer noopener">period</a> named <code>vt</code> using the column <code>vt_start</code> for the beginning of the period and <code>vt_end</code> for the end of the period. Please note that Oracle Database uses half-open intervals for temporal periods and <code>NULL</code> for <code>-∞</code> and <code>+∞</code>.</p>



<p class="wp-block-paragraph">Non-temporal tables store the most recent version of the data, which is kept in their history tables. This simplifies access to the latest version and provides the expected performance for non-temporal data. The disadvantage is that the API must maintain redundant data. Note that the latest version is not necessarily the current version. The current version is the one whose valid-time period contains the current date and time.</p>



<p class="wp-block-paragraph">This model versions all columns of the base table, potentially resulting in more rows in the history tables than necessary. Furthermore, the model does not support soft deletes. In other words, there is no <code>is_deleted</code> flag. This makes managing data integrity easier. No need to keep reference and structure data just because some deleted rows still reference it. In any case, this is sufficient for this blog post.</p>



<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/03/dept-emp.svg"><img decoding="async" src="https://www.salvis.com/blog/wp-content/uploads/2026/03/dept-emp.svg" alt="" class="wp-image-16270"/></a></figure>



<h2 class="wp-block-heading" id="setup">Setup</h2>



<p class="wp-block-paragraph">For the examples in this blog post, I used Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0.</p>



<p class="wp-block-paragraph">Connected as&nbsp;<code>SYS</code>,&nbsp;I ran the following script to create the user&nbsp;<code>DEMO</code>&nbsp;with the necessary privileges.</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">1) DEMO user</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>create user demo identified by demo
   default tablespace users
   temporary tablespace temp
   quota unlimited on users;
   
grant create session to demo;
grant create table to demo;
grant create sequence to demo;
grant create assertion to demo;</textarea></pre><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: #DCDCAA">user</span><span style="color: #D4D4D4"> demo identified by demo</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">default</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">tablespace</span><span style="color: #D4D4D4"> users</span></span>
<span class="line"><span style="color: #D4D4D4">   temporary </span><span style="color: #569CD6">tablespace</span><span style="color: #D4D4D4"> temp</span></span>
<span class="line"><span style="color: #D4D4D4">   quota unlimited </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> users;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span></span>
<span class="line"><span style="color: #569CD6">grant</span><span style="color: #D4D4D4"> create session to demo;</span></span>
<span class="line"><span style="color: #569CD6">grant</span><span style="color: #D4D4D4"> create </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> to demo;</span></span>
<span class="line"><span style="color: #569CD6">grant</span><span style="color: #D4D4D4"> create </span><span style="color: #569CD6">sequence</span><span style="color: #D4D4D4"> to demo;</span></span>
<span class="line"><span style="color: #569CD6">grant</span><span style="color: #D4D4D4"> create assertion to demo;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>User DEMO created.


Grant succeeded.


Grant succeeded.


Grant succeeded.


Grant succeeded.</textarea></pre><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">User DEMO created.</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">Grant succeeded.</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">Grant succeeded.</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">Grant succeeded.</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">Grant succeeded.</span></span></code></pre></div>



<p class="wp-block-paragraph">Connected as&nbsp;<code>DEMO</code>,&nbsp;I ran the following script to implement the data model as outlined in the previous chapter with initial data.</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">2) Install model with data</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>create table dept (
   deptno      number(2, 0)      not null,
   dname       varchar2(14 char) not null,
   loc         varchar2(13 char) not null,
   constraint dept_pk primary key (deptno) deferrable initially immediate
);

create table dept_ht (
   hist_id     integer generated always as identity not null,
   vt_start    date              null,
   vt_end      date              null,
   deptno      number(2, 0)      not null,
   dname       varchar2(14 char) not null,
   loc         varchar2(13 char) not null,
   period for vt (vt_start, vt_end),
   constraint dept_ht_pk primary key (hist_id),
   constraint dept_ht_uk unique (deptno, vt_start) deferrable initially immediate,
   constraint dept_ht_dept_fk foreign key (deptno) references dept deferrable initially immediate,
   constraint dept_ht_vt_ck check (vt_start is null or vt_end is null or vt_start &lt; vt_end) deferrable initially immediate
);

create index dept_ht_dept_fk_i on dept_ht (deptno);

create table emp (
   empno       number(4, 0)      not null,
   ename       varchar2(10 char) not null,
   job         varchar2(9 char)  not null,
   mgr         number(4, 0),
   hiredate    date              not null,
   sal         number(7, 2)      not null,
   comm        number(7, 2),
   deptno      number(2, 0)      not null,
   constraint emp_pk primary key (empno) deferrable initially immediate,
   constraint emp_emp_fk foreign key (mgr) references emp deferrable initially immediate,
   constraint emp_dept_fk foreign key (deptno) references dept deferrable initially immediate
);

create index emp_dept_fk_i on emp(deptno);
create index emp_emp_fk_i on emp(mgr);

create table emp_ht (
   hist_id     integer generated always as identity not null,
   vt_start    date              null,
   vt_end      date              null,
   empno       number(4, 0)      not null,
   ename       varchar2(10 char) not null,
   job         varchar2(9 char)  not null,
   mgr         number(4, 0)      null,
   hiredate    date              not null,
   sal         number(7, 2)      not null,
   comm        number(7, 2)      null,
   deptno      number(2, 0)      not null,
   period for vt (vt_start, vt_end),
   constraint emp_ht_pk primary key (hist_id),
   constraint emp_ht_uk unique (empno, vt_start) deferrable initially immediate,
   constraint emp_ht_emp_empno_fk foreign key (empno) references emp deferrable initially immediate,
   constraint emp_ht_emp_mgr_fk foreign key (mgr) references emp deferrable initially immediate,
   constraint emp_ht_dept_fk foreign key (deptno) references dept deferrable initially immediate,
   constraint emp_ht_vt_ck check (vt_start is null or vt_end is null or vt_start &lt; vt_end) deferrable initially immediate
);

create index emp_ht_emp_fk on emp_ht (deptno);
create index emp_ht_dept_fk on emp_ht (mgr);

insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK'),
       (20, 'RESEARCH',   'DALLAS'),
       (30, 'SALES',      'CHICAGO'),
       (40, 'OPERATIONS', 'BOSTON');

insert into dept_ht (deptno, dname, loc)
select deptno, dname, loc
  from dept;

insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES',  'MANAGER',   7839, date '1981-04-02', 2975, null, 20),
       (7698, 'BLAKE',  'MANAGER',   7839, date '1981-05-01', 2850, null, 30),
       (7782, 'CLARK',  'MANAGER',   7839, date '1981-06-09', 2450, null, 10),
       (7788, 'SCOTT',  'ANALYST',   7566, date '1987-04-19', 3000, null, 20),
       (7902, 'FORD',   'ANALYST',   7566, date '1981-12-03', 3000, null, 20),
       (7499, 'ALLEN',  'SALESMAN',  7698, date '1981-02-20', 1600,  300, 30),
       (7521, 'WARD',   'SALESMAN',  7698, date '1981-02-22', 1250,  500, 30),
       (7654, 'MARTIN', 'SALESMAN',  7698, date '1981-09-28', 1250, 1400, 30),
       (7844, 'TURNER', 'SALESMAN',  7698, date '1981-09-08', 1500,    0, 30),
       (7900, 'JAMES',  'CLERK',     7698, date '1981-12-03',  950, null, 30),
       (7934, 'MILLER', 'CLERK',     7782, date '1982-01-23', 1300, null, 10),
       (7369, 'SMITH',  'CLERK',     7902, date '1980-12-17',  800, null, 20),
       (7839, 'KING',   'PRESIDENT', null, date '1981-11-17', 5000, null, 10),
       (7876, 'ADAMS',  'CLERK',     7788, date '1987-05-23', 1100, null, 20);

insert into emp_ht (empno, ename, job, mgr, hiredate, sal, comm, deptno)
select empno, ename, job, mgr, hiredate, sal, comm, deptno
  from emp;

commit;</textarea></pre><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">table</span><span style="color: #D4D4D4"> dept (</span></span>
<span class="line"><span style="color: #D4D4D4">   deptno      </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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">   dname       </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">14</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</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">   loc         </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">13</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</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 style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> dept_pk </span><span style="color: #569CD6">primary key</span><span style="color: #D4D4D4"> (deptno) deferrable initially immediate</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> dept_ht (</span></span>
<span class="line"><span style="color: #D4D4D4">   hist_id     </span><span style="color: #569CD6">integer</span><span style="color: #D4D4D4"> generated always </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> identity </span><span style="color: #569CD6">not</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">   vt_start    </span><span style="color: #569CD6">date</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">   vt_end      </span><span style="color: #569CD6">date</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">   deptno      </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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">   dname       </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">14</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</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">   loc         </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">13</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</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">   period </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> vt (vt_start, vt_end),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> dept_ht_pk </span><span style="color: #569CD6">primary key</span><span style="color: #D4D4D4"> (hist_id),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> dept_ht_uk </span><span style="color: #569CD6">unique</span><span style="color: #D4D4D4"> (deptno, vt_start) deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> dept_ht_dept_fk </span><span style="color: #569CD6">foreign key</span><span style="color: #D4D4D4"> (deptno) </span><span style="color: #569CD6">references</span><span style="color: #D4D4D4"> dept deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> dept_ht_vt_ck </span><span style="color: #569CD6">check</span><span style="color: #D4D4D4"> (vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> vt_start &lt; vt_end) deferrable initially immediate</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> index dept_ht_dept_fk_i </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> dept_ht (deptno);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> emp (</span></span>
<span class="line"><span style="color: #D4D4D4">   empno       </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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">   ename       </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</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">   job         </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">9</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">)  </span><span style="color: #569CD6">not</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">   mgr         </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   hiredate    </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4">              </span><span style="color: #569CD6">not</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">   sal         </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">7</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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">   comm        </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">7</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   deptno      </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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 style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_pk </span><span style="color: #569CD6">primary key</span><span style="color: #D4D4D4"> (empno) deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_emp_fk </span><span style="color: #569CD6">foreign key</span><span style="color: #D4D4D4"> (mgr) </span><span style="color: #569CD6">references</span><span style="color: #D4D4D4"> emp deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_dept_fk </span><span style="color: #569CD6">foreign key</span><span style="color: #D4D4D4"> (deptno) </span><span style="color: #569CD6">references</span><span style="color: #D4D4D4"> dept deferrable initially immediate</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> index emp_dept_fk_i </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> emp(deptno);</span></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> index emp_emp_fk_i </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> emp(mgr);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> emp_ht (</span></span>
<span class="line"><span style="color: #D4D4D4">   hist_id     </span><span style="color: #569CD6">integer</span><span style="color: #D4D4D4"> generated always </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> identity </span><span style="color: #569CD6">not</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">   vt_start    </span><span style="color: #569CD6">date</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">   vt_end      </span><span style="color: #569CD6">date</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">   empno       </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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">   ename       </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</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">   job         </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">9</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">)  </span><span style="color: #569CD6">not</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">   mgr         </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</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">   hiredate    </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4">              </span><span style="color: #569CD6">not</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">   sal         </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">7</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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">   comm        </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">7</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</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">   deptno      </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</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">   period </span><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> vt (vt_start, vt_end),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_ht_pk </span><span style="color: #569CD6">primary key</span><span style="color: #D4D4D4"> (hist_id),</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_ht_uk </span><span style="color: #569CD6">unique</span><span style="color: #D4D4D4"> (empno, vt_start) deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_ht_emp_empno_fk </span><span style="color: #569CD6">foreign key</span><span style="color: #D4D4D4"> (empno) </span><span style="color: #569CD6">references</span><span style="color: #D4D4D4"> emp deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_ht_emp_mgr_fk </span><span style="color: #569CD6">foreign key</span><span style="color: #D4D4D4"> (mgr) </span><span style="color: #569CD6">references</span><span style="color: #D4D4D4"> emp deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_ht_dept_fk </span><span style="color: #569CD6">foreign key</span><span style="color: #D4D4D4"> (deptno) </span><span style="color: #569CD6">references</span><span style="color: #D4D4D4"> dept deferrable initially immediate,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_ht_vt_ck </span><span style="color: #569CD6">check</span><span style="color: #D4D4D4"> (vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> vt_start &lt; vt_end) deferrable initially immediate</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> index emp_ht_emp_fk </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> emp_ht (deptno);</span></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> index emp_ht_dept_fk </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> emp_ht (mgr);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> dept (deptno, dname, loc)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ACCOUNTING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;NEW YORK&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;RESEARCH&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;DALLAS&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SALES&#39;</span><span style="color: #D4D4D4">,      </span><span style="color: #CE9178">&#39;CHICAGO&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">40</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;OPERATIONS&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;BOSTON&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> dept_ht (deptno, dname, loc)</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> deptno, dname, loc</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">7566</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;JONES&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;MANAGER&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-04-02&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2975</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;BLAKE&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;MANAGER&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-05-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2850</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</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">       (</span><span style="color: #B5CEA8">7782</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;CLARK&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;MANAGER&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-06-09&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2450</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7788</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SCOTT&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;ANALYST&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7566</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1987-04-19&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">3000</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7902</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FORD&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;ANALYST&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7566</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-12-03&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">3000</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7499</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ALLEN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-02-20&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1600</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">300</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">       (</span><span style="color: #B5CEA8">7521</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;WARD&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-02-22&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1250</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">500</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">       (</span><span style="color: #B5CEA8">7654</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;MARTIN&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-09-28&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1250</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1400</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">       (</span><span style="color: #B5CEA8">7844</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TURNER&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-09-08&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1500</span><span style="color: #D4D4D4">,    </span><span style="color: #B5CEA8">0</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">       (</span><span style="color: #B5CEA8">7900</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;JAMES&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-12-03&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">950</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</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">       (</span><span style="color: #B5CEA8">7934</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;MILLER&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7782</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1982-01-23&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1300</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7369</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SMITH&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7902</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1980-12-17&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">800</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5000</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7876</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ADAMS&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7788</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1987-05-23&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1100</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> emp_ht (empno, ename, job, mgr, hiredate, sal, comm, deptno)</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> empno, ename, job, mgr, hiredate, sal, comm, deptno</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Table DEPT created.


Table DEPT_HT created.


Index DEPT_HT_DEPT_FK_I created.


Table EMP created.


Index EMP_DEPT_FK_I created.


Index EMP_EMP_FK_I created.


Table EMP_HT created.


Index EMP_HT_EMP_FK created.


Index EMP_HT_DEPT_FK created.


4 rows inserted.


4 rows inserted.


14 rows inserted.


14 rows inserted.


Commit complete.</textarea></pre><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">Table DEPT created.</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">Table DEPT_HT created.</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">Index DEPT_HT_DEPT_FK_I created.</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">Table EMP created.</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">Index EMP_DEPT_FK_I created.</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">Index EMP_EMP_FK_I created.</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">Table EMP_HT created.</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">Index EMP_HT_EMP_FK created.</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">Index EMP_HT_DEPT_FK created.</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">4 rows inserted.</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">4 rows inserted.</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">14 rows inserted.</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">14 rows inserted.</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">Commit complete.</span></span></code></pre></div>



<h2 class="wp-block-heading" id="prohibit-overlapping-periods">Prohibit Overlapping Periods</h2>



<p class="wp-block-paragraph">Chris Saxon explains in this <a href="https://blogs.oracle.com/sql/how-to-stop-overlapping-date-ranges-in-oracle-ai-database" type="link" id="https://blogs.oracle.com/sql/how-to-stop-overlapping-date-ranges-in-oracle-ai-database" target="_blank" rel="noreferrer noopener">blog post</a> how to prevent overlapping time ranges with SQL assertions. We use a similar approach here for <code>dept_ht</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);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">3) Create assertion: no overlapping in dept_ht for vt period</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>create assertion if not exists no_overlapping_dept_ht_vt_period_as
check (
   not exists (
      select 'a department version (d1)'
        from dept_ht d1
       where exists (
              select 'an overlapping department version (d2)'
                from dept_ht d2
               where d2.deptno = d1.deptno
                 and d2.hist_id != d1.hist_id
                 and (d1.vt_start is null or d2.vt_end is null or d1.vt_start &lt; d2.vt_end)
                 and (d2.vt_start is null or d1.vt_end is null or d2.vt_start &lt; d1.vt_end)
             )
   )
) deferrable initially immediate;</textarea></pre><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"> assertion </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> no_overlapping_dept_ht_vt_period_as</span></span>
<span class="line"><span style="color: #569CD6">check</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;a department version (d1)&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_ht d1</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">              </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;an overlapping department version (d2)&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_ht d2</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> d2.deptno = d1.deptno</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> d2.hist_id != d1.hist_id</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (d1.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> d2.vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> d1.vt_start &lt; d2.vt_end)</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (d2.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> d1.vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> d2.vt_start &lt; d1.vt_end)</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">) deferrable initially immediate;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Assertion NO_OVERLAPPING_DEPT_HT_VT_PERIOD_AS created.</textarea></pre><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">Assertion NO_OVERLAPPING_DEPT_HT_VT_PERIOD_AS created.</span></span></code></pre></div>



<p class="wp-block-paragraph">Let&#8217;s test the assertion. We defer all constraints to make the example easier to implement and read.</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);--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">4) Overlapping test</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>set constraints all deferred;
delete from dept_ht where deptno = 10;
insert into dept_ht (deptno, dname, loc, vt_start, vt_end)
values (10, 'ACCOUNTING', 'NEW_YORK',   null,              date '2026-04-01'),
       (10, 'ACCOUNTING', 'WINTERTHUR', date '2026-03-01', null             );
commit;</textarea></pre><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">set</span><span style="color: #D4D4D4"> constraints </span><span style="color: #569CD6">all</span><span style="color: #D4D4D4"> deferred;</span></span>
<span class="line"><span style="color: #569CD6">delete</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_ht </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> deptno = </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> dept_ht (deptno, dname, loc, vt_start, vt_end)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ACCOUNTING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;NEW_YORK&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,              </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2026-04-01&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ACCOUNTING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;WINTERTHUR&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2026-03-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">             );</span></span>
<span class="line cbp-line-highlight"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Constraints ALL succeeded.


1 row deleted.


2 rows inserted.


Error starting at line : 6 in command -
commit
Error report -
ORA-02091: transaction rolled back
ORA-08601: SQL assertion (DEMO.NO_OVERLAPPING_DEPT_HT_VT_PERIOD_AS) violated.

https://docs.oracle.com/error-help/db/ora-02091/
02091. 00000 -  "transaction rolled back"
*Cause:    Also see error 2092. If the transaction is aborted at a remote
           site then you will only see 2091; if aborted at host then you will
           see 2092 and 2091.
*Action:   Add rollback segment and retry the transaction.</textarea></pre><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">Constraints ALL succeeded.</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">1 row deleted.</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">2 rows inserted.</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">Error starting at line : 6 in command -</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">commit</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Error report -</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">ORA-02091: transaction rolled back</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">ORA-08601: SQL assertion (DEMO.NO_OVERLAPPING_DEPT_HT_VT_PERIOD_AS) violated.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">https://docs.oracle.com/error-help/db/ora-02091/</span></span>
<span class="line"><span style="color: #D4D4D4">02091. 00000 -  &quot;transaction rolled back&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">*Cause:    Also see error 2092. If the transaction is aborted at a remote</span></span>
<span class="line"><span style="color: #D4D4D4">           site then you will only see 2091; if aborted at host then you will</span></span>
<span class="line"><span style="color: #D4D4D4">           see 2092 and 2091.</span></span>
<span class="line"><span style="color: #D4D4D4">*Action:   Add rollback segment and retry the transaction.</span></span></code></pre></div>



<p class="wp-block-paragraph">The test fails at line 6, at the <code>commit</code> statement, exactly as expected.</p>



<p class="wp-block-paragraph">Let&#8217;s insert two adjacent (gapless) periods.</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);--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">5) Non-overlapping test</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>set constraints all deferred;
delete from dept_ht where deptno = 10;
insert into dept_ht (deptno, dname, loc, vt_start, vt_end)
values (10, 'ACCOUNTING', 'NEW_YORK',   null,              date '2026-04-01'),
       (10, 'ACCOUNTING', 'WINTERTHUR', date '2026-04-01', null             );
commit;</textarea></pre><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">set</span><span style="color: #D4D4D4"> constraints </span><span style="color: #569CD6">all</span><span style="color: #D4D4D4"> deferred;</span></span>
<span class="line"><span style="color: #569CD6">delete</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_ht </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> deptno = </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> dept_ht (deptno, dname, loc, vt_start, vt_end)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ACCOUNTING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;NEW_YORK&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,              </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2026-04-01&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ACCOUNTING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;WINTERTHUR&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2026-04-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">             );</span></span>
<span class="line cbp-line-highlight"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Constraints ALL succeeded.


1 row deleted.


2 rows inserted.


Commit complete.</textarea></pre><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">Constraints ALL succeeded.</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">1 row deleted.</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">2 rows inserted.</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">Commit complete.</span></span></code></pre></div>



<p class="wp-block-paragraph">The test succeeds. So far so good.</p>



<p class="wp-block-paragraph">However, this change leaves the redundant current-state copy in <code>dept</code> out of sync. After any change to <code>dept_ht</code>, the API should execute a statement like the following within the same transaction:</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">6) Updating redundancy in DEPT from DEPT_HT</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>update dept d
   set d.dname = ht.dname,
       d.loc   = ht.loc
  from (
          select deptno, dname, loc
            from dept_ht
           where deptno = 10
           order by vt_start desc nulls first
           fetch first 1 row only
       ) ht
 where d.deptno = ht.deptno;</textarea></pre><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">update</span><span style="color: #D4D4D4"> dept d</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> d.dname = ht.dname,</span></span>
<span class="line"><span style="color: #D4D4D4">       d.loc   = ht.loc</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> deptno, dname, loc</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_ht</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> deptno = </span><span style="color: #B5CEA8">10</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> vt_start </span><span style="color: #569CD6">desc</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">nulls first</span></span>
<span class="line"><span style="color: #D4D4D4">           </span><span style="color: #569CD6">fetch</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">first</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">row</span><span style="color: #D4D4D4"> only</span></span>
<span class="line"><span style="color: #D4D4D4">       ) ht</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> d.deptno = ht.deptno;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>1 row updated.</textarea></pre><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">1 row updated.</span></span></code></pre></div>



<p class="wp-block-paragraph">Of course, we would need a similar SQL assertion for the period in <code>emp_ht</code>. However, this is not essential for this blog post. Therefore, we will skip it.</p>



<h2 class="wp-block-heading" id="temporal-foreign-keys">Temporal Foreign Keys</h2>



<p class="wp-block-paragraph">Let’s now look at another typical problem in temporal data models: Temporal foreign keys.  We have two temporal foreign keys in our model:</p>



<ul class="wp-block-list">
<li><code>emp_ht_emp_mgr_fk</code></li>



<li><code>emp_ht_dept_fk</code></li>
</ul>



<p class="wp-block-paragraph">Although the foreign key technically references a non-temporal table, the business rule is temporal: the referenced entity must be valid throughout the relevant period of the referencing row.</p>



<p class="wp-block-paragraph">In this example, that means a manager must exist for the entire validity period of the employee version.</p>



<p class="wp-block-paragraph">Sounds complicated? Let&#8217;s look at an example based on <code>emp_ht_emp_mgr_fk</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);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">7) Inconsistent emp_ht_emp_mgr_fk</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>update emp_ht
   set vt_start = hiredate;

select e.vt_start, e.vt_end, e.empno, e.ename, e.mgr, m.ename as mgr_name, m.hiredate as mgr_hiredate,
       e.mgr is not null and hm.empno is null as is_inconsistent
 from emp_ht e
 left join emp m
   on m.empno = e.mgr
 left join emp_ht hm
   on hm.empno = e.mgr
      and (hm.vt_start is null or (e.vt_start is not null and hm.vt_start &lt;= e.vt_start))
      and (hm.vt_end is null or e.vt_start is null or hm.vt_end > e.vt_start)
order by e.empno;

rollback;</textarea></pre><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">update</span><span style="color: #D4D4D4"> emp_ht</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> vt_start = hiredate;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> e.vt_start, e.vt_end, e.empno, e.ename, e.mgr, m.ename </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> mgr_name, m.hiredate </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> mgr_hiredate,</span></span>
<span class="line"><span style="color: #D4D4D4">       e.mgr </span><span style="color: #569CD6">is not null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> hm.empno </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> is_inconsistent</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht e</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">left join</span><span style="color: #D4D4D4"> emp m</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> m.empno = e.mgr</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">left join</span><span style="color: #D4D4D4"> emp_ht hm</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> hm.empno = e.mgr</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (hm.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> (e.vt_start </span><span style="color: #569CD6">is not null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> hm.vt_start &lt;= e.vt_start))</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (hm.vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> e.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> hm.vt_end &gt; e.vt_start)</span></span>
<span class="line"><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> e.empno;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #DCDCAA">rollback</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>14 rows updated.


VT_START   VT_END          EMPNO ENAME             MGR MGR_NAME   MGR_HIREDATE IS_INCONSISTENT
---------- ---------- ---------- ---------- ---------- ---------- ------------ ---------------
1980-12-17                  7369 SMITH            7902 FORD       1981-12-03   true           
1981-02-20                  7499 ALLEN            7698 BLAKE      1981-05-01   true           
1981-02-22                  7521 WARD             7698 BLAKE      1981-05-01   true           
1981-04-02                  7566 JONES            7839 KING       1981-11-17   true           
1981-09-28                  7654 MARTIN           7698 BLAKE      1981-05-01   false          
1981-05-01                  7698 BLAKE            7839 KING       1981-11-17   true           
1981-06-09                  7782 CLARK            7839 KING       1981-11-17   true           
1987-04-19                  7788 SCOTT            7566 JONES      1981-04-02   false          
1981-11-17                  7839 KING                                          false          
1981-09-08                  7844 TURNER           7698 BLAKE      1981-05-01   false          
1987-05-23                  7876 ADAMS            7788 SCOTT      1987-04-19   false          
1981-12-03                  7900 JAMES            7698 BLAKE      1981-05-01   false          
1981-12-03                  7902 FORD             7566 JONES      1981-04-02   false          
1982-01-23                  7934 MILLER           7782 CLARK      1981-06-09   false          

14 rows selected. 


Rollback complete.</textarea></pre><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">14 rows updated.</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">VT_START   VT_END          EMPNO ENAME             MGR MGR_NAME   MGR_HIREDATE IS_INCONSISTENT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- ---------- ---------- ---------- ---------- ------------ ---------------</span></span>
<span class="line"><span style="color: #D4D4D4">1980-12-17                  7369 SMITH            7902 FORD       1981-12-03   true           </span></span>
<span class="line"><span style="color: #D4D4D4">1981-02-20                  7499 ALLEN            7698 BLAKE      1981-05-01   true           </span></span>
<span class="line"><span style="color: #D4D4D4">1981-02-22                  7521 WARD             7698 BLAKE      1981-05-01   true           </span></span>
<span class="line"><span style="color: #D4D4D4">1981-04-02                  7566 JONES            7839 KING       1981-11-17   true           </span></span>
<span class="line"><span style="color: #D4D4D4">1981-09-28                  7654 MARTIN           7698 BLAKE      1981-05-01   false          </span></span>
<span class="line"><span style="color: #D4D4D4">1981-05-01                  7698 BLAKE            7839 KING       1981-11-17   true           </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">1981-06-09                  7782 CLARK            7839 KING       1981-11-17   true           </span></span>
<span class="line"><span style="color: #D4D4D4">1987-04-19                  7788 SCOTT            7566 JONES      1981-04-02   false          </span></span>
<span class="line"><span style="color: #D4D4D4">1981-11-17                  7839 KING                                          false          </span></span>
<span class="line"><span style="color: #D4D4D4">1981-09-08                  7844 TURNER           7698 BLAKE      1981-05-01   false          </span></span>
<span class="line"><span style="color: #D4D4D4">1987-05-23                  7876 ADAMS            7788 SCOTT      1987-04-19   false          </span></span>
<span class="line"><span style="color: #D4D4D4">1981-12-03                  7900 JAMES            7698 BLAKE      1981-05-01   false          </span></span>
<span class="line"><span style="color: #D4D4D4">1981-12-03                  7902 FORD             7566 JONES      1981-04-02   false          </span></span>
<span class="line"><span style="color: #D4D4D4">1982-01-23                  7934 MILLER           7782 CLARK      1981-06-09   false          </span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">14 rows selected. </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">Rollback complete.</span></span></code></pre></div>



<p class="wp-block-paragraph">First, we set the start of the valid period for all employees according to their hire date.</p>



<p class="wp-block-paragraph">Then, we queried the employees and their managers at the start of their valid time period. Employees without a manager at that time are marked with <code>true</code> in the result column <code>is_inconsistent</code>.</p>



<p class="wp-block-paragraph">CLARK, for example, was hired on 9 June 1981. His manager, KING, was hired on 17 November 1981. Consequently, CLARK had no assigned manager between 9 June 1981 and 17 November 1981. This is an invalid temporal foreign key. To resolve this issue, we must either assign CLARK a manager for this period or amend KING&#8217;s valid time period, which would likely require adjusting his hire date as well.</p>



<h2 class="wp-block-heading" id="valid-manager-at-the-start-of-a-period">Valid Manager At the Start of a Period</h2>



<p class="wp-block-paragraph">Let&#8217;s implement the check in the previous query as an SQL assertion.</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">8) Create assertion: cover_vt_start_in_emp_ht_emp_mgr_fk_as</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>create assertion if not exists cover_vt_start_in_emp_ht_emp_mgr_fk_as
check (
   not exists (
      select 'an employee version (e)'
        from emp_ht e
       where e.mgr is not null
         and not exists (
                select 'a manager version (m) covering e.vt_start'
                  from emp_ht m
                 where m.empno = e.mgr
                   and (m.vt_start is null or (e.vt_start is not null and m.vt_start &lt;= e.vt_start))
                   and (m.vt_end is null or e.vt_start is null or m.vt_end > e.vt_start)
             )
   )
) deferrable initially immediate;</textarea></pre><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"> assertion </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> cover_vt_start_in_emp_ht_emp_mgr_fk_as</span></span>
<span class="line"><span style="color: #569CD6">check</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;an employee version (e)&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht e</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.mgr </span><span style="color: #569CD6">is not null</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;a manager version (m) covering e.vt_start&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht m</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> m.empno = e.mgr</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (m.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> (e.vt_start </span><span style="color: #569CD6">is not null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> m.vt_start &lt;= e.vt_start))</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (m.vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> e.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> m.vt_end &gt; e.vt_start)</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">) deferrable initially immediate;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Assertion COVER_VT_START_IN_EMP_HT_EMP_MGR_FK_AS created.</textarea></pre><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">Assertion COVER_VT_START_IN_EMP_HT_EMP_MGR_FK_AS created.</span></span></code></pre></div>



<p class="wp-block-paragraph">Let&#8217;s try to create a gap in manager coverage by setting the <code>vt_start</code> to a non-null value for a manager.</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">9) Test gap in manager coverage (vt_start)</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>update emp_ht
   set vt_start = hiredate
 where ename = 'KING';</textarea></pre><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">update</span><span style="color: #D4D4D4"> emp_ht</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> vt_start = hiredate</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> ename = </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Error starting at line : 1 in command -
update emp_ht
   set vt_start = hiredate
 where ename = 'KING'
Error report -
ORA-08601: SQL assertion (DEMO.COVER_VT_START_IN_EMP_HT_EMP_MGR_FK_AS) violated.

https://docs.oracle.com/error-help/db/ora-08601/</textarea></pre><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">Error starting at line : 1 in command -</span></span>
<span class="line"><span style="color: #D4D4D4">update emp_ht</span></span>
<span class="line"><span style="color: #D4D4D4">   set vt_start = hiredate</span></span>
<span class="line"><span style="color: #D4D4D4"> where ename = &#39;KING&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">Error report -</span></span>
<span class="line"><span style="color: #D4D4D4">ORA-08601: SQL assertion (DEMO.COVER_VT_START_IN_EMP_HT_EMP_MGR_FK_AS) violated.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">https://docs.oracle.com/error-help/db/ora-08601/</span></span></code></pre></div>



<p class="wp-block-paragraph">Good. The update fails because JONES, BLAKE and CLARK would have no manager assigned at the beginning of their valid time period. </p>



<p class="wp-block-paragraph">Now let&#8217;s try to set <code>vt_start</code> for an employee who is not a manager.</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">10) Test no gap in manager coverage (vt_start)</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>update emp_ht
   set vt_start = hiredate
 where ename = 'ADAMS';
rollback;</textarea></pre><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">update</span><span style="color: #D4D4D4"> emp_ht</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> vt_start = hiredate</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> ename = </span><span style="color: #CE9178">&#39;ADAMS&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #DCDCAA">rollback</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>1 row updated.


Rollback complete.</textarea></pre><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">1 row updated.</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">Rollback complete.</span></span></code></pre></div>



<p class="wp-block-paragraph">The update succeeded because ADAMS is not a manager and, therefore, no gap in manager coverage was created.</p>



<h2 class="wp-block-heading" id="valid-manager-at-the-end-of-a-period">Valid Manager At the End of a Period</h2>



<p class="wp-block-paragraph">The previous SQL assertion ensures that manager coverage exists at the start of a period. However, to guarantee temporal data integrity for the entire period, we need an additional SQL assertion.</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">11) Create assertion: cover_vt_end_in_emp_ht_emp_mgr_fk_as</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>create assertion if not exists cover_vt_end_in_emp_ht_emp_mgr_fk_as
check (
   not exists (
      select 'an employee version (e)'
        from emp_ht e
       where e.mgr is not null
         and exists (
                select 'a manager version (m) ending before e.vt_end'
                  from emp_ht m
                 where m.empno = e.mgr
                   and m.vt_end is not null
                   and (e.vt_start is null or m.vt_end > e.vt_start)
                   and (e.vt_end is null or m.vt_end &lt; e.vt_end)
                   and not exists (
                          select 'a manager version (m2) covering the m.vt_end'
                            from emp_ht m2
                           where m2.empno = e.mgr
                             and m2.hist_id != m.hist_id
                             and (m2.vt_start is null or m2.vt_start &lt;= m.vt_end)
                             and (m2.vt_end is null or m2.vt_end > m.vt_end)
                       )
             )
   )
) deferrable initially immediate;</textarea></pre><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"> assertion </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> cover_vt_end_in_emp_ht_emp_mgr_fk_as</span></span>
<span class="line"><span style="color: #569CD6">check</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;an employee version (e)&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht e</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.mgr </span><span style="color: #569CD6">is not null</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;a manager version (m) ending before e.vt_end&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht m</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> m.empno = e.mgr</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> m.vt_end </span><span style="color: #569CD6">is not null</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (e.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> m.vt_end &gt; e.vt_start)</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (e.vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> m.vt_end &lt; e.vt_end)</span></span>
<span class="line"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">                          </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;a manager version (m2) covering the m.vt_end&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                            </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht m2</span></span>
<span class="line"><span style="color: #D4D4D4">                           </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> m2.empno = e.mgr</span></span>
<span class="line"><span style="color: #D4D4D4">                             </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> m2.hist_id != m.hist_id</span></span>
<span class="line"><span style="color: #D4D4D4">                             </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (m2.vt_start </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> m2.vt_start &lt;= m.vt_end)</span></span>
<span class="line"><span style="color: #D4D4D4">                             </span><span style="color: #569CD6">and</span><span style="color: #D4D4D4"> (m2.vt_end </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> m2.vt_end &gt; m.vt_end)</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">) deferrable initially immediate;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Assertion COVER_VT_END_IN_EMP_HT_EMP_MGR_FK_AS created.</textarea></pre><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">Assertion COVER_VT_END_IN_EMP_HT_EMP_MGR_FK_AS created.</span></span></code></pre></div>



<p class="wp-block-paragraph">Let&#8217;s try now to set the <code>vt_end</code> to a non-null value of a manager.</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">12) Test gap in manager coverage (vt_end)</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>update emp_ht
   set vt_end = date '2100-01-01'
 where ename = 'KING';</textarea></pre><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">update</span><span style="color: #D4D4D4"> emp_ht</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> vt_end = </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2100-01-01&#39;</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> ename = </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Error starting at line : 1 in command -
update emp_ht
   set vt_end = date '2100-01-01'
 where ename = 'KING'
Error at Command Line : 1 Column : 8
Error report -
SQL Error: ORA-08601: SQL assertion (DEMO.COVER_VT_END_IN_EMP_HT_EMP_MGR_FK_AS) violated.

https://docs.oracle.com/error-help/db/ora-08601/</textarea></pre><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">Error starting at line : 1 in command -</span></span>
<span class="line"><span style="color: #D4D4D4">update emp_ht</span></span>
<span class="line"><span style="color: #D4D4D4">   set vt_end = date &#39;2100-01-01&#39;</span></span>
<span class="line"><span style="color: #D4D4D4"> where ename = &#39;KING&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">Error at Command Line : 1 Column : 8</span></span>
<span class="line"><span style="color: #D4D4D4">Error report -</span></span>
<span class="line"><span style="color: #D4D4D4">SQL Error: ORA-08601: SQL assertion (DEMO.COVER_VT_END_IN_EMP_HT_EMP_MGR_FK_AS) violated.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">https://docs.oracle.com/error-help/db/ora-08601/</span></span></code></pre></div>



<p class="wp-block-paragraph">Good. The update failed because JONES, BLAKE and CLARK would have had no manager from 1 January 2100 until the end of time.</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">13) Test no gap in manager coverage (vt_end)</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>update emp_ht
   set vt_end = date '2100-01-01'
  where ename = 'ADAMS';
rollback;</textarea></pre><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">update</span><span style="color: #D4D4D4"> emp_ht</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> vt_end = </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2100-01-01&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> ename = </span><span style="color: #CE9178">&#39;ADAMS&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #DCDCAA">rollback</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>1 row updated.


Rollback complete.</textarea></pre><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">1 row updated.</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">Rollback complete.</span></span></code></pre></div>



<p class="wp-block-paragraph">The update succeeded because ADAMS is not a manager and, therefore, no gap in manager coverage was created.</p>



<p class="wp-block-paragraph">Well, those were just simple test cases. What would happen if we left a one-day gap between versions of the history? Would this be detected?</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);--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">14) Test gap in manager coverage of multiple versions</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>set constraints all deferred;
delete from emp_ht where ename = 'KING';
insert into emp_ht (vt_start, vt_end, empno, ename, job, hiredate, sal, deptno)
values (null,              date '1981-11-17', 7839, 'KING', 'PRESIDENT', date '1981-11-17', 2000, 10),
       (date '1981-11-17', date '2100-01-01', 7839, 'KING', 'PRESIDENT', date '1981-11-17', 4500, 10),
       (date '2100-01-02', date '2200-01-01', 7839, 'KING', 'PRESIDENT', date '1981-11-17', 4600, 10),
       (date '2200-01-01', null             , 7839, 'KING', 'PRESIDENT', date '1981-11-17', 5000, 10);
commit;</textarea></pre><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">set</span><span style="color: #D4D4D4"> constraints </span><span style="color: #569CD6">all</span><span style="color: #D4D4D4"> deferred;</span></span>
<span class="line"><span style="color: #569CD6">delete</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> ename = </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> emp_ht (vt_start, vt_end, empno, ename, job, hiredate, sal, deptno)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,              </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2000</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2100-01-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">4500</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       (</span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2100-01-02&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2200-01-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">4600</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2200-01-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">             , </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5000</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">);</span></span>
<span class="line cbp-line-highlight"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Constraints ALL succeeded.


1 row deleted.


4 rows inserted.


Error starting at line : 8 in command -
commit
Error report -
ORA-02091: transaction rolled back
ORA-08601: SQL assertion (DEMO.COVER_VT_END_IN_EMP_HT_EMP_MGR_FK_AS) violated.

https://docs.oracle.com/error-help/db/ora-02091/
02091. 00000 -  "transaction rolled back"
*Cause:    Also see error 2092. If the transaction is aborted at a remote
           site then you will only see 2091; if aborted at host then you will
           see 2092 and 2091.
*Action:   Add rollback segment and retry the transaction.</textarea></pre><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">Constraints ALL succeeded.</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">1 row deleted.</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">4 rows inserted.</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">Error starting at line : 8 in command -</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">commit</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Error report -</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">ORA-02091: transaction rolled back</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">ORA-08601: SQL assertion (DEMO.COVER_VT_END_IN_EMP_HT_EMP_MGR_FK_AS) violated.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">https://docs.oracle.com/error-help/db/ora-02091/</span></span>
<span class="line"><span style="color: #D4D4D4">02091. 00000 -  &quot;transaction rolled back&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">*Cause:    Also see error 2092. If the transaction is aborted at a remote</span></span>
<span class="line"><span style="color: #D4D4D4">           site then you will only see 2091; if aborted at host then you will</span></span>
<span class="line"><span style="color: #D4D4D4">           see 2092 and 2091.</span></span>
<span class="line"><span style="color: #D4D4D4">*Action:   Add rollback segment and retry the transaction.</span></span></code></pre></div>



<p class="wp-block-paragraph">Yes! The commit statement failed because no version covered 1 January 2100.</p>



<p class="wp-block-paragraph">When we fix the date on line 6, the transaction should succeed. Let&#8217;s try that.</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);--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">15) Test no gap in manager coverage of multiple versions</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>set constraints all deferred;
delete from emp_ht where ename = 'KING';
insert into emp_ht (vt_start, vt_end, empno, ename, job, hiredate, sal, deptno)
values (null,              date '1981-11-17', 7839, 'KING', 'PRESIDENT', date '1981-11-17', 2000, 10),
       (date '1981-11-17', date '2100-01-01', 7839, 'KING', 'PRESIDENT', date '1981-11-17', 4500, 10),
       (date '2100-01-01', date '2200-01-01', 7839, 'KING', 'PRESIDENT', date '1981-11-17', 4600, 10),
       (date '2200-01-01', null             , 7839, 'KING', 'PRESIDENT', date '1981-11-17', 5000, 10);
commit;</textarea></pre><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">set</span><span style="color: #D4D4D4"> constraints </span><span style="color: #569CD6">all</span><span style="color: #D4D4D4"> deferred;</span></span>
<span class="line"><span style="color: #569CD6">delete</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp_ht </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> ename = </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> emp_ht (vt_start, vt_end, empno, ename, job, hiredate, sal, deptno)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,              </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2000</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2100-01-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">4500</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       (</span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2100-01-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2200-01-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">4600</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;2200-01-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">             , </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5000</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Constraints ALL succeeded.


1 row deleted.


4 rows inserted.


Commit complete.</textarea></pre><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">Constraints ALL succeeded.</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">1 row deleted.</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">4 rows inserted.</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">Commit complete.</span></span></code></pre></div>



<p class="wp-block-paragraph">Perfect. This works.</p>



<p class="wp-block-paragraph">We have successfully enforced temporal referential integrity for the manager relationship using SQL assertions.</p>



<h2 class="wp-block-heading" id="summary">Summary</h2>



<p class="wp-block-paragraph">In this blog post, we created the SQL assertion <a href="#prohibit-overlapping-periods" type="internal" id="#prohibit-overlapping-periods" rel="nofollow">no_overlapping_dept_ht_vt_period_as</a> to ensure validity periods in the table <code>dept_ht</code> do not overlap.</p>



<p class="wp-block-paragraph">We enforced temporal referential data integrity for the foreign key <code>emp_ht_emp_mgr_fk</code> using the SQL assertions <a href="#valid-manager-at-the-start-of-a-period" type="internal" id="#valid-manager-at-the-start-of-a-period" rel="nofollow">cover_vt_start_in_emp_ht_emp_mgr_fk_as</a> and <a href="#valid-manager-at-the-end-of-a-period" type="internal" id="#valid-manager-at-the-end-of-a-period" rel="nofollow">cover_vt_end_in_emp_ht_emp_mgr_fk_as</a>. This means that an employee always has a valid manager assigned throughout their validity period. Any gaps in manager coverage are detected correctly.</p>



<p class="wp-block-paragraph">Adapting these SQL assertions for use in templates for temporal API generators should not be too difficult. All necessary information is in the Oracle data dictionary. With some additional metadata, we can generate additional SQL assertions for related, optional topics such as:</p>



<ul class="wp-block-list">
<li>Enforce adjacent periods (no gaps)</li>



<li>Disallow adjacent periods with the same business values (enforce merge of periods)</li>



<li>Disallow different business keys across periods (enforce business key updates on all versions)</li>



<li>Disallow new versions for changes to non-versioned columns only (enforce update of all versions instead)</li>
</ul>



<p class="wp-block-paragraph">Although SQL assertions make it easier to enforce the integrity of temporal data, the use of temporal tables measurably increases complexity. Therefore, only use temporal tables if you really need to. Document which columns require temporal handling and explain why. </p>



<p class="wp-block-paragraph">In any case, the integration of SQL assertions into Oracle AI Database makes the use of temporal tables much easier.</p>
<p>The post <a href="https://www.salvis.com/blog/2026/03/09/using-sql-assertions-to-enforce-temporal-data-integrity/">Using SQL Assertions to Enforce Temporal Data Integrity</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
