<?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>Valid Time Archives - Philipp Salvisberg&#039;s Blog</title>
	<atom:link href="https://www.salvis.com/blog/tag/valid-time/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.salvis.com/blog/tag/valid-time/</link>
	<description>Database-centric development</description>
	<lastBuildDate>Tue, 10 Mar 2026 10:50:01 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</url>
	<title>Valid Time Archives - Philipp Salvisberg&#039;s Blog</title>
	<link>https://www.salvis.com/blog/tag/valid-time/</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/valid-time/feed/"/>
	<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>
					<comments>https://www.salvis.com/blog/2026/03/09/using-sql-assertions-to-enforce-temporal-data-integrity/#respond</comments>
		
		<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>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>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>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>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>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>For the examples in this blog post, I used Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0.</p>



<p>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>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>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>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>The test fails at line 6, at the <code>commit</code> statement, exactly as expected.</p>



<p>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>The test succeeds. So far so good.</p>



<p>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>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>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>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>In this example, that means a manager must exist for the entire validity period of the employee version.</p>



<p>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>First, we set the start of the valid period for all employees according to their hire date.</p>



<p>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>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>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>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>Good. The update fails because JONES, BLAKE and CLARK would have no manager assigned at the beginning of their valid time period. </p>



<p>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>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>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>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>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>The update succeeded because ADAMS is not a manager and, therefore, no gap in manager coverage was created.</p>



<p>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>Yes! The commit statement failed because no version covered 1 January 2100.</p>



<p>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>Perfect. This works.</p>



