{"id":15957,"date":"2026-02-23T17:24:15","date_gmt":"2026-02-23T16:24:15","guid":{"rendered":"https:\/\/www.salvis.com\/blog\/?p=15957"},"modified":"2026-03-31T08:36:18","modified_gmt":"2026-03-31T06:36:18","slug":"enforcing-acyclic-hierarchies-with-sql-assertions","status":"publish","type":"post","link":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/","title":{"rendered":"Enforcing Acyclic Hierarchies With SQL Assertions"},"content":{"rendered":"\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"introduction\">Introduction<\/h2>\n\n\n\n<p>Referential integrity constraints have been available since version 7 of the Oracle Database. While these constraints ensure that referenced rows exist, they cannot express more complex integrity rules that span multiple rows or tables. Check constraints are similarly limited, as they can only validate conditions on the columns of a single row.<\/p>\n\n\n\n<p>The latest version of the Oracle AI Database (23.26.1) introduced SQL Assertions, enabling us to define cross-row and cross-table checks declaratively.<\/p>\n\n\n\n<p>SQL Assertions support a wide range of use cases where data must satisfy global consistency rules. One particularly interesting example is ensuring that hierarchical structures remain free of cycles.<\/p>\n\n\n\n<p>In this blog post, I will demonstrate how SQL Assertions can detect and prevent cycles in hierarchical data structures.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setup\">Setup<\/h2>\n\n\n\n<p>For the examples in this blog post, I used an Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0.<\/p>\n\n\n\n<p>Connected as <code>SYS<\/code> I ran the following script to create the user <code>DEMO<\/code> with the necessary privileges.<\/p>\n\n\n\n<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\n   default tablespace users\n   temporary tablespace temp\n   quota unlimited on users;\n\ngrant create session, create table, 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>\n<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>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   temporary <\/span><span style=\"color: #569CD6\">tablespace<\/span><span style=\"color: #D4D4D4\"> temp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   quota unlimited <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> users;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">grant<\/span><span style=\"color: #D4D4D4\"> create session, create <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\">, create assertion to demo;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Connected as <code>DEMO<\/code> I ran the following script to create the famous tables <code>DEPT<\/code> and <code>EMP<\/code> with initial data:<\/p>\n\n\n\n<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 DEPT\/EMP example<\/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 (\n   deptno number(2, 0)      not null constraint dept_pk primary key,\n   dname  varchar2(14 char) not null,\n   loc    varchar2(13 char) not null\n);\n\ncreate table emp (\n   empno    number(4, 0)      not null  constraint emp_pk primary key,\n   ename    varchar2(10 char) not null,\n   job      varchar2(9 char)  not null,\n   mgr      number(4, 0)                constraint emp_mgr_fk references emp,\n   hiredate date              not null,\n   sal      number(7, 2)      not null,\n   comm     number(7, 2),\n   deptno   number(2, 0)      not null  constraint emp_deptno_fk references dept\n);\n\ncreate index emp_deptno_fk_i on emp(deptno);\ncreate index emp_mgr_fk_i on emp(mgr);\n\ninsert into dept (deptno, dname, loc)\nvalues (10, 'ACCOUNTING', 'NEW YORK'),\n       (20, 'RESEARCH',   'DALLAS'),\n       (30, 'SALES',      'CHICAGO'),\n       (40, 'OPERATIONS', 'BOSTON');\n\ninsert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)\nvalues (7566, 'JONES',  'MANAGER',   7839, date '1981-04-02', 2975, null, 20),\n       (7698, 'BLAKE',  'MANAGER',   7839, date '1981-05-01', 2850, null, 30),\n       (7782, 'CLARK',  'MANAGER',   7839, date '1981-06-09', 2450, null, 10),\n       (7788, 'SCOTT',  'ANALYST',   7566, date '1987-04-19', 3000, null, 20),\n       (7902, 'FORD',   'ANALYST',   7566, date '1981-12-03', 3000, null, 20),\n       (7499, 'ALLEN',  'SALESMAN',  7698, date '1981-02-20', 1600,  300, 30),\n       (7521, 'WARD',   'SALESMAN',  7698, date '1981-02-22', 1250,  500, 30),\n       (7654, 'MARTIN', 'SALESMAN',  7698, date '1981-09-28', 1250, 1400, 30),\n       (7844, 'TURNER', 'SALESMAN',  7698, date '1981-09-08', 1500,    0, 30),\n       (7900, 'JAMES',  'CLERK',     7698, date '1981-12-03',  950, null, 30),\n       (7934, 'MILLER', 'CLERK',     7782, date '1982-01-23', 1300, null, 10),\n       (7369, 'SMITH',  'CLERK',     7902, date '1980-12-17',  800, null, 20),\n       (7839, 'KING',   'PRESIDENT', null, date '1981-11-17', 5000, null, 10),\n       (7876, 'ADAMS',  'CLERK',     7788, date '1987-05-23', 1100, null, 20);\ncommit;<\/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>\n<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 style=\"color: #569CD6\">constraint<\/span><span style=\"color: #D4D4D4\"> dept_pk <\/span><span style=\"color: #569CD6\">primary key<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<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>\n<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>\n<span class=\"line\"><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<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>\n<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 style=\"color: #569CD6\">constraint<\/span><span style=\"color: #D4D4D4\"> emp_pk <\/span><span style=\"color: #569CD6\">primary key<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<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>\n<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>\n<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\">constraint<\/span><span style=\"color: #D4D4D4\"> emp_mgr_fk <\/span><span style=\"color: #569CD6\">references<\/span><span style=\"color: #D4D4D4\"> emp,<\/span><\/span>\n<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>\n<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>\n<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>\n<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 style=\"color: #569CD6\">constraint<\/span><span style=\"color: #D4D4D4\"> emp_deptno_fk <\/span><span style=\"color: #569CD6\">references<\/span><span style=\"color: #D4D4D4\"> dept<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">create<\/span><span style=\"color: #D4D4D4\"> index emp_deptno_fk_i <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> emp(deptno);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">create<\/span><span style=\"color: #D4D4D4\"> index emp_mgr_fk_i <\/span><span style=\"color: #569CD6\">on<\/span><span style=\"color: #D4D4D4\"> emp(mgr);<\/span><\/span>\n<span class=\"line\"><\/span>\n<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>\n<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>\n<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>\n<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>\n<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>\n<span class=\"line\"><\/span>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<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>\n<span class=\"line\"><span style=\"color: #DCDCAA\">commit<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"hierarchical-sql-query\">Hierarchical SQL Query<\/h2>\n\n\n\n<p>Let&#8217;s look at the acyclic data first.<\/p>\n\n\n\n<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\">3) Hierarchical Query<\/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>column ename format a15\n select lpad(' ', 2 * (level - 1)) || ename as ename,\n        empno,\n        mgr\n   from emp\nconnect by prior empno = mgr\n  start with 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\">column<\/span><span style=\"color: #D4D4D4\"> ename format a15<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">lpad<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39; &#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #569CD6\">level<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)) || ename <\/span><span style=\"color: #569CD6\">as<\/span><span style=\"color: #D4D4D4\"> ename,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        empno,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        mgr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">connect by prior<\/span><span style=\"color: #D4D4D4\"> empno = mgr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">start with<\/span><span style=\"color: #D4D4D4\"> ename = <\/span><span style=\"color: #CE9178\">&#39;KING&#39;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<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>ENAME                EMPNO        MGR\n--------------- ---------- ----------\nKING                  7839           \n  JONES               7566       7839\n    SCOTT             7788       7566\n      ADAMS           7876       7788\n    FORD              7902       7566\n      SMITH           7369       7902\n  BLAKE               7698       7839\n    ALLEN             7499       7698\n    WARD              7521       7698\n    MARTIN            7654       7698\n    TURNER            7844       7698\n    JAMES             7900       7698\n  CLARK               7782       7839\n    MILLER            7934       7782\n\n14 rows selected. <\/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\">ENAME                EMPNO        MGR<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">--------------- ---------- ----------<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">KING                  7839           <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  JONES               7566       7839<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    SCOTT             7788       7566<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      ADAMS           7876       7788<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    FORD              7902       7566<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      SMITH           7369       7902<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  BLAKE               7698       7839<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ALLEN             7499       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    WARD              7521       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    MARTIN            7654       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    TURNER            7844       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    JAMES             7900       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  CLARK               7782       7839<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    MILLER            7934       7782<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">14 rows selected. <\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"detecting-cycles-via-sql-query\">Detecting Cycles Via SQL Query<\/h2>\n\n\n\n<p>We see that <code>KING<\/code> is the only employee without a manager. With the next update, we create a cycle by making <code>SCOTT<\/code> the manager of <code>KING<\/code>:<\/p>\n\n\n\n<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\">4) Create Cycle<\/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 \n   set mgr = 7788 \n where empno = 7839;\ncommit;<\/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 <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> mgr = <\/span><span style=\"color: #B5CEA8\">7788<\/span><span style=\"color: #D4D4D4\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> empno = <\/span><span style=\"color: #B5CEA8\">7839<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">commit<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>When we now re-run the previous query, we get an <code>ORA-01436: CONNECT BY loop in user data<\/code> error.<\/p>\n\n\n\n<p>Of course, we can work around it by adding a <code>NOCYCLE<\/code> parameter to produce a result:<\/p>\n\n\n\n<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) NOCYCLE Hierarchical Query<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly> select lpad(' ', 2 * (level - 1)) || ename as ename,\n        empno,\n        mgr\n   from emp\nconnect by nocycle prior empno = mgr\n  start with 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: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">lpad<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&#39; &#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> * (<\/span><span style=\"color: #569CD6\">level<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">)) || ename <\/span><span style=\"color: #569CD6\">as<\/span><span style=\"color: #D4D4D4\"> ename,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        empno,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        mgr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #569CD6\">connect by nocycle prior<\/span><span style=\"color: #D4D4D4\"> empno = mgr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">start with<\/span><span style=\"color: #D4D4D4\"> ename = <\/span><span style=\"color: #CE9178\">&#39;KING&#39;<\/span><span style=\"color: #D4D4D4\">; <\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<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>ENAME                EMPNO        MGR\n--------------- ---------- ----------\nKING                  7839       7788\n  JONES               7566       7839\n    SCOTT             7788       7566\n      ADAMS           7876       7788\n    FORD              7902       7566\n      SMITH           7369       7902\n  BLAKE               7698       7839\n    ALLEN             7499       7698\n    WARD              7521       7698\n    MARTIN            7654       7698\n    TURNER            7844       7698\n    JAMES             7900       7698\n  CLARK               7782       7839\n    MILLER            7934       7782\n\n14 rows selected. <\/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\">ENAME                EMPNO        MGR<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">--------------- ---------- ----------<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">KING                  7839       7788<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  JONES               7566       7839<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    SCOTT             7788       7566<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      ADAMS           7876       7788<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    FORD              7902       7566<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      SMITH           7369       7902<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  BLAKE               7698       7839<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    ALLEN             7499       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    WARD              7521       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    MARTIN            7654       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    TURNER            7844       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    JAMES             7900       7698<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  CLARK               7782       7839<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    MILLER            7934       7782<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">14 rows selected. <\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>However, I want a query that shows the reason for the cycle, rather than ignoring it. Something like this:<\/p>\n\n\n\n<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\">6) Detecting Cycles<\/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>column ename_path format a20\nselect *\n  from (\n          select e.ename,\n                 e.empno,\n                 e.mgr,\n                 connect_by_iscycle as is_cycle,\n                 sys_connect_by_path(e.ename, '\/') as ename_path\n            from emp e\n         connect by nocycle prior e.empno = e.mgr\n           start with e.mgr is not null\n       )\n where is_cycle = 1;<\/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\">column<\/span><span style=\"color: #D4D4D4\"> ename_path format a20<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> e.ename,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                 e.empno,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                 e.mgr,<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">                 connect_by_iscycle <\/span><span style=\"color: #569CD6\">as<\/span><span style=\"color: #D4D4D4\"> is_cycle,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                 <\/span><span style=\"color: #DCDCAA\">sys_connect_by_path<\/span><span style=\"color: #D4D4D4\">(e.ename, <\/span><span style=\"color: #CE9178\">&#39;\/&#39;<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">as<\/span><span style=\"color: #D4D4D4\"> ename_path<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp e<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">connect by nocycle prior<\/span><span style=\"color: #D4D4D4\"> e.empno = e.mgr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">           <\/span><span style=\"color: #569CD6\">start with<\/span><span style=\"color: #D4D4D4\"> e.mgr <\/span><span style=\"color: #569CD6\">is not null<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       )<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> is_cycle = <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<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>ENAME                EMPNO        MGR   IS_CYCLE ENAME_PATH          \n--------------- ---------- ---------- ---------- --------------------\nJONES                 7566       7839          1 \/SCOTT\/KING\/JONES   \nSCOTT                 7788       7566          1 \/KING\/JONES\/SCOTT   \nKING                  7839       7788          1 \/JONES\/SCOTT\/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: #D4D4D4\">ENAME                EMPNO        MGR   IS_CYCLE ENAME_PATH          <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">--------------- ---------- ---------- ---------- --------------------<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">JONES                 7566       7839          1 \/SCOTT\/KING\/JONES   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SCOTT                 7788       7566          1 \/KING\/JONES\/SCOTT   <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">KING                  7839       7788          1 \/JONES\/SCOTT\/KING <\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sql-assertion-using-connect-by\">SQL Assertion Using Connect By<\/h2>\n\n\n\n<p>According to the <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/26\/sqlrf\/create-assertion.html#GUID-9FB74CAA-0CAD-4FE6-B873-1B3877CB8AB9__GUID-70274BBE-EE5C-4471-B88A-A35DE7A9F9B1\" type=\"link\" id=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/26\/sqlrf\/create-assertion.html#GUID-9FB74CAA-0CAD-4FE6-B873-1B3877CB8AB9__GUID-70274BBE-EE5C-4471-B88A-A35DE7A9F9B1\" target=\"_blank\" rel=\"noreferrer noopener\">CREATE ASSERTION<\/a> syntax diagram, we should be able to use the previous query within the SQL Assertion as follows:<\/p>\n\n\n\n<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) Create assertion with CONNECT_BY<\/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 emp_mgr_fk_no_cycle_as\n   check (\n      not exists (\n         select 'cycle detected'\n           from (\n                   select connect_by_iscycle as is_cycle\n                     from emp e\n                  connect by nocycle prior e.empno = e.mgr\n                    start with e.mgr is not null\n                )\n          where is_cycle = 1\n      )\n   );<\/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\"> emp_mgr_fk_no_cycle_as<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">check<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<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>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;cycle detected&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">           <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                   <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> connect_by_iscycle <\/span><span style=\"color: #569CD6\">as<\/span><span style=\"color: #D4D4D4\"> is_cycle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                     <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp e<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                  <\/span><span style=\"color: #569CD6\">connect by nocycle prior<\/span><span style=\"color: #D4D4D4\"> e.empno = e.mgr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #569CD6\">start with<\/span><span style=\"color: #D4D4D4\"> e.mgr <\/span><span style=\"color: #569CD6\">is not null<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> is_cycle = <\/span><span style=\"color: #B5CEA8\">1<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<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>ORA-08689: CREATE ASSERTION failed\nORA-08677: Certain SQL functions are not supported.<\/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\">ORA-08689: CREATE ASSERTION failed<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ORA-08677: Certain SQL functions are not supported.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Unfortunately, this does not work. We get a generic error. The documentation for <a href=\"https:\/\/docs.oracle.com\/en\/error-help\/db\/ora-08677\/?r=26ai\" target=\"_blank\" rel=\"noreferrer noopener\">ORA-08677: Certain SQL functions are not supported.<\/a> does not reveal the culprit either. However, there is a rather long list of limitations listed at the end of <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/26\/sqlrf\/create-assertion.html#GUID-9FB74CAA-0CAD-4FE6-B873-1B3877CB8AB9__GUID-26F60086-F19C-446E-B979-352CD0E8D50D\" type=\"link\" id=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/26\/sqlrf\/create-assertion.html#GUID-9FB74CAA-0CAD-4FE6-B873-1B3877CB8AB9__GUID-26F60086-F19C-446E-B979-352CD0E8D50D\" target=\"_blank\" rel=\"noreferrer noopener\">this section<\/a> for the CREATE ASSERTION statement in the SQL Language Reference.<\/p>\n\n\n\n<p>After some experimentation, I have concluded that as of version 23.26.1, hierarchical queries are not supported in SQL assertions and that this limitation is not explicitly documented. <em>(Updated on 2026-03-30: The SQL Language Reference now lists &#8220;Hierarchical queries&#8221; as a feature that cannot be used with assertions.) <\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"sql-assertion-using-joins\">SQL Assertion Using Joins<\/h2>\n\n\n\n<p>It would be useful to be able to use hierarchical queries to identify cycles within hierarchies. <\/p>\n\n\n\n<p>However, we can tighten up the business requirements. From<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&#8220;Cycles are not allowed for the <code>emp_mgr_fk<\/code> relationship.&#8221; <\/p>\n<\/blockquote>\n\n\n\n<p>to <\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&#8220;The number of levels in the <code>emp_mgr_fk<\/code> relationship is limited to 5.&#8221;<\/p>\n<\/blockquote>\n\n\n\n<p>Now we can rewrite the <code>CREATE ASSERTION<\/code> statement like this:<\/p>\n\n\n\n<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 with joins<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>create assertion if not exists emp_mgr_fk_no_cycle_as\n   check (\n      not exists (\n         select '6 Levels detected, cycle assumed'\n           from emp e1, emp e2, emp e3, emp e4, emp e5, emp e6\n          where e1.mgr is not null and e1.mgr = e2.empno\n            and e2.mgr is not null and e2.mgr = e3.empno\n            and e3.mgr is not null and e3.mgr = e4.empno\n            and e4.mgr is not null and e4.mgr = e5.empno\n            and e5.mgr is not null and e5.mgr = e6.empno\n      )\n   );<\/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\"> emp_mgr_fk_no_cycle_as<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">check<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<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>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;6 Levels detected, cycle assumed&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">           <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp e1, emp e2, emp e3, emp e4, emp e5, emp e6<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> e1.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\"> e1.mgr = e2.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e2.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\"> e2.mgr = e3.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e3.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\"> e3.mgr = e4.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e4.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\"> e4.mgr = e5.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e5.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\"> e5.mgr = e6.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<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>ORA-08689: CREATE ASSERTION failed\nORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.<\/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\">ORA-08689: CREATE ASSERTION failed<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This error is expected since we have a cycle in our data. Let&#8217;s fix that.<\/p>\n\n\n\n<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) Remove Cycle<\/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 \n   set mgr = null \n where ename = 'KING';\ncommit;<\/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 <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> mgr = <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> <\/span><\/span>\n<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>\n<span class=\"line\"><span style=\"color: #DCDCAA\">commit<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Let&#8217;s try to create the SQL Assertion again.<\/p>\n\n\n\n<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\">10) Create assertion with joins (try again)<\/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 emp_mgr_fk_no_cycle_as\n   check (\n      not exists (\n         select '6 Levels detected, cycle assumed'\n           from emp e1, emp e2, emp e3, emp e4, emp e5, emp e6\n          where e1.mgr is not null and e1.mgr = e2.empno\n            and e2.mgr is not null and e2.mgr = e3.empno\n            and e3.mgr is not null and e3.mgr = e4.empno\n            and e4.mgr is not null and e4.mgr = e5.empno\n            and e5.mgr is not null and e5.mgr = e6.empno\n      )\n   );<\/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\"> emp_mgr_fk_no_cycle_as<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">check<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<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>\n<span class=\"line\"><span style=\"color: #D4D4D4\">         <\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;6 Levels detected, cycle assumed&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">           <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp e1, emp e2, emp e3, emp e4, emp e5, emp e6<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> e1.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\"> e1.mgr = e2.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e2.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\"> e2.mgr = e3.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e3.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\"> e3.mgr = e4.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e4.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\"> e4.mgr = e5.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #569CD6\">and<\/span><span style=\"color: #D4D4D4\"> e5.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\"> e5.mgr = e6.empno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   );<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<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 EMP_MGR_FK_NO_CYCLE_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 EMP_MGR_FK_NO_CYCLE_AS created.<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Success! <\/p>\n\n\n\n<p>This approach enforces acyclic hierarchies and additionally limits the number of hierarchical levels to 5.<\/p>\n\n\n\n<p>For real-life applications, you may wish to increase the number of levels to more than 5. In any case, you should be able to decide on a suitable maximum number of levels. The number of joins will match the number of levels. The code for that is boring but not too complicated.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"test-cases\">Test Cases<\/h2>\n\n\n\n<p>Let&#8217;s run some tests to verify if the SQL Assertion behaves as expected.<\/p>\n\n\n\n<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) Test cases<\/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 echo on\n-- fails (cycle)\nupdate emp\n   set mgr = (select empno from emp where ename = 'SCOTT')\n where ename = 'KING';\n\n-- fails (cycle)\nupdate emp\n   set mgr = (select empno from emp where ename = 'SMITH')\n where ename = 'JONES';\n\n-- succeeds\ninsert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)\nvalues (1000, 'LEVEL5', 'TESTER', (select empno from emp where ename = 'ADAMS'), date '2026-02-01', 1000, null, 10);\n\n-- fails (6 levels, no cycle)\ninsert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)\nvalues (1001, 'LEVEL6', 'TESTER', (select empno from emp where ename = 'LEVEL5'), date '2026-02-01', 1100, null, 20);<\/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\"> echo <\/span><span style=\"color: #569CD6\">on<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- fails (cycle)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">update<\/span><span style=\"color: #D4D4D4\"> emp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> mgr = (<\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> empno <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> ename = <\/span><span style=\"color: #CE9178\">&#39;SCOTT&#39;<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<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>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- fails (cycle)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">update<\/span><span style=\"color: #D4D4D4\"> emp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">set<\/span><span style=\"color: #D4D4D4\"> mgr = (<\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> empno <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> ename = <\/span><span style=\"color: #CE9178\">&#39;SMITH&#39;<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<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;JONES&#39;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- succeeds<\/span><\/span>\n<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>\n<span class=\"line\"><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">1000<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;LEVEL5&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;TESTER&#39;<\/span><span style=\"color: #D4D4D4\">, (<\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> empno <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp <\/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 style=\"color: #569CD6\">date<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;2026-02-01&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #B5CEA8\">1000<\/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>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">-- fails (6 levels, no cycle)<\/span><\/span>\n<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>\n<span class=\"line\"><span style=\"color: #569CD6\">values<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #B5CEA8\">1001<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;LEVEL6&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;TESTER&#39;<\/span><span style=\"color: #D4D4D4\">, (<\/span><span style=\"color: #569CD6\">select<\/span><span style=\"color: #D4D4D4\"> empno <\/span><span style=\"color: #569CD6\">from<\/span><span style=\"color: #D4D4D4\"> emp <\/span><span style=\"color: #569CD6\">where<\/span><span style=\"color: #D4D4D4\"> ename = <\/span><span style=\"color: #CE9178\">&#39;LEVEL5&#39;<\/span><span style=\"color: #D4D4D4\">), <\/span><span style=\"color: #569CD6\">date<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;2026-02-01&#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><\/code><\/pre><\/div>\n\n\n\n<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>SQL> -- fails (cycle)\nSQL> update emp\n  2  \tset mgr = (select empno from emp where ename = 'SCOTT')\n  3   where ename = 'KING';\nupdate emp\n*\nERROR at line 1:\nORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.\nHelp: https:\/\/docs.oracle.com\/error-help\/db\/ora-08601\/\n\n\nSQL> \nSQL> -- fails (cycle)\nSQL> update emp\n  2  \tset mgr = (select empno from emp where ename = 'SMITH')\n  3   where ename = 'JONES';\nupdate emp\n       *\nERROR at line 1:\nORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.\nHelp: https:\/\/docs.oracle.com\/error-help\/db\/ora-08601\/\n\n\nSQL> \nSQL> -- succeeds\nSQL> insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)\n  2  values (1000, 'LEVEL5', 'TESTER', (select empno from emp where ename = 'ADAMS'), date '2026-02-01', 1000, null, 10);\n\n1 row created.\n\nSQL> \nSQL> -- fails (6 levels, no cycle)\nSQL> insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)\n  2  values (1001, 'LEVEL6', 'TESTER', (select empno from emp where ename = 'LEVEL5'), date '2026-02-01', 1100, null, 20);\ninsert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)\n            *\nERROR at line 1:\nORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.\nHelp: 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\">SQL&gt; -- fails (cycle)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; update emp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2  \tset mgr = (select empno from emp where ename = &#39;SCOTT&#39;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  3   where ename = &#39;KING&#39;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">update emp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">*<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ERROR at line 1:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Help: https:\/\/docs.oracle.com\/error-help\/db\/ora-08601\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; -- fails (cycle)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; update emp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2  \tset mgr = (select empno from emp where ename = &#39;SMITH&#39;)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  3   where ename = &#39;JONES&#39;;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">update emp<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ERROR at line 1:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Help: https:\/\/docs.oracle.com\/error-help\/db\/ora-08601\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; -- succeeds<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2  values (1000, &#39;LEVEL5&#39;, &#39;TESTER&#39;, (select empno from emp where ename = &#39;ADAMS&#39;), date &#39;2026-02-01&#39;, 1000, null, 10);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">1 row created.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"><\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; -- fails (6 levels, no cycle)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">SQL&gt; insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  2  values (1001, &#39;LEVEL6&#39;, &#39;TESTER&#39;, (select empno from emp where ename = &#39;LEVEL5&#39;), date &#39;2026-02-01&#39;, 1100, null, 20);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ERROR at line 1:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">ORA-08601: SQL assertion (DEMO.EMP_MGR_FK_NO_CYCLE_AS) violated.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">Help: https:\/\/docs.oracle.com\/error-help\/db\/ora-08601\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>SQL Assertions allow us to implement integrity rules that were previously difficult to enforce when taking factors such as concurrency and performance into account. They allow us to perform consistency checks in the database layer instead of relying on application logic.<\/p>\n\n\n\n<p>Although the inability to use hierarchical queries within SQL Assertions is a significant limitation, the join-based approach presented in this post can effectively prevent hierarchical cycles and ensure consistency through a purely declarative solution. For most real-life data models, limiting the depth of the hierarchy should be a feasible workaround.<\/p>\n\n\n\n<p>SQL Assertions close one of the last major gaps toward Codd\u2019s principle of integrity independence (Rule 10 of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Codd%27s_12_rules\" type=\"link\" id=\"https:\/\/en.wikipedia.org\/wiki\/Codd%27s_12_rules\" target=\"_blank\" rel=\"noreferrer noopener\">Codd&#8217;s 12 rules<\/a>), making declarative data integrity in the Oracle AI Database nearly complete.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><em>Updated on 2026-03-30: The SQL Language Reference now lists &#8220;Hierarchical queries&#8221; as a feature that cannot be used with assertions. <\/em><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Referential integrity constraints have been available since version 7 of the Oracle Database. While these constraints ensure that referenced rows exist, they cannot express more complex integrity rules that span multiple rows or tables. Check constraints are similarly limited, as they can only validate conditions on the columns of a single<span class=\"excerpt-hellip\"> [\u2026]<\/span><\/p>\n","protected":false},"author":1,"featured_media":15992,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[140,85,152],"class_list":["post-15957","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle","tag-oracle-26ai","tag-sql","tag-sql-assertions"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Enforcing Acyclic Hierarchies With SQL Assertions - Philipp Salvisberg&#039;s Blog<\/title>\n<meta name=\"description\" content=\"Explore SQL Assertions in Oracle AI Database and learn how to enforce hierarchy integrity by detecting cycles with declarative constraints.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Enforcing Acyclic Hierarchies With SQL Assertions - Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"Explore SQL Assertions in Oracle AI Database and learn how to enforce hierarchy integrity by detecting cycles with declarative constraints.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/\" \/>\n<meta property=\"og:site_name\" content=\"Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-23T16:24:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-31T06:36:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2026\/02\/sql-assertions.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Philipp Salvisberg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:site\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Philipp Salvisberg\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/\"},\"author\":{\"name\":\"Philipp Salvisberg\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"headline\":\"Enforcing Acyclic Hierarchies With SQL Assertions\",\"datePublished\":\"2026-02-23T16:24:15+00:00\",\"dateModified\":\"2026-03-31T06:36:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/\"},\"wordCount\":726,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/02\\\/sql-assertions.png\",\"keywords\":[\"Oracle 26ai\",\"SQL\",\"SQL Assertions\"],\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/\",\"name\":\"Enforcing Acyclic Hierarchies With SQL Assertions - Philipp Salvisberg&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/02\\\/sql-assertions.png\",\"datePublished\":\"2026-02-23T16:24:15+00:00\",\"dateModified\":\"2026-03-31T06:36:18+00:00\",\"description\":\"Explore SQL Assertions in Oracle AI Database and learn how to enforce hierarchy integrity by detecting cycles with declarative constraints.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/02\\\/sql-assertions.png\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/02\\\/sql-assertions.png\",\"width\":1536,\"height\":1024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2026\\\/02\\\/23\\\/enforcing-acyclic-hierarchies-with-sql-assertions\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Enforcing Acyclic Hierarchies With SQL Assertions\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\",\"name\":\"Philipp Salvisberg&#039;s Blog\",\"description\":\"Database-centric development\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\",\"name\":\"Philipp Salvisberg\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"width\":400,\"height\":400,\"caption\":\"Philipp Salvisberg\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\"},\"sameAs\":[\"http:\\\/\\\/www.salvis.com\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Enforcing Acyclic Hierarchies With SQL Assertions - Philipp Salvisberg&#039;s Blog","description":"Explore SQL Assertions in Oracle AI Database and learn how to enforce hierarchy integrity by detecting cycles with declarative constraints.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/","og_locale":"en_US","og_type":"article","og_title":"Enforcing Acyclic Hierarchies With SQL Assertions - Philipp Salvisberg&#039;s Blog","og_description":"Explore SQL Assertions in Oracle AI Database and learn how to enforce hierarchy integrity by detecting cycles with declarative constraints.","og_url":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/","og_site_name":"Philipp Salvisberg&#039;s Blog","article_published_time":"2026-02-23T16:24:15+00:00","article_modified_time":"2026-03-31T06:36:18+00:00","og_image":[{"width":1536,"height":1024,"url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2026\/02\/sql-assertions.png","type":"image\/png"}],"author":"Philipp Salvisberg","twitter_card":"summary_large_image","twitter_creator":"@phsalvisberg","twitter_site":"@phsalvisberg","twitter_misc":{"Written by":"Philipp Salvisberg","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#article","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/"},"author":{"name":"Philipp Salvisberg","@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"headline":"Enforcing Acyclic Hierarchies With SQL Assertions","datePublished":"2026-02-23T16:24:15+00:00","dateModified":"2026-03-31T06:36:18+00:00","mainEntityOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/"},"wordCount":726,"commentCount":0,"publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2026\/02\/sql-assertions.png","keywords":["Oracle 26ai","SQL","SQL Assertions"],"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/","url":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/","name":"Enforcing Acyclic Hierarchies With SQL Assertions - Philipp Salvisberg&#039;s Blog","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#primaryimage"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2026\/02\/sql-assertions.png","datePublished":"2026-02-23T16:24:15+00:00","dateModified":"2026-03-31T06:36:18+00:00","description":"Explore SQL Assertions in Oracle AI Database and learn how to enforce hierarchy integrity by detecting cycles with declarative constraints.","breadcrumb":{"@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#primaryimage","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2026\/02\/sql-assertions.png","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2026\/02\/sql-assertions.png","width":1536,"height":1024},{"@type":"BreadcrumbList","@id":"https:\/\/www.salvis.com\/blog\/2026\/02\/23\/enforcing-acyclic-hierarchies-with-sql-assertions\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.salvis.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Enforcing Acyclic Hierarchies With SQL Assertions"}]},{"@type":"WebSite","@id":"https:\/\/www.salvis.com\/blog\/#website","url":"https:\/\/www.salvis.com\/blog\/","name":"Philipp Salvisberg&#039;s Blog","description":"Database-centric development","publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.salvis.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515","name":"Philipp Salvisberg","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","width":400,"height":400,"caption":"Philipp Salvisberg"},"logo":{"@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg"},"sameAs":["http:\/\/www.salvis.com\/"]}]}},"_links":{"self":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/15957","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/comments?post=15957"}],"version-history":[{"count":31,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/15957\/revisions"}],"predecessor-version":[{"id":16806,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/15957\/revisions\/16806"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media\/15992"}],"wp:attachment":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media?parent=15957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/categories?post=15957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/tags?post=15957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}