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

<channel>
	<title>IslandSQL Archives - Philipp Salvisberg&#039;s Blog</title>
	<atom:link href="https://www.salvis.com/blog/tag/islandsql/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.salvis.com/blog/tag/islandsql/</link>
	<description>Database-centric development</description>
	<lastBuildDate>Fri, 06 Dec 2024 12:04:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</url>
	<title>IslandSQL Archives - Philipp Salvisberg&#039;s Blog</title>
	<link>https://www.salvis.com/blog/tag/islandsql/</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/>
<atom:link rel="hub" href="https://websubhub.com/hub"/>
<atom:link rel="self" href="https://www.salvis.com/blog/tag/islandsql/feed/"/>
	<item>
		<title>IslandSQL Final Episode 10: Parsing PL/pgSQL</title>
		<link>https://www.salvis.com/blog/2024/07/29/islandsql-final-episode-10-parsing-pl-pgsql/</link>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Mon, 29 Jul 2024 14:00:55 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[ANTLR]]></category>
		<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[IslandSQL]]></category>
		<category><![CDATA[Oracle 26ai]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=13526</guid>

					<description><![CDATA[<p>Introduction IslandSQL is a parser for SQL files targeting OracleDB or PostgreSQL. The parser is available on Maven Central and can process SQL*Plus, SQLcl or psql statements besides SQL statements. However, the focus is on statements with static DML statements and code in PL/SQL and PL/pgSQL. For static code analysis, for example.<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2024/07/29/islandsql-final-episode-10-parsing-pl-pgsql/">IslandSQL Final Episode 10: Parsing PL/pgSQL</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="introduction">Introduction</h2>



<p>IslandSQL is a parser for SQL files targeting OracleDB or PostgreSQL. The parser is available on <a href="https://central.sonatype.com/artifact/ch.islandsql/islandsql">Maven Central</a> and can process SQL*Plus, SQLcl or psql statements besides SQL statements. However, the focus is on statements with static DML statements and code in PL/SQL and PL/pgSQL. For static code analysis, for example.</p>



<p>In PostgreSQL <code>create function</code>, <code>create procedure</code> and <code>do</code> accept code as a string. This simplifies parsing and the implementation of additional languages. As a result, you can write functions and procedures in SQL, PL/pgSQL, PL/Tcl, PL/Perl and PL/Python in any standard PostgreSQL distribution.</p>



<p>Starting with IslandSQL version 0.10 it&#8217;s possible to parse SQL and PL/pgSQL in strings and extend the parse tree accordingly. In this blog post, I will explain how this works.</p>



<p>This <a href="https://marketplace.visualstudio.com/items?itemName=phsalvisberg.islandsql">VS Code extension</a> uses IslandSQL in a language server to report syntax errors and to produce parse trees as shown in this blog post.</p>



<h2 class="wp-block-heading" id="plpgsql_as_string">PL/pgSQL as String</h2>



<p>Let&#8217;s look at a <code>do</code> statement executing a PL/pgSQL block provided as a string.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">1) hello_world.sql</span><span role="button" tabindex="0" data-code="do '
begin
   raise notice $$Hello World!$$;
end
';" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">do </span><span style="color: #CE9178">&#39;</span></span>
<span class="line"><span style="color: #CE9178">begin</span></span>
<span class="line"><span style="color: #CE9178">   raise notice $$Hello World!$$;</span></span>
<span class="line"><span style="color: #CE9178">end</span></span>
<span class="line"><span style="color: #CE9178">&#39;</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="NOTICE:  Hello World!
DO" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">NOTICE:  Hello World!</span></span>
<span class="line"><span style="color: #D4D4D4">DO</span></span></code></pre></div>



<p>The parse tree in IslandSQL version 0.9 looks as follows:</p>



<figure class="wp-block-image size-full is-resized is-style-default"><a href="https://www.salvis.com/blog/wp-content/uploads/2024/07/1-plpgsql-string-only.svg"><img decoding="async" src="https://www.salvis.com/blog/wp-content/uploads/2024/07/1-plpgsql-string-only.svg" alt="Parse tree with PL/pgSQL as string" class="wp-image-13529" style="width:310px"/></a></figure>



<p>Look at the parse tree. It is quite simple. Interesting is the PL/pgSQL block. The content in single quotes is represented as a single token. The big rectangle at the bottom. It&#8217;s a single token regardless of the code size.</p>



<h2 class="wp-block-heading" id="plpgsql_as_subtree">PL/pgSQL as Subtree</h2>



<p>Parsing PL/pgSQL as a string is easy. The lexer produces the token for the string containing the PL/pgSQL code. The parser does not need to understand the PL/pgSQL at all.</p>



<p>But this does not help analyse the PL/pgSQL code. We need a parser that </p>



<ul class="wp-block-list">
<li>understands PL/pgSQL </li>



<li>parses PL/pgSQL code provided as a string</li>



<li>extends the main parse tree by sub-parse trees with PL/pgSQL code</li>
</ul>



<p>The IslandSQL parser in version 0.10 does exactly that. It produces this parse tree by default:</p>



<figure class="wp-block-image size-full is-resized"><a href="https://www.salvis.com/blog/wp-content/uploads/2024/07/2-plpgsql-string-and-subtree.svg"><img decoding="async" src="https://www.salvis.com/blog/wp-content/uploads/2024/07/2-plpgsql-string-and-subtree.svg" alt="Parse tree with PL/pgSQL as string and as subtree" class="wp-image-13540" style="width:550px"/></a></figure>



<p>The PL/pgSQL code is represented twice in this parse tree. Once as a single token. And once as a node named <code>postgresqlPlpgsqlCode</code>.</p>



<h2 class="wp-block-heading" id="plpgsql_as_subtree_only">PL/pgSQL as Subtree Only</h2>



<p>Maybe you do not like it when PL/pgSQL code is represented twice in the parse tree. In this case, you can override the default options when creating an IslandSQL document.</p>



<p>The IslandSQL library requires Java 8 or newer. In the next example, we use Java 22 to reduce boilerplate code. <a href="https://docs.oracle.com/en/java/javase/22/language/implicitly-declared-classes-and-instance-main-methods.html">Implicitly declared classes</a> are still in preview. Hence we have to pass the parameters <code>--enable-preview --source 22</code> when running the <code>HelloWorld.java</code> program. </p>



<h5 class="wp-block-heading">Explaining HelloWorld.java</h5>



<p>In line 13 we create the IslandSQL document with a series of parameters. One of them is <code>removeCode(true)</code> in line 19 which oversteers the default behaviour and removes the code as a string from the parse tree.</p>



<p>In line 21 we print a profile. Thanks to Cary Millsap, I can&#8217;t deal with performance issues without thinking about a bicycle, a Ferrari and kissing&#8230; The profile helps to understand where the parser has spent its time.</p>



<p>Finally, in lines 22 and 23 we print the parse tree. Once as a simple textual hierarchy and once as a <a href="https://www.graphviz.org/doc/info/lang.html">DOT</a> graph. You can visualise the result in <a href="https://edotor.net/?engine=dot#digraph%20islandSQL%20%7B%0A%20%20bgcolor%3D%22transparent%22%0A%20%20%221155757579%22%20%5Bshape%3Dellipse%20label%3D%22file%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%221155757579%22%20-%3E%20%221785111044%22%0A%20%20%221155757579%22%20-%3E%20%221482748887%22%0A%20%20%221785111044%22%20%5Bshape%3Dellipse%20label%3D%22statement%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%221785111044%22%20-%3E%20%22494894055%22%0A%20%20%22494894055%22%20%5Bshape%3Dellipse%20label%3D%22doStatement%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22494894055%22%20-%3E%20%221123226989%22%0A%20%20%22494894055%22%20-%3E%20%22500885941%22%0A%20%20%221123226989%22%20%5Bshape%3Dellipse%20label%3D%22postgresqlDo%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%221123226989%22%20-%3E%20%221115381650%22%0A%20%20%221123226989%22%20-%3E%20%22616412281%22%0A%20%20%221115381650%22%20%5Bshape%3Dbox%20label%3D%22do%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22616412281%22%20%5Bshape%3Dellipse%20label%3D%22postgresqlPlpgsqlCode%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22616412281%22%20-%3E%20%222118096382%22%0A%20%20%22616412281%22%20-%3E%20%22878861517%22%0A%20%20%22616412281%22%20-%3E%20%22746394140%22%0A%20%20%222118096382%22%20%5Bshape%3Dbox%20label%3D%22begin%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22878861517%22%20%5Bshape%3Dellipse%20label%3D%22plsqlStatement%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22878861517%22%20-%3E%20%221705665942%22%0A%20%20%221705665942%22%20%5Bshape%3Dellipse%20label%3D%22postgresqlRaiseStatement%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%221705665942%22%20-%3E%20%221731763384%22%0A%20%20%221705665942%22%20-%3E%20%221100619942%22%0A%20%20%221705665942%22%20-%3E%20%2287242619%22%0A%20%20%221705665942%22%20-%3E%20%22864248990%22%0A%20%20%221731763384%22%20%5Bshape%3Dbox%20label%3D%22raise%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%221100619942%22%20%5Bshape%3Dellipse%20label%3D%22raiseLevel%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%221100619942%22%20-%3E%20%22285074186%22%0A%20%20%22285074186%22%20%5Bshape%3Dbox%20label%3D%22notice%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%2287242619%22%20%5Bshape%3Dellipse%20label%3D%22dollarString%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%2287242619%22%20-%3E%20%2215892131%22%0A%20%20%2215892131%22%20%5Bshape%3Dbox%20label%3D%22%24%24Hello%20World!%24%24%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22864248990%22%20%5Bshape%3Dbox%20label%3D%22%3B%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22746394140%22%20%5Bshape%3Dbox%20label%3D%22end%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22500885941%22%20%5Bshape%3Dellipse%20label%3D%22sqlEnd%22%20style%3Dfilled%20fillcolor%3D%22%23bfe6ff%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%22500885941%22%20-%3E%20%22484841769%22%0A%20%20%22484841769%22%20%5Bshape%3Dbox%20label%3D%22%3B%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%20%20%221482748887%22%20%5Bshape%3Dbox%20label%3D%22%3CEOF%3E%22%20style%3Dfilled%20fillcolor%3D%22%23fadabd%22%20fontname%3D%22Helvetica%22%5D%0A%7D%0A">Edotor.net</a>, for example.</p>



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

void main() {
    var source = &quot;&quot;&quot;
            do '
            begin
               raise notice $$Hello World!$$;
            end
            ';
            &quot;&quot;&quot;;
    var doc = new IslandSqlDocument.Builder()
            .sql(source)
            .hideOutOfScopeTokens(false)
            .dialect(IslandSqlDialect.POSTGRESQL)
            .profile(true)
            .subtrees(true)
            .removeCode(true)
            .build();
    System.out.println(doc.getParserMetrics().printProfile());
    System.out.println(ParseTreeUtil.printParseTree(doc.getFile()));
    System.out.println(ParseTreeUtil.dotParseTree(doc.getFile()));
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> ch.islandsql.grammar.IslandSqlDialect;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> ch.islandsql.grammar.IslandSqlDocument;</span></span>
<span class="line"><span style="color: #569CD6">import</span><span style="color: #D4D4D4"> ch.islandsql.grammar.util.ParseTreeUtil;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #4EC9B0">void</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">main</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">source</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&quot;&quot;&quot;</span></span>
<span class="line"><span style="color: #CE9178">            do &#39;</span></span>
<span class="line"><span style="color: #CE9178">            begin</span></span>
<span class="line"><span style="color: #CE9178">               raise notice $$Hello World!$$;</span></span>
<span class="line"><span style="color: #CE9178">            end</span></span>
<span class="line"><span style="color: #CE9178">            &#39;;</span></span>
<span class="line"><span style="color: #CE9178">            &quot;&quot;&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">doc</span><span style="color: #D4D4D4"> = </span><span style="color: #C586C0">new</span><span style="color: #D4D4D4"> IslandSqlDocument.</span><span style="color: #DCDCAA">Builder</span><span style="color: #D4D4D4">()</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">sql</span><span style="color: #D4D4D4">(source)</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">hideOutOfScopeTokens</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">false</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">dialect</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">IslandSqlDialect</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">POSTGRESQL</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">profile</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">subtrees</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">removeCode</span><span style="color: #D4D4D4">(</span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">)</span></span>
<span class="line"><span style="color: #D4D4D4">            .</span><span style="color: #DCDCAA">build</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">doc</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getParserMetrics</span><span style="color: #D4D4D4">().</span><span style="color: #DCDCAA">printProfile</span><span style="color: #D4D4D4">());</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">ParseTreeUtil</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">printParseTree</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">doc</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getFile</span><span style="color: #D4D4D4">()));</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">System</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">out</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">println</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">ParseTreeUtil</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">dotParseTree</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">doc</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">getFile</span><span style="color: #D4D4D4">()));</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="java --enable-preview --source 22 -cp .:islandsql-0.10.0.jar:antlr4-runtime-4.13.1.jar HelloWorld.java" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">java</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--enable-preview</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--source</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">22</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-cp</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">.:islandsql-0.10.0.jar:antlr4-runtime-4.13.1.jar</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">HelloWorld.java</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Profile
=======

Total memory used by parser    : 5’164 KB
Total time spent in parser     : 27.918 ms
Total time recorded by profiler: 14.167 ms (100%)

Rule Name (Decision)                          Time (ms) Percent Invocations Lookahead Max Lookahead Ambiguities Errors
---------------------------------------- -------------- ------- ----------- --------- ------------- ----------- ------
string (1887)                                    10.302   72.72           2         0             0           0      0
plsqlStatement (1129)                             1.337    9.44           1         0             0           0      0
postgresqlDo (576)                                0.750    5.30           1         0             0           0      0
postgresqlPlpgsqlCode (6)                         0.735    5.19           2         0             0           0      0
statement (11)                                    0.566    3.99           1         0             0           0      0
sqlEnd (1888)                                     0.314    2.21           1         0             0           0      0
postgresqlRaiseStatement (1260)                   0.134    0.95           1         0             0           0      0
postgresqlRaiseStatement (1269)                   0.030    0.21           1         0             0           0      0

file
  statement
    doStatement
      postgresqlDo
        K_DO:do
        postgresqlPlpgsqlCode
          K_BEGIN:begin
          plsqlStatement
            postgresqlRaiseStatement
              K_RAISE:raise
              raiseLevel
                K_NOTICE:notice
              string:dollarString
                DOLLAR_STRING:$$Hello World!$$
              SEMI:;
          K_END:end
      sqlEnd
        SEMI:;
  &lt;EOF&gt;

digraph islandSQL {
  bgcolor=&quot;transparent&quot;
  &quot;1155757579&quot; [shape=ellipse label=&quot;file&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;1155757579&quot; -&gt; &quot;1785111044&quot;
  &quot;1155757579&quot; -&gt; &quot;1482748887&quot;
  &quot;1785111044&quot; [shape=ellipse label=&quot;statement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;1785111044&quot; -&gt; &quot;494894055&quot;
  &quot;494894055&quot; [shape=ellipse label=&quot;doStatement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;494894055&quot; -&gt; &quot;1123226989&quot;
  &quot;494894055&quot; -&gt; &quot;500885941&quot;
  &quot;1123226989&quot; [shape=ellipse label=&quot;postgresqlDo&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;1123226989&quot; -&gt; &quot;1115381650&quot;
  &quot;1123226989&quot; -&gt; &quot;616412281&quot;
  &quot;1115381650&quot; [shape=box label=&quot;do&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;616412281&quot; [shape=ellipse label=&quot;postgresqlPlpgsqlCode&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;616412281&quot; -&gt; &quot;2118096382&quot;
  &quot;616412281&quot; -&gt; &quot;878861517&quot;
  &quot;616412281&quot; -&gt; &quot;746394140&quot;
  &quot;2118096382&quot; [shape=box label=&quot;begin&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;878861517&quot; [shape=ellipse label=&quot;plsqlStatement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;878861517&quot; -&gt; &quot;1705665942&quot;
  &quot;1705665942&quot; [shape=ellipse label=&quot;postgresqlRaiseStatement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;1705665942&quot; -&gt; &quot;1731763384&quot;
  &quot;1705665942&quot; -&gt; &quot;1100619942&quot;
  &quot;1705665942&quot; -&gt; &quot;87242619&quot;
  &quot;1705665942&quot; -&gt; &quot;864248990&quot;
  &quot;1731763384&quot; [shape=box label=&quot;raise&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;1100619942&quot; [shape=ellipse label=&quot;raiseLevel&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;1100619942&quot; -&gt; &quot;285074186&quot;
  &quot;285074186&quot; [shape=box label=&quot;notice&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;87242619&quot; [shape=ellipse label=&quot;dollarString&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;87242619&quot; -&gt; &quot;15892131&quot;
  &quot;15892131&quot; [shape=box label=&quot;$$Hello World!$$&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;864248990&quot; [shape=box label=&quot;;&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;746394140&quot; [shape=box label=&quot;end&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;500885941&quot; [shape=ellipse label=&quot;sqlEnd&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]
  &quot;500885941&quot; -&gt; &quot;484841769&quot;
  &quot;484841769&quot; [shape=box label=&quot;;&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
  &quot;1482748887&quot; [shape=box label=&quot;&lt;EOF&gt;&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Profile</span></span>
<span class="line"><span style="color: #D4D4D4">=======</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Total memory used by parser    : 5’164 KB</span></span>
<span class="line"><span style="color: #D4D4D4">Total time spent in parser     : 27.918 ms</span></span>
<span class="line"><span style="color: #D4D4D4">Total time recorded by profiler: 14.167 ms (100%)</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Rule Name (Decision)                          Time (ms) Percent Invocations Lookahead Max Lookahead Ambiguities Errors</span></span>
<span class="line"><span style="color: #D4D4D4">---------------------------------------- -------------- ------- ----------- --------- ------------- ----------- ------</span></span>
<span class="line"><span style="color: #D4D4D4">string (1887)                                    10.302   72.72           2         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4">plsqlStatement (1129)                             1.337    9.44           1         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4">postgresqlDo (576)                                0.750    5.30           1         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4">postgresqlPlpgsqlCode (6)                         0.735    5.19           2         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4">statement (11)                                    0.566    3.99           1         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4">sqlEnd (1888)                                     0.314    2.21           1         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4">postgresqlRaiseStatement (1260)                   0.134    0.95           1         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4">postgresqlRaiseStatement (1269)                   0.030    0.21           1         0             0           0      0</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">file</span></span>
<span class="line"><span style="color: #D4D4D4">  statement</span></span>
<span class="line"><span style="color: #D4D4D4">    doStatement</span></span>
<span class="line"><span style="color: #D4D4D4">      postgresqlDo</span></span>
<span class="line"><span style="color: #D4D4D4">        K_DO:do</span></span>
<span class="line"><span style="color: #D4D4D4">        postgresqlPlpgsqlCode</span></span>
<span class="line"><span style="color: #D4D4D4">          K_BEGIN:begin</span></span>
<span class="line"><span style="color: #D4D4D4">          plsqlStatement</span></span>
<span class="line"><span style="color: #D4D4D4">            postgresqlRaiseStatement</span></span>
<span class="line"><span style="color: #D4D4D4">              K_RAISE:raise</span></span>
<span class="line"><span style="color: #D4D4D4">              raiseLevel</span></span>
<span class="line"><span style="color: #D4D4D4">                K_NOTICE:notice</span></span>
<span class="line"><span style="color: #D4D4D4">              string:dollarString</span></span>
<span class="line"><span style="color: #D4D4D4">                DOLLAR_STRING:$$Hello World!$$</span></span>
<span class="line"><span style="color: #D4D4D4">              SEMI:;</span></span>
<span class="line"><span style="color: #D4D4D4">          K_END:end</span></span>
<span class="line"><span style="color: #D4D4D4">      sqlEnd</span></span>
<span class="line"><span style="color: #D4D4D4">        SEMI:;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;EOF&gt;</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">digraph islandSQL {</span></span>
<span class="line"><span style="color: #D4D4D4">  bgcolor=&quot;transparent&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1155757579&quot; [shape=ellipse label=&quot;file&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1155757579&quot; -&gt; &quot;1785111044&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1155757579&quot; -&gt; &quot;1482748887&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1785111044&quot; [shape=ellipse label=&quot;statement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1785111044&quot; -&gt; &quot;494894055&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;494894055&quot; [shape=ellipse label=&quot;doStatement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;494894055&quot; -&gt; &quot;1123226989&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;494894055&quot; -&gt; &quot;500885941&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1123226989&quot; [shape=ellipse label=&quot;postgresqlDo&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1123226989&quot; -&gt; &quot;1115381650&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1123226989&quot; -&gt; &quot;616412281&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1115381650&quot; [shape=box label=&quot;do&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;616412281&quot; [shape=ellipse label=&quot;postgresqlPlpgsqlCode&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;616412281&quot; -&gt; &quot;2118096382&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;616412281&quot; -&gt; &quot;878861517&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;616412281&quot; -&gt; &quot;746394140&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;2118096382&quot; [shape=box label=&quot;begin&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;878861517&quot; [shape=ellipse label=&quot;plsqlStatement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;878861517&quot; -&gt; &quot;1705665942&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1705665942&quot; [shape=ellipse label=&quot;postgresqlRaiseStatement&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1705665942&quot; -&gt; &quot;1731763384&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1705665942&quot; -&gt; &quot;1100619942&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1705665942&quot; -&gt; &quot;87242619&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1705665942&quot; -&gt; &quot;864248990&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1731763384&quot; [shape=box label=&quot;raise&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1100619942&quot; [shape=ellipse label=&quot;raiseLevel&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1100619942&quot; -&gt; &quot;285074186&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;285074186&quot; [shape=box label=&quot;notice&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;87242619&quot; [shape=ellipse label=&quot;dollarString&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;87242619&quot; -&gt; &quot;15892131&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;15892131&quot; [shape=box label=&quot;$$Hello World!$$&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;864248990&quot; [shape=box label=&quot;;&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;746394140&quot; [shape=box label=&quot;end&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;500885941&quot; [shape=ellipse label=&quot;sqlEnd&quot; style=filled fillcolor=&quot;#bfe6ff&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;500885941&quot; -&gt; &quot;484841769&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;484841769&quot; [shape=box label=&quot;;&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;1482748887&quot; [shape=box label=&quot;&lt;EOF&gt;&quot; style=filled fillcolor=&quot;#fadabd&quot; fontname=&quot;Helvetica&quot;]</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p>The parse tree looks now like this:</p>



<figure class="wp-block-image size-full is-resized"><a href="https://www.salvis.com/blog/wp-content/uploads/2024/07/3-plpgsql-subtree-only.svg"><img decoding="async" src="https://www.salvis.com/blog/wp-content/uploads/2024/07/3-plpgsql-subtree-only.svg" alt="Parse tree with PL/pgSQL as subtree only" class="wp-image-13539" style="width:380px"/></a></figure>



<h2 class="wp-block-heading" id="sql_dialect">SQL Dialect</h2>



<p>In line 16 of the previous <code>HelloWorld.java</code> program we set the dialect to <code>POSTGRESQL</code>.  Is that required? &#8211; No, it&#8217;s not. But when do we need to set the SQL dialect in IslandSQL? &#8211; When the lexical incompatibility between OracleDB and PostgreSQL leads to syntax errors in the code to be parsed. </p>



<p>What? &#8211; Let me explain.</p>



<h2 class="wp-block-heading" id="identifiers">Identifiers</h2>



<p>OracleDB and PostgreSQL use different characters to build an identifier. The following table shows the differences. The allowed characters are listed in square brackets. Read <code>\p{Alpha}</code> as any alphabetic letter in the character set of the database.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>DBMS</th><th>Allowed as First Character</th><th>Allowed in Subsequent Characters</th></tr></thead><tbody><tr><td>OracleDB</td><td><code>[\p{Alpha}]</code></td><td>[_$#0-9\p{Alpha}]</td></tr><tr><td>PostgreSQL</td><td><code>[_\p{Alpha}]</code></td><td>[_$0-9\p{Alpha}]</td></tr></tbody></table></figure>



<p>PostgreSQL allows identifiers that start with an underscore. That&#8217;s not a problem. However, OracleDB allows the hash sign (<code>#</code>) to be used in an identifier. That leads to unexpected results when the PostgreSQL code uses the <a href="https://www.postgresql.org/docs/current/functions-bitstring.html">bitwise XOR operator</a> without spaces around it. Here&#8217;s an example</p>



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



<p>PostgreSQL expects that the columns <code>a</code> and <code>b</code> exists in table <code>t</code>.</p>



<p>OracleDB expects that the column <code>a#b</code> exists in table <code>t</code>.</p>



<p>In this case, IslandSQL can parse the code without errors. However, the parse tree might not look as expected. That&#8217;s a documented limitation and cannot be influenced by setting the dialect. At least not in version 0.10 of IslandSQL. Nevertheless, it shows the impact of a lexical incompatibility.</p>



<h2 class="wp-block-heading" id="inquiry_directives">Inquiry Directives</h2>



<p>PL/SQL supports predefined and custom <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/lnpls/plsql-language-fundamentals.html#GUID-E918087C-D5A8-4CEE-841B-5333DE6D4C15">Inquiry Directives</a>. These directives are lexically incompatible with PostgreSQL <a href="https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING">dollar-quoted string constants</a>.</p>



<p>Here&#8217;s an example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">4) Using custom inquiry directives</span><span role="button" tabindex="0" data-code="alter session set plsql_ccflags = 'custom1:41, custom2:42';
begin
   dbms_output.put_line($$custom1);
   dbms_output.put_line($$custom2 || '(2)');
end;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">alter session</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> plsql_ccflags = </span><span style="color: #CE9178">&#39;custom1:41, custom2:42&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">begin</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">($$custom1);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">($$custom2 || </span><span style="color: #CE9178">&#39;(2)&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #569CD6">end</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<p>By default, this causes a parse error, because <code>$$custom1);\n dbms_output.put_line($$</code> is identified as a dollar-quoted string constant by the lexer. As a result, the code is interpreted like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">5) Visualising how two custom inquiry directives  are treated as a string</span><span role="button" tabindex="0" data-code="alter session set plsql_ccflags = 'custom1:41, custom2:42';
begin
   dbms_output.put_line('custom1);
   dbms_output.put_line('custom2 || '(2)');
end;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">alter session</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> plsql_ccflags = </span><span style="color: #CE9178">&#39;custom1:41, custom2:42&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">begin</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;custom1);</span></span>
<span class="line"><span style="color: #CE9178">   dbms_output.put_line(&#39;</span><span style="color: #D4D4D4">custom2 || </span><span style="color: #CE9178">&#39;(2)&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #569CD6">end</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<p>This makes it clearer, why we get a syntax error in line 4 at <code>custom2</code>.</p>



<p>In this case, we have to set the SQL dialect to <code>ORACLEDB</code> to parse <code>custom_inquiry_directives.sql</code> without errors. </p>



<h2 class="wp-block-heading" id="predefined_inquiry_directives">Predefined Inquiry Directives</h2>



<p>To simplify the use, we want to avoid specifying the SQL dialect. One way to achieve that is to handle predefined inquiry directives in the <code>GENERIC</code> SQL dialect.</p>



<p>Here&#8217;s an example, that does not report syntax errors:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">6) Using predefined inquiry directives</span><span role="button" tabindex="0" data-code="begin
   dbms_output.put_line($$plsql_line);
   dbms_output.put_line($$plsql_line || '(2)');
end;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">begin</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">($$plsql_line);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">($$plsql_line || </span><span style="color: #CE9178">&#39;(2)&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #569CD6">end</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<p>We know the predefined inquiry directives and can deal with them in the lexer.</p>



<p>However, this special treatment can cause problems in corner cases like this one:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">7) Using the name of a predefined inquiry directive at the start of a dollar-quoted string constant</span><span role="button" tabindex="0" data-code="do '
begin
   raise notice $$plsql_line is a predefined inquiry directive$$;
end
';" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">do </span><span style="color: #CE9178">&#39;</span></span>
<span class="line"><span style="color: #CE9178">begin</span></span>
<span class="line"><span style="color: #CE9178">   raise notice $$plsql_line is a predefined inquiry directive$$;</span></span>
<span class="line"><span style="color: #CE9178">end</span></span>
<span class="line"><span style="color: #CE9178">&#39;</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<p>In such cases, we should use the <code>POSTGRESQL</code> dialect to avoid parse errors.</p>



<h2 class="wp-block-heading" id="detect_sql_dialect">Detect SQL Dialect</h2>



<p>Is there a way to detect the SQL dialect of an SQL input automatically? Sure. Several. I&#8217;m sure there is a way to use an LLM to get a reasonable result. I&#8217;m more of a rule-based guy. So we could parse the code with one dialect and on parse errors try other dialects. If all dialects produce errors, we could choose the one with the fewest errors.</p>



<p>This sounds costly, right? Therefore I decided to start with a simple SQL dialect detection mechanism. The current implementation looks like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">8) Excerpt of IslandSqlDocument.java in version 0.10.0</span><span role="button" tabindex="0" data-code="private static IslandSqlDialect guessDialect(String sql) {
    return sql.contains(&quot;\n/\n&quot;) ? IslandSqlDialect.ORACLEDB : IslandSqlDialect.GENERIC;
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">private</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">static</span><span style="color: #D4D4D4"> </span><span style="color: #4EC9B0">IslandSqlDialect</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">guessDialect</span><span style="color: #D4D4D4">(</span><span style="color: #4EC9B0">String</span><span style="color: #D4D4D4"> sql) {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">sql</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">contains</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&quot;</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">/</span><span style="color: #D7BA7D">\n</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4">) </span><span style="color: #C586C0">?</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">IslandSqlDialect</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">ORACLEDB</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">:</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">IslandSqlDialect</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">GENERIC</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p>In other words, if the code contains a slash followed by a newline character in the first column of a line, then we go with the <code>ORACLEDB</code> dialect. In all other cases, we go with the <code>GENERIC</code> SQL dialect.</p>



<p>My first version was even simpler. However, I had to add a final <code>\n</code> to the search string to ensure that SQL code containing multiline comments is not recognized as <code>ORACLEDB</code> dialect. Files with Windows newline characters are always recognized as GENERIC. That&#8217;s the price when trying to keep things simple and fast.</p>



<p>Now, the ORACLEDB SQL dialect is correctly detected in the next example. As a result, no syntax errors are reported.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">9) Using custom inquiry directives in a PL/SQL Block ending on slash</span><span role="button" tabindex="0" data-code="alter session set plsql_ccflags = 'custom1:41, custom2:42';
begin
   dbms_output.put_line($$custom1);
   dbms_output.put_line($$custom2 || '(2)');
end;
/
" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">alter session</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> plsql_ccflags = </span><span style="color: #CE9178">&#39;custom1:41, custom2:42&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">begin</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">($$custom1);</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #DCDCAA">dbms_output.</span><span style="color: #4EC9B0">put_line</span><span style="color: #D4D4D4">($$custom2 || </span><span style="color: #CE9178">&#39;(2)&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #569CD6">end</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span>
<span class="line"></span></code></pre></div>



<p>The SQL dialect detection mechanism kicks in when no SQL dialect is specified (<code>null</code>). </p>



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



<p>Developing a single grammar for OracleDB and PostgreSQL was an interesting work. I learned a lot about the underlying DBMS. I often looked at the grammar documentation and did not understand it fully. So I had to run the provided examples or create some myself. The typical test cases are based on working examples, extended by tests based on the cartesian product of a subset of clauses that verified if I had defined the order, the optionality, and the cardinality according to the documentation.</p>



<p>A challenge is the undocumented stuff. There are various reasons why something is not documented. In the end, it does not matter why something is missing. The parser fails when processing code that works but should not according to the docs. This cannot be covered by tests based on the official documentation. I found some bugs while processing real-life code. And I expect to find more.</p>



<p>This is the season finale of IslandSQL. There won&#8217;t be a second season. However, there might be some spin-offs since I plan to build products based on IslandSQL. Therefore I plan to keep the parser compatible with the latest versions of OracleDB and PostgreSQL.</p>



<p>Feedback is welcome. Please leave your comments on this blog post or open an issue in the <a href="https://github.com/IslandSQL/IslandSQL">IslandSQL GitHub repository</a> for questions, bugs or feature requests.</p>



<p>Thank you.</p>
<p>The post <a href="https://www.salvis.com/blog/2024/07/29/islandsql-final-episode-10-parsing-pl-pgsql/">IslandSQL Final Episode 10: Parsing PL/pgSQL</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IslandSQL Episode 9: GraphQL, JSON and Flexible Schemas With Duality Views</title>
		<link>https://www.salvis.com/blog/2024/06/27/islandsql-episode-9-graphql-json-and-flexible-schemas-with-duality-views/</link>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Thu, 27 Jun 2024 11:31:12 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[ANTLR]]></category>
		<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[IslandSQL]]></category>
		<category><![CDATA[Oracle 26ai]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=13430</guid>

					<description><![CDATA[<p>Introduction In the last episode, we looked at some new features in Oracle Database 23.4. The IslandSQL grammar now covers all statements that can contain static DML statements and code in PL/SQL and PL/pgSQL. While implementing the ANTLR grammar for the create JSON relational duality view statement I stumbled over GraphQL in<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2024/06/27/islandsql-episode-9-graphql-json-and-flexible-schemas-with-duality-views/">IslandSQL Episode 9: GraphQL, JSON and Flexible Schemas With Duality Views</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>In the <a href="https://www.salvis.com/blog/2024/06/15/islandsql-episode-8-whats-new-in-oracle-database-23-4/">last episode</a>, we looked at some new features in Oracle Database 23.4. The <a href="https://github.com/IslandSQL/IslandSQL">IslandSQL</a> grammar now covers all statements that can contain static DML statements and code in PL/SQL and PL/pgSQL. </p>



<p>While implementing the ANTLR grammar for the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/create-json-relational-duality-view.html">create JSON relational duality view</a> statement I stumbled over GraphQL in this syntax diagram:</p>



<figure class="wp-block-image size-large is-resized"><a href="https://www.salvis.com/blog/wp-content/uploads/2024/06/image.png"><img fetchpriority="high" decoding="async" width="1024" height="469" src="https://www.salvis.com/blog/wp-content/uploads/2024/06/image-1024x469.png" alt="create_json_relational_duality_view railroad diagram" class="wp-image-13431" style="width:541px" srcset="https://www.salvis.com/blog/wp-content/uploads/2024/06/image-1024x469.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2024/06/image-300x138.png 300w, https://www.salvis.com/blog/wp-content/uploads/2024/06/image-768x352.png 768w, https://www.salvis.com/blog/wp-content/uploads/2024/06/image-150x69.png 150w, https://www.salvis.com/blog/wp-content/uploads/2024/06/image-480x220.png 480w, https://www.salvis.com/blog/wp-content/uploads/2024/06/image.png 1082w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p>You can use <a href="https://graphql.org/learn/">GraphQL</a> as an alternative to a subquery to describe the source of your JSON relational duality view. This feature was already part of 23.3. Usually, I don&#8217;t like it when there are several ways to do the same thing. However, in this case, GraphQL helped me to understand the variant of the <code>select statement</code> in the duality view better. GraphQL might even be better suited to describe the content of a duality view.</p>



<p>The funny thing is that JSON is about schema flexibility and GraphQL needs a schema to work. That sounds contradictory. However, if we reduce the scope of schema flexibility to a JSON object within existing entities, this can work quite well.</p>



<p>In this blog post, I explore some features related to the schema flexibility of JSON relational duality views.</p>



<ol class="wp-block-list">
<li><a href="#setup">Setup</a></li>



<li><a href="#read-only-view">Read-only View à la 19c</a></li>



<li><a href="#read-only-duality-view">Read-only Duality View</a></li>



<li><a href="#updateable-duality-view-using-select">Updateable Duality View Using SELECT</a></li>



<li><a href="#updateable-duality-view-using-graphql">Updateable Duality View Using GraphQL</a></li>



<li><a href="#graphql-vs-select">GraphQL vs. SELECT</a></li>



<li><a href="#insert-into-duality-view">Insert Into Duality View</a></li>



<li><a href="#update-duality-view">Update Duality View</a></li>



<li><a href="#delete-from-duality-view">Delete From Duality View</a></li>
</ol>



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



<p>The examples in this blog post require an Oracle Database 23.4 (yes, 23.3 is not enough). In a schema of your choice you can run the following setup script:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">1) Setup for extended dept and emp table</span><span role="button" tabindex="0" data-code="set linesize 200
set pagesize 1000  
set long 32767
column ext format a72
column data format a130
alter session set nls_date_format = 'YYYY-MM-DD';

drop table if exists emp;
drop table if exists dept;

create table dept (
   deptno number(2, 0)      not null constraint dept_pk primary key,
   dname  varchar2(14 char) not null,
   loc    varchar2(13 char) not null,
   ext    json(object)
);

create table emp (
   empno    number(4, 0)      not null  constraint emp_pk primary key,
   ename    varchar2(10 char) not null,
   job      varchar2(9 char)  not null,
   mgr      number(4, 0)                constraint emp_mgr_fk references emp,
   hiredate date              not null,
   sal      number(7, 2)      not null,
   comm     number(7, 2),
   deptno   number(2, 0)      not null  constraint emp_deptno_fk references dept,
   ext      json(object)
);

insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK'),
       (20, 'RESEARCH',   'DALLAS'),
       (30, 'SALES',      'CHICAGO'),
       (40, 'OPERATIONS', 'BOSTON');
commit;
       
insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7566, 'JONES',  'MANAGER',   7839, date '1981-04-02', 2975, null, 20),
       (7698, 'BLAKE',  'MANAGER',   7839, date '1981-05-01', 2850, null, 30),
       (7782, 'CLARK',  'MANAGER',   7839, date '1981-06-09', 2450, null, 10),
       (7788, 'SCOTT',  'ANALYST',   7566, date '1987-04-19', 3000, null, 20),
       (7902, 'FORD',   'ANALYST',   7566, date '1981-12-03', 3000, null, 20),
       (7499, 'ALLEN',  'SALESMAN',  7698, date '1981-02-20', 1600,  300, 30),
       (7521, 'WARD',   'SALESMAN',  7698, date '1981-02-22', 1250,  500, 30),
       (7654, 'MARTIN', 'SALESMAN',  7698, date '1981-09-28', 1250, 1400, 30),
       (7844, 'TURNER', 'SALESMAN',  7698, date '1981-09-08', 1500,    0, 30),
       (7900, 'JAMES',  'CLERK',     7698, date '1981-12-03',  950, null, 30),
       (7934, 'MILLER', 'CLERK',     7782, date '1982-01-23', 1300, null, 10),
       (7369, 'SMITH',  'CLERK',     7902, date '1980-12-17',  800, null, 20),
       (7839, 'KING',   'PRESIDENT', null, date '1981-11-17', 5000, null, 10),
       (7876, 'ADAMS',  'CLERK',     7788, date '1987-05-23', 1100, null, 20);
commit;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> linesize </span><span style="color: #B5CEA8">200</span></span>
<span class="line"><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> pagesize </span><span style="color: #B5CEA8">1000</span><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">long</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">32767</span></span>
<span class="line"><span style="color: #569CD6">column</span><span style="color: #D4D4D4"> ext format a72</span></span>
<span class="line"><span style="color: #569CD6">column</span><span style="color: #D4D4D4"> data format a130</span></span>
<span class="line"><span style="color: #DCDCAA">alter session</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> nls_date_format = </span><span style="color: #CE9178">&#39;YYYY-MM-DD&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">drop</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> emp;</span></span>
<span class="line"><span style="color: #569CD6">drop</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> dept;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> dept (</span></span>
<span class="line"><span style="color: #D4D4D4">   deptno </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4"> </span><span 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>
<span class="line"><span style="color: #D4D4D4">   dname  </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">14</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   loc    </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">13</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   ext    json(object)</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> emp (</span></span>
<span class="line"><span style="color: #D4D4D4">   empno    </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">  </span><span 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>
<span class="line"><span style="color: #D4D4D4">   ename    </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   job      </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">9</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">char</span><span style="color: #D4D4D4">)  </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   mgr      </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)                </span><span style="color: #569CD6">constraint</span><span style="color: #D4D4D4"> emp_mgr_fk </span><span style="color: #569CD6">references</span><span style="color: #D4D4D4"> emp,</span></span>
<span class="line"><span style="color: #D4D4D4">   hiredate </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4">              </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   sal      </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">7</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   comm     </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">7</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   deptno   </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">)      </span><span style="color: #569CD6">not</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">  </span><span 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>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   ext      json(object)</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> dept (deptno, dname, loc)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ACCOUNTING&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;NEW YORK&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;RESEARCH&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;DALLAS&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SALES&#39;</span><span style="color: #D4D4D4">,      </span><span style="color: #CE9178">&#39;CHICAGO&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">40</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;OPERATIONS&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;BOSTON&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">       </span></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">7566</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;JONES&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;MANAGER&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-04-02&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2975</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;BLAKE&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;MANAGER&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-05-01&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2850</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7782</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;CLARK&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;MANAGER&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-06-09&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">2450</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7788</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SCOTT&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;ANALYST&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7566</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1987-04-19&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">3000</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7902</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;FORD&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;ANALYST&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #B5CEA8">7566</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-12-03&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">3000</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7499</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ALLEN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-02-20&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1600</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">300</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7521</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;WARD&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-02-22&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1250</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">500</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7654</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;MARTIN&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-09-28&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1250</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1400</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7844</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;TURNER&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SALESMAN&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-09-08&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1500</span><span style="color: #D4D4D4">,    </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7900</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;JAMES&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7698</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-12-03&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">950</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">30</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7934</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;MILLER&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7782</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1982-01-23&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1300</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7369</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;SMITH&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7902</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1980-12-17&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #B5CEA8">800</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7839</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;KING&#39;</span><span style="color: #D4D4D4">,   </span><span style="color: #CE9178">&#39;PRESIDENT&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1981-11-17&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5000</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">       (</span><span style="color: #B5CEA8">7876</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;ADAMS&#39;</span><span style="color: #D4D4D4">,  </span><span style="color: #CE9178">&#39;CLERK&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #B5CEA8">7788</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">date</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;1987-05-23&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">1100</span><span style="color: #D4D4D4">, </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="
Session altered.


Table EMP dropped.


Table DEPT dropped.


Table DEPT created.


Table EMP created.


4 rows inserted.


Commit complete.


14 rows inserted.


Commit complete." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Session altered.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Table EMP dropped.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Table DEPT dropped.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Table DEPT created.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Table EMP created.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">4 rows inserted.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Commit complete.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">14 rows inserted.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Commit complete.</span></span></code></pre></div>



<p>There are a few changes to the well-known <code>dept</code> and <code>emp</code> tables I&#8217;d like to highlight:</p>



<ul class="wp-block-list">
<li>Firstly, primary keys and foreign keys. They are required for the duality views, however, they do not need to be enabled.</li>



<li>Secondly, both tables got an additional <code>ext</code> column. The data type is <code>json(object)</code>. Before 23.4 there was just a generic <code>json</code> data type. With 23.4 it&#8217;s possible to add <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/SQL-JSON-Conditions.html#GUID-99B9493D-2929-4A09-BA39-A56F8E7319DA__SECTION_AFR_B3S_KBC">modifiers</a>. The modifier <code>object</code> is required for <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/jsnvu/json-data-stored-json-relational-duality-views.html#GUID-8D09B4D6-2853-40ED-8E7A-A921C197D5A8">flex columns</a> in duality views.</li>
</ul>



<h2 class="wp-block-heading" id="read-only-view">2. Read-Only View à la 19c</h2>



<p>Let&#8217;s step back and create a view that returns a single JSON column, as in Oracle Database 19c (to make it work in 19c you have to use for example <code>ext clob check (ext is json)</code> instead of <code>ext json(object)</code> in the tables <code>dept</code> and <code>emp</code>).</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">2) Read-only view à la 19c</span><span role="button" tabindex="0" data-code="create or replace view dept_v as
select json_object(
          deptno,
          dname,
          loc,
          ext,
          'sal': (select sum(sal) from emp where emp.deptno = dept.deptno)
          absent on null
       ) as data
  from dept;

select * from dept_v;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_v </span><span style="color: #569CD6">as</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_object(</span></span>
<span class="line"><span style="color: #D4D4D4">          deptno,</span></span>
<span class="line"><span style="color: #D4D4D4">          dname,</span></span>
<span class="line"><span style="color: #D4D4D4">          loc,</span></span>
<span class="line"><span style="color: #D4D4D4">          ext,</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #CE9178">&#39;sal&#39;</span><span style="color: #D4D4D4">: (</span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(sal) </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> emp.deptno = dept.deptno)</span></span>
<span class="line"><span style="color: #D4D4D4">          absent </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span></span>
<span class="line"><span style="color: #D4D4D4">       ) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_v;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="View DEPT_V created.


DATA
--------------------------------------------------------------
{&quot;deptno&quot;:10,&quot;dname&quot;:&quot;ACCOUNTING&quot;,&quot;loc&quot;:&quot;NEW YORK&quot;,&quot;sal&quot;:8750}
{&quot;deptno&quot;:20,&quot;dname&quot;:&quot;RESEARCH&quot;,&quot;loc&quot;:&quot;DALLAS&quot;,&quot;sal&quot;:10875}
{&quot;deptno&quot;:30,&quot;dname&quot;:&quot;SALES&quot;,&quot;loc&quot;:&quot;CHICAGO&quot;,&quot;sal&quot;:9400}
{&quot;deptno&quot;:40,&quot;dname&quot;:&quot;OPERATIONS&quot;,&quot;loc&quot;:&quot;BOSTON&quot;}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">View DEPT_V created.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">DATA</span></span>
<span class="line"><span style="color: #D4D4D4">--------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;deptno&quot;:10,&quot;dname&quot;:&quot;ACCOUNTING&quot;,&quot;loc&quot;:&quot;NEW YORK&quot;,&quot;sal&quot;:8750}</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;deptno&quot;:20,&quot;dname&quot;:&quot;RESEARCH&quot;,&quot;loc&quot;:&quot;DALLAS&quot;,&quot;sal&quot;:10875}</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;deptno&quot;:30,&quot;dname&quot;:&quot;SALES&quot;,&quot;loc&quot;:&quot;CHICAGO&quot;,&quot;sal&quot;:9400}</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;deptno&quot;:40,&quot;dname&quot;:&quot;OPERATIONS&quot;,&quot;loc&quot;:&quot;BOSTON&quot;}</span></span></code></pre></div>



<h2 class="wp-block-heading" id="read-only-duality-view">3. Read-Only Duality View</h2>



<p>And now let&#8217;s try to use the previous subquery in a duality view.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">3a) Read-only duality view (ORA-40616)</span><span role="button" tabindex="0" data-code="create or replace json duality view dept_dv as
select json_object(
          deptno,
          dname,
          loc,
          ext,
          'sal': (select sum(sal) from emp where emp.deptno = dept.deptno)
          absent on null
       ) as data
  from dept;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> json duality </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">as</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_object(</span></span>
<span class="line"><span style="color: #D4D4D4">          deptno,</span></span>
<span class="line"><span style="color: #D4D4D4">          dname,</span></span>
<span class="line"><span style="color: #D4D4D4">          loc,</span></span>
<span class="line"><span style="color: #D4D4D4">          ext,</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #CE9178">&#39;sal&#39;</span><span style="color: #D4D4D4">: (</span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(sal) </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> emp.deptno = dept.deptno)</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          absent </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">null</span></span>
<span class="line"><span style="color: #D4D4D4">       ) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ORA-40616: Cannot create JSON Relational Duality View 'DEPT_DV': using ABSENT ON NULL in JSON_OBJECT() is not permitted." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">ORA-40616: Cannot create JSON Relational Duality View &#39;DEPT_DV&#39;: using ABSENT ON NULL in JSON_OBJECT() is not permitted.</span></span></code></pre></div>



<p>This does not work. The <code>absent on null</code> clause on line 8 is not supported in a duality view. Let&#8217;s remove this line and try again.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">3b) Read-only duality view (ORA-40895)</span><span role="button" tabindex="0" data-code="create or replace json duality view dept_dv as
select json_object(
          deptno,
          dname,
          loc,
          ext,
          'sal': (select sum(sal) from emp where emp.deptno = dept.deptno)
       ) as data
  from dept;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> json duality </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">as</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_object(</span></span>
<span class="line"><span style="color: #D4D4D4">          deptno,</span></span>
<span class="line"><span style="color: #D4D4D4">          dname,</span></span>
<span class="line"><span style="color: #D4D4D4">          loc,</span></span>
<span class="line"><span style="color: #D4D4D4">          ext,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          </span><span style="color: #CE9178">&#39;sal&#39;</span><span style="color: #D4D4D4">: (</span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">sum</span><span style="color: #D4D4D4">(sal) </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> emp.deptno = dept.deptno)</span></span>
<span class="line"><span style="color: #D4D4D4">       ) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ORA-40895: invalid SQL expression in JSON relational duality view (operators except JSON_OBJECT or JSON_ARRAYAGG not allowed)" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">ORA-40895: invalid SQL expression in JSON relational duality view (operators except JSON_OBJECT or JSON_ARRAYAGG not allowed)</span></span></code></pre></div>



<p>This still does not work. It&#8217;s not allowed to include an aggregate as in line 7. Let&#8217;s also remove this line and try again.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">3c) Read-only duality view (ORA-40941)</span><span role="button" tabindex="0" data-code="create or replace json duality view dept_dv as
select json_object(
          deptno,
          dname,
          loc,
          ext
       ) as data
  from dept;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> json duality </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">as</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_object(</span></span>
<span class="line"><span style="color: #D4D4D4">          deptno,</span></span>
<span class="line"><span style="color: #D4D4D4">          dname,</span></span>
<span class="line"><span style="color: #D4D4D4">          loc,</span></span>
<span class="line"><span style="color: #D4D4D4">          ext</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">       ) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ORA-40941: cannot specify a column name or subquery alias for JSON relational duality view" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">ORA-40941: cannot specify a column name or subquery alias for JSON relational duality view</span></span></code></pre></div>



<p>Argh. We cannot use the column alias <code>data</code> on line 7. Let&#8217;s remove the alias and try again.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">3d) Read-only duality view (ORA-42647)</span><span role="button" tabindex="0" data-code="create or replace json duality view dept_dv as
select json_object(
          deptno,
          dname,
          loc,
          ext
       )
  from dept;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> json duality </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">as</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_object(</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          deptno,</span></span>
<span class="line"><span style="color: #D4D4D4">          dname,</span></span>
<span class="line"><span style="color: #D4D4D4">          loc,</span></span>
<span class="line"><span style="color: #D4D4D4">          ext</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="ORA-42647: Missing '_id' field at the root level for JSON-relational duality view 'DEPT_DV'." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">ORA-42647: Missing &#39;_id&#39; field at the root level for JSON-relational duality view &#39;DEPT_DV&#39;.</span></span></code></pre></div>



<p>Okay, an <code>_id</code> field is required to identify a document. Composite keys can be passed as a JSON array. In this case, we do not need that. We can use <code>deptno</code>. Let&#8217;s amend the query and try again.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">3e) Read-only duality view</span><span role="button" tabindex="0" data-code="create or replace json duality view dept_dv as
select json_object(
          '_id': deptno,
          dname,
          loc,
          ext
       )
  from dept;

select * from dept_dv;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> json duality </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">as</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_object(</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #CE9178">&#39;_id&#39;</span><span style="color: #D4D4D4">: deptno,</span></span>
<span class="line"><span style="color: #D4D4D4">          dname,</span></span>
<span class="line"><span style="color: #D4D4D4">          loc,</span></span>
<span class="line"><span style="color: #D4D4D4">          ext</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_dv;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Json DUALITY created.


DATA
----------------------------------------------------------------------------------------------------------------------------------
{&quot;_id&quot;:10,&quot;dname&quot;:&quot;ACCOUNTING&quot;,&quot;loc&quot;:&quot;NEW YORK&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;38CBB37294BEE09C6D9867B5B1871FE2&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}
{&quot;_id&quot;:20,&quot;dname&quot;:&quot;RESEARCH&quot;,&quot;loc&quot;:&quot;DALLAS&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;1D1973E9B068183129F7DA59F6A9C283&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}
{&quot;_id&quot;:30,&quot;dname&quot;:&quot;SALES&quot;,&quot;loc&quot;:&quot;CHICAGO&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;11CC2AE352D52FFDAE0B7A3DFC99F836&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}
{&quot;_id&quot;:40,&quot;dname&quot;:&quot;OPERATIONS&quot;,&quot;loc&quot;:&quot;BOSTON&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;B33BBA9A74C046813C59BA0763AD81C9&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Json DUALITY created.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">DATA</span></span>
<span class="line"><span style="color: #D4D4D4">----------------------------------------------------------------------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;_id&quot;:10,&quot;dname&quot;:&quot;ACCOUNTING&quot;,&quot;loc&quot;:&quot;NEW YORK&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;38CBB37294BEE09C6D9867B5B1871FE2&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;_id&quot;:20,&quot;dname&quot;:&quot;RESEARCH&quot;,&quot;loc&quot;:&quot;DALLAS&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;1D1973E9B068183129F7DA59F6A9C283&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;_id&quot;:30,&quot;dname&quot;:&quot;SALES&quot;,&quot;loc&quot;:&quot;CHICAGO&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;11CC2AE352D52FFDAE0B7A3DFC99F836&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}</span></span>
<span class="line"><span style="color: #D4D4D4">{&quot;_id&quot;:40,&quot;dname&quot;:&quot;OPERATIONS&quot;,&quot;loc&quot;:&quot;BOSTON&quot;,&quot;_metadata&quot;:{&quot;etag&quot;:&quot;B33BBA9A74C046813C59BA0763AD81C9&quot;,&quot;asof&quot;:&quot;000025652FBC556F&quot;}}</span></span></code></pre></div>



<p>Finally, we have a working read-only duality view. </p>



<p>Please note that each document contains a <code>_metadata</code> object. The <code>etag</code> field is a hash value based on all document fields by default. It can be used for optimistic locking. The <code>asof</code> field represents the SCN (system change number). It&#8217;s useful for read consistency, this means querying related data in subsequent queries using the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-9CA8AB48-7DE6-4601-A798-42B2038CA3A6">flashback_query_clause</a>.</p>



<h2 class="wp-block-heading" id="updateable-duality-view-using-select">4. Updateable Duality View Using SELECT</h2>



<p>Let&#8217;s create an updateable duality view that represents all data in our model and uses all relationships. </p>



<p>The highlighted lines contain clauses that work only in a duality view. In other words, the &#8220;select&#8221; part does not work as a standalone statement as in common relational views.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">4) Updateable duality view using select</span><span role="button" tabindex="0" data-code="create or replace json duality view dept_dv as
select json {
          '_id': deptno,
          dname,
          loc,
          ext as flex,
          'emps':
             (
                select json_arrayagg(
                          JSON {
                             emp.empno,
                             emp.ename,
                             emp.job,
                             unnest
                                (
                                   select json {
                                             'mgr'    : mgr.empno with nocheck,
                                             'mgrname': mgr.ename with nocheck
                                          }
                                     from emp mgr
                                    where mgr.empno = emp.mgr
                                ),
                             emp.hiredate,
                             emp.sal,
                             emp.comm,
                             ext as flex
                          }
                       )
                  from emp with insert update delete
                 where emp.deptno = dept.deptno
             )
       }
  from dept with insert update delete;

select json_serialize(data returning clob pretty) as data
  from dept_dv dv
 where dv.data.&quot;_id&quot;.numberOnly() in (20, 40);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> json duality </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">as</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json {</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #CE9178">&#39;_id&#39;</span><span style="color: #D4D4D4">: deptno,</span></span>
<span class="line"><span style="color: #D4D4D4">          dname,</span></span>
<span class="line"><span style="color: #D4D4D4">          loc,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          ext </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> flex,</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #CE9178">&#39;emps&#39;</span><span style="color: #D4D4D4">:</span></span>
<span class="line"><span style="color: #D4D4D4">             (</span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_arrayagg(</span></span>
<span class="line"><span style="color: #D4D4D4">                          JSON {</span></span>
<span class="line"><span style="color: #D4D4D4">                             emp.empno,</span></span>
<span class="line"><span style="color: #D4D4D4">                             emp.ename,</span></span>
<span class="line"><span style="color: #D4D4D4">                             emp.job,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                             unnest</span></span>
<span class="line"><span style="color: #D4D4D4">                                (</span></span>
<span class="line"><span style="color: #D4D4D4">                                   </span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                                             </span><span style="color: #CE9178">&#39;mgr&#39;</span><span style="color: #D4D4D4">    : mgr.empno </span><span style="color: #569CD6">with</span><span style="color: #D4D4D4"> nocheck,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                                             </span><span style="color: #CE9178">&#39;mgrname&#39;</span><span style="color: #D4D4D4">: mgr.ename </span><span style="color: #569CD6">with</span><span style="color: #D4D4D4"> nocheck</span></span>
<span class="line"><span style="color: #D4D4D4">                                          }</span></span>
<span class="line"><span style="color: #D4D4D4">                                     </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp mgr</span></span>
<span class="line"><span style="color: #D4D4D4">                                    </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> mgr.empno = emp.mgr</span></span>
<span class="line"><span style="color: #D4D4D4">                                ),</span></span>
<span class="line"><span style="color: #D4D4D4">                             emp.hiredate,</span></span>
<span class="line"><span style="color: #D4D4D4">                             emp.sal,</span></span>
<span class="line"><span style="color: #D4D4D4">                             emp.comm,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                             ext </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> flex</span></span>
<span class="line"><span style="color: #D4D4D4">                          }</span></span>
<span class="line"><span style="color: #D4D4D4">                       )</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">with</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">update</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">delete</span></span>
<span class="line"><span style="color: #D4D4D4">                 </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> emp.deptno = dept.deptno</span></span>
<span class="line"><span style="color: #D4D4D4">             )</span></span>
<span class="line"><span style="color: #D4D4D4">       }</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept </span><span style="color: #569CD6">with</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">update</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">delete</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_serialize(data </span><span style="color: #569CD6">returning</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">clob</span><span style="color: #D4D4D4"> pretty) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_dv dv</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> dv.data.</span><span style="color: #CE9178">&quot;_id&quot;</span><span style="color: #D4D4D4">.numberOnly() </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">40</span><span style="color: #D4D4D4">);</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Json DUALITY created.


DATA
------------------------------------------------
{
  &quot;_id&quot; : 20,
  &quot;_metadata&quot; :
  {
    &quot;etag&quot; : &quot;88A4A9648C2CA1752E477545DCA85FD3&quot;,
    &quot;asof&quot; : &quot;00002565300350E5&quot;
  },
  &quot;dname&quot; : &quot;RESEARCH&quot;,
  &quot;loc&quot; : &quot;DALLAS&quot;,
  &quot;emps&quot; :
  [
    {
      &quot;empno&quot; : 7369,
      &quot;ename&quot; : &quot;SMITH&quot;,
      &quot;job&quot; : &quot;CLERK&quot;,
      &quot;mgr&quot; : 7902,
      &quot;mgrname&quot; : &quot;FORD&quot;,
      &quot;hiredate&quot; : &quot;1980-12-17T00:00:00&quot;,
      &quot;sal&quot; : 800,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7566,
      &quot;ename&quot; : &quot;JONES&quot;,
      &quot;job&quot; : &quot;MANAGER&quot;,
      &quot;mgr&quot; : 7839,
      &quot;mgrname&quot; : &quot;KING&quot;,
      &quot;hiredate&quot; : &quot;1981-04-02T00:00:00&quot;,
      &quot;sal&quot; : 2975,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7788,
      &quot;ename&quot; : &quot;SCOTT&quot;,
      &quot;job&quot; : &quot;ANALYST&quot;,
      &quot;mgr&quot; : 7566,
      &quot;mgrname&quot; : &quot;JONES&quot;,
      &quot;hiredate&quot; : &quot;1987-04-19T00:00:00&quot;,
      &quot;sal&quot; : 3000,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7876,
      &quot;ename&quot; : &quot;ADAMS&quot;,
      &quot;job&quot; : &quot;CLERK&quot;,
      &quot;mgr&quot; : 7788,
      &quot;mgrname&quot; : &quot;SCOTT&quot;,
      &quot;hiredate&quot; : &quot;1987-05-23T00:00:00&quot;,
      &quot;sal&quot; : 1100,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7902,
      &quot;ename&quot; : &quot;FORD&quot;,
      &quot;job&quot; : &quot;ANALYST&quot;,
      &quot;mgr&quot; : 7566,
      &quot;mgrname&quot; : &quot;JONES&quot;,
      &quot;hiredate&quot; : &quot;1981-12-03T00:00:00&quot;,
      &quot;sal&quot; : 3000,
      &quot;comm&quot; : null
    }
  ]
}

{
  &quot;_id&quot; : 40,
  &quot;_metadata&quot; :
  {
    &quot;etag&quot; : &quot;28E9C49240CD26A29FDED7B253A38ED7&quot;,
    &quot;asof&quot; : &quot;00002565300350E5&quot;
  },
  &quot;dname&quot; : &quot;OPERATIONS&quot;,
  &quot;loc&quot; : &quot;BOSTON&quot;,
  &quot;emps&quot; :
  [
  ]
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Json DUALITY created.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">DATA</span></span>
<span class="line"><span style="color: #D4D4D4">------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_id&quot; : 20,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_metadata&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;etag&quot; : &quot;88A4A9648C2CA1752E477545DCA85FD3&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;asof&quot; : &quot;00002565300350E5&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;dname&quot; : &quot;RESEARCH&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;loc&quot; : &quot;DALLAS&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;emps&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  [</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7369,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;SMITH&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;CLERK&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7902,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;FORD&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1980-12-17T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 800,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7566,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;JONES&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;MANAGER&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7839,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;KING&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1981-04-02T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 2975,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7788,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;SCOTT&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;ANALYST&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7566,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;JONES&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1987-04-19T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 3000,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7876,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;ADAMS&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;CLERK&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7788,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;SCOTT&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1987-05-23T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 1100,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7902,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;FORD&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;ANALYST&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7566,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;JONES&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1981-12-03T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 3000,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">  ]</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_id&quot; : 40,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_metadata&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;etag&quot; : &quot;28E9C49240CD26A29FDED7B253A38ED7&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;asof&quot; : &quot;00002565300350E5&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;dname&quot; : &quot;OPERATIONS&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;loc&quot; : &quot;BOSTON&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;emps&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  [</span></span>
<span class="line"><span style="color: #D4D4D4">  ]</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p>Since the <code>ext</code> column in the <code>dept</code> and <code>emp</code> table is empty for all rows, we do not see any additional fields in the two JSON documents. </p>



<p>Due to the <code>unest</code> clause in line 14, the fields <code>mgr</code> and <code>mgrname</code> appear on the same level as all other fields of the table <code>emp</code>.</p>



<h2 class="wp-block-heading" id="updateable-duality-view-using-graphql">5. Updateable Duality View Using GraphQL</h2>



<p>The next duality view is equivalent to the one in the previous chapter.</p>



<p>The highlighted lines with annotations match the highlighted clauses in the previous statement.</p>



<p>GraphQL requires a model for a query. The Oracle implementation uses tables, primary, and foreign keys to build the underlying model.</p>



<h5 class="wp-block-heading">Some explanations</h5>



<ul class="wp-block-list">
<li>In line 2, we use the <code>dept</code> table as root. For select, insert, update and delete. This means we get a JSON document per department.</li>



<li>In line 8, we use the <code>emp</code> table for the field <code>emps</code>. We expect an array of objects. However, we do not have to tell that explicitly. The Oracle Database will figure that out. There is just one relationship between <code>dept</code> and <code>emp</code>. Therefore it is clear how to join the tables and access the data. For select, insert, update and delete.</li>



<li>In line 13, we use the <code>emp</code> table for the fields <code>mgr</code> and <code>mgrname</code>. The access is possible via the foreign keys <code>emp_mgr_fk</code> and <code>emp_deptno_fk</code>. We know that it is <code>emp_mgr_fk</code> but the Oracle Database does not. We have to tell it. We do that with the <code>@link(from: [mgr])</code> annotation, to use the <code>mgr</code> field for the recursive join. An update of <code>mgrname</code> is not allowed (it is read-only by default). An update of <code>mgr</code> is allowed (it will update the foreign key column in <code>emp</code>).</li>
</ul>



<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">5) Updateable duality view using GraphQL</span><span role="button" tabindex="0" data-code="create or replace json duality view dept_dv as
dept @insert @update @delete
{
   _id: deptno
   dname
   loc
   ext @flex
   emps: emp @insert @update @delete
      {
         empno
         ename
         job
         emp @unnest @link(from: [mgr])
            {
               mgr    : empno @nocheck
               mgrname: ename @nocheck
            }
         hiredate
         sal
         comm
         ext @flex
      }
};

select json_serialize(data returning clob pretty) as data
  from dept_dv dv
 where dv.data.&quot;_id&quot;.numberOnly() in (20, 40);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> json duality </span><span style="color: #569CD6">view</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">as</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">dept @</span><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> @</span><span style="color: #569CD6">update</span><span style="color: #D4D4D4"> @</span><span style="color: #569CD6">delete</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">   _id: deptno</span></span>
<span class="line"><span style="color: #D4D4D4">   dname</span></span>
<span class="line"><span style="color: #D4D4D4">   loc</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   ext @flex</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   emps: emp @</span><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> @</span><span style="color: #569CD6">update</span><span style="color: #D4D4D4"> @</span><span style="color: #569CD6">delete</span></span>
<span class="line"><span style="color: #D4D4D4">      {</span></span>
<span class="line"><span style="color: #D4D4D4">         empno</span></span>
<span class="line"><span style="color: #D4D4D4">         ename</span></span>
<span class="line"><span style="color: #D4D4D4">         job</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         emp @unnest @link(</span><span style="color: #569CD6">from</span><span style="color: #D4D4D4">: [mgr])</span></span>
<span class="line"><span style="color: #D4D4D4">            {</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">               mgr    : empno @nocheck</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">               mgrname: ename @nocheck</span></span>
<span class="line"><span style="color: #D4D4D4">            }</span></span>
<span class="line"><span style="color: #D4D4D4">         hiredate</span></span>
<span class="line"><span style="color: #D4D4D4">         sal</span></span>
<span class="line"><span style="color: #D4D4D4">         comm</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         ext @flex</span></span>
<span class="line"><span style="color: #D4D4D4">      }</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_serialize(data </span><span style="color: #569CD6">returning</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">clob</span><span style="color: #D4D4D4"> pretty) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_dv dv</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> dv.data.</span><span style="color: #CE9178">&quot;_id&quot;</span><span style="color: #D4D4D4">.numberOnly() </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> (</span><span style="color: #B5CEA8">20</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">40</span><span style="color: #D4D4D4">);</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Json DUALITY created.


DATA
------------------------------------------------
{
  &quot;_id&quot; : 20,
  &quot;_metadata&quot; :
  {
    &quot;etag&quot; : &quot;88A4A9648C2CA1752E477545DCA85FD3&quot;,
    &quot;asof&quot; : &quot;00002565301D6D5C&quot;
  },
  &quot;dname&quot; : &quot;RESEARCH&quot;,
  &quot;loc&quot; : &quot;DALLAS&quot;,
  &quot;emps&quot; :
  [
    {
      &quot;empno&quot; : 7369,
      &quot;ename&quot; : &quot;SMITH&quot;,
      &quot;job&quot; : &quot;CLERK&quot;,
      &quot;mgr&quot; : 7902,
      &quot;mgrname&quot; : &quot;FORD&quot;,
      &quot;hiredate&quot; : &quot;1980-12-17T00:00:00&quot;,
      &quot;sal&quot; : 800,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7566,
      &quot;ename&quot; : &quot;JONES&quot;,
      &quot;job&quot; : &quot;MANAGER&quot;,
      &quot;mgr&quot; : 7839,
      &quot;mgrname&quot; : &quot;KING&quot;,
      &quot;hiredate&quot; : &quot;1981-04-02T00:00:00&quot;,
      &quot;sal&quot; : 2975,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7788,
      &quot;ename&quot; : &quot;SCOTT&quot;,
      &quot;job&quot; : &quot;ANALYST&quot;,
      &quot;mgr&quot; : 7566,
      &quot;mgrname&quot; : &quot;JONES&quot;,
      &quot;hiredate&quot; : &quot;1987-04-19T00:00:00&quot;,
      &quot;sal&quot; : 3000,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7876,
      &quot;ename&quot; : &quot;ADAMS&quot;,
      &quot;job&quot; : &quot;CLERK&quot;,
      &quot;mgr&quot; : 7788,
      &quot;mgrname&quot; : &quot;SCOTT&quot;,
      &quot;hiredate&quot; : &quot;1987-05-23T00:00:00&quot;,
      &quot;sal&quot; : 1100,
      &quot;comm&quot; : null
    },
    {
      &quot;empno&quot; : 7902,
      &quot;ename&quot; : &quot;FORD&quot;,
      &quot;job&quot; : &quot;ANALYST&quot;,
      &quot;mgr&quot; : 7566,
      &quot;mgrname&quot; : &quot;JONES&quot;,
      &quot;hiredate&quot; : &quot;1981-12-03T00:00:00&quot;,
      &quot;sal&quot; : 3000,
      &quot;comm&quot; : null
    }
  ]
}

{
  &quot;_id&quot; : 40,
  &quot;_metadata&quot; :
  {
    &quot;etag&quot; : &quot;28E9C49240CD26A29FDED7B253A38ED7&quot;,
    &quot;asof&quot; : &quot;00002565301D6D5C&quot;
  },
  &quot;dname&quot; : &quot;OPERATIONS&quot;,
  &quot;loc&quot; : &quot;BOSTON&quot;,
  &quot;emps&quot; :
  [
  ]
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Json DUALITY created.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">DATA</span></span>
<span class="line"><span style="color: #D4D4D4">------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_id&quot; : 20,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_metadata&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;etag&quot; : &quot;88A4A9648C2CA1752E477545DCA85FD3&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;asof&quot; : &quot;00002565301D6D5C&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;dname&quot; : &quot;RESEARCH&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;loc&quot; : &quot;DALLAS&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;emps&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  [</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7369,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;SMITH&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;CLERK&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7902,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;FORD&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1980-12-17T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 800,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7566,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;JONES&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;MANAGER&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7839,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;KING&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1981-04-02T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 2975,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7788,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;SCOTT&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;ANALYST&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7566,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;JONES&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1987-04-19T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 3000,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7876,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;ADAMS&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;CLERK&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7788,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;SCOTT&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1987-05-23T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 1100,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7902,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;FORD&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;ANALYST&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 7566,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;JONES&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1981-12-03T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 3000,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">  ]</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_id&quot; : 40,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_metadata&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;etag&quot; : &quot;28E9C49240CD26A29FDED7B253A38ED7&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;asof&quot; : &quot;00002565301D6D5C&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;dname&quot; : &quot;OPERATIONS&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;loc&quot; : &quot;BOSTON&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;emps&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  [</span></span>
<span class="line"><span style="color: #D4D4D4">  ]</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p>The result is the same as for the variant based on <code>select</code>. The only difference is the <code>asof</code> fields, which is expected.</p>



<h2 class="wp-block-heading" id="graphql-vs-select">6. GraphQL vs. SELECT</h2>



<p>What I like about the GraphQL variant is that the syntax is simple. It looks similar to the result document and is easy to read. No compromises due to feature parity. I run less risk of trying SQL expressions that are not applicable in a duality view.  The downside is that the definition might become ambiguous when extending the model with additional foreign key relationships. You might need to add <code>@link</code> annotations to your existing duality views to successfully recreate them. The variant using <code>select</code> cannot become ambiguous. There is no default join logic in SQL yet.</p>



<p>However, writing complex duality views might be easier with the variant using <code>select</code>. I can temporarily comment out all duality-view-specific clauses to make the <code>select</code> part work as a standalone statement until I&#8217;m happy with the result.</p>



<p>From a performance point of view, it should theoretically not matter which syntax variant you use. Any duality view can be built on GraphQL or <code>select</code>. The optimizer has all the information it needs to produce an optimal execution plan for both variants. I see no reason why the internal representation should differ.</p>



<p>Maybe a future version of the Oracle Database will offer options to generate the preferred syntax variant independently of the originally deployed variant. By extending <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/arpls/DBMS_METADATA.html#GUID-A4683EEE-6F54-4081-B7BF-1496096675FA">dbms_metadata.get_ddl</a>, for example.</p>



<h2 class="wp-block-heading" id="insert-into-duality-view">7. Insert Into Duality View</h2>



<p>Here&#8217;s an example of inserting a JSON document with one department and two employees into the previously created duality view. </p>



<h5 class="wp-block-heading">Some explanations</h5>



<ul class="wp-block-list">
<li>In line 6, we populate a department field named <code>secret</code> with the boolean value <code>true</code>. This field does not exist in the model. Therefore it will be stored in the <code>ext</code> column of the <code>dept</code> table.</li>



<li>In line 13, we set the <code>mgr</code> field to <code>1</code>. That&#8217;s the foreign key column in the <code>emp</code> table.</li>



<li>In line 16 we populate an employee field named <code>tools</code> with an array. The field does not exist in the model. Therefore it will be stored in the <code>ext</code> column of the <code>emp</code> table.   </li>
</ul>



<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">7) Insert into duality view (extending the schema)</span><span role="button" tabindex="0" data-code="insert into dept_dv values ('
{
  &quot;_id&quot; : 50,
  &quot;dname&quot; : &quot;MI6&quot;,
  &quot;loc&quot; : &quot;LONDON&quot;,
  &quot;secret&quot; : true,
  &quot;emps&quot; :
  [
    {
      &quot;empno&quot; : 7,
      &quot;ename&quot; : &quot;BOND&quot;,
      &quot;job&quot; : &quot;AGENT&quot;,
      &quot;mgr&quot; : 1,
      &quot;hiredate&quot; : &quot;1950-01-01T00:00:00&quot;,
      &quot;sal&quot; : 500,
      &quot;tools&quot; : [&quot;Knife&quot;, &quot;Garrote Watch&quot;, &quot;Walther PPK&quot;]
    },
    {
      &quot;empno&quot; : 1,
      &quot;ename&quot; : &quot;M&quot;,
      &quot;job&quot; : &quot;MANAGER&quot;,
      &quot;hiredate&quot; : &quot;1940-01-01T00:00:00&quot;,
      &quot;sal&quot; : 1000,
      &quot;comm&quot; : 8000
    }
  ]
}
');
commit;

select * from dept where deptno = 50;
select * from emp where deptno = 50;
select json_serialize(data returning clob pretty) as data 
  from dept_dv dv
 where dv.data.secret.booleanOnly();" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> dept_dv </span><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> (</span><span style="color: #CE9178">&#39;</span></span>
<span class="line"><span style="color: #CE9178">{</span></span>
<span class="line"><span style="color: #CE9178">  &quot;_id&quot; : 50,</span></span>
<span class="line"><span style="color: #CE9178">  &quot;dname&quot; : &quot;MI6&quot;,</span></span>
<span class="line"><span style="color: #CE9178">  &quot;loc&quot; : &quot;LONDON&quot;,</span></span>
<span class="line cbp-line-highlight"><span style="color: #CE9178">  &quot;secret&quot; : true,</span></span>
<span class="line"><span style="color: #CE9178">  &quot;emps&quot; :</span></span>
<span class="line"><span style="color: #CE9178">  [</span></span>
<span class="line"><span style="color: #CE9178">    {</span></span>
<span class="line"><span style="color: #CE9178">      &quot;empno&quot; : 7,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;ename&quot; : &quot;BOND&quot;,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;job&quot; : &quot;AGENT&quot;,</span></span>
<span class="line cbp-line-highlight"><span style="color: #CE9178">      &quot;mgr&quot; : 1,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;hiredate&quot; : &quot;1950-01-01T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;sal&quot; : 500,</span></span>
<span class="line cbp-line-highlight"><span style="color: #CE9178">      &quot;tools&quot; : [&quot;Knife&quot;, &quot;Garrote Watch&quot;, &quot;Walther PPK&quot;]</span></span>
<span class="line"><span style="color: #CE9178">    },</span></span>
<span class="line"><span style="color: #CE9178">    {</span></span>
<span class="line"><span style="color: #CE9178">      &quot;empno&quot; : 1,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;ename&quot; : &quot;M&quot;,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;job&quot; : &quot;MANAGER&quot;,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;hiredate&quot; : &quot;1940-01-01T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;sal&quot; : 1000,</span></span>
<span class="line"><span style="color: #CE9178">      &quot;comm&quot; : 8000</span></span>
<span class="line"><span style="color: #CE9178">    }</span></span>
<span class="line"><span style="color: #CE9178">  ]</span></span>
<span class="line"><span style="color: #CE9178">}</span></span>
<span class="line"><span style="color: #CE9178">&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> deptno = </span><span style="color: #B5CEA8">50</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> deptno = </span><span style="color: #B5CEA8">50</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_serialize(data </span><span style="color: #569CD6">returning</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">clob</span><span style="color: #D4D4D4"> pretty) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_dv dv</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> dv.data.secret.booleanOnly();</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(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 role="button" tabindex="0" data-code="1 row inserted.


Commit complete.


    DEPTNO DNAME          LOC           EXT
---------- -------------- ------------- --------------------
        50 MI6            LONDON        {&quot;secret&quot;:true}


     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO EXT
---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ---------------------------------------------------
         1 M          MANAGER              1940-01-01       1000       8000         50
         7 BOND       AGENT              1 1950-01-01        500                    50 {&quot;tools&quot;:[&quot;Knife&quot;,&quot;Garrote Watch&quot;,&quot;Walther PPK&quot;]}


DATA
------------------------------------------------
{
  &quot;_id&quot; : 50,
  &quot;_metadata&quot; :
  {
    &quot;etag&quot; : &quot;486256AA33D638F4D339FFE534EC910F&quot;,
    &quot;asof&quot; : &quot;0000256530950ADB&quot;
  },
  &quot;dname&quot; : &quot;MI6&quot;,
  &quot;loc&quot; : &quot;LONDON&quot;,
  &quot;emps&quot; :
  [
    {
      &quot;empno&quot; : 1,
      &quot;ename&quot; : &quot;M&quot;,
      &quot;job&quot; : &quot;MANAGER&quot;,
      &quot;hiredate&quot; : &quot;1940-01-01T00:00:00&quot;,
      &quot;sal&quot; : 1000,
      &quot;comm&quot; : 8000
    },
    {
      &quot;empno&quot; : 7,
      &quot;ename&quot; : &quot;BOND&quot;,
      &quot;job&quot; : &quot;AGENT&quot;,
      &quot;mgr&quot; : 1,
      &quot;mgrname&quot; : &quot;M&quot;,
      &quot;hiredate&quot; : &quot;1950-01-01T00:00:00&quot;,
      &quot;sal&quot; : 500,
      &quot;comm&quot; : null,
      &quot;tools&quot; :
      [
        &quot;Knife&quot;,
        &quot;Garrote Watch&quot;,
        &quot;Walther PPK&quot;
      ]
    }
  ],
  &quot;secret&quot; : true
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">1 row inserted.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Commit complete.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">    DEPTNO DNAME          LOC           EXT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- -------------- ------------- --------------------</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        50 MI6            LONDON        {&quot;secret&quot;:true}</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO EXT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ---------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">         1 M          MANAGER              1940-01-01       1000       8000         50</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">         7 BOND       AGENT              1 1950-01-01        500                    50 {&quot;tools&quot;:[&quot;Knife&quot;,&quot;Garrote Watch&quot;,&quot;Walther PPK&quot;]}</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">DATA</span></span>
<span class="line"><span style="color: #D4D4D4">------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_id&quot; : 50,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_metadata&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;etag&quot; : &quot;486256AA33D638F4D339FFE534EC910F&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;asof&quot; : &quot;0000256530950ADB&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;dname&quot; : &quot;MI6&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;loc&quot; : &quot;LONDON&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;emps&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  [</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 1,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;M&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;MANAGER&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1940-01-01T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 1000,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : 8000</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;BOND&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;AGENT&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 1,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;M&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1950-01-01T00:00:00&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;sal&quot; : 500,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      &quot;tools&quot; :</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      [</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        &quot;Knife&quot;,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        &quot;Garrote Watch&quot;,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        &quot;Walther PPK&quot;</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      ]</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">  ],</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  &quot;secret&quot; : true</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<p>One insert statement leads to three new rows in two tables. Before 23ai, a view and an instead-of trigger would have been required for this.</p>



<p>The fields <code>secret</code> and <code>tools</code> are automatically stored in the flex columns <code>ext</code>. This shows how easy it is to extend the data model on the fly with an <code>insert</code> statement. Without DDL statements. Without PL/SQL code.</p>



<h2 class="wp-block-heading" id="update-duality-view">8. Update Duality View</h2>



<p>Let&#8217;s update the previously created document.</p>



<h5 class="wp-block-heading">Some explanations</h5>



<ul class="wp-block-list">
<li>In line 4, we add a new field named <code>street</code> for the department <code>50</code>.</li>



<li>In line 6, we change the salary for all employees in the department <code>50</code> by the factor of <code>42</code>.</li>



<li>In line 9, we increase the salary of <code>BOND</code> by <code>1</code>. Please note that this is the second change of the salary for this employee in this <code>update</code> statement.</li>



<li>In line 10, we append the <code>Aston Martin DB5</code> to the list of <code>BOND</code>&#8216;s tools.</li>
</ul>



<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">8) Update duality view (extending the schema again)</span><span role="button" tabindex="0" data-code="update dept_dv v
   set v.data = json_transform(
                   v.data, 
                   set '$.street' = '85 Albert Embankment',
                   nested '$.emps[*]' (
                      set '@.sal' = path '@.sal * 42'
                   ),
                   nested '$.emps[*]?(@.ename == &quot;BOND&quot;)' (
                      set '@.sal' = path '@.sal + 1',
                      append '@.tools' = 'Aston Martin DB5'
                   )
                )
 where v.data.&quot;_id&quot;.numberOnly() = 50;
commit;

select * from dept where deptno = 50;
select * from emp where deptno = 50;
select json_serialize(data returning clob pretty) as data 
  from dept_dv v
 where v.data.&quot;_id&quot;.numberOnly() = 50;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">update</span><span style="color: #D4D4D4"> dept_dv v</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> v.data = json_transform(</span></span>
<span class="line"><span style="color: #D4D4D4">                   v.data, </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                   </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;$.street&#39;</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&#39;85 Albert Embankment&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">                   nested </span><span style="color: #CE9178">&#39;$.emps[*]&#39;</span><span style="color: #D4D4D4"> (</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;@.sal&#39;</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">path</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;@.sal * 42&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                   ),</span></span>
<span class="line"><span style="color: #D4D4D4">                   nested </span><span style="color: #CE9178">&#39;$.emps[*]?(@.ename == &quot;BOND&quot;)&#39;</span><span style="color: #D4D4D4"> (</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                      </span><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;@.sal&#39;</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">path</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;@.sal + 1&#39;</span><span style="color: #D4D4D4">,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                      append </span><span style="color: #CE9178">&#39;@.tools&#39;</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&#39;Aston Martin DB5&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">                   )</span></span>
<span class="line"><span style="color: #D4D4D4">                )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> v.data.</span><span style="color: #CE9178">&quot;_id&quot;</span><span style="color: #D4D4D4">.numberOnly() = </span><span style="color: #B5CEA8">50</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> deptno = </span><span style="color: #B5CEA8">50</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> deptno = </span><span style="color: #B5CEA8">50</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> json_serialize(data </span><span style="color: #569CD6">returning</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">clob</span><span style="color: #D4D4D4"> pretty) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> data </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept_dv v</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> v.data.</span><span style="color: #CE9178">&quot;_id&quot;</span><span style="color: #D4D4D4">.numberOnly() = </span><span style="color: #B5CEA8">50</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(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 role="button" tabindex="0" data-code="1 row updated.


Commit complete.


    DEPTNO DNAME          LOC           EXT
---------- -------------- ------------- -----------------------------------------------
        50 MI6            LONDON        {&quot;secret&quot;:true,&quot;street&quot;:&quot;85 Albert Embankment&quot;}


     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO EXT
---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ----------------------------------------------------------------------
         1 M          MANAGER              1940-01-01      42000       8000         50
         7 BOND       AGENT              1 1950-01-01      21001                    50 {&quot;tools&quot;:[&quot;Knife&quot;,&quot;Garrote Watch&quot;,&quot;Walther PPK&quot;,&quot;Aston Martin DB5&quot;]}


DATA
------------------------------------------------
{
  &quot;_id&quot; : 50,
  &quot;_metadata&quot; :
  {
    &quot;etag&quot; : &quot;1591A6C3A20C4BC85C0498F7B1F4031F&quot;,
    &quot;asof&quot; : &quot;000025653374F0C7&quot;
  },
  &quot;dname&quot; : &quot;MI6&quot;,
  &quot;loc&quot; : &quot;LONDON&quot;,
  &quot;emps&quot; :
  [
    {
      &quot;empno&quot; : 1,
      &quot;ename&quot; : &quot;M&quot;,
      &quot;job&quot; : &quot;MANAGER&quot;,
      &quot;hiredate&quot; : &quot;1940-01-01T00:00:00&quot;,
      &quot;sal&quot; : 42000,
      &quot;comm&quot; : 8000
    },
    {
      &quot;empno&quot; : 7,
      &quot;ename&quot; : &quot;BOND&quot;,
      &quot;job&quot; : &quot;AGENT&quot;,
      &quot;mgr&quot; : 1,
      &quot;mgrname&quot; : &quot;M&quot;,
      &quot;hiredate&quot; : &quot;1950-01-01T00:00:00&quot;,
      &quot;sal&quot; : 21001,
      &quot;comm&quot; : null,
      &quot;tools&quot; :
      [
        &quot;Knife&quot;,
        &quot;Garrote Watch&quot;,
        &quot;Walther PPK&quot;,
        &quot;Aston Martin DB5&quot;
      ]
    }
  ],
  &quot;secret&quot; : true,
  &quot;street&quot; : &quot;85 Albert Embankment&quot;
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">1 row updated.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Commit complete.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">    DEPTNO DNAME          LOC           EXT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- -------------- ------------- -----------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">        50 MI6            LONDON        {&quot;secret&quot;:true,&quot;street&quot;:&quot;85 Albert Embankment&quot;}</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO EXT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ----------------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">         1 M          MANAGER              1940-01-01      42000       8000         50</span></span>
<span class="line"><span style="color: #D4D4D4">         7 BOND       AGENT              1 1950-01-01      21001                    50 {&quot;tools&quot;:[&quot;Knife&quot;,&quot;Garrote Watch&quot;,&quot;Walther PPK&quot;,&quot;Aston Martin DB5&quot;]}</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">DATA</span></span>
<span class="line"><span style="color: #D4D4D4">------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">{</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_id&quot; : 50,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;_metadata&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  {</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;etag&quot; : &quot;1591A6C3A20C4BC85C0498F7B1F4031F&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">    &quot;asof&quot; : &quot;000025653374F0C7&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;dname&quot; : &quot;MI6&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;loc&quot; : &quot;LONDON&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;emps&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">  [</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 1,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;M&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;MANAGER&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1940-01-01T00:00:00&quot;,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      &quot;sal&quot; : 42000,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : 8000</span></span>
<span class="line"><span style="color: #D4D4D4">    },</span></span>
<span class="line"><span style="color: #D4D4D4">    {</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;empno&quot; : 7,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;ename&quot; : &quot;BOND&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;job&quot; : &quot;AGENT&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgr&quot; : 1,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;mgrname&quot; : &quot;M&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;hiredate&quot; : &quot;1950-01-01T00:00:00&quot;,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">      &quot;sal&quot; : 21001,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;comm&quot; : null,</span></span>
<span class="line"><span style="color: #D4D4D4">      &quot;tools&quot; :</span></span>
<span class="line"><span style="color: #D4D4D4">      [</span></span>
<span class="line"><span style="color: #D4D4D4">        &quot;Knife&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">        &quot;Garrote Watch&quot;,</span></span>
<span class="line"><span style="color: #D4D4D4">        &quot;Walther PPK&quot;,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">        &quot;Aston Martin DB5&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">      ]</span></span>
<span class="line"><span style="color: #D4D4D4">    }</span></span>
<span class="line"><span style="color: #D4D4D4">  ],</span></span>
<span class="line"><span style="color: #D4D4D4">  &quot;secret&quot; : true,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  &quot;street&quot; : &quot;85 Albert Embankment&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<h2 class="wp-block-heading" id="delete-from-duality-view">9. Delete From Duality View</h2>



<p>And now, let&#8217;s delete department 50 with all its employees to restore the original content of the <code>dept</code> and <code>emp</code> tables.</p>



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

select * from dept order by deptno;
select * from emp order by deptno, empno;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">delete</span><span style="color: #D4D4D4"> dept_dv v</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> v.data.</span><span style="color: #CE9178">&quot;_id&quot;</span><span style="color: #D4D4D4">.numberOnly() = </span><span style="color: #B5CEA8">50</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> dept </span><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> deptno;</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> deptno, empno;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(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 role="button" tabindex="0" data-code="1 row deleted.


Commit complete.


    DEPTNO DNAME          LOC           EXT
---------- -------------- ------------- --------------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON


     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO EXT
---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- --------------------
      7782 CLARK      MANAGER         7839 1981-06-09       2450                    10
      7839 KING       PRESIDENT            1981-11-17       5000                    10
      7934 MILLER     CLERK           7782 1982-01-23       1300                    10
      7369 SMITH      CLERK           7902 1980-12-17        800                    20
      7566 JONES      MANAGER         7839 1981-04-02       2975                    20
      7788 SCOTT      ANALYST         7566 1987-04-19       3000                    20
      7876 ADAMS      CLERK           7788 1987-05-23       1100                    20
      7902 FORD       ANALYST         7566 1981-12-03       3000                    20
      7499 ALLEN      SALESMAN        7698 1981-02-20       1600        300         30
      7521 WARD       SALESMAN        7698 1981-02-22       1250        500         30
      7654 MARTIN     SALESMAN        7698 1981-09-28       1250       1400         30
      7698 BLAKE      MANAGER         7839 1981-05-01       2850                    30
      7844 TURNER     SALESMAN        7698 1981-09-08       1500          0         30
      7900 JAMES      CLERK           7698 1981-12-03        950                    30

14 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">1 row deleted.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Commit complete.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">    DEPTNO DNAME          LOC           EXT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- -------------- ------------- --------------------</span></span>
<span class="line"><span style="color: #D4D4D4">        10 ACCOUNTING     NEW YORK</span></span>
<span class="line"><span style="color: #D4D4D4">        20 RESEARCH       DALLAS</span></span>
<span class="line"><span style="color: #D4D4D4">        30 SALES          CHICAGO</span></span>
<span class="line"><span style="color: #D4D4D4">        40 OPERATIONS     BOSTON</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO EXT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- --------------------</span></span>
<span class="line"><span style="color: #D4D4D4">      7782 CLARK      MANAGER         7839 1981-06-09       2450                    10</span></span>
<span class="line"><span style="color: #D4D4D4">      7839 KING       PRESIDENT            1981-11-17       5000                    10</span></span>
<span class="line"><span style="color: #D4D4D4">      7934 MILLER     CLERK           7782 1982-01-23       1300                    10</span></span>
<span class="line"><span style="color: #D4D4D4">      7369 SMITH      CLERK           7902 1980-12-17        800                    20</span></span>
<span class="line"><span style="color: #D4D4D4">      7566 JONES      MANAGER         7839 1981-04-02       2975                    20</span></span>
<span class="line"><span style="color: #D4D4D4">      7788 SCOTT      ANALYST         7566 1987-04-19       3000                    20</span></span>
<span class="line"><span style="color: #D4D4D4">      7876 ADAMS      CLERK           7788 1987-05-23       1100                    20</span></span>
<span class="line"><span style="color: #D4D4D4">      7902 FORD       ANALYST         7566 1981-12-03       3000                    20</span></span>
<span class="line"><span style="color: #D4D4D4">      7499 ALLEN      SALESMAN        7698 1981-02-20       1600        300         30</span></span>
<span class="line"><span style="color: #D4D4D4">      7521 WARD       SALESMAN        7698 1981-02-22       1250        500         30</span></span>
<span class="line"><span style="color: #D4D4D4">      7654 MARTIN     SALESMAN        7698 1981-09-28       1250       1400         30</span></span>
<span class="line"><span style="color: #D4D4D4">      7698 BLAKE      MANAGER         7839 1981-05-01       2850                    30</span></span>
<span class="line"><span style="color: #D4D4D4">      7844 TURNER     SALESMAN        7698 1981-09-08       1500          0         30</span></span>
<span class="line"><span style="color: #D4D4D4">      7900 JAMES      CLERK           7698 1981-12-03        950                    30</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">14 rows selected.</span></span></code></pre></div>



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



<p>One thing is missing in version 0.9 of IslandSQL grammar. The support of PL/pgSQL in PostgreSQL statements <code>create function</code>, <code>create procedure</code>, <code>create trigger</code> and <code>do</code>. These statements can already be parsed but the PL/pgSQL code passed as string is not further analyzed. This will change in the next and final episode of this season.</p>
<p>The post <a href="https://www.salvis.com/blog/2024/06/27/islandsql-episode-9-graphql-json-and-flexible-schemas-with-duality-views/">IslandSQL Episode 9: GraphQL, JSON and Flexible Schemas With Duality Views</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IslandSQL Episode 8: What&#8217;s New in Oracle Database 23.4?</title>
		<link>https://www.salvis.com/blog/2024/06/15/islandsql-episode-8-whats-new-in-oracle-database-23-4/</link>
					<comments>https://www.salvis.com/blog/2024/06/15/islandsql-episode-8-whats-new-in-oracle-database-23-4/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sat, 15 Jun 2024 18:45:43 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[ANTLR]]></category>
		<category><![CDATA[Code Analysis]]></category>
		<category><![CDATA[IslandSQL]]></category>
		<category><![CDATA[Oracle 26ai]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=13386</guid>

					<description><![CDATA[<p>Introduction In the last episode, we looked at some features in PostgreSQL which I miss in the Oracle Database. The IslandSQL grammar now covers PL/SQL and the related DDL statements. The implementation was more complex than expected, mainly because of the incompatibilities between PostgreSQL and the Oracle Database. I will probably deal<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2024/06/15/islandsql-episode-8-whats-new-in-oracle-database-23-4/">IslandSQL Episode 8: What&#8217;s New in Oracle Database 23.4?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>In the <a href="https://www.salvis.com/blog/2024/03/23/islandsql-episode-7-dml-statements-in-postgresql-16-and-what-i-miss-in-oracle-database-23c/">last episode</a>, we looked at some features in PostgreSQL which I miss in the Oracle Database. The <a href="https://github.com/IslandSQL/IslandSQL">IslandSQL</a> grammar now covers PL/SQL and the related DDL statements. The implementation was more complex than expected, mainly because of the incompatibilities between PostgreSQL and the Oracle Database. I will probably deal with this topic in a future blog post.</p>



<p>Now I&#8217;d like to talk about the new features in Oracle Database 23ai. Not about all features in the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/nfcoa/introduction.html#GUID-feature_highlights142">New Features Guide</a>, but only about some changes since the release of 23.3, which was known as 23c. It&#8217;s hard to find changes from 23.3 to 23.4 in the documentation. So, I guess it&#8217;s worth a blog post. I focus on the features that are relevant to the IslandSQL grammar. In other words, the interesting ones from a developer&#8217;s perspective.</p>



<h2 class="wp-block-heading">1. Vector Data Type</h2>



<p>A vector is a number array for which you can optionally define the number of dimensions (size) and the data type (int8, float32 or float64) of the dimension values. This data type is the basis for the vector search functionality.</p>



<p>Here&#8217;s a slightly amended example from the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/insert-vectors-database-table-using-insert-statement.html">documentation</a> creating and populating a table with a vector data type.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">1) Table with vector column</span><span role="button" tabindex="0" data-code="drop table if exists galaxies purge;
create table galaxies (
   id        number             not null primary key,
   name      varchar2(10 char)  not null unique,
   embedding vector(5, int8)    not null, -- 5 dimensions, stored as int8
   doc       varchar2(120 char) not null
);

insert into galaxies 
   (id, name, embedding, doc)
values 
   (1, 'M31',     '[0,2,2,0,0]', 'Messier 31 is a barred spiral galaxy in the Andromeda constellation which has a lot of barred spiral galaxies.'),
   (2, 'M33',     '[0,0,1,0,0]', 'Messier 33 is a spiral galaxy in the Triangulum constellation.'),
   (3, 'M58',     '[1,1,1,0,0]', 'Messier 58 is an intermediate barred spiral galaxy in the Virgo constellation.'),
   (4, 'M63',     '[0,0,1,0,0]', 'Messier 63 is a spiral galaxy in the Canes Venatici constellation.'),
   (5, 'M77',     '[0,1,1,0,0]', 'Messier 77 is a barred spiral galaxy in the Cetus constellation.'),
   (6, 'M91',     '[0,1,1,0,0]', 'Messier 91 is a barred spiral galaxy in the Coma Berenices constellation.'),
   (7, 'M49',     '[0,0,0,1,1]', 'Messier 49 is a giant elliptical galaxy in the Virgo constellation.'),
   (8, 'M60',     '[0,0,0,0,1]', 'Messier 60 is an elliptical galaxy in the Virgo constellation.'),
   (9, 'NGC1073', '[0,1,1,0,0]', 'NGC 1073 is a barred spiral galaxy in Cetus constellation.');
commit;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">drop</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">exists</span><span style="color: #D4D4D4"> galaxies purge;</span></span>
<span class="line"><span style="color: #569CD6">create</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">table</span><span style="color: #D4D4D4"> galaxies (</span></span>
<span class="line"><span style="color: #D4D4D4">   id        </span><span style="color: #569CD6">number</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">primary key</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">   </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">      </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 style="color: #569CD6">unique</span><span style="color: #D4D4D4">,</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   embedding vector(</span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">, int8)    </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: #6A9955">-- 5 dimensions, stored as int8</span></span>
<span class="line"><span style="color: #D4D4D4">   doc       </span><span style="color: #569CD6">varchar2</span><span style="color: #D4D4D4">(</span><span style="color: #B5CEA8">120</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>
<span class="line"><span style="color: #D4D4D4">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">insert</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">into</span><span style="color: #D4D4D4"> galaxies </span></span>
<span class="line"><span style="color: #D4D4D4">   (id, </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">, embedding, doc)</span></span>
<span class="line"><span style="color: #569CD6">values</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M31&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[0,2,2,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 31 is a barred spiral galaxy in the Andromeda constellation which has a lot of barred spiral galaxies.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M33&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[0,0,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 33 is a spiral galaxy in the Triangulum constellation.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M58&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[1,1,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 58 is an intermediate barred spiral galaxy in the Virgo constellation.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M63&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[0,0,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 63 is a spiral galaxy in the Canes Venatici constellation.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M77&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[0,1,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 77 is a barred spiral galaxy in the Cetus constellation.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">6</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M91&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[0,1,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 91 is a barred spiral galaxy in the Coma Berenices constellation.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">7</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M49&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[0,0,0,1,1]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 49 is a giant elliptical galaxy in the Virgo constellation.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;M60&#39;</span><span style="color: #D4D4D4">,     </span><span style="color: #CE9178">&#39;[0,0,0,0,1]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;Messier 60 is an elliptical galaxy in the Virgo constellation.&#39;</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">   (</span><span style="color: #B5CEA8">9</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;NGC1073&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;[0,1,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&#39;NGC 1073 is a barred spiral galaxy in Cetus constellation.&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #DCDCAA">commit</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<p>The vector in this example has 5 dimensions with the following meaning:</p>



<ol class="wp-block-list">
<li>Number of occurrences of <code>intermediate</code> in the <code>doc</code> column</li>



<li>Number of occurrences of <code>barred</code> in the <code>doc</code> column</li>



<li>Number of occurrences of <code>spiral</code> in the <code>doc</code> column</li>



<li>Number of occurrences of <code>giant</code> in the <code>doc</code> column</li>



<li>Number of occurrences of <code>elliptical</code> in the <code>doc</code> column</li>
</ol>



<h2 class="wp-block-heading">2. Vector Functions and PL/SQL Packages</h2>



<p>The <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_distance.html#GUID-BA4BCFB2-D905-43DC-87B0-E53522CF07B7">vector_distance</a> function is a key functionality for similarity searches. Let&#8217;s say we want to see galaxies that are similar to <code>NGC1073</code> (<code>barred</code> and <code>spiral</code>). The following query shows how vector functions can help to get this result:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">2) Different vector_distance metrics in action</span><span role="button" tabindex="0" data-code="with ngc1073 as (select vector('[0,1,1,0,0]', 5, int8) as query_vector)
select name, 
       round(vector_distance(embedding, query_vector, cosine), 3) as cosine_distance,
       round(vector_distance(embedding, query_vector, dot), 3) as inner_product,
       round(vector_distance(embedding, query_vector, euclidean), 3) as l2_distance,
       round(vector_distance(embedding, query_vector, euclidean_squared), 3) as l2_squared,
       round(vector_distance(embedding, query_vector, hamming), 3) as hamming_distance,
       round(vector_distance(embedding, query_vector, manhattan), 3) as l1_distance
  from galaxies, ngc1073
 order by cosine_distance;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">with</span><span style="color: #D4D4D4"> ngc1073 </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> vector(</span><span style="color: #CE9178">&#39;[0,1,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">, int8) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> query_vector)</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(vector_distance(embedding, query_vector, cosine), </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> cosine_distance,</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(vector_distance(embedding, query_vector, dot), </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> inner_product,</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(vector_distance(embedding, query_vector, euclidean), </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> l2_distance,</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(vector_distance(embedding, query_vector, euclidean_squared), </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> l2_squared,</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(vector_distance(embedding, query_vector, hamming), </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> hamming_distance,</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(vector_distance(embedding, query_vector, manhattan), </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> l1_distance</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> galaxies, ngc1073</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> cosine_distance;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="NAME       COSINE_DISTANCE INNER_PRODUCT L2_DISTANCE L2_SQUARED HAMMING_DISTANCE L1_DISTANCE
---------- --------------- ------------- ----------- ---------- ---------------- -----------
M31                      0            -4       1.414          2                2           2
M77                      0            -2           0          0                0           0
M91                      0            -2           0          0                0           0
NGC1073                  0            -2           0          0                0           0
M58                   .184            -2           1          1                1           1
M63                   .293            -1           1          1                1           1
M33                   .293            -1           1          1                1           1
M60                      1             0       1.732          3                3           3
M49                      1             0           2          4                4           4

9 rows selected." style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">NAME       COSINE_DISTANCE INNER_PRODUCT L2_DISTANCE L2_SQUARED HAMMING_DISTANCE L1_DISTANCE</span></span>
<span class="line"><span style="color: #D4D4D4">---------- --------------- ------------- ----------- ---------- ---------------- -----------</span></span>
<span class="line"><span style="color: #D4D4D4">M31                      0            -4       1.414          2                2           2</span></span>
<span class="line"><span style="color: #D4D4D4">M77                      0            -2           0          0                0           0</span></span>
<span class="line"><span style="color: #D4D4D4">M91                      0            -2           0          0                0           0</span></span>
<span class="line"><span style="color: #D4D4D4">NGC1073                  0            -2           0          0                0           0</span></span>
<span class="line"><span style="color: #D4D4D4">M58                   .184            -2           1          1                1           1</span></span>
<span class="line"><span style="color: #D4D4D4">M63                   .293            -1           1          1                1           1</span></span>
<span class="line"><span style="color: #D4D4D4">M33                   .293            -1           1          1                1           1</span></span>
<span class="line"><span style="color: #D4D4D4">M60                      1             0       1.732          3                3           3</span></span>
<span class="line"><span style="color: #D4D4D4">M49                      1             0           2          4                4           4</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">9 rows selected.</span></span></code></pre></div>



<p><code>M77</code> and <code>M91</code> have identical vectors and they are expected to be very similar. However, <code>M31</code> is interesting. It has a similar shape to <code>NGC1073</code> but the words <code>barred</code> and <code>spiral</code> appear twice. This is a good match only for some distance metrics.</p>



<p>A conventional query, e.g. based on Oracle Text might be good enough to find similar galaxies. However, if you have vectors with tons of dimensions then a vector similarity search might become appealing. Especially, since you can index vector columns to speed up your queries.</p>



<p>The following SQL functions are provided for the vector data type in the Oracle Database:</p>



<ul class="wp-block-list">
<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_chunks.html#GUID-5927E2FA-6419-4744-A7CB-3E62DBB027AD">vector_chunks</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector.html#GUID-8A63005B-5512-4D20-954C-7A9DA877FE4B">vector</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/to_vector.html#GUID-2CCAB607-A28B-43F7-A71D-9800C0B9A380">to_vector</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_dimension_count.html#GUID-C3D937E0-7F9F-4C21-A214-0CFA31472E67">vector_dimension_count</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_dims.html#GUID-010349D7-190D-430B-A798-ACC486E1036A">vector_dims</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_dimension_format.html#GUID-354ACE80-7120-4D45-B2B0-AB1D86E3D37D">vector_dimension_format</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_distance.html#GUID-BA4BCFB2-D905-43DC-87B0-E53522CF07B7">vector_distance</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/cosine_distance.html#GUID-2128DC1D-612A-444F-87D8-3D249CD8F12D">cosine_distance</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/inner_product.html#GUID-6AE745CF-93E7-4192-8F80-7B9853DF5B72">inner_product</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/l1_distance.html#GUID-604A5B68-10AF-48F3-A84F-ED0B90624059">l1_distance</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/l2_distance.html#GUID-2FD8BC27-7614-471F-A4F5-3ED52130A05A">l2_distance</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_embedding.html#GUID-5ED78260-6D21-4B6B-86E0-A1E70EFA11CA">vector_embedding</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_norm.html#GUID-41554068-9EB8-49E8-A771-4E666674DDA8">vector_norm</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/vector_serialize.html#GUID-9E3FFB34-F924-4C02-B35D-30B9FA1DA1A3">vector_serialize</a> or <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/from_vector.html#GUID-AA60B3CB-FCB7-4944-9E06-976C272855B1">from_vector</a></li>
</ul>



<p>Furthermore, the following supplied PL/SQL packages provide additional functionality related to the vector data type:</p>



<ul class="wp-block-list">
<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/arpls/dbms_vector1.html">dbms_vector</a></li>



<li><a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/arpls/dbms_vector_chain1.html">dbms_vector_chain</a></li>
</ul>



<h2 class="wp-block-heading">3. Shorthand Operators for Distances</h2>



<p>For some <code>vector_distance</code> metrics shorthand operators (<code>&lt;=&gt;</code>, <code>&lt;-&gt;</code>, <code>&lt;#&gt;</code>) are available. Here&#8217;s an example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">3) Shorthand operators for vector_distance metrics</span><span role="button" tabindex="0" data-code="with ngc1073 as (select vector('[0,1,1,0,0]', 5, int8) as query_vector)
select name, 
       round(embedding &lt;=&gt; query_vector, 3) as cosine_distance,
       round(embedding &lt;-&gt; query_vector, 3) as l2_distance,
       round(embedding &lt;#&gt; query_vector, 3) as inner_product
  from galaxies, ngc1073
 order by cosine_distance;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">with</span><span style="color: #D4D4D4"> ngc1073 </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> (</span><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> vector(</span><span style="color: #CE9178">&#39;[0,1,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">, int8) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> query_vector)</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">, </span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(embedding &lt;=&gt; query_vector, </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> cosine_distance,</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(embedding &lt;-&gt; query_vector, </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> l2_distance,</span></span>
<span class="line"><span style="color: #D4D4D4">       </span><span style="color: #DCDCAA">round</span><span style="color: #D4D4D4">(embedding &lt;#&gt; query_vector, </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> inner_product</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> galaxies, ngc1073</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> cosine_distance;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="NAME       COSINE_DISTANCE L2_DISTANCE INNER_PRODUCT
---------- --------------- ----------- -------------
M31                      0       1.414            -4
M77                      0           0            -2
M91                      0           0            -2
NGC1073                  0           0            -2
M58                   .184           1            -2
M63                   .293           1            -1
M33                   .293           1            -1
M60                      1       1.732             0
M49                      1           2             0

9 rows selected. " style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">NAME       COSINE_DISTANCE L2_DISTANCE INNER_PRODUCT</span></span>
<span class="line"><span style="color: #D4D4D4">---------- --------------- ----------- -------------</span></span>
<span class="line"><span style="color: #D4D4D4">M31                      0       1.414            -4</span></span>
<span class="line"><span style="color: #D4D4D4">M77                      0           0            -2</span></span>
<span class="line"><span style="color: #D4D4D4">M91                      0           0            -2</span></span>
<span class="line"><span style="color: #D4D4D4">NGC1073                  0           0            -2</span></span>
<span class="line"><span style="color: #D4D4D4">M58                   .184           1            -2</span></span>
<span class="line"><span style="color: #D4D4D4">M63                   .293           1            -1</span></span>
<span class="line"><span style="color: #D4D4D4">M33                   .293           1            -1</span></span>
<span class="line"><span style="color: #D4D4D4">M60                      1       1.732             0</span></span>
<span class="line"><span style="color: #D4D4D4">M49                      1           2             0</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">9 rows selected. </span></span></code></pre></div>



<p></p>



<h2 class="wp-block-heading">4. Approximate Similarity Searches</h2>



<p>You can imagine producing a top-N result of the previous queries using the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__BABBADDD">row_limiting_clause</a>. This clause was introduced in 12.1 to limit search results. Exactly to be precise. In 23.4 the clause was extended to support approximate similarity searches. The idea is to get a good enough result with a better performance when using vector indexes. Here&#8217;s an example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">4) Approximate Similarity Search</span><span role="button" tabindex="0" data-code="select name, embedding
  from galaxies
 order by embedding &lt;=&gt; vector('[0,1,1,0,0]', 5, int8)
 fetch approx first 3 rows only
  with target accuracy 80 percent;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">name</span><span style="color: #D4D4D4">, embedding</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> galaxies</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> embedding &lt;=&gt; vector(</span><span style="color: #CE9178">&#39;[0,1,1,0,0]&#39;</span><span style="color: #D4D4D4">, </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">, int8)</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">fetch</span><span style="color: #D4D4D4"> approx </span><span style="color: #DCDCAA">first</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4"> rows only</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">with</span><span style="color: #D4D4D4"> target accuracy </span><span style="color: #B5CEA8">80</span><span style="color: #D4D4D4"> percent;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="NAME       EMBEDDING           
---------- --------------------
M31        [0,2,2,0,0]         
M91        [0,1,1,0,0]         
M77        [0,1,1,0,0]         " style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">NAME       EMBEDDING           </span></span>
<span class="line"><span style="color: #D4D4D4">---------- --------------------</span></span>
<span class="line"><span style="color: #D4D4D4">M31        [0,2,2,0,0]         </span></span>
<span class="line"><span style="color: #D4D4D4">M91        [0,1,1,0,0]         </span></span>
<span class="line"><span style="color: #D4D4D4">M77        [0,1,1,0,0]         </span></span></code></pre></div>



<h2 class="wp-block-heading">5. Source and Destination Predicates in Graph Operator</h2>



<p>The graph operator is a new 23ai feature. In 23.4 it got two additional predicates: <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/value-expressions-graph_table.html#GUID-3CA85A62-A083-4D12-9EFE-CF127BD8A3CD__GUID-ECB7861E-F863-4CB5-AA28-A1AF76E5952F">source_predicate</a> and <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/value-expressions-graph_table.html#GUID-3CA85A62-A083-4D12-9EFE-CF127BD8A3CD__GUID-AB824BA8-ED46-41D3-A13E-A8A0C43ECB5C">destination_predicate</a>. It allows us to test if a vertex is a source or a destination of an edge. The direction of the arrow so to speak. Here&#8217;s a formatted example from the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/value-expressions-graph_table.html#GUID-3CA85A62-A083-4D12-9EFE-CF127BD8A3CD__GUID-BBAA8483-B9AE-4889-B463-D21850A6931E">documentation</a>, based on <a href="https://www.salvis.com/blog/2024/01/12/islandsql-episode-5-select/#graph-table-operator">this model</a>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">5) Source and destination predicates</span><span role="button" tabindex="0" data-code="select *
  from graph_table (students_graph
          match (p1 is person) -[e is friends]- (p2 is person)
          where p1.name = 'Mary'
          columns (
             e.friendship_id,
             e.meeting_date,
             case 
                when p1 is source of e then 
                   p1.name 
                else
                   p2.name 
             end as from_person,
             case 
                when p1 is destination of e then
                   p1.name
               else
                   p2.name 
             end as to_person
          )
       )
 order by friendship_id;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> *</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> graph_table (students_graph</span></span>
<span class="line"><span style="color: #D4D4D4">          match (p1 </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> person) -[e </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> friends]- (p2 </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> person)</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> p1.</span><span style="color: #569CD6">name</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&#39;Mary&#39;</span></span>
<span class="line"><span style="color: #D4D4D4">          columns (</span></span>
<span class="line"><span style="color: #D4D4D4">             e.friendship_id,</span></span>
<span class="line"><span style="color: #D4D4D4">             e.meeting_date,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #C586C0">case</span><span style="color: #D4D4D4"> </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">when</span><span style="color: #D4D4D4"> p1 </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> source </span><span style="color: #569CD6">of</span><span style="color: #D4D4D4"> e </span><span style="color: #569CD6">then</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">                   p1.</span><span style="color: #569CD6">name</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">                </span><span style="color: #C586C0">else</span></span>
<span class="line"><span style="color: #D4D4D4">                   p2.</span><span style="color: #569CD6">name</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">end</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> from_person,</span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #C586C0">case</span><span style="color: #D4D4D4"> </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">                </span><span style="color: #569CD6">when</span><span style="color: #D4D4D4"> p1 </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> destination </span><span style="color: #569CD6">of</span><span style="color: #D4D4D4"> e </span><span style="color: #569CD6">then</span></span>
<span class="line"><span style="color: #D4D4D4">                   p1.</span><span style="color: #569CD6">name</span></span>
<span class="line"><span style="color: #D4D4D4">               </span><span style="color: #C586C0">else</span></span>
<span class="line"><span style="color: #D4D4D4">                   p2.</span><span style="color: #569CD6">name</span><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">             </span><span style="color: #569CD6">end</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> to_person</span></span>
<span class="line"><span style="color: #D4D4D4">          )</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">order by</span><span style="color: #D4D4D4"> friendship_id;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="FRIENDSHIP_ID MEETING_DATE        FROM_PERSON TO_PERSON 
------------- ------------------- ----------- ----------
            1 19.09.2000 00:00:00 Mary        Alice     
            5 19.09.2000 00:00:00 Mary        John      
            7 10.07.2001 00:00:00 Bob         Mary " style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">FRIENDSHIP_ID MEETING_DATE        FROM_PERSON TO_PERSON </span></span>
<span class="line"><span style="color: #D4D4D4">------------- ------------------- ----------- ----------</span></span>
<span class="line"><span style="color: #D4D4D4">            1 19.09.2000 00:00:00 Mary        Alice     </span></span>
<span class="line"><span style="color: #D4D4D4">            5 19.09.2000 00:00:00 Mary        John      </span></span>
<span class="line"><span style="color: #D4D4D4">            7 10.07.2001 00:00:00 Bob         Mary </span></span></code></pre></div>



<h2 class="wp-block-heading">6. Breaking Change for Inlined MLE Call Specification</h2>



<p>In 23.3 the following code works.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">6) MLE Call Specification in 23.3</span><span role="button" tabindex="0" data-code="create or replace function get42 return number is 
   mle language javascript q'[return 42;]';
/
select get42();" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> function get42 </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   mle </span><span style="color: #569CD6">language</span><span style="color: #D4D4D4"> javascript q</span><span style="color: #CE9178">&#39;[return 42;]&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> get42();</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Function GET42 compiled


   GET42()
----------
        42" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Function GET42 compiled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">   GET42()</span></span>
<span class="line"><span style="color: #D4D4D4">----------</span></span>
<span class="line"><span style="color: #D4D4D4">        42</span></span></code></pre></div>



<p>In 24.4 the same code produces this error:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Function GET42 compiled

LINE/COL  ERROR
--------- -------------------------------------------------------------
2/28      PLS-00881: missing closing delimiter 'q'[return' for MLE language code
Errors: check compiler log" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Function GET42 compiled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">LINE/COL  ERROR</span></span>
<span class="line"><span style="color: #D4D4D4">--------- -------------------------------------------------------------</span></span>
<span class="line"><span style="color: #D4D4D4">2/28      PLS-00881: missing closing delimiter &#39;q&#39;[return&#39; for MLE language code</span></span>
<span class="line"><span style="color: #D4D4D4">Errors: check compiler log</span></span></code></pre></div>



<p>The reason is a change in the syntax of the inlined MLE call specification. The JavaScript code cannot be passed as a string anymore. Instead, a new type of delimiter must be used as documented <a href="https://docs.oracle.com/en/database/oracle/oracle-database/23/mlejs/calling-mle-js-functions.html#MLEJS-GUID-B0BBB967-2C4E-43D0-8D38-F4962AD23FE2">here</a>. You can use almost any sequence of characters as a delimiter for the JavaScript code. The same character sequence must be used for the start and the end delimiter. Exceptions are the pairs <code>()</code>, <code>[]</code>, <code>{}</code> and <code>&lt;&gt;</code>. </p>



<p>PostgreSQL <a href="https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING">dollar-quoted string constants</a> are also valid delimiters. This works in 23.4: </p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">7) MLE Call Specification in 23.4</span><span role="button" tabindex="0" data-code="create or replace function get42 return number is 
   mle language javascript $code$ return 42;$code$;
/

select get42();" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> function get42 </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">number</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">is</span><span style="color: #D4D4D4"> </span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">   mle </span><span style="color: #569CD6">language</span><span style="color: #D4D4D4"> javascript $code$ </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">42</span><span style="color: #D4D4D4">;$code$;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> get42();</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="Function GET42 compiled


   GET42()
----------
        42" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">Function GET42 compiled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">   GET42()</span></span>
<span class="line"><span style="color: #D4D4D4">----------</span></span>
<span class="line"><span style="color: #D4D4D4">        42</span></span></code></pre></div>



<p>Please note that the space after the first <code>$code$</code> is required for the Oracle Database to recognize the end of the delimiter. </p>



<p>This change might simplify the implementation of additional MLE languages. Nevertheless, this is a breaking change that requires an amendment of the existing code base.</p>



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



<p>In the next episode, the IslandSQL grammar will be extended to cover the missing statements with a query block. This means the</p>



<ul class="wp-block-list">
<li><code>create view</code>, </li>



<li><code>create materialized view</code> and </li>



<li><code>create table</code> statement</li>
</ul>



<p>for PostgreSQL and the Oracle Database. Only two episodes are left until the end of the first IslandSQL season.</p>
<p>The post <a href="https://www.salvis.com/blog/2024/06/15/islandsql-episode-8-whats-new-in-oracle-database-23-4/">IslandSQL Episode 8: What&#8217;s New in Oracle Database 23.4?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2024/06/15/islandsql-episode-8-whats-new-in-oracle-database-23-4/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