<p>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>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>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>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>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>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>
					
					<wfw:commentRss>https://www.salvis.com/blog/2026/03/09/using-sql-assertions-to-enforce-temporal-data-integrity/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Names Matter</title>
		<link>https://www.salvis.com/blog/2020/06/21/names-matter/</link>
					<comments>https://www.salvis.com/blog/2020/06/21/names-matter/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 21 Jun 2020 15:00:30 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[accessible_by_clause]]></category>
		<category><![CDATA[Decision Time]]></category>
		<category><![CDATA[Flashback]]></category>
		<category><![CDATA[Flashback Data Archive]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[PL/SQL Cop]]></category>
		<category><![CDATA[SonarQube]]></category>
		<category><![CDATA[Transaction Time]]></category>
		<category><![CDATA[Valid Time]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=9890</guid>

					<description><![CDATA[<p>This is one of my favourite quotes: There are only two hard things in Computer Science: cache invalidation and naming things.&#8212; Phil Karlton IT is my daily life. And this quote is so true. Lately, I&#8217;ve been thinking much more than usual about naming, and that names really matter. This led to<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2020/06/21/names-matter/">Names Matter</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>This is one of my favourite quotes:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>There are only two hard things in Computer Science: cache invalidation and naming things.<br />&#8212; Phil Karlton</p>
</blockquote>



<p>IT is my daily life. And this quote is so true. Lately, I&#8217;ve been thinking much more than usual about naming, and that names really matter. This led to some refactoring activities.</p>



<h2 class="wp-block-heading">Why Is Naming Important?</h2>



<p>When a person with German mother tongue hears the word &#8220;eagle&#8221;, she or he automatically associates it with a &#8220;hedgehog&#8221;. Simply because the German word for it (&#8220;Igel&#8221;) is pronounced exactly the same. Of course, language skills and the concrete context play a role. The point is, a wrong association is likely. When we give a name to a thing, we basically want to avoid such false associations. In the best case, they are not helpful. In the worst case, this leads to rejection, as the next example shows.</p>



<p>In 1982 Mitsubishi Motors launched a SUV with the name &#8220;Pajero&#8221;. This name had to be changed in some regions, because &#8220;pajero&#8221; means &#8220;wanker&#8221; in Spanish. This example also shows that it is more important what others think about a name than we do.</p>



<p>In IT we have to name many things. Databases, schemas, tables, columns, views, packages, triggers, variables, fields, methods, classes, modules, components, products, etc. etc. Using an established name with a known and accepted definition help others to understand it better.</p>



<p>When we use a name, it is actually associated with a definition and properties, whether we like it or not. When names have a common and widely accepted meaning, it simplifies the communication. For example &#8220;banana&#8221;. Everybody knows what it means. <a href="https://www.merriam-webster.com/dictionary/banana">Merriam-Webster&#8217;s definition</a> is:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>An elongated usually tapering tropical fruit with soft pulpy flesh enclosed in a soft usually yellow rind.</p>
</blockquote>



<p>And I am sure that each of us could add a few characteristics to this definition.</p>



<h2 class="wp-block-heading">Why Is Naming Difficult?</h2>



<p>A name must fulfil many characteristics. For example</p>



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



<li>Fitting (naturally relates to the intended meaning, and characteristics)</li>



<li>Easy to spell,&nbsp;pronounce, remember</li>



<li>Not associated with unwanted characteristics</li>



<li>Common and widely accepted meaning and definition, that fits the intention (for names without commercial value)</li>



<li>New, not used already (for marketable names)</li>
</ul>



<p>Depending on context there are some goal conflicts. However, even without a major conflict, it is difficult to name something adequately in the early stages. Because we do not know enough about the thing we want to name. Hence, we use an iterative approach. We name something (e.g. an entity, package or class) and while working on it we find out that the name does not fit (anymore) and we change it. Maybe we split the thing and have to name now two things, etc. etc.</p>



<p>Finding a fitting name means doing some research. How have others named that thing? What is the definition of it? Does it fit 100 percent? This is an interesting and instructive work. In any case, it takes time. And at the time we need a new name, we want it now (e.g. when a wizard asks for a name). We can always rename it later, right? &#8211; Technically yes. And often we do. But the longer we wait, the less likely we are renaming.</p>



<h2 class="wp-block-heading">Are Some Names More Important Than Others?</h2>



<p>Yes. The more visible a name is the more important it is.</p>



<p>For example, the names behind an API are very easy to change. We do not have to ask anyone before changing it. It&#8217;s no problem as long as the API provides the same results. That&#8217;s one of the reasons we strive for tight APIs, right? To get some leeway.</p>



<p>As soon as others are involved, we are not fully in control of the change anymore. For example, when I change a name in one of my blog posts, this change is visible immediately to everyone visiting my blog. But I cannot control the caches of others, like search engines, blog mirrors and other services that copy web content to third-party storages. Remember, cache invalidation is the other hard thing in IT.</p>



<p>As a consequence, before we release an artefact that becomes visible to others, we should take some time to verify the used names. We cannot take back what we&#8217;ve said (at least not completely). However, we are in control of what we say in the future.</p>



<h2 class="wp-block-heading">Banned Names on This Blog</h2>



<p>Some terms (names) were discussed recently (again) due to a series of sad events. I used these terms as well. I never really thought about them as &#8220;bad&#8221;. However, I&#8217;ve changed my mind. I&#8217;m part of the problem. And I do not like it. One thing I can do is to stop using terms, that a large group of people associate with slavery and racism. No big deal, right?</p>



<p>This is another quote I like very much:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>One cannot not communicate<br />&#8212; Paul Watzlawick</p>
</blockquote>



<p>It is difficult to draw a line for certain terms. However, I believe that &#8220;you cannot not decide&#8221;. You decide either explicitly or implicitly. Of course, very seldom something is purely black or white. It&#8217;s much more often a shade of grey. Some decision take some time. And that&#8217;s okay. But it is impossible to postpone a decision forever. At a certain point, it becomes a decision.</p>



<p>So, I decided to decommission some terms on this blog and introduce new ones. Here&#8217;s the list:</p>



<table id="tablepress-16" class="tablepress tablepress-id-16">
<thead>
<tr class="row-1">
	<th class="column-1">Current Term</th><th class="column-2">Decommissioned Term</th><th class="column-3">Context</th>
</tr>
</thead>
<tbody class="row-striping row-hover">
<tr class="row-2">
	<td class="column-1">accessible</td><td class="column-2"><del>white listed</del></td><td class="column-3">PL/SQL accessible_by clause</td>
</tr>
<tr class="row-3">
	<td class="column-1">agent</td><td class="column-2"><del>slave</del></td><td class="column-3">Jenkins</td>
</tr>
<tr class="row-4">
	<td class="column-1">exclusion list</td><td class="column-2"><del>blacklist</del></td><td class="column-3">PL/SQL Cop, PL/SQL accessible_by clause</td>
</tr>
<tr class="row-5">
	<td class="column-1">inclusion list</td><td class="column-2"><del>whitelist</del></td><td class="column-3">PL/SQL Cop, PL/SQL accessible_by clause</td>
</tr>
<tr class="row-6">
	<td class="column-1">main</td><td class="column-2"><del>master</del></td><td class="column-3">Git branch</td>
</tr>
<tr class="row-7">
	<td class="column-1">transaction structure data + enterprise structure data</td><td class="column-2"><del>master data</del></td><td class="column-3">Data modeling</td>
</tr>
<tr class="row-8">
	<td class="column-1">worker</td><td class="column-2"><del>slave</del></td><td class="column-3">Oracle DB background process </td>
</tr>
</tbody>
</table>
<!-- #tablepress-16 from cache -->


<p>Finding alternative names was surprisingly easy because others had already done the work and defined alternative names. They existed for years&#8230;</p>



<h3 class="wp-block-heading">Master Data</h3>



<p>However, finding an alternative for <a href="https://en.wikipedia.org/wiki/Master_data">master data</a> was harder. I reached out to my friends on Twitter. And got some helpful feedback. Finally, Robert Marti suggested having a look at <a href="https://www.linkedin.com/in/malcolmchisholm/">Malcolm Chisholm</a>&#8216;s book <a href="https://books.google.ch/books?id=WxtW5SUUAYAC&amp;printsec=frontcover#v=onepage&amp;q&amp;f=false">Managing Reference Data in Enterprise Databases</a>. On page <a href="https://books.google.ch/books?id=WxtW5SUUAYAC&amp;lpg=PP1&amp;pg=PA258#v=onepage&amp;q&amp;f=false">258ff</a> the different data classes are defined and explained. The book is from 2000. In the meantime Malcolm Chisholm has published revised definitions <a href="https://www.topquadrant.com/docs/whitepapers/TopBraid_ReferenceDataManagementWhitepaper-3-18-15.pdf">here</a> and <a href="https://www.topquadrant.com/resources/blogs/semantic-ecosystem-journal/docs/RefDataPrepMCRC-Final060215.pdf">here</a>.</p>



<p>In the next subchapter, I repeat the definition of the data groups defined by Malcolm Chisholm on slide 5 in <a href="https://www.topquadrant.com/resources/blogs/semantic-ecosystem-journal/docs/RefDataPrepMCRC-Final060215.pdf">this deck</a>. I like these definitions and plan to use them in the future.</p>



<h4 class="wp-block-heading">Metadata</h4>



<p>The data that describes all aspects of an enterprise’s information assets, and enables the enterprise to effectively use and manage these assets.</p>



<p><em>Here it is confined to the structure of databases. Found in a database’s system catalog. Sometimes included in database tables.</em></p>



<h4 class="wp-block-heading">Reference Data</h4>



<p>Any kind of data that is used solely to categorize other data found in a database, or solely for relating data in a database to information beyond the boundaries of the enterprise.</p>



<p><em>Codes and descriptions. Tables containing this data usually have just a few rows and columns.</em></p>



<h4 class="wp-block-heading">Transaction Structure Data</h4>



<p>Data that represents the direct participants in a transaction, and which must be present before a transaction fires.</p>



<p><em>The parties to the transactions of the enterprise. E.g. Customer, Product.</em></p>



<h4 class="wp-block-heading">Enterprise Structure Data</h4>



<p>Data that permits business activity to be reported and/or analyzed by business responsibility.</p>



<p><em>Typically, data that describes the structure of the enterprise. E.g. organizational or financial structure.</em></p>



<h4 class="wp-block-heading">Transaction Activity Data</h4>



<p>Data that represents the operations an enterprise carries out.</p>



<p><em>Traditional focus of IT – in many enterprises the only focus.</em></p>



<h4 class="wp-block-heading">Transaction Audit Data</h4>



<p>Data that tracks the life cycle of individual transactions.</p>



<p><em>Includes application logs, database logs, web server logs<span class="s1">.</span></em></p>



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



<p>You use a name to simplify communication. A name is a proxy for a longer definition and meaning. If the meaning is badly received by others and especially by the target community, this does not simplify communication. Using a different name sounds like a simple solution. Why not, if changing a name is simple enough?</p>



<p>In this case, I only had to edit a few blog posts. I handled them like typos. This means that I did not add any update information. I also had to register new URL redirects. That was straightforward. However, changing the branch name in 26 GitHub repositories was a bit more work than anticipated, because I also had to change URLs in several related files. For certain GitHub pages, I had to keep a non-default master branch. I suppose that sooner or later GitHub will allow me to get rid of them as well. If I had to change more repositories, I would probably automate this task.</p>



<p>Most of the time I spent finding an alternative name for &#8220;master data&#8221;. In the end, I learned something new and found good names and definitions. That will help me in the future.</p>
<p>The post <a href="https://www.salvis.com/blog/2020/06/21/names-matter/">Names Matter</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/2020/06/21/names-matter/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Bitemp Remodeler v0.1.0 Released</title>
		<link>https://www.salvis.com/blog/2016/09/25/bitemp-remodeler-v0-1-0-released/</link>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 25 Sep 2016 21:21:21 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Flashback]]></category>
		<category><![CDATA[Flashback Data Archive]]></category>
		<category><![CDATA[oddgen]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Developer]]></category>
		<category><![CDATA[Temporal Database]]></category>
		<category><![CDATA[Transaction Time]]></category>
		<category><![CDATA[Valid Time]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=7254</guid>

					<description><![CDATA[<p>I&#8217;ve been working on a flexible table API generator for Oracle Databases for several months. A TAPI generator doesn&#8217;t sound like a real innovation. But this one contains some features you probably have not seen before in the TAPI generator and hopefully will like it as much as I do. In this post, I will<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2016/09/25/bitemp-remodeler-v0-1-0-released/">Bitemp Remodeler v0.1.0 Released</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve been working on a flexible table API generator for Oracle Databases for several months. A TAPI generator doesn&#8217;t sound like a real innovation. But this one contains some features you probably have not seen before in the TAPI generator and hopefully will like it as much as I do.</p>



<p>In this post, I will not explain the feature set thoroughly. Instead, I will more or less focus on one of my favourite features.</p>



<h2 class="wp-block-heading">Four models</h2>



<p>The generator knows the following four data models.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2016/09/four_models.png"><img fetchpriority="high" decoding="async" width="1424" height="643" src="https://www.salvis.com/blog/wp-content/uploads/2016/09/four_models.png" alt="four_models" class="wp-image-7258" srcset="https://www.salvis.com/blog/wp-content/uploads/2016/09/four_models.png 1424w, https://www.salvis.com/blog/wp-content/uploads/2016/09/four_models-300x135.png 300w, https://www.salvis.com/blog/wp-content/uploads/2016/09/four_models-768x347.png 768w, https://www.salvis.com/blog/wp-content/uploads/2016/09/four_models-1024x462.png 1024w" sizes="(max-width:767px) 480px, (max-width:1424px) 100vw, 1424px" /></a></figure>



<p>If your table is based on one of these four models you may</p>



<ol class="wp-block-list">
<li>simply generate a table API for it&nbsp;or</li>



<li>switch to another model and optionally generate a table API as well.</li>
</ol>



<p>Option 2) is extraordinary, since it will preserve the existing data. E.g. it will preserve the content of the flashback data archive when you switch your model from uni-temporal transaction time to a bi-temporal model even if the flashback archive tables need to be moved to another table. Furthermore, it will keep the interface for the latest table the same. No application change is required. Everything with just a few mouse clicks. If this sounds interesting to you, then have a look at https://github.com/oddgen/bitemp/blob/main/README.md where the concept is briefly explained or join me in my session &#8220;oddgen &#8211; Bi-temporal Table API in Action&#8221; at the <a href="http://www.trivadis.com/en/training/more-just-performance-days-2016-tvdpdays">More than just – Performance Days 2016</a>. Remote participation is still possible.</p>



<p>Option 1) is what we had for years. It was part of Oracle Designer, it&#8217;s part of SQL Developer in a simplified way and there are some more or less simple table API generators around. So no big deal. However, when you choose option 1), there is one cool part. The hook API package concept.</p>



<h2 class="wp-block-heading">The Hook API</h2>



<p>The problem with a lot of table API solutions is, that there is typically no developer-friendly way to include the business logic. I&#8217;ve seen the following:</p>



<ul class="wp-block-list">
<li>Manual changes of the generated code, which is for various reasons not a good solution.</li>



<li>External hooks, e.g. in XML files, INI files, relational tables, etc. and merged at generation time into the final code. Oracle Designer worked that way.</li>



<li>Code which is dynamically executed by the generator at runtime, e.g. code snippets is stored in a pre-defined way in relational tables.</li>
</ul>



<p>But what I&#8217;ve never seen, was business logic implemented in manually crafted PL/SQL packages, separated from the PL/SQL generated code. That&#8217;s strange because this is a common practice in Java-based projects.</p>



<p>In Java, you typically define an interface for that and configure at runtime the right implementation. In PL/SQL we may do that similarly. A PL/SQL specification is an interface definition. That just one implementation may exist for an interface is not a limiting factor in this case.</p>



<p>Bitemp Remodeler generates the following hook API package specification for the famous EMP&nbsp;table in schema SCOTT:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Package specification EMP_HOOK</span><span role="button" tabindex="0" data-code="CREATE OR REPLACE PACKAGE emp_hook AS
   /** 
   * Hooks called by non-temporal API for table emp_lt (see package body of emp_api)
   * generated by Bitemp Remodeler for SQL Developer.
   * The body of this package is not generated. It has to be crafted and maintained manually. 
   * Since the API for table emp_lt ignores errors caused by a missing hook package body, the implementation is optional.
   *
   * @headcom
   */

   /**
   * Hook called before insert into non-temporal table emp_lt.
   *
   * @param io_new_row new Row to be inserted
   */
   PROCEDURE pre_ins (
      io_new_row IN OUT emp_ot
   );

   /**
   * Hook called after insert into non-temporal table emp_lt.
   *
   * @param in_new_row new Row to be inserted
   */
   PROCEDURE post_ins (
      in_new_row IN emp_ot
   );

   /**
   * Hook called before update non-temporal table emp_lt.
   *
   * @param io_new_row Row with updated column values
   * @param in_old_row Row with original column values
   */
   PROCEDURE pre_upd (
      io_new_row IN OUT emp_ot,
      in_old_row IN emp_ot
   );

   /**
   * Hook called after update non-temporal table emp_lt.
   *
   * @param in_new_row Row with updated column values
   * @param in_old_row Row with original column values
   */
   PROCEDURE post_upd (
      in_new_row IN emp_ot,
      in_old_row IN emp_ot
   );

   /**
   * Hook called before delete from non-temporal table emp_lt.
   *
   * @param in_old_row Row with original column values
   */
   PROCEDURE pre_del (
      in_old_row IN emp_ot
   );

   /**
   * Hook called after delete from non-temporal table emp_lt.
   *
   * @param in_old_row Row with original column values
   */
   PROCEDURE post_del (
      in_old_row IN emp_ot
   );

END emp_hook;
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">CREATE OR REPLACE</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">PACKAGE</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">emp_hook</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">AS</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">/** </span></span>
<span class="line"><span style="color: #6A9955">   * Hooks called by non-temporal API for table emp_lt (see package body of emp_api)</span></span>
<span class="line"><span style="color: #6A9955">   * generated by Bitemp Remodeler for SQL Developer.</span></span>
<span class="line cbp-line-highlight"><span style="color: #6A9955">   * The body of this package is not generated. It has to be crafted and maintained manually. </span></span>
<span class="line cbp-line-highlight"><span style="color: #6A9955">   * Since the API for table emp_lt ignores errors caused by a missing hook package body, the implementation is optional.</span></span>
<span class="line"><span style="color: #6A9955">   *</span></span>
<span class="line"><span style="color: #6A9955">   * @headcom</span></span>
<span class="line"><span style="color: #6A9955">   */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">/**</span></span>
<span class="line"><span style="color: #6A9955">   * Hook called before insert into non-temporal table emp_lt.</span></span>
<span class="line"><span style="color: #6A9955">   *</span></span>
<span class="line"><span style="color: #6A9955">   * @param io_new_row new Row to be inserted</span></span>
<span class="line"><span style="color: #6A9955">   */</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">pre_ins</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      io_new_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">OUT</span><span style="color: #D4D4D4"> emp_ot</span></span>
<span class="line"><span style="color: #D4D4D4">   );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">/**</span></span>
<span class="line"><span style="color: #6A9955">   * Hook called after insert into non-temporal table emp_lt.</span></span>
<span class="line"><span style="color: #6A9955">   *</span></span>
<span class="line"><span style="color: #6A9955">   * @param in_new_row new Row to be inserted</span></span>
<span class="line"><span style="color: #6A9955">   */</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">post_ins</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      in_new_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> emp_ot</span></span>
<span class="line"><span style="color: #D4D4D4">   );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">/**</span></span>
<span class="line"><span style="color: #6A9955">   * Hook called before update non-temporal table emp_lt.</span></span>
<span class="line"><span style="color: #6A9955">   *</span></span>
<span class="line"><span style="color: #6A9955">   * @param io_new_row Row with updated column values</span></span>
<span class="line"><span style="color: #6A9955">   * @param in_old_row Row with original column values</span></span>
<span class="line"><span style="color: #6A9955">   */</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">pre_upd</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      io_new_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">OUT</span><span style="color: #D4D4D4"> emp_ot,</span></span>
<span class="line"><span style="color: #D4D4D4">      in_old_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> emp_ot</span></span>
<span class="line"><span style="color: #D4D4D4">   );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">/**</span></span>
<span class="line"><span style="color: #6A9955">   * Hook called after update non-temporal table emp_lt.</span></span>
<span class="line"><span style="color: #6A9955">   *</span></span>
<span class="line"><span style="color: #6A9955">   * @param in_new_row Row with updated column values</span></span>
<span class="line"><span style="color: #6A9955">   * @param in_old_row Row with original column values</span></span>
<span class="line"><span style="color: #6A9955">   */</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">post_upd</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      in_new_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> emp_ot,</span></span>
<span class="line"><span style="color: #D4D4D4">      in_old_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> emp_ot</span></span>
<span class="line"><span style="color: #D4D4D4">   );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">/**</span></span>
<span class="line"><span style="color: #6A9955">   * Hook called before delete from non-temporal table emp_lt.</span></span>
<span class="line"><span style="color: #6A9955">   *</span></span>
<span class="line"><span style="color: #6A9955">   * @param in_old_row Row with original column values</span></span>
<span class="line"><span style="color: #6A9955">   */</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">pre_del</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      in_old_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> emp_ot</span></span>
<span class="line"><span style="color: #D4D4D4">   );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #6A9955">/**</span></span>
<span class="line"><span style="color: #6A9955">   * Hook called after delete from non-temporal table emp_lt.</span></span>
<span class="line"><span style="color: #6A9955">   *</span></span>
<span class="line"><span style="color: #6A9955">   * @param in_old_row Row with original column values</span></span>
<span class="line"><span style="color: #6A9955">   */</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PROCEDURE</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">post_del</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">      in_old_row </span><span style="color: #569CD6">IN</span><span style="color: #D4D4D4"> emp_ot</span></span>
<span class="line"><span style="color: #D4D4D4">   );</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">END</span><span style="color: #D4D4D4"> emp_hook;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>The generated table API calls before an INSERT the pre_ins procedure and after the INSERT the post_ins procedures. For DELETE and UPDATE this works the same way. On the highlighted line 5 and 6 two interested things are pointed out. The body is not generated and the body does not need to be implemented since the API ignores errors caused by a missing PL/SQL hook package body.</p>



<p>Technically this is solved as follows in the API package body:</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-start:16;--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">Excerpt 1 of package body EMP_API</span><span role="button" tabindex="0" data-code="   e_hook_body_missing EXCEPTION;
   PRAGMA exception_init(e_hook_body_missing, -6508);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">   e_hook_body_missing </span><span style="color: #569CD6">EXCEPTION</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">PRAGMA exception_init</span><span style="color: #D4D4D4">(e_hook_body_missing, -</span><span style="color: #B5CEA8">6508</span><span style="color: #D4D4D4">);</span></span></code></pre></div>



<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-start:167;--cbp-line-number-width:calc(3 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Excerpt 2 of package body EMP_API</span><span role="button" tabindex="0" data-code="      &lt;&lt;pre_ins&gt;&gt;
      BEGIN
         emp_hook.pre_ins(io_new_row =&gt; l_new_row);
      EXCEPTION
         WHEN e_hook_body_missing THEN
            NULL;
      END pre_ins;
      do_ins(io_row =&gt; l_new_row);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">      &lt;&lt;pre_ins&gt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">         emp_hook.pre_ins(io_new_row =&gt; </span><span style="color: #9CDCFE">l_new_row</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #569CD6">EXCEPTION</span></span>
<span class="line"><span style="color: #D4D4D4">         </span><span style="color: #569CD6">WHEN</span><span style="color: #D4D4D4"> e_hook_body_missing </span><span style="color: #569CD6">THEN</span></span>
<span class="line"><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">END</span><span style="color: #D4D4D4"> pre_ins;</span></span>
<span class="line"><span style="color: #D4D4D4">      do_ins(io_row =&gt; </span><span style="color: #9CDCFE">l_new_row</span><span style="color: #D4D4D4">);</span></span></code></pre></div>



<p>Now you may ask what the performance impact of these e_hook_body_missing exceptions are. I&#8217;ve done a small test and called a procedure without and with implemented body 1 million times. The overhead of the missing body exception is about 7 microseconds per call. Here&#8217;s the test output from SQL Developer, the relevant lines 51 and 89 are highlighted.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Overhead of missing package body</span><span role="button" tabindex="0" data-code="SQL&gt; SET FEEDBACK ON
SQL&gt; SET ECHO ON
SQL&gt; SET TIMING ON
SQL&gt; DROP PACKAGE dummy_api;

Package DUMMY_API dropped.

Elapsed: 00:00:00.027
SQL&gt; DROP PACKAGE dummy_hook;

Package DUMMY_HOOK dropped.

Elapsed: 00:00:00.030
SQL&gt; CREATE OR REPLACE PACKAGE dummy_hook AS
   PROCEDURE pre_ins;
END dummy_hook;
/

Package DUMMY_HOOK compiled

Elapsed: 00:00:00.023
SQL&gt; CREATE OR REPLACE PACKAGE dummy_api AS
   PROCEDURE ins;
END dummy_api;
/

Package DUMMY_API compiled

Elapsed: 00:00:00.034
SQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_api AS
   e_hook_body_missing EXCEPTION;
   PRAGMA exception_init(e_hook_body_missing, -6508);  
   PROCEDURE ins IS
   BEGIN
      BEGIN
         dummy_hook.pre_ins;
      EXCEPTION
         WHEN e_hook_body_missing THEN
            NULL;
      END pre_ins;
      dbms_output.put('.');
   END ins;
END dummy_api;
/

Package body DUMMY_API compiled

Elapsed: 00:00:00.040
SQL&gt; -- without hook body
SQL&gt; BEGIN
   FOR i IN 1..1E6 LOOP
      dummy_api.ins;
   END LOOP;
END;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:07.878
SQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_hook AS
   PROCEDURE pre_ins IS
   BEGIN
      dbms_output.put('-');
   END pre_ins;
END dummy_hook;
/

Package body DUMMY_HOOK compiled

Elapsed: 00:00:00.029
SQL&gt; -- with hook body
SQL&gt; BEGIN
   FOR i IN 1..1E6 LOOP
      dummy_api.ins;
   END LOOP;
END;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.632" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">SQL&gt; SET FEEDBACK ON</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; SET ECHO ON</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; SET TIMING ON</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; DROP PACKAGE dummy_api;</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Package DUMMY_API dropped.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed: 00:00:00.027</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; DROP PACKAGE dummy_hook;</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Package DUMMY_HOOK dropped.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed: 00:00:00.030</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; CREATE OR REPLACE PACKAGE dummy_hook AS</span></span>
<span class="line"><span style="color: #D4D4D4">   PROCEDURE pre_ins;</span></span>
<span class="line"><span style="color: #D4D4D4">END dummy_hook;</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">Package DUMMY_HOOK compiled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed: 00:00:00.023</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; CREATE OR REPLACE PACKAGE dummy_api AS</span></span>
<span class="line"><span style="color: #D4D4D4">   PROCEDURE ins;</span></span>
<span class="line"><span style="color: #D4D4D4">END dummy_api;</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">Package DUMMY_API compiled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed: 00:00:00.034</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_api AS</span></span>
<span class="line"><span style="color: #D4D4D4">   e_hook_body_missing EXCEPTION;</span></span>
<span class="line"><span style="color: #D4D4D4">   PRAGMA exception_init(e_hook_body_missing, -6508);  </span></span>
<span class="line"><span style="color: #D4D4D4">   PROCEDURE ins IS</span></span>
<span class="line"><span style="color: #D4D4D4">   BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">         dummy_hook.pre_ins;</span></span>
<span class="line"><span style="color: #D4D4D4">      EXCEPTION</span></span>
<span class="line"><span style="color: #D4D4D4">         WHEN e_hook_body_missing THEN</span></span>
<span class="line"><span style="color: #D4D4D4">            NULL;</span></span>
<span class="line"><span style="color: #D4D4D4">      END pre_ins;</span></span>
<span class="line"><span style="color: #D4D4D4">      dbms_output.put(&#39;.&#39;);</span></span>
<span class="line"><span style="color: #D4D4D4">   END ins;</span></span>
<span class="line"><span style="color: #D4D4D4">END dummy_api;</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">Package body DUMMY_API compiled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed: 00:00:00.040</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; -- without hook body</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   FOR i IN 1..1E6 LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">      dummy_api.ins;</span></span>
<span class="line"><span style="color: #D4D4D4">   END LOOP;</span></span>
<span class="line"><span style="color: #D4D4D4">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">PL/SQL procedure successfully completed.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Elapsed: 00:00:07.878</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; CREATE OR REPLACE PACKAGE BODY dummy_hook AS</span></span>
<span class="line"><span style="color: #D4D4D4">   PROCEDURE pre_ins IS</span></span>
<span class="line"><span style="color: #D4D4D4">   BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">      dbms_output.put(&#39;-&#39;);</span></span>
<span class="line"><span style="color: #D4D4D4">   END pre_ins;</span></span>
<span class="line"><span style="color: #D4D4D4">END dummy_hook;</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">Package body DUMMY_HOOK compiled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Elapsed: 00:00:00.029</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; -- with hook body</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; BEGIN</span></span>
<span class="line"><span style="color: #D4D4D4">   FOR i IN 1..1E6 LOOP</span></span>
<span class="line"><span style="color: #D4D4D4">      dummy_api.ins;</span></span>
<span class="line"><span style="color: #D4D4D4">   END LOOP;</span></span>
<span class="line"><span style="color: #D4D4D4">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">PL/SQL procedure successfully completed.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Elapsed: 00:00:00.632</span></span></code></pre></div>



<p>It makes sense to provide a body with a NULL implementation to avoid the small overhead of handling the missing body exception.</p>



<p>Nonetheless, the way the business logic is separated from the generated code is one of the many things I like about Bitemp Remodeler.</p>



<p>Download Bitemp Remodeler from the&nbsp;<a href="https://www.salvis.com/blog/download/">Download</a> section on&nbsp;my blog or install it directly via the SQL Developer update site <a href="http://update.oddgen.org/">http://update.oddgen.org/</a></p>
<p>The post <a href="https://www.salvis.com/blog/2016/09/25/bitemp-remodeler-v0-1-0-released/">Bitemp Remodeler v0.1.0 Released</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
