<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[David Pataki]]></title><description><![CDATA[Oracle ACE Pro, founder of Enrol Consulting, and Oracle Database and APEX developer with more than two decades of experience building data-driven business appli]]></description><link>https://davidpataki.com</link><image><url>https://cdn.hashnode.com/uploads/logos/6461f51b60bafcc7fa959d8c/5e87a187-302e-4e7c-8d29-f798e517915c.png</url><title>David Pataki</title><link>https://davidpataki.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 29 Sep 2026 22:29:34 GMT</lastBuildDate><atom:link href="https://davidpataki.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[APEXlang and AI-Assisted Oracle APEX Development]]></title><description><![CDATA[Based on a 2026 Oracle APEX Budapest Meetup talk
This article is based on material I presented at the Oracle APEX Budapest Meetup on June 10, 2026, during a session about Oracle APEX 26.1 and AI-assis]]></description><link>https://davidpataki.com/apexlang-and-ai-assisted-oracle-apex-development</link><guid isPermaLink="true">https://davidpataki.com/apexlang-and-ai-assisted-oracle-apex-development</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[apex_lang]]></category><category><![CDATA[AI-assisted development]]></category><category><![CDATA[oracle-apex-26-1]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Tue, 29 Sep 2026 14:57:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6461f51b60bafcc7fa959d8c/a6176f85-a902-4b77-8505-4ad64ad8f2d4.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Based on a 2026 Oracle APEX Budapest Meetup talk</strong></p>
<p>This article is based on material I presented at the <strong>Oracle APEX Budapest Meetup on June 10, 2026</strong>, during a session about <strong>Oracle APEX 26.1 and AI-assisted development</strong>.</p>
<p>The focus here is APEXlang: why I believe it represents more than a new export format, and why it may become an important bridge between Oracle APEX, source control, AI-assisted development and enterprise governance.</p>
</blockquote>
<p>For years, Oracle APEX has given developers a higher level of abstraction.</p>
<p>We do not normally build every page by writing low-level code.</p>
<p>Instead, we describe what we want:</p>
<ul>
<li>a report</li>
<li>a form</li>
<li>a validation</li>
<li>a process</li>
<li>a navigation entry</li>
<li>an authorization rule</li>
</ul>
<p>APEX turns those declarations into a working application.</p>
<p>That declarative model is one of the reasons APEX can be so productive.</p>
<p>But AI-assisted development introduces a new question:</p>
<p><strong>How can an AI understand an APEX application well enough to help us build and modify it safely?</strong></p>
<p>This is where I find <strong>APEXlang</strong> particularly interesting.</p>
<h2>APEXlang is not just another export format</h2>
<p>At first glance, APEXlang can look like a different way to export an APEX application.</p>
<p>I think that interpretation is too narrow.</p>
<p>The more important idea is that the application becomes available as a <strong>readable, structured application specification</strong>.</p>
<p>In other words:</p>
<pre><code class="language-text">Business intent
      ↓
APEXlang specification
      ↓
Review and governance
      ↓
Running APEX application
</code></pre>
<p>That changes how we can think about an APEX application as a development artifact.</p>
<p>Traditionally, an export was often something we mainly associated with:</p>
<ul>
<li>deployment</li>
<li>migration</li>
<li>backup</li>
<li>source control</li>
</ul>
<p>APEXlang adds another possibility:</p>
<p><strong>the application definition itself becomes something humans, development tools and AI assistants can reason about.</strong></p>
<h2>An Open Application Specification Language</h2>
<p>The way I described APEXlang in my presentation was:</p>
<p><strong>an Open Application Specification Language for Oracle APEX.</strong></p>
<p>The important word here is not only <em>language</em>.</p>
<p>It is <em>specification</em>.</p>
<p>APEXlang describes the application at a higher level.</p>
<p>It focuses on the application's structure and intent rather than trying to represent everything as low-level implementation code.</p>
<p>That makes it naturally compatible with the declarative philosophy APEX has always had.</p>
<p>APEXlang is designed to be:</p>
<ul>
<li>declarative</li>
<li>human-readable</li>
<li>AI-friendly</li>
<li>file-based</li>
<li>versionable</li>
<li>mergeable</li>
<li>suitable for review</li>
<li>compatible with modern development workflows</li>
</ul>
<p>This is an important distinction.</p>
<p>The goal is not:</p>
<blockquote>
<p>Generate as much code as possible.</p>
</blockquote>
<p>The goal is:</p>
<blockquote>
<p>Express the application clearly enough that people and tools can understand what it is supposed to do.</p>
</blockquote>
<h2>From black box to readable source</h2>
<p>Low-code platforms have always had an interesting challenge.</p>
<p>They give us abstraction and productivity.</p>
<p>But that abstraction can also make the application definition harder to inspect outside the development environment.</p>
<p>A traditional export may be technically useful while still being difficult to:</p>
<ul>
<li>read</li>
<li>compare</li>
<li>review</li>
<li>validate</li>
<li>explain to an AI model</li>
</ul>
<p>APEXlang addresses this visibility gap.</p>
<p>Conceptually:</p>
<pre><code class="language-text">Traditional application export

harder to read
harder to diff
harder to review
harder for AI to interpret

              ↓

APEXlang

readable
versionable
diffable
reviewable
validatable
AI-friendly
</code></pre>
<p>That matters even without AI.</p>
<p>But AI makes the value much easier to see.</p>
<h2>A simple APEXlang example</h2>
<p>An application specification can describe things such as:</p>
<pre><code class="language-text">page "Sales" {
    id: 5

    identification {
        name: Sales
        title: Sales
    }

    security {
        authentication: pageRequiresAuthentication
    }

    regions {
        region "Sales Dashboard" {
            identification {
                name: Sales Dashboard
                type: classicReport
            }

            source {
                location: localDatabase
                type: sqlQuery
            }
        }
    }
}
</code></pre>
<p>Even without knowing every detail of the syntax, a developer can understand what is being described.</p>
<p>There is:</p>
<ul>
<li>a page</li>
<li>a title</li>
<li>an authentication requirement</li>
<li>a report region</li>
<li>a database source</li>
</ul>
<p>This is very different from asking an AI assistant to infer the structure of the application from screenshots or an opaque deployment artifact.</p>
<h2>The AI needs application context</h2>
<p>When AI assistants work well with source code, one reason is simple:</p>
<p><strong>they can see the source.</strong></p>
<p>They can analyze:</p>
<ul>
<li>files</li>
<li>functions</li>
<li>dependencies</li>
<li>structures</li>
<li>changes</li>
</ul>
<p>Historically, that has been more difficult with low-code applications.</p>
<p>The application may be perfectly understandable inside the low-code IDE, while an external AI tool has very little useful context.</p>
<p>APEXlang helps close this gap.</p>
<p>Instead of giving the AI screenshots and saying:</p>
<blockquote>
<p>Guess how this application works.</p>
</blockquote>
<p>we can give it a structured application definition.</p>
<p>That creates much better conditions for AI-assisted development.</p>
<h2>This is not "vibe coding for APEX"</h2>
<p>One of the messages I emphasized in the meetup was that APEXlang should not be interpreted as uncontrolled AI code generation.</p>
<p>The workflow I find more interesting looks like this:</p>
<pre><code class="language-text">Prompt
   ↓
APEXlang
structured application definition
   ↓
Review
Git diff + rules + validation
   ↓
Import
   ↓
APEX application
</code></pre>
<p>The roles are different:</p>
<pre><code class="language-text">AI
↓
accelerates

APEXlang
↓
makes the intent visible

Developer
↓
controls
</code></pre>
<p>That is a much better enterprise development model than:</p>
<pre><code class="language-text">Prompt
↓
Generate something
↓
Hope it works
</code></pre>
<p>The intermediate specification matters.</p>
<h2>Why the intermediate representation matters</h2>
<p>A prompt is temporary.</p>
<p>A specification can become a durable development artifact.</p>
<p>Suppose I tell an AI:</p>
<blockquote>
<p>Create a customer search page.</p>
</blockquote>
<p>That prompt alone is not enough for a serious business application.</p>
<p>We still need to know:</p>
<ul>
<li>which data source it uses</li>
<li>which fields are searchable</li>
<li>which users are allowed to access it</li>
<li>how navigation works</li>
<li>which components belong to the page</li>
<li>what validations apply</li>
<li>how the result fits the rest of the application</li>
</ul>
<p>In an enterprise environment, we need something persistent between the idea and the running application.</p>
<p>Conceptually:</p>
<pre><code class="language-text">"Create a customer search page"
                ↓
             APEXlang
                ↓
     structured specification
                ↓
              review
                ↓
       controlled application
</code></pre>
<p>This is where I see APEXlang becoming much more than an export mechanism.</p>
<h2>AI speed with enterprise control</h2>
<p>Generative AI is very good at increasing speed.</p>
<p>Enterprise software development needs something else as well:</p>
<p><strong>control.</strong></p>
<p>We need to be able to answer questions such as:</p>
<ul>
<li>What changed?</li>
<li>Who reviewed the change?</li>
<li>Is the application still secure?</li>
<li>Can we reproduce the application?</li>
<li>Can we compare two versions?</li>
<li>Can we validate the result?</li>
<li>Can we audit the development process?</li>
</ul>
<p>AI generation does not remove these requirements.</p>
<p>If anything, faster generation makes them more important.</p>
<p>The faster we can create software, the more important it becomes to understand what has actually been created.</p>
<h2>Source control becomes more meaningful</h2>
<p>A file-based, readable representation naturally fits source control better.</p>
<p>A possible workflow becomes:</p>
<pre><code class="language-text">APEX application
      ↓
APEXlang export
      ↓
Git
      ↓
change
      ↓
diff
      ↓
review
      ↓
merge
      ↓
import
</code></pre>
<p>Now consider AI inside the same process.</p>
<pre><code class="language-text">Requirement
      ↓
AI-assisted generation
      ↓
APEXlang change
      ↓
Git diff
      ↓
Developer review
      ↓
Validation
      ↓
APEX
</code></pre>
<p>This is a very different development model from letting an AI modify production application behavior without a visible intermediate step.</p>
<h2>The developer stays in control</h2>
<p>One of the most important points for me is that APEXlang does not make the APEX developer irrelevant.</p>
<p>I believe the opposite is more likely.</p>
<p>AI can generate.</p>
<p>APEXlang can make that generation visible.</p>
<p>But someone still needs to understand:</p>
<ul>
<li>the business requirement</li>
<li>the APEX model</li>
<li>Oracle Database</li>
<li>security</li>
<li>architecture</li>
<li>performance</li>
<li>maintainability</li>
</ul>
<p>That remains the developer's responsibility.</p>
<p>I summarized the roles like this:</p>
<pre><code class="language-text">AI
accelerates

APEXlang
makes the application intent visible

Developer
understands, evaluates and controls
</code></pre>
<p>The developer's job does not become:</p>
<blockquote>
<p>Write every component manually.</p>
</blockquote>
<p>But it also does not become:</p>
<blockquote>
<p>Type a prompt and accept whatever appears.</p>
</blockquote>
<p>The role moves toward:</p>
<ul>
<li>understanding intent</li>
<li>evaluating generated specifications</li>
<li>correcting them</li>
<li>approving them</li>
<li>validating architecture</li>
<li>protecting security and maintainability</li>
</ul>
<h2>From implementation to application intent</h2>
<p>This is a broader change in how I think about AI-assisted development.</p>
<p>The most important artifact may increasingly become the <strong>application intent</strong>.</p>
<p>Traditionally we often move from requirement to implementation like this:</p>
<pre><code class="language-text">Requirement
    ↓
Developer interpretation
    ↓
Implementation
</code></pre>
<p>With generative tools, another model becomes possible:</p>
<pre><code class="language-text">Requirement
    ↓
Structured application intent
    ↓
AI + developer
    ↓
Implementation
</code></pre>
<p>APEXlang gives that structured intent a possible technical form.</p>
<p>That is why I find the philosophy behind it more interesting than the syntax itself.</p>
<h2>A generative APEX development lifecycle</h2>
<p>The development lifecycle I presented can be summarized like this:</p>
<pre><code class="language-text">Requirements
business intent
      ↓
AI Generation
prompts + agents
      ↓
APEXlang
      ↓
Source control
merge + diff
      ↓
Application Builder
      ↓
Application
      ↓
Runtime
</code></pre>
<p>But the flow is not necessarily strictly linear.</p>
<p>Developers may work directly in Application Builder.</p>
<p>AI tools may generate or modify application specifications.</p>
<p>Source control may contain the shared definition.</p>
<p>The important point is that these paths can converge around a common application artifact.</p>
<p>That creates a new balance between:</p>
<p><strong>business intent → AI → developer tools → review → running application</strong></p>
<h2>APEX was already prepared for this idea</h2>
<p>What makes this particularly interesting is that APEX has always been declarative.</p>
<p>The platform already works at a higher level of abstraction.</p>
<p>We do not normally say:</p>
<blockquote>
<p>Generate the HTML, JavaScript, server logic and database interaction for this complete report manually.</p>
</blockquote>
<p>We say:</p>
<blockquote>
<p>This is a report.</p>
</blockquote>
<p>The platform knows how to implement it.</p>
<p>That is one reason I think APEX and generative AI fit together naturally.</p>
<p>AI is much more useful when it can operate on concepts that have clear meaning.</p>
<p>For example:</p>
<pre><code class="language-text">page
region
report
form
item
validation
process
authorization
navigation
</code></pre>
<p>These are already part of the APEX vocabulary.</p>
<p>APEXlang makes that vocabulary available in a form external tools can work with.</p>
<h2>The "what", not only the "how"</h2>
<p>One of the design goals I find particularly important is abstraction.</p>
<p>APEXlang aims to describe <strong>what</strong> the application should contain rather than forcing developers to express everything in terms of <strong>how</strong> the platform internally implements it.</p>
<p>This mirrors the strength of low-code itself.</p>
<p>A low-code platform gives developers leverage because they work with higher-level concepts.</p>
<p>AI can potentially benefit from the same abstraction.</p>
<p>Instead of generating large amounts of low-level code, the AI can work with application concepts.</p>
<p>That is a much more attractive direction for maintainable enterprise software.</p>
<h2>Human-readable matters</h2>
<p>It is tempting to think that if AI generates the application, humans do not need to understand the generated representation.</p>
<p>I strongly disagree.</p>
<p>Human readability becomes even more important when generation becomes faster.</p>
<p>If a generated specification is readable, the developer can ask:</p>
<ul>
<li>Is this really what we wanted?</li>
<li>Is this page correct?</li>
<li>Is authentication required?</li>
<li>Did a new region appear unexpectedly?</li>
<li>Did the SQL source change?</li>
<li>Has a security rule disappeared?</li>
</ul>
<p>Human readability makes AI output reviewable.</p>
<p>Without reviewability, enterprise adoption becomes much harder.</p>
<h2>Diffable matters</h2>
<p>Imagine asking an AI:</p>
<blockquote>
<p>Add a new filter to the customer search page.</p>
</blockquote>
<p>I do not only want the result.</p>
<p>I want to see the change.</p>
<pre><code class="language-diff">customer search page

+ item "Country"
+ source: CUSTOMER.COUNTRY_ID
+ lov: COUNTRY_LOV
</code></pre>
<p>The exact syntax is less important than the principle.</p>
<p>A developer should be able to review what changed before accepting it.</p>
<p>This is one of the reasons source-control-friendly application definitions are important.</p>
<h2>Mergeable matters</h2>
<p>Team development also requires merging changes.</p>
<p>One developer may work on one part of the application.</p>
<p>Another developer may work on another.</p>
<p>An AI assistant may propose a third change.</p>
<p>If the application definition can participate in normal source-control workflows, these changes become much easier to manage systematically.</p>
<p>This brings low-code development closer to development practices that are already familiar in code-centric environments.</p>
<h2>Validation matters</h2>
<p>AI can produce incorrect output.</p>
<p>This is not unique to AI.</p>
<p>Developers produce incorrect output too.</p>
<p>The difference is speed.</p>
<p>AI may produce a large amount of incorrect output very quickly.</p>
<p>That makes validation essential.</p>
<p>A structured specification creates opportunities for automated checks before a change becomes a running application.</p>
<p>The principle is:</p>
<pre><code class="language-text">Generate
   ↓
Validate
   ↓
Review
   ↓
Deploy
</code></pre>
<p>not:</p>
<pre><code class="language-text">Generate
   ↓
Deploy immediately
</code></pre>
<h2>Governance matters</h2>
<p>For enterprise applications, governance is not optional.</p>
<p>We need standards.</p>
<p>For example:</p>
<ul>
<li>naming conventions</li>
<li>security requirements</li>
<li>approved components</li>
<li>architectural patterns</li>
<li>logging requirements</li>
<li>accessibility rules</li>
<li>database standards</li>
</ul>
<p>If application intent is represented in a structured way, it becomes easier to imagine automated governance around it.</p>
<p>An organization could potentially verify that generated application changes comply with its internal rules before they are accepted.</p>
<p>That is much more interesting than AI generation alone.</p>
<h2>AI-assisted development is broader than generation</h2>
<p>At the June 2026 meetup, the broader theme was <strong>AI-assisted development</strong> in Oracle APEX.</p>
<p>Generation is only one part of that.</p>
<p>AI may help developers with:</p>
<ul>
<li>understanding existing applications</li>
<li>explaining PL/SQL</li>
<li>generating initial structures</li>
<li>suggesting changes</li>
<li>documenting applications</li>
<li>analyzing reports</li>
<li>creating test ideas</li>
<li>working with project knowledge</li>
</ul>
<p>The important question is not:</p>
<blockquote>
<p>Can AI generate an APEX application?</p>
</blockquote>
<p>The more useful question is:</p>
<blockquote>
<p>Where can AI remove repetitive work while keeping the application understandable and controlled?</p>
</blockquote>
<h2>APEXlang as context for AI assistants</h2>
<p>One particularly useful role for APEXlang is context.</p>
<p>An AI assistant needs to understand the application before giving useful advice.</p>
<p>A readable application definition can give it that context.</p>
<p>A workflow could look like this:</p>
<pre><code class="language-text">APEX application
      ↓
APEXlang
      ↓
AI assistant
      ↓
"Explain this page"

"Where is this authorization used?"

"Which pages depend on this shared component?"

"Suggest how to add this requirement"

"What changed between these two versions?"
</code></pre>
<p>This may be just as valuable as generation.</p>
<p>In mature enterprise systems, understanding existing applications is often more important than creating new applications from scratch.</p>
<h2>This connects to something I was already thinking about</h2>
<p>In 2023, I was already asking what generative AI could mean for Oracle APEX application development.</p>
<p>At that time, one of the interesting possibilities was moving from natural-language requirements toward generated application structures.</p>
<p>I wrote about that evolution here:</p>
<p><strong><a href="https://davidpataki.com/generative-ai-in-oracle-apex-from-a-2023-vision-to-apex-26-1">Generative AI in Oracle APEX: From a 2023 Vision to APEX 26.1 →</a></strong></p>
<p>APEXlang makes that discussion much more concrete.</p>
<p>The missing layer between:</p>
<pre><code class="language-text">natural language
</code></pre>
<p>and:</p>
<pre><code class="language-text">running application
</code></pre>
<p>can now become a structured application specification.</p>
<p>That is an important architectural difference.</p>
<h2>Prompt engineering is not enough</h2>
<p>Another reason I like this direction is that it moves the discussion beyond prompt engineering.</p>
<p>A good prompt is useful.</p>
<p>But enterprise application development needs more than a good prompt.</p>
<p>It needs:</p>
<pre><code class="language-text">Requirement
+
Application model
+
Data model
+
Security
+
Standards
+
Existing application context
+
Review
</code></pre>
<p>The prompt is only one input.</p>
<p>APEXlang can provide a more durable representation of the application itself.</p>
<h2>The future APEX developer</h2>
<p>I do not expect the APEX developer to disappear.</p>
<p>I expect the role to change.</p>
<p>Less time may be spent on some repetitive implementation tasks.</p>
<p>More time may be spent on:</p>
<ul>
<li>business analysis</li>
<li>data modelling</li>
<li>architecture</li>
<li>security</li>
<li>defining application intent</li>
<li>reviewing AI output</li>
<li>integration</li>
<li>validation</li>
<li>governance</li>
</ul>
<p>That is not a weaker developer role.</p>
<p>It is a role operating at a higher level of abstraction.</p>
<h2>The database still matters</h2>
<p>It is also important not to separate this discussion from Oracle Database.</p>
<p>An APEX application is not only a collection of pages.</p>
<p>In serious business systems, much of the value is in:</p>
<ul>
<li>the data model</li>
<li>SQL</li>
<li>PL/SQL</li>
<li>constraints</li>
<li>security</li>
<li>integrations</li>
<li>transactional consistency</li>
</ul>
<p>AI-assisted APEX development still depends on these foundations.</p>
<p>APEXlang can describe more of the application layer.</p>
<p>It does not remove the need to understand the database underneath it.</p>
<p>This is why my own professional journey still feels continuous:</p>
<pre><code class="language-text">Oracle Database
      ↓
Oracle APEX
      ↓
Oracle Cloud
      ↓
AI-assisted development
</code></pre>
<p>AI is not replacing the previous layers.</p>
<p>It is building on them.</p>
<h2>What should APEX teams do now?</h2>
<p>My recommendation at the meetup was not to try to transform everything at once.</p>
<p>Start with a small use case.</p>
<p>For example:</p>
<ul>
<li>explain an existing report</li>
<li>analyze an APEX application definition</li>
<li>generate documentation</li>
<li>explain PL/SQL</li>
<li>create a small application specification</li>
<li>build an internal project assistant</li>
</ul>
<p>Then measure the value.</p>
<p>Look for:</p>
<ul>
<li>time saved</li>
<li>fewer errors</li>
<li>faster onboarding</li>
<li>less repetitive work</li>
<li>better documentation</li>
</ul>
<p>And build reusable patterns.</p>
<p>For example:</p>
<pre><code class="language-text">prompt templates
PL/SQL packages
REST wrappers
logging
authorization patterns
review processes
</code></pre>
<p>AI usage itself is becoming a development skill.</p>
<p>Developers need to learn:</p>
<ul>
<li>how to ask</li>
<li>how to provide context</li>
<li>how to verify</li>
<li>how to recognize risk</li>
<li>how to control the result</li>
</ul>
<h2>The real question is not how much AI can generate</h2>
<p>AI can generate more and more.</p>
<p>That is becoming less surprising every year.</p>
<p>For enterprise development, I think the more important questions are:</p>
<blockquote>
<p>Can we clearly express what the application should do?</p>
</blockquote>
<blockquote>
<p>Can we inspect what the AI created?</p>
</blockquote>
<blockquote>
<p>Can we compare it with the previous version?</p>
</blockquote>
<blockquote>
<p>Can we validate it?</p>
</blockquote>
<blockquote>
<p>Can we review it?</p>
</blockquote>
<blockquote>
<p>Can we govern it?</p>
</blockquote>
<blockquote>
<p>Can we maintain it five years later?</p>
</blockquote>
<p>That is why I believe APEXlang is important.</p>
<h2>Looking back from 2026</h2>
<p>When I look at APEXlang, I do not mainly see a new file format.</p>
<p>I see the continuation of the original APEX philosophy.</p>
<p>APEX has always allowed us to describe applications at a higher level than traditional hand-coded development.</p>
<p>APEXlang takes that declarative model and makes it more visible to:</p>
<ul>
<li>developers</li>
<li>source control</li>
<li>development tools</li>
<li>automation</li>
<li>AI assistants</li>
</ul>
<p>That visibility may become extremely important in AI-assisted software development.</p>
<h2>The idea in one sentence</h2>
<p>If I had to summarize the philosophy in one sentence:</p>
<p><strong>APEXlang connects the speed of AI with the declarative model of Oracle APEX and the control required by enterprise software development.</strong></p>
<p>The future question may not be:</p>
<blockquote>
<p>How much code can AI generate?</p>
</blockquote>
<p>It may be:</p>
<blockquote>
<p>How clearly can we express, validate and govern application intent?</p>
</blockquote>
<p>That is the direction I find much more interesting.</p>
]]></content:encoded></item><item><title><![CDATA[Generative AI with Your Own Data and Documents]]></title><description><![CDATA[Based on a 2025 Oracle APEX Budapest Meetup talk
This article is based on my presentation “Generative AI with Your Own Data and Documents”, delivered at the Oracle APEX Budapest Meetup on November 26,]]></description><link>https://davidpataki.com/generative-ai-with-your-own-data-and-documents</link><guid isPermaLink="true">https://davidpataki.com/generative-ai-with-your-own-data-and-documents</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[generative ai]]></category><category><![CDATA[RAG ]]></category><category><![CDATA[oracle-select-ai]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Tue, 29 Sep 2026 14:45:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6461f51b60bafcc7fa959d8c/198c5b5d-a5f5-409a-8142-863aef725c21.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Based on a 2025 Oracle APEX Budapest Meetup talk</strong></p>
<p>This article is based on my presentation <strong>“Generative AI with Your Own Data and Documents”</strong>, delivered at the <strong>Oracle APEX Budapest Meetup on November 26, 2025</strong>.</p>
<p>The article follows the ideas, architecture and practical experiments I presented at the time, adapted into English for publication on davidpataki.com in 2026.</p>
</blockquote>
<p>Generative AI becomes much more interesting for a company when it can work with information that actually belongs to that company.</p>
<p>A general-purpose language model can already do many impressive things.</p>
<p>But businesses usually want more.</p>
<p>They want AI to understand:</p>
<ul>
<li>their own data</li>
<li>their own documents</li>
<li>their own terminology</li>
<li>their own rules</li>
<li>and their own business context</li>
</ul>
<p>That was the topic I explored in late 2025:</p>
<p><strong>How can we use generative AI with our own enterprise data and documents?</strong></p>
<h2>What do companies actually want from generative AI?</h2>
<p>For a business, the goal is not simply to have access to a large language model.</p>
<p>The goal is to create value from it.</p>
<p>In my presentation, I summarized three main objectives:</p>
<ul>
<li>create value from language models</li>
<li>simplify processes and improve operational efficiency</li>
<li>operate virtual assistants that can improve employee productivity</li>
</ul>
<p>These goals sound straightforward.</p>
<p>The implementation is not.</p>
<h2>The enterprise challenges</h2>
<p>There were several challenges I wanted to understand through practical experiments.</p>
<h3>Too many models</h3>
<p>The AI market was already moving very quickly.</p>
<p>Different models had different capabilities, behaviors and limitations.</p>
<p>Choosing a model was therefore not necessarily a one-time architectural decision.</p>
<h3>Company-specific knowledge</h3>
<p>A general model does not automatically understand a company's internal information.</p>
<p>It does not know:</p>
<ul>
<li>internal processes</li>
<li>project documentation</li>
<li>business rules</li>
<li>database structures</li>
<li>private documents</li>
</ul>
<p>The model needs access to the right context.</p>
<h3>Infrastructure and authorization</h3>
<p>Enterprise AI cannot simply receive unrestricted access to everything.</p>
<p>Infrastructure and permissions become part of the AI architecture.</p>
<h3>Hungarian language</h3>
<p>For us, this was especially important.</p>
<p>An enterprise AI solution used by Hungarian employees and customers also needs to perform well in Hungarian.</p>
<p>That is something I explicitly wanted to test rather than simply assume.</p>
<h2>An LLM alone is not enough</h2>
<p>One of the main messages of the presentation was:</p>
<p><strong>the language model itself is not enough.</strong></p>
<p>Consider three very different requests.</p>
<h3>“How much were my weekly sales?”</h3>
<p>The model needs access to company data.</p>
<pre><code class="language-text">Question
   ↓
Company data
   ↓
Answer
</code></pre>
<p>Without access to the actual sales information, the model cannot answer reliably.</p>
<h3>“Turn off the lights at 9 PM.”</h3>
<p>Now information retrieval is not enough.</p>
<p>The AI needs to perform an action.</p>
<pre><code class="language-text">Request
   ↓
API call
   ↓
External system
</code></pre>
<h3>“Analyze the proposal based on my own policy.”</h3>
<p>Here the model needs company-specific knowledge and instructions.</p>
<pre><code class="language-text">Proposal
   +
Company policy
   +
Instructions
   ↓
Reasoning
</code></pre>
<p>These examples represent three important enterprise AI requirements:</p>
<p><strong>data, tools and business context.</strong></p>
<h2>Working with structured data: Select AI</h2>
<p>One of the technologies I tested was <strong>Select AI</strong>.</p>
<p>The idea is especially interesting for Oracle-based applications because the question can be expressed in natural language while the relevant information already exists in Oracle Database.</p>
<p>In my test application, I experimented with multiple providers and compared the generated SQL.</p>
<p>For the same request, I could inspect SQL generated through different configurations.</p>
<p>The goal was not simply to create a chatbot.</p>
<p>The interesting part was connecting natural-language interaction to existing enterprise data.</p>
<h2>DBMS_CLOUD_AI.GENERATE</h2>
<p>The presentation also included direct use of <code>DBMS_CLOUD_AI.GENERATE</code>.</p>
<p>A simplified example from the demo was:</p>
<pre><code class="language-sql">DBMS_CLOUD_AI.GENERATE(
    prompt       =&gt; v_prompt,
    profile_name =&gt; 'OPEN_AI',
    action       =&gt; 'showsql'
);
</code></pre>
<p>The profile determines the AI configuration used for the request.</p>
<p>The environment I presented supported several provider options, including:</p>
<pre><code class="language-text">openai
cohere
azure
database
oci
google
anthropic
huggingface
aws
</code></pre>
<p>The available actions included:</p>
<pre><code class="language-text">runsql
showsql
explainsql
narrate
chat
</code></pre>
<p>This gives us different ways of using a language model around database information.</p>
<p>For example, sometimes I only want to see the SQL.</p>
<p>In another situation I may want to execute it, explain it or generate a natural-language response.</p>
<h2>Credentials and profiles</h2>
<p>The configuration separates several concerns.</p>
<p>Conceptually:</p>
<pre><code class="language-text">Credential
     ↓
AI Profile
     ↓
DBMS_CLOUD_AI.GENERATE
     ↓
Provider
</code></pre>
<p>This is useful because the application does not have to hard-code everything about the model into each AI request.</p>
<p>The profile becomes an important part of the configuration.</p>
<h2>Voice can be another input</h2>
<p>The presentation also contained an experiment where spoken input became part of the process.</p>
<p>The flow was approximately:</p>
<pre><code class="language-text">Voice
  ↓
WAV
  ↓
Base64
  ↓
Speech-to-Text
  ↓
Transcript
  ↓
AI processing
</code></pre>
<p>The transcript could then become the prompt passed to the AI service.</p>
<p>This was another example of an important idea:</p>
<p><strong>the AI interface does not have to begin with typing into a chat box.</strong></p>
<p>Business users may interact through different forms of input.</p>
<h2>From Select AI to an AI agent</h2>
<p>The next step in my experiments was an <strong>AI agent</strong>.</p>
<p>The difference is important.</p>
<p>Instead of using only one model call, the agent can work with several tools.</p>
<p>In the architecture I presented, the agent had access to different types of capabilities:</p>
<pre><code class="language-text">Agent
  ↓
Tools
</code></pre>
<p>Those tools could include:</p>
<pre><code class="language-text">RAG
SQL
Custom tool
Agent tool
</code></pre>
<p>This changes the role of the language model.</p>
<p>Instead of being expected to know everything itself, it can use the appropriate tool depending on the question.</p>
<h2>RAG for company documents</h2>
<p>For information stored in documents, I tested a RAG-based approach.</p>
<p>The structure presented at the meetup was:</p>
<pre><code class="language-text">Agent
  ↓
Tool
  ↓
RAG
  ↓
Knowledge Base
  ↓
Bucket
  ↓
File
</code></pre>
<p>The knowledge base could contain files such as:</p>
<pre><code class="language-text">PDF
DOC
PPT
images
</code></pre>
<p>Metadata was also part of this structure.</p>
<p>Conceptually:</p>
<pre><code class="language-text">File
  +
Metadata
  ↓
Knowledge Base
</code></pre>
<p>This makes it possible for the agent to work with information that is not stored as normal relational database rows.</p>
<h2>Why documents matter</h2>
<p>A large part of a company's knowledge is not stored in tables.</p>
<p>It may exist in:</p>
<ul>
<li>policies</li>
<li>job descriptions</li>
<li>presentations</li>
<li>specifications</li>
<li>internal documents</li>
<li>other uploaded files</li>
</ul>
<p>In one of my demonstrations, I asked the agent about employee experience levels based on job descriptions.</p>
<p>The important point was that the answer was expected to come from the available documents.</p>
<p>If the information could not be found there, the agent should not simply invent it.</p>
<p>That is very different from asking a general model to make a guess.</p>
<h2>SQL as an agent tool</h2>
<p>Documents are only one source of enterprise knowledge.</p>
<p>Another important source is the database.</p>
<p>The agent architecture therefore also contained a <strong>SQL tool</strong>.</p>
<p>The SQL tool could be configured with:</p>
<ul>
<li>schema configuration</li>
<li>in-context learning examples</li>
<li>descriptions of tables and columns</li>
<li>custom instructions</li>
</ul>
<p>Conceptually:</p>
<pre><code class="language-text">Agent
   ↓
SQL Tool
   ↓
Schema configuration
Table and column descriptions
Examples
Custom instructions
   ↓
Database
</code></pre>
<p>This gives the model additional information about how to interact with the database.</p>
<h2>Why database descriptions matter</h2>
<p>A human developer who knows an application already understands much of its database context.</p>
<p>The AI does not.</p>
<p>A column name alone may not explain its real business meaning.</p>
<p>That is why descriptions of:</p>
<ul>
<li>schemas</li>
<li>tables</li>
<li>columns</li>
</ul>
<p>can be valuable.</p>
<p>The AI needs context about the data model before it can use that model effectively.</p>
<h2>In-context learning examples</h2>
<p>The presentation also included <strong>in-context learning examples</strong> as part of the SQL tool configuration.</p>
<p>Examples can help the model understand how particular questions relate to a company's database.</p>
<p>Rather than relying only on generic knowledge, we can provide patterns that are specific to our application.</p>
<p>This again reflects the central theme of the talk:</p>
<p><strong>enterprise AI becomes useful when general model capabilities are combined with company-specific context.</strong></p>
<h2>Custom instructions</h2>
<p>The SQL tool could also receive custom instructions.</p>
<p>These instructions help shape how the tool should behave within the company's environment.</p>
<p>This is another layer between a generic language model and a useful enterprise assistant.</p>
<p>The model provides the general language capability.</p>
<p>The configuration provides the business-specific guidance.</p>
<h2>Other tools</h2>
<p>The architecture was not limited to RAG and SQL.</p>
<p>I also included:</p>
<pre><code class="language-text">Custom tool
Agent tool
</code></pre>
<p>The purpose of the experiment was to see the AI agent as a coordinator of different capabilities rather than as a single isolated chatbot.</p>
<p>Conceptually:</p>
<pre><code class="language-text">                     ┌── RAG
                     │
User → Agent → Tools ├── SQL
                     │
                     ├── Custom tool
                     │
                     └── Agent tool
</code></pre>
<p>The agent can decide which capability is relevant to the user's request.</p>
<h2>One question may need a document</h2>
<p>For example:</p>
<blockquote>
<p>What does our policy say about this situation?</p>
</blockquote>
<p>The appropriate source may be the knowledge base.</p>
<pre><code class="language-text">Question
   ↓
Agent
   ↓
RAG
   ↓
Company documents
</code></pre>
<h2>Another question may need database data</h2>
<p>For example:</p>
<blockquote>
<p>Who has tasks this week?</p>
</blockquote>
<p>Now the answer belongs in structured business data.</p>
<pre><code class="language-text">Question
   ↓
Agent
   ↓
SQL tool
   ↓
Database
</code></pre>
<p>The user should not need to decide which technical mechanism is required.</p>
<p>That is the agent's job.</p>
<h2>And another request may require an action</h2>
<p>A more advanced request may eventually need a specialized tool or API.</p>
<pre><code class="language-text">Question / instruction
        ↓
Agent
        ↓
Custom tool
        ↓
External operation
</code></pre>
<p>This is why I found the agent model more interesting than simply putting a chat interface in front of an LLM.</p>
<h2>What did I learn from the experiments?</h2>
<p>At the end of the November 2025 presentation, I summarized my practical conclusions.</p>
<p>These were not theoretical conclusions.</p>
<p>They came from experimenting with the different approaches.</p>
<h3>The SQL tool was not efficient enough</h3>
<p>In the form I tested at the time, my conclusion was:</p>
<p><strong>the SQL tool was not efficient enough.</strong></p>
<p>That does not mean that using AI with SQL is a bad idea.</p>
<p>In fact, my Select AI experiments showed the opposite.</p>
<p>But the particular agent-tool approach still needed improvement.</p>
<h2>RAG worked well</h2>
<p>My experience with RAG was much more positive.</p>
<p><strong>RAG worked well.</strong></p>
<p>For questions based on company documents, this approach showed clear potential.</p>
<p>This was particularly important because documents contain a large amount of business knowledge that is difficult to use through traditional structured queries.</p>
<h2>Select AI worked well in OCI</h2>
<p>Another positive conclusion was:</p>
<p><strong>Select AI worked well in OCI.</strong></p>
<p>Natural-language access to database information was therefore one of the stronger parts of the experiment.</p>
<p>For an Oracle-based application environment, that was particularly relevant.</p>
<h2>The cost was acceptable</h2>
<p>Cost is always part of enterprise architecture.</p>
<p>An impressive demo is not useful if normal usage makes the solution economically unrealistic.</p>
<p>In my experiments, my conclusion was that:</p>
<p><strong>the price was acceptable.</strong></p>
<p>That made further experimentation worthwhile.</p>
<h2>Hungarian required more testing</h2>
<p>One of the open questions remained the Hungarian language.</p>
<p>My conclusion was that we needed:</p>
<p><strong>more Hungarian-language tests for further tuning.</strong></p>
<p>This matters because a solution that works well in English does not automatically provide the same experience in another language.</p>
<p>For a Hungarian business application, this cannot be ignored.</p>
<h2>Tool tuning still needed work</h2>
<p>Another point in the presentation was the usefulness of OpenAI in helping to tune the tools.</p>
<p>The tool definitions and instructions matter.</p>
<p>An agent is only as useful as the tools it can call and the way those tools are described.</p>
<p>This means that building an AI agent is not simply:</p>
<pre><code class="language-text">Connect model
→ done
</code></pre>
<p>It is an iterative process.</p>
<h2>Efficient APIs matter</h2>
<p>Another conclusion was the importance of <strong>efficient APIs</strong>.</p>
<p>If an AI agent is expected to perform business operations, the quality of the available tools becomes critical.</p>
<p>The AI layer cannot compensate indefinitely for poorly designed interfaces underneath it.</p>
<p>A good AI agent therefore also depends on good application architecture.</p>
<h2>Some limitations remained</h2>
<p>The original presentation explicitly identified several limitations.</p>
<p>I had listed three of them as points that still needed attention.</p>
<p>I will not reconstruct those details from memory here because the purpose of this article is to preserve what was actually demonstrated in 2025.</p>
<p>The important point is that the system was promising but not something I considered finished.</p>
<h2>Language and vision were still open questions in Hungarian</h2>
<p>Another conclusion from the tests was that <strong>Language and Vision in Hungarian were not yet where I wanted them to be</strong>.</p>
<p>Again, this is why practical testing matters.</p>
<p>A feature list can tell us what a service supports.</p>
<p>It cannot tell us whether the experience is good enough for our specific users and language.</p>
<h2>What the experiment changed in my thinking</h2>
<p>The most important lesson for me was that there is no single technology called “enterprise AI.”</p>
<p>A useful company assistant needs access to several different capabilities.</p>
<p>The architecture I explored looked more like this:</p>
<pre><code class="language-text">                         User
                           ↓
                         Agent
                           ↓
                         Tools
              ┌────────────┼────────────┐
              ↓            ↓            ↓
             RAG          SQL       Custom tools
              ↓            ↓            ↓
         Documents      Database       APIs
</code></pre>
<p>The language model sits above these capabilities.</p>
<p>It helps understand the user's request and work with the result.</p>
<p>But the actual company knowledge still comes from company systems.</p>
<h2>The LLM is only one part of the solution</h2>
<p>This brings us back to the point from the beginning:</p>
<p><strong>the LLM is not enough.</strong></p>
<p>If the user asks about sales, the AI needs data.</p>
<p>If the user asks about internal rules, it needs documents.</p>
<p>If the user wants something to happen, it needs a tool or API.</p>
<p>The model provides the conversational and reasoning layer.</p>
<p>The enterprise systems provide the real context.</p>
<h2>Looking back from 2026</h2>
<p>I presented these experiments on <strong>November 26, 2025</strong>.</p>
<p>What I find most useful about them today is that they moved the discussion away from the question:</p>
<blockquote>
<p>Which AI model should we use?</p>
</blockquote>
<p>and toward more practical questions:</p>
<blockquote>
<p>What information does the AI need?</p>
</blockquote>
<blockquote>
<p>Where does that information live?</p>
</blockquote>
<blockquote>
<p>Is it structured data or a document?</p>
</blockquote>
<blockquote>
<p>Which tool should retrieve it?</p>
</blockquote>
<blockquote>
<p>Does the agent have enough context to use that tool correctly?</p>
</blockquote>
<blockquote>
<p>Can the solution work reliably in the language our users actually speak?</p>
</blockquote>
<p>Those questions are still much more important to me than simply connecting another LLM.</p>
<p>The most promising architecture was not a chatbot with access to everything.</p>
<p>It was an agent with <strong>specific, controlled tools</strong> for different kinds of enterprise knowledge.</p>
<p>For our Oracle environment, that meant combining ideas such as:</p>
<p><strong>Select AI + SQL + RAG + company documents + tools.</strong></p>
<p>That was the real lesson of the experiment:</p>
<p><strong>generative AI becomes useful for a company when it can work with the company's own context - through the right tool for the right information.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Connecting Oracle APEX Applications with REST Enabled SQL]]></title><description><![CDATA[Based on a 2024 conference talk
This article is based on my presentation “Linking All My APEX Together with REST Enabled SQL”, delivered at APEX Alpe Adria on April 12, 2024.
It reflects the architect]]></description><link>https://davidpataki.com/connecting-oracle-apex-applications-with-rest-enabled-sql</link><guid isPermaLink="true">https://davidpataki.com/connecting-oracle-apex-applications-with-rest-enabled-sql</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[rest-enabled-sql]]></category><category><![CDATA[integration]]></category><category><![CDATA[Oracle Database]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Tue, 29 Sep 2026 14:19:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6461f51b60bafcc7fa959d8c/4f278730-0dce-4629-9583-a3d738ec92e8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Based on a 2024 conference talk</strong></p>
<p>This article is based on my presentation <strong>“Linking All My APEX Together with REST Enabled SQL”</strong>, delivered at <strong>APEX Alpe Adria on April 12, 2024</strong>.</p>
<p>It reflects the architecture, problems and lessons I presented at the time, adapted into article form for publication on davidpataki.com in 2026.</p>
</blockquote>
<p>Running a software development company means constantly trying to answer questions that are surprisingly difficult to answer well.</p>
<p>What are my developers working on?</p>
<p>What should we be working on?</p>
<p>What have we already completed?</p>
<p>What do our clients want from us?</p>
<p>Are we within budget?</p>
<p>Is the project profitable?</p>
<p>And perhaps most importantly:</p>
<p><strong>Do I actually have enough information to answer these questions in time?</strong></p>
<p>In 2024, I presented at APEX Alpe Adria how we approached this problem at Enrol Consulting using Oracle APEX and REST Enabled SQL.</p>
<p>The technical solution was important.</p>
<p>But the real problem was information.</p>
<h2>The information problem</h2>
<p>At the time, there were several things I found difficult to follow:</p>
<ul>
<li><p>what my employees were doing</p>
</li>
<li><p>what we should do next</p>
</li>
<li><p>what we had already done</p>
</li>
<li><p>what our clients wanted us to do</p>
</li>
<li><p>whether we were within budget</p>
</li>
<li><p>whether a project was profitable</p>
</li>
<li><p>whether individual employees were profitable</p>
</li>
<li><p>whether we had deviated from the project plan</p>
</li>
<li><p>which errors still had to be handled</p>
</li>
</ul>
<p>The information existed.</p>
<p>The problem was that it often arrived:</p>
<ul>
<li><p><strong>too late</strong></p>
</li>
<li><p><strong>in too little detail</strong></p>
</li>
<li><p><strong>too generally</strong></p>
</li>
<li><p><strong>too fragmented</strong></p>
</li>
</ul>
<p>This is a common problem in software projects.</p>
<p>The customer has information.</p>
<p>The developer has information.</p>
<p>The project manager has information.</p>
<p>The application has information.</p>
<p>The timesheet has information.</p>
<p>But these pieces do not necessarily form one coherent picture.</p>
<h2>A typical workflow</h2>
<p>A simplified software development workflow might look like this:</p>
<pre><code class="language-text">Customer
   ↓
Idea / need / error
   ↓
Task management
   ↓
Developer
   ↓
Doing / fixing
   ↓
Timesheet
   ↓
Testing
</code></pre>
<p>The problem becomes more complicated when the customer's business application and the development company's internal task-management system are separate.</p>
<p>A requirement may originate inside the client's application, while the corresponding task is managed somewhere else.</p>
<p>The developer then performs the work in the client's environment and later records it in yet another place.</p>
<p>Every additional system increases the chance that information will be:</p>
<ul>
<li><p>duplicated</p>
</li>
<li><p>delayed</p>
</li>
<li><p>simplified</p>
</li>
<li><p>forgotten</p>
</li>
<li><p>disconnected from its original context</p>
</li>
</ul>
<h2>What did we actually need?</h2>
<p>We identified three important goals.</p>
<h3>Manage tasks where they belong</h3>
<p>A problem occurring on a particular page of an application should be easy to create and follow from that context.</p>
<p>The user should not have to leave the business application, open another task-management product and reconstruct where the problem occurred.</p>
<h3>Manage all tasks in one place</h3>
<p>From our side, however, we needed a consolidated view.</p>
<p>We work with multiple applications and multiple clients.</p>
<p>Project managers and developers cannot efficiently manage work if every client's requests remain isolated inside separate systems.</p>
<h3>Make administration as easy as possible</h3>
<p>This was especially important for developers.</p>
<p>If recording information creates too much additional work, people naturally postpone it.</p>
<p>And once information is entered days later, it becomes less accurate.</p>
<p>So the goal was not to create more administration.</p>
<p>The goal was to capture useful information <strong>as part of the work itself</strong>.</p>
<h2>Two systems, one workflow</h2>
<p>The basic architecture involved two different environments:</p>
<pre><code class="language-text">Client's ERP / APEX application
             ↕
      REST Enabled SQL
             ↕
        Enrol's ERP
</code></pre>
<p>The client continued using their own application.</p>
<p>We continued using our own internal ERP.</p>
<p>REST Enabled SQL connected the two.</p>
<p>This allowed the client-facing functionality to stay where it made sense while giving us a centralized view of the work.</p>
<p>The customer did not need to become a user of our internal project-management system.</p>
<p>And our developers did not need to manually recreate every customer request inside another application.</p>
<h2>Why REST Enabled SQL?</h2>
<p>Oracle APEX applications are frequently built around Oracle Database.</p>
<p>When both sides of an integration belong to the Oracle ecosystem, REST Enabled SQL provides an interesting option.</p>
<p>Instead of building a separate REST endpoint for every individual operation, an APEX application can work with SQL and PL/SQL executed against a REST-enabled remote Oracle schema.</p>
<p>For our use case, this was attractive because the data model and business processes were still evolving.</p>
<p>But REST Enabled SQL was not something we simply enabled and forgot about.</p>
<p>The original presentation deliberately included several questions we had to consider:</p>
<ul>
<li><p>limitations of REST Enabled SQL</p>
</li>
<li><p>security</p>
</li>
<li><p>the right architecture</p>
</li>
<li><p>what happens when the connection is unavailable</p>
</li>
<li><p>user synchronization</p>
</li>
<li><p>maintainability</p>
</li>
</ul>
<p>Those architectural questions were just as important as establishing the connection itself.</p>
<h2>The connection schema</h2>
<p>One of the important architectural decisions was the use of a separate <strong>connection schema</strong>.</p>
<p>Instead of exposing the internal ERP schema directly, the integration could operate through a dedicated database layer.</p>
<p>Conceptually:</p>
<pre><code class="language-text">Client APEX application
        ↓
REST Enabled SQL
        ↓
Connection schema
        ↓
Internal application data
</code></pre>
<p>This provided a natural place to control what the remote application could access.</p>
<p>The connection layer could expose only the database objects and operations required by the integration.</p>
<p>That separation matters.</p>
<p>When connecting systems, the easiest technical solution is not always the architecture you want to maintain for years.</p>
<h2>Client-side configuration</h2>
<p>The client application also needed its own REST Enabled SQL configuration.</p>
<p>Once the remote data source had been configured, APEX components could use information from the connected environment.</p>
<p>Some of the practical examples in the presentation included:</p>
<ul>
<li><p>Lists of Values</p>
</li>
<li><p>lists of users</p>
</li>
<li><p>lists of statuses</p>
</li>
<li><p>application maintenance</p>
</li>
<li><p>status maintenance</p>
</li>
<li><p>user maintenance</p>
</li>
</ul>
<p>This meant that information did not necessarily have to be duplicated into every client database.</p>
<p>The application could retrieve the relevant values through the connection.</p>
<h2>Think about maintenance from the beginning</h2>
<p>Connecting two systems is only the first step.</p>
<p>Sooner or later, something changes.</p>
<p>A new system is added.</p>
<p>A status changes.</p>
<p>A user joins or leaves.</p>
<p>Permissions change.</p>
<p>That is why the presentation included dedicated maintenance functions for:</p>
<pre><code class="language-text">Systems
Statuses
Users
</code></pre>
<p>These may look like small administrative details.</p>
<p>They are not.</p>
<p>An integration that works only while its original configuration remains unchanged becomes expensive very quickly.</p>
<p>The maintenance model is part of the architecture.</p>
<h2>User synchronization is a real problem</h2>
<p>Users are particularly interesting.</p>
<p>The same person may exist in both environments, but the two systems do not necessarily identify them in the same way.</p>
<p>A developer may exist in our ERP.</p>
<p>A customer user exists in the client's system.</p>
<p>Permissions and identities may change independently.</p>
<p>The original project therefore had to consider user synchronization as a separate architectural issue.</p>
<p>This is a good example of why integration is rarely just about transporting data.</p>
<p>You also need to decide what the data <strong>means</strong> on both sides.</p>
<h2>What if there is no connection?</h2>
<p>Another question we considered was simple:</p>
<p><strong>What happens when the remote system cannot be reached?</strong></p>
<p>Distributed systems fail.</p>
<p>Networks fail.</p>
<p>Services become temporarily unavailable.</p>
<p>Authentication can fail.</p>
<p>An architecture that assumes a permanent connection without considering failure conditions will eventually create problems.</p>
<p>This is especially important when the remote functionality is embedded inside the normal user workflow.</p>
<p>The technical integration should therefore never be considered separately from availability and error handling.</p>
<h2>The resulting workflow</h2>
<p>The final solution connected our internal ERP and the client's ERP through REST Enabled SQL.</p>
<p>The customer could work with development-related information from their own application.</p>
<p>For example, they could:</p>
<ul>
<li><p>add new client needs</p>
</li>
<li><p>define priorities</p>
</li>
<li><p>follow tasks</p>
</li>
<li><p>ask additional questions</p>
</li>
<li><p>answer questions</p>
</li>
<li><p>report errors</p>
</li>
</ul>
<p>At the same time, our internal system could use that information for:</p>
<ul>
<li><p>time management</p>
</li>
<li><p>project planning</p>
</li>
<li><p>an overview of all projects</p>
</li>
</ul>
<p>The fundamental idea was:</p>
<pre><code class="language-text">Customer works here
        ↓
Client's application
        ↓
REST Enabled SQL
        ↓
Enrol's ERP
        ↓
Project management and development
</code></pre>
<p>The customer stays in the customer's application.</p>
<p>Our team stays in our system.</p>
<p>The information connects the two.</p>
<h2>Everything happens in context</h2>
<p>One of the most important design goals was that the customer should be able to work with the task <strong>where the task actually belongs</strong>.</p>
<p>Imagine that a user is on a particular page of an APEX application and finds a problem.</p>
<p>Instead of opening a completely separate task-management system, the application can already know:</p>
<ul>
<li><p>which system the user is in</p>
</li>
<li><p>which page they are on</p>
</li>
<li><p>which business context is involved</p>
</li>
</ul>
<p>The request can therefore be connected to that context from the beginning.</p>
<p>This reduces one of the most common sources of wasted time in support and development:</p>
<blockquote>
<p>“Which screen are you talking about?”</p>
</blockquote>
<h2>Task list</h2>
<p>From the client's point of view, tasks can still appear as a normal part of their application.</p>
<p>They can see the tasks relevant to their system.</p>
<p>They do not need access to all projects or all customers.</p>
<p>On our side, those same tasks can become part of a consolidated task-management environment.</p>
<p>This gives the two sides different views of the same work.</p>
<h2>Editing a task</h2>
<p>A task is not just a text description.</p>
<p>During its lifecycle it accumulates information.</p>
<p>For example:</p>
<ul>
<li><p>description</p>
</li>
<li><p>priority</p>
</li>
<li><p>questions</p>
</li>
<li><p>answers</p>
</li>
<li><p>assignments</p>
</li>
<li><p>status changes</p>
</li>
<li><p>timing information</p>
</li>
</ul>
<p>Connecting the task to the application gives all of this information context.</p>
<h2>How many issues are related to this page?</h2>
<p>One of the ideas demonstrated in the original presentation was showing the number of issues related to the current system or page.</p>
<p>This is a small feature, but it illustrates the advantage of integration very well.</p>
<p>Instead of thinking of task management as a completely separate application, task information becomes another dimension of the business application.</p>
<p>A user can see that there are open issues related to the area they are currently using.</p>
<p>That is very different from maintaining a completely disconnected ticket list.</p>
<h2>A task is also a history</h2>
<p>We did not only need the current status of a task.</p>
<p>The sequence of status changes was valuable too.</p>
<p>Conceptually:</p>
<pre><code class="language-text">Task
 ├── Status 1
 ├── Status 2
 ├── Status 3
 └── Current status
</code></pre>
<p>A task's status history tells a story.</p>
<p>It can show when:</p>
<ul>
<li><p>work started</p>
</li>
<li><p>additional information was requested</p>
</li>
<li><p>the customer responded</p>
</li>
<li><p>development finished</p>
</li>
<li><p>testing began</p>
</li>
<li><p>a problem was reopened</p>
</li>
<li><p>the task was completed</p>
</li>
</ul>
<p>That history later becomes useful for reporting.</p>
<h2>Tasks became part of a larger model</h2>
<p>In our internal system, the task did not remain an isolated object.</p>
<p>It became connected to other business information.</p>
<p>The presentation showed relationships between areas such as:</p>
<pre><code class="language-text">Client
  ↓
System
  ↓
Order
  ↓
Task
  ↓
Task Status

Task
  ↓
Timesheet
  ↓
Developer

Developer
  ↓
Employee Performance

Orders and Tasks
  ↓
Financial Planning

Developer
  ↓
Presence Planning

Client
  ↓
Transaction
  ↓
Invoice
</code></pre>
<p>This is where the solution became much more valuable.</p>
<p>Once the task is connected to the rest of the company's operational data, it becomes possible to analyze much more than whether the task is open or closed.</p>
<h2>From task management to time management</h2>
<p>The next step was connecting tasks with timesheets.</p>
<p>Traditional timesheets often have an inherent problem.</p>
<p>At the end of the day—or sometimes several days later—the developer has to remember:</p>
<blockquote>
<p>What exactly did I work on?</p>
</blockquote>
<p>But our system already had activity information.</p>
<p>It knew which tasks the developer had interacted with.</p>
<p>That gave us the idea of showing:</p>
<p><strong>Tasks I have touched today</strong></p>
<p>Instead of starting from an empty timesheet, the developer could start from actual task activity.</p>
<h2>A different approach to filling the timesheet</h2>
<p>The process became approximately:</p>
<pre><code class="language-text">Tasks I touched today
        ↓
Assign hours
        ↓
Assign start time / break
        ↓
Generate the daily time settlement
</code></pre>
<p>This is a fundamentally different experience from entering timesheet rows from memory.</p>
<p>The administrative process starts with data that already exists.</p>
<p>The developer mainly needs to add the time dimension.</p>
<h2>Daily time settlement</h2>
<p>Once the tasks and hours are connected, the system can create a daily time settlement.</p>
<p>Now every recorded period of work has context.</p>
<p>It is not just:</p>
<pre><code class="language-text">8 hours - development
</code></pre>
<p>It can be associated with:</p>
<pre><code class="language-text">Developer
    ↓
Task
    ↓
System
    ↓
Project / Order
    ↓
Client
</code></pre>
<p>That produces much more useful management information without requiring the developer to enter all of that information manually.</p>
<h2>Better data changes reporting</h2>
<p>The final part of my 2024 presentation focused heavily on the results.</p>
<p>Once tasks, statuses, systems, projects, developers and timesheets were connected, we could build reports that previously would have been difficult or unreliable.</p>
<h2>Project phases</h2>
<p>Because task statuses were recorded over time, we could analyze project phases.</p>
<p>Instead of having only a current snapshot, we could see how work moved through the process.</p>
<p>This helps answer questions such as:</p>
<ul>
<li><p>Where is work accumulating?</p>
</li>
<li><p>Where do tasks spend the most time?</p>
</li>
<li><p>Has testing become a bottleneck?</p>
</li>
<li><p>Are many tasks waiting for additional information?</p>
</li>
</ul>
<h2>Activity based on statuses</h2>
<p>Status changes also became a useful measure of activity.</p>
<p>They do not tell the complete story of developer productivity.</p>
<p>But they provide another view of what is happening in the system.</p>
<p>The important thing is that this information is generated naturally by the workflow.</p>
<p>No separate reporting process is required just to create the data.</p>
<h2>What are we working on now?</h2>
<p>This was one of the questions that originally motivated the project.</p>
<p>With the integrated data model, we could begin answering it from actual system activity.</p>
<p>The answer no longer depended only on somebody manually preparing a project-status report.</p>
<h2>Systems, projects and orders</h2>
<p>Tasks could also be analyzed in the context of projects and orders.</p>
<p>That allowed us to compare planned work with actual activity.</p>
<p>For a software company, that connection is particularly important.</p>
<p>A project can appear busy while consuming much more effort than expected.</p>
<p>Without connecting task activity to commercial and planning information, that problem may only become visible much later.</p>
<h2>Project timesheets</h2>
<p>Because timesheet entries were connected to tasks and projects, project-level time analysis became much more accurate.</p>
<p>We could move from:</p>
<blockquote>
<p>How many hours did this developer report?</p>
</blockquote>
<p>toward questions like:</p>
<blockquote>
<p>How much effort did this particular project, system or group of tasks consume?</p>
</blockquote>
<p>That is much more useful for project management.</p>
<h2>Task statuses over time</h2>
<p>The presentation included reports analyzing task statuses over selected periods.</p>
<p>Historical status information can reveal patterns that a current task list cannot.</p>
<p>For example, a current task may simply show:</p>
<pre><code class="language-text">Done
</code></pre>
<p>But the history can reveal that it spent a long time waiting in another phase.</p>
<p>That information can help explain delays and improve future planning.</p>
<h2>Tasks assigned to developers</h2>
<p>Because tasks were connected to developers, workload distribution could also be analyzed.</p>
<p>Again, the purpose was not simply to count tasks.</p>
<p>Ten trivial tasks and one major task are not equivalent.</p>
<p>But task assignments combined with statuses, estimates and timesheets provide useful context.</p>
<h2>Closed and open tasks</h2>
<p>The system could analyze task statuses both including and excluding closed tasks.</p>
<p>This matters because different questions require different views.</p>
<p>For operational work, we may care mainly about active tasks.</p>
<p>For retrospective project analysis, closed tasks are essential.</p>
<p>A good reporting model needs both perspectives.</p>
<h2>Overrun tasks</h2>
<p>Once estimated effort and actual timesheet information exist in the same data model, we can identify tasks whose actual effort exceeds expectations.</p>
<p>Conceptually:</p>
<pre><code class="language-text">Estimated effort
       vs.
Actual recorded effort
</code></pre>
<p>This is one of the most useful connections between task management and financial management.</p>
<p>Without the connection, overruns may become visible only at project level.</p>
<p>With it, the problematic task can be identified much earlier.</p>
<h2>Overdue tasks</h2>
<p>The same applies to deadlines.</p>
<p>Open and closed tasks can be evaluated against expected completion dates.</p>
<p>That provides a practical basis for investigating:</p>
<ul>
<li><p>delays</p>
</li>
<li><p>bottlenecks</p>
</li>
<li><p>underestimated work</p>
</li>
<li><p>blocked activities</p>
</li>
</ul>
<h2>System profitability</h2>
<p>This was one of the questions at the very beginning of the presentation:</p>
<p><strong>Is the project profitable?</strong></p>
<p>By connecting clients, systems, orders, tasks, developers and timesheets, we created a much stronger foundation for answering that question.</p>
<p>The integration did not magically calculate profitability.</p>
<p>It did something more fundamental:</p>
<p><strong>it created the data relationships required to understand it.</strong></p>
<h2>Weekly dashboard</h2>
<p>The same data could finally be summarized in management dashboards.</p>
<p>The path from the original problem to the dashboard was not:</p>
<pre><code class="language-text">Build a better dashboard
</code></pre>
<p>It was:</p>
<pre><code class="language-text">Capture better information
        ↓
Connect it to the right business objects
        ↓
Make the workflow easy enough to use
        ↓
Then build the dashboard
</code></pre>
<p>That distinction is important.</p>
<p>A beautiful dashboard cannot fix incomplete or fragmented source data.</p>
<h2>What I learned from the project</h2>
<p>Looking back at the 2024 presentation, REST Enabled SQL was an important part of the solution.</p>
<p>But it was not the main lesson.</p>
<p>The main lesson was about <strong>information flow</strong>.</p>
<p>We wanted to manage tasks where they naturally belonged.</p>
<p>We wanted to see all development work in one place.</p>
<p>And we wanted the administrative burden to be as small as possible.</p>
<p>REST Enabled SQL helped us connect those goals technically.</p>
<h2>The database was the integration layer</h2>
<p>There is also a broader architectural lesson here.</p>
<p>Both sides were based on Oracle technologies.</p>
<p>That meant the database itself could play a significant role in the integration.</p>
<p>Rather than moving all data into a new central application or forcing every customer to use the same task-management interface, we could connect applications while allowing each system to retain its role.</p>
<p>For this particular use case, that was a very powerful model.</p>
<h2>Would I use REST Enabled SQL everywhere?</h2>
<p>No.</p>
<p>The presentation itself already considered:</p>
<ul>
<li><p>its limitations</p>
</li>
<li><p>security</p>
</li>
<li><p>architecture</p>
</li>
<li><p>availability</p>
</li>
<li><p>user synchronization</p>
</li>
<li><p>maintenance</p>
</li>
</ul>
<p>Those questions still matter.</p>
<p>For public integrations, external consumers or strongly versioned service contracts, a dedicated REST API may be a more appropriate abstraction.</p>
<p>But when connecting Oracle-based environments that we understand and control, REST Enabled SQL can be a remarkably productive tool.</p>
<p>The right question is not:</p>
<blockquote>
<p>Is REST Enabled SQL better than REST APIs?</p>
</blockquote>
<p>The better question is:</p>
<blockquote>
<p>Which integration model best fits the systems, data ownership, security requirements and development process we actually have?</p>
</blockquote>
<h2>Looking back from 2026</h2>
<p>I gave this presentation on <strong>April 12, 2024</strong>.</p>
<p>Two years later, I find the underlying idea even more relevant than the specific implementation.</p>
<p>Modern development gives us more tools, more APIs, more automation and increasingly more AI.</p>
<p>But the central architectural questions remain surprisingly stable:</p>
<ul>
<li><p>Where should the information live?</p>
</li>
<li><p>Where should the user work?</p>
</li>
<li><p>Who owns the data?</p>
</li>
<li><p>How can we avoid entering the same information twice?</p>
</li>
<li><p>How do we capture useful data without creating unnecessary administration?</p>
</li>
<li><p>How do we turn operational activity into information that helps us make better decisions?</p>
</li>
</ul>
<p>In our case, connecting multiple Oracle APEX applications with REST Enabled SQL was one practical answer.</p>
<p>The result was not simply an integration between databases.</p>
<p>It was a connection between:</p>
<p><strong>customer needs, tasks, developer activity, time, project planning and business results.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Planning Oracle APEX Applications Before You Build]]></title><description><![CDATA[Based on a 2023 talk
This article is based on a presentation I gave at the Oracle APEX Budapest Meetup in October 2023.
The examples used the familiar Oracle HR schema, but the underlying planning pri]]></description><link>https://davidpataki.com/planning-oracle-apex-applications-before-you-build</link><guid isPermaLink="true">https://davidpataki.com/planning-oracle-apex-applications-before-you-build</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[application design]]></category><category><![CDATA[architecture]]></category><category><![CDATA[Low Code]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Tue, 29 Sep 2026 12:37:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6461f51b60bafcc7fa959d8c/f2c4b433-4e16-47a7-b3e0-f2584bccb647.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Based on a 2023 talk</strong></p>
<p>This article is based on a presentation I gave at the Oracle APEX Budapest Meetup in October 2023.</p>
<p>The examples used the familiar Oracle HR schema, but the underlying planning principles apply to much larger business applications as well.</p>
</blockquote>
<p>Oracle APEX makes it very easy to start building.</p>
<p>That is one of its greatest strengths.</p>
<p>But it also creates a temptation:</p>
<p><strong>to start creating pages before thinking through the application structure.</strong></p>
<p>For small applications, this may work.</p>
<p>For larger business systems, it usually creates problems later:</p>
<ul>
<li>inconsistent navigation</li>
<li>duplicated pages</li>
<li>unclear authorization</li>
<li>too many Dynamic Actions</li>
<li>unnecessary modal dialogs</li>
<li>an application that becomes harder to understand as it grows</li>
</ul>
<p>In my experience, a little planning before opening Page Designer saves a lot of restructuring later.</p>
<h2>Start with the data model</h2>
<p>For the original presentation, I used the Oracle HR schema.</p>
<p>It contains familiar entities such as:</p>
<ul>
<li>Employees</li>
<li>Departments</li>
<li>Locations</li>
<li>Countries</li>
<li>Regions</li>
</ul>
<p>This is a simple model, but it is enough to illustrate an important point:</p>
<p><strong>application structure should reflect both the relationships in the data and the way users work with that data.</strong></p>
<p>The first question is therefore not:</p>
<blockquote>
<p>Which APEX page type should I create?</p>
</blockquote>
<p>It is:</p>
<blockquote>
<p>How does the user move through the business information?</p>
</blockquote>
<h2>The simplest navigation model</h2>
<p>A first version of the application might look like this:</p>
<pre><code class="language-text">Home
├── Employees
│   └── Employee Data
├── Departments
│   └── Department Data
├── Locations
│   └── Location Data
├── Countries
│   └── Country Data
└── Regions
    └── Region Data
</code></pre>
<p>This is straightforward.</p>
<p>Every entity gets a list page and a detail page.</p>
<p>For a small application, this can already work well.</p>
<p>But business applications rarely remain this simple.</p>
<h2>Master-detail relationships change navigation</h2>
<p>Consider Departments and Employees.</p>
<p>A department is not only an independent record.</p>
<p>It also has employees.</p>
<p>Instead of forcing users to return to the Employees menu and search again, it is much more natural to allow them to navigate directly:</p>
<pre><code class="language-text">Department
    ↓
Department Data
    ↓
Department Employees
    ↓
Employee Data
</code></pre>
<p>The application begins to reflect the actual relationship between the data.</p>
<p>The same idea can be extended further:</p>
<pre><code class="language-text">Region
    ↓
Countries
    ↓
Locations
    ↓
Departments
    ↓
Employees
</code></pre>
<p>This is much closer to how users often think about business data.</p>
<h2>Think in user journeys, not only pages</h2>
<p>A common mistake is to design an APEX application as a collection of isolated pages.</p>
<p>The better question is:</p>
<p><strong>What path will the user follow?</strong></p>
<p>For example:</p>
<pre><code class="language-text">Regions
→ Region
→ Countries in Region
→ Country
→ Locations in Country
→ Location
→ Departments at Location
→ Department
→ Employees in Department
→ Employee
</code></pre>
<p>Once this flow is clear, several design decisions become easier:</p>
<ul>
<li>which pages should exist</li>
<li>which pages can be reused</li>
<li>where links should appear</li>
<li>what should be shown as related information</li>
<li>which actions should return the user to the previous context</li>
</ul>
<p>The application becomes a connected system rather than a collection of separate screens.</p>
<h2>Reuse pages where possible</h2>
<p>One of the things I explicitly warned against in the original presentation was:</p>
<p><strong>duplicated pages.</strong></p>
<p>It is tempting to create a separate Employee page for every context:</p>
<ul>
<li>Employee from the Employees menu</li>
<li>Employee from a Department</li>
<li>Employee from Search</li>
<li>Employee from another report</li>
</ul>
<p>Usually, this is unnecessary.</p>
<p>A better design is to reuse the same page and pass the appropriate record ID and context.</p>
<p>This reduces:</p>
<ul>
<li>duplicated logic</li>
<li>duplicated validations</li>
<li>maintenance effort</li>
<li>inconsistent behavior</li>
</ul>
<p>The more business logic a page contains, the more important reuse becomes.</p>
<h2>Master-detail is a design concept</h2>
<p>When I say master-detail, I am not necessarily talking about one specific APEX page type.</p>
<p>I am talking about the relationship between business objects and the way users navigate between them.</p>
<p>There are several ways to represent these relationships in APEX:</p>
<ul>
<li>master-detail pages</li>
<li>related reports</li>
<li>tabs</li>
<li>regions</li>
<li>links</li>
<li>cards</li>
<li>Interactive Reports</li>
<li>modal dialogs</li>
</ul>
<p>The important decision comes before the component choice.</p>
<p>First define:</p>
<p><strong>what information belongs together and how the user should move between it.</strong></p>
<p>Then choose the APEX components that best support that flow.</p>
<h2>Plan authorization early</h2>
<p>Authorization should not be something we add at the very end of the project.</p>
<p>Even a simple application can quickly develop several permission levels.</p>
<p>For example:</p>
<pre><code class="language-text">Login
├── Data View
├── Data Edit
├── Parameter View
└── Parameter Edit
</code></pre>
<p>These permissions affect much more than buttons.</p>
<p>They may determine:</p>
<ul>
<li>which pages are visible</li>
<li>which menu entries appear</li>
<li>which regions are rendered</li>
<li>which actions are available</li>
<li>which data can be modified</li>
</ul>
<p>If authorization is considered only after the application is already built, the existing structure may make permission management unnecessarily difficult.</p>
<h2>Navigation and authorization belong together</h2>
<p>A page may technically exist while being unavailable to a particular user.</p>
<p>That is often correct.</p>
<p>But the navigation should reflect the same authorization model.</p>
<p>For example, if a user cannot maintain parameters, there should usually be no visible navigation path leading to parameter maintenance.</p>
<p>This sounds obvious, but in larger applications inconsistent menu and page authorization can become confusing very quickly.</p>
<p>Planning both together avoids this.</p>
<h2>Standardization matters</h2>
<p>Another key point in the original talk was:</p>
<p><strong>standardize as much as possible.</strong></p>
<p>Oracle APEX already gives us an important advantage through Universal Theme.</p>
<p>Use that advantage.</p>
<p>Standardization can include:</p>
<ul>
<li>page layouts</li>
<li>report behavior</li>
<li>button placement</li>
<li>dialog behavior</li>
<li>navigation patterns</li>
<li>naming conventions</li>
<li>templates</li>
<li>validation patterns</li>
<li>authorization schemes</li>
</ul>
<p>Users should not have to learn the same application again on every page.</p>
<p>Developers should not have to rediscover how every page was built.</p>
<h2>Universal Theme is more than visual design</h2>
<p>Universal Theme is often treated mainly as a visual layer.</p>
<p>I think it is more useful to view it as a shared design vocabulary.</p>
<p>When standard components already solve a problem, creating a custom implementation should require a reason.</p>
<p>Custom JavaScript and CSS are sometimes necessary.</p>
<p>But every custom solution also creates something developers need to understand, test and maintain later.</p>
<p>Consistency is especially valuable in large business applications.</p>
<h2>Five things I try to avoid</h2>
<p>The original presentation ended with a short <strong>DON'T DO</strong> list.</p>
<p>These were the five points.</p>
<h3>1. A modal dialog opening another modal dialog</h3>
<p>A modal can be very useful.</p>
<p>A chain of modal dialogs usually is not.</p>
<p>Users can quickly lose track of:</p>
<ul>
<li>where they are</li>
<li>what they are editing</li>
<li>what happens when they close a dialog</li>
<li>which page owns the current state</li>
</ul>
<p>If a workflow becomes that deep, it may deserve a normal page.</p>
<h3>2. Duplicate pages</h3>
<p>Avoid creating nearly identical pages for slightly different navigation paths.</p>
<p>Reuse the same page when the business function is the same.</p>
<p>Otherwise every later change may have to be repeated in several places.</p>
<h3>3. Excessive Dynamic Actions</h3>
<p>Dynamic Actions are powerful.</p>
<p>That does not mean every piece of application behavior should become a Dynamic Action.</p>
<p>If a page contains many interacting client-side actions, understanding its behavior becomes increasingly difficult.</p>
<p>Use Dynamic Actions where they make the interaction clearer, but keep the overall application flow understandable.</p>
<h3>4. Missing navigation</h3>
<p>A technically working page is not automatically a usable application.</p>
<p>Users need to understand:</p>
<ul>
<li>where they are</li>
<li>how they arrived there</li>
<li>where they can go next</li>
<li>how they can return</li>
</ul>
<p>Navigation is part of application design, not decoration.</p>
<h3>5. Missing grouping</h3>
<p>As applications grow, flat menus and long page lists become difficult to understand.</p>
<p>Group related functions.</p>
<p>This can be done through:</p>
<ul>
<li>navigation hierarchy</li>
<li>menus</li>
<li>cards</li>
<li>page groups</li>
<li>functional modules</li>
<li>consistent naming</li>
</ul>
<p>Structure becomes increasingly valuable as the number of pages grows.</p>
<h2>Plan before Page Designer</h2>
<p>The main message of my 2023 presentation was simple:</p>
<p><strong>do not let the speed of Oracle APEX development replace application design.</strong></p>
<p>APEX allows us to create pages extremely quickly.</p>
<p>That makes planning more important, not less.</p>
<p>Before building an application, I try to answer questions such as:</p>
<ol>
<li>What are the main business objects?</li>
<li>How are they related?</li>
<li>What are the main user journeys?</li>
<li>Which pages can be reused?</li>
<li>What authorization levels exist?</li>
<li>How should navigation reflect those permissions?</li>
<li>Which UI patterns should be standardized?</li>
</ol>
<p>Once these questions are reasonably clear, Page Designer becomes much easier to use effectively.</p>
<h2>A simple planning model</h2>
<p>For many applications, the planning process can be summarized like this:</p>
<pre><code class="language-text">Data model
    ↓
Business objects
    ↓
Relationships
    ↓
User journeys
    ↓
Pages
    ↓
Navigation
    ↓
Authorization
    ↓
Standardized UI
</code></pre>
<p>The exact implementation may change.</p>
<p>The sequence of thinking is what matters.</p>
<h2>Build quickly, but design deliberately</h2>
<p>Oracle APEX gives developers an unusually fast way to turn database structures into working business applications.</p>
<p>That speed is a major advantage.</p>
<p>But speed should not mean that architecture, navigation and usability are decided accidentally while pages are being created.</p>
<p>A few minutes spent drawing relationships and user journeys before development can prevent much more expensive restructuring later.</p>
<p>That is one of the principles I have continued to use when building larger Oracle APEX applications:</p>
<p><strong>build quickly, but design deliberately.</strong></p>
]]></content:encoded></item><item><title><![CDATA[Generative AI in Oracle APEX: From a 2023 Vision to APEX 26.1]]></title><description><![CDATA[Looking back at 2023
In October 2023, I published an article in Hungarian about generative AI in application development.
At the time, many of the ideas discussed here were still expectations about wh]]></description><link>https://davidpataki.com/generative-ai-in-oracle-apex-from-a-2023-vision-to-apex-26-1</link><guid isPermaLink="true">https://davidpataki.com/generative-ai-in-oracle-apex-from-a-2023-vision-to-apex-26-1</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[AI]]></category><category><![CDATA[generative ai]]></category><category><![CDATA[apex_lang]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Tue, 29 Sep 2026 12:21:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6461f51b60bafcc7fa959d8c/ab3aaa30-71f3-4a83-b1db-40046e20c7e5.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Looking back at 2023</strong></p>
<p>In October 2023, I published an article in Hungarian about generative AI in application development.</p>
<p>At the time, many of the ideas discussed here were still expectations about where low-code and AI might take us.</p>
<p>Three years later, it is interesting to look back at what actually happened.</p>
<p><strong><a href="https://www.linkedin.com/pulse/generat%C3%ADv-ai-az-alkalmaz%C3%A1sfejleszt%C3%A9sben-david-pataki">Read the original Hungarian article →</a></strong></p>
</blockquote>
<p>In 2023, generative AI was already changing the way we thought about software development.</p>
<p>My main interest was not whether AI could write code.</p>
<p>The more interesting question was whether it could change the relationship between business users, developers and the applications they build together.</p>
<p>That question still matters today.</p>
<h2>The problem existed long before generative AI</h2>
<p>For many years, I have worked with business teams that were not simply users of enterprise software.</p>
<p>They understood their processes deeply and often knew exactly what would make their daily work more efficient.</p>
<p>The traditional software development model, however, creates a difficult translation problem:</p>
<p><strong>the business user describes a requirement, the developer interprets it, builds something, and the user later decides whether the result actually solves the original problem.</strong></p>
<p>This takes time.</p>
<p>And while the software project is progressing, users often create their own solutions using spreadsheets, small databases or other tools.</p>
<p>This is one of the reasons low-code platforms became interesting to me long before the current AI wave.</p>
<h2>Low-code had already started changing the boundary</h2>
<p>Oracle APEX allows applications to be built close to the data, using a largely declarative development model.</p>
<p>A developer — and in some cases an experienced business user — can create useful applications without building an entire technology stack from scratch.</p>
<p>In my 2023 article, I argued that generative AI could push this idea significantly further.</p>
<p>Instead of selecting components and manually writing every SQL statement, developers could increasingly describe what they wanted in natural language.</p>
<p>For example:</p>
<blockquote>
<p>Show the average salary of employees by department.</p>
</blockquote>
<p>The development environment could use information about the database structure to generate the SQL needed for the report or chart.</p>
<p>At the time, this felt like an important next step.</p>
<h2>From natural language to SQL</h2>
<p>One of the examples I discussed in 2023 was an AI assistant helping generate SQL based on a natural-language request.</p>
<p>The important part was not only the language model itself.</p>
<p>The model also needed context:</p>
<ul>
<li><p>available tables</p>
</li>
<li><p>columns and data types</p>
</li>
<li><p>primary keys</p>
</li>
<li><p>foreign keys</p>
</li>
<li><p>relationships between database objects</p>
</li>
</ul>
<p>Without this context, an LLM only knows SQL.</p>
<p>With the context, it can begin to understand <strong>your application and your data model</strong>.</p>
<p>This distinction is even more important today.</p>
<h2>What happened next?</h2>
<p>By 2026, AI support in Oracle APEX has moved considerably beyond the experiment I described in 2023.</p>
<p>APEX Assistant can help developers work with SQL directly inside the development environment.</p>
<p>Generative AI can also be used during application creation.</p>
<p>But perhaps the most interesting development for me is that AI-assisted development is moving beyond generating individual pieces of SQL or PL/SQL.</p>
<p>It is beginning to work with the structure of the application itself.</p>
<h2>APEXlang changes the discussion</h2>
<p>Oracle APEX 26.1 introduced APEXlang, an open, human-readable representation of an APEX application.</p>
<p>This is important for AI-assisted development.</p>
<p>Instead of treating an APEX application only as something configured through Page Designer or represented by a large SQL export, developers and AI tools can work with a structured application definition.</p>
<p>This makes new workflows possible:</p>
<ul>
<li><p>AI-assisted application generation</p>
</li>
<li><p>reviewing proposed application changes</p>
</li>
<li><p>version control</p>
</li>
<li><p>validation</p>
</li>
<li><p>application comparison</p>
</li>
<li><p>controlled modification of pages and components</p>
</li>
<li><p>collaboration between external AI coding agents and APEX</p>
</li>
</ul>
<p>The AI is no longer helping only with a SQL statement.</p>
<p>It can increasingly help work with the application model itself.</p>
<h2>From prompt to specification</h2>
<p>Another important change is the move from simple prompting toward structured specifications.</p>
<p>For enterprise applications, saying:</p>
<blockquote>
<p>Build me an application for managing customers.</p>
</blockquote>
<p>is rarely enough.</p>
<p>Real systems have:</p>
<ul>
<li><p>roles</p>
</li>
<li><p>workflows</p>
</li>
<li><p>validations</p>
</li>
<li><p>security rules</p>
</li>
<li><p>integrations</p>
</li>
<li><p>data models</p>
</li>
<li><p>business constraints</p>
</li>
<li><p>existing applications and processes</p>
</li>
</ul>
<p>The better the specification and context we provide, the more useful AI becomes.</p>
<p>This is why I think AI-assisted development will increasingly become <strong>specification-driven development</strong> rather than simply prompt-driven coding.</p>
<h2>AI does not remove the need for structure</h2>
<p>This is probably the biggest difference between how I thought about the subject in 2023 and how I think about it today.</p>
<p>In the early generative AI discussion, the emphasis was often on what AI could generate.</p>
<p>Today, I think the more important questions are:</p>
<ul>
<li><p>Can we understand what was generated?</p>
</li>
<li><p>Can we validate it?</p>
</li>
<li><p>Can we maintain it?</p>
</li>
<li><p>Can we safely modify it?</p>
</li>
<li><p>Can we integrate it with existing systems?</p>
</li>
<li><p>Can we govern the development process?</p>
</li>
</ul>
<p>Generating software is becoming easier.</p>
<p>Maintaining reliable enterprise software is not.</p>
<h2>Why low-code may become more important, not less</h2>
<p>It might seem logical that if AI can generate code, low-code platforms become less important.</p>
<p>I increasingly think the opposite may happen.</p>
<p>AI can generate almost unlimited amounts of code.</p>
<p>But more code also means more complexity to understand, test and maintain.</p>
<p>A declarative platform provides an abstraction layer.</p>
<p>Instead of asking AI to generate every technical implementation detail, we can describe the application's intent within a defined application model.</p>
<p>This is where I believe platforms such as Oracle APEX become particularly interesting in an AI-driven development world.</p>
<h2>The user and developer move closer together</h2>
<p>One idea from my 2023 article has become even more relevant.</p>
<p>The boundary between:</p>
<ul>
<li><p>developer and user</p>
</li>
<li><p>IT and business</p>
</li>
<li><p>supplier and customer</p>
</li>
</ul>
<p>continues to become less rigid.</p>
<p>AI allows people to express requirements more directly.</p>
<p>Low-code provides a controlled environment in which those requirements can become applications.</p>
<p>The developer's role does not disappear.</p>
<p>It changes.</p>
<p>More attention moves toward:</p>
<ul>
<li><p>architecture</p>
</li>
<li><p>data</p>
</li>
<li><p>security</p>
</li>
<li><p>integration</p>
</li>
<li><p>validation</p>
</li>
<li><p>governance</p>
</li>
<li><p>maintainability</p>
</li>
</ul>
<p>and less toward manually producing every line of implementation code.</p>
<h2>Looking back</h2>
<p>When I wrote about generative AI and APEX in 2023, I mainly saw AI as a new way to help developers and users communicate with the application platform.</p>
<p>Three years later, that idea has expanded considerably.</p>
<p>We are moving from:</p>
<p><strong>natural language → SQL</strong></p>
<p>toward:</p>
<p><strong>requirements → specification → application model → validated application</strong></p>
<p>That is a much bigger change.</p>
<p>And I think we are still near the beginning.</p>
<hr />
<p>My broader professional journey has followed a similar path:</p>
<p><strong>Database → APEX → Cloud → AI</strong></p>
<p>The technologies keep changing.</p>
<p>The central question remains remarkably consistent:</p>
<p><strong>How can we turn business knowledge and data into reliable software more effectively?</strong></p>
]]></content:encoded></item><item><title><![CDATA[Calling PL/SQL from JavaScript in Oracle APEX with AJAX]]></title><description><![CDATA[Updated from 2023
This article is an updated English version of a post I originally published in Hungarian in 2023. Read the original Hungarian version →

Oracle APEX does an excellent job of supporti]]></description><link>https://davidpataki.com/calling-pl-sql-from-javascript-in-oracle-apex-with-ajax</link><guid isPermaLink="true">https://davidpataki.com/calling-pl-sql-from-javascript-in-oracle-apex-with-ajax</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[PL/SQL]]></category><category><![CDATA[Ajax]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Tue, 29 Sep 2026 12:08:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6461f51b60bafcc7fa959d8c/07cbc269-53fb-4d4b-a423-862a1a92e2ea.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Updated from 2023</strong></p>
<p>This article is an updated English version of a post I originally published in Hungarian in 2023. <a href="/plsql-futtatasa-a-hatterben"><strong>Read the original Hungarian version →</strong></a></p>
</blockquote>
<p>Oracle APEX does an excellent job of supporting declarative application development.</p>
<p>In Page Designer, we can build a page using components, configure their properties, add a few processes or validations, and very quickly have a working business application.</p>
<p>But sometimes we want to execute server-side logic without submitting and rebuilding the whole page.</p>
<p>This is where AJAX becomes useful.</p>
<p>In this example, I will show how to call a PL/SQL process from JavaScript using <code>apex.server.process</code>, pass a value to the server, update data in the database, and refresh only the affected region.</p>
<h2>The example</h2>
<p>Let's use a very simple Classic Report showing employees and their salaries.</p>
<p>When the user clicks a salary value, we want to:</p>
<ol>
<li><p>identify the employee,</p>
</li>
<li><p>call a server-side PL/SQL process,</p>
</li>
<li><p>double the employee's salary,</p>
</li>
<li><p>return control to the browser,</p>
</li>
<li><p>refresh the report.</p>
</li>
</ol>
<p>There is no full page submit.</p>
<h2>1. Make the report value clickable</h2>
<p>Assume our Classic Report query returns:</p>
<ul>
<li><p><code>EMPLOYEE_ID</code></p>
</li>
<li><p><code>SALARY</code></p>
</li>
</ul>
<p>Instead of using an inline JavaScript handler, we can give the link a CSS class and store the employee ID in a data attribute.</p>
<p>In the <strong>HTML Expression</strong> of the Salary column:</p>
<pre><code class="language-html">&lt;a href="#" class="js-salary" data-employee-id="#EMPLOYEE_ID#"&gt;#SALARY#&lt;/a&gt;
</code></pre>
<p>The report now renders the salary as a clickable value.</p>
<p>The <code>data-employee-id</code> attribute contains the ID of the employee whose salary we want to update.</p>
<h2>2. Create a Dynamic Action</h2>
<p>Create a Dynamic Action with:</p>
<ul>
<li><p><strong>Event:</strong> Click</p>
</li>
<li><p><strong>Selection Type:</strong> jQuery Selector</p>
</li>
<li><p><strong>jQuery Selector:</strong> <code>.js-salary</code></p>
</li>
</ul>
<p>Because the report will later be refreshed, configure the event so that it also works for dynamically refreshed report rows.</p>
<p>For the True Action, choose <strong>Execute JavaScript Code</strong>.</p>
<p>Use:</p>
<pre><code class="language-javascript">const employeeId = this.triggeringElement.dataset.employeeId;

console.log("Employee ID:", employeeId);

apex.server.process(
    "PROC_SALARY",
    {
        x01: employeeId
    },
    {
        dataType: "text",

        success: function (pData) {
            console.log("Server response:", pData);
            apex.region("myREPORT").refresh();
        },

        error: function (jqXHR, textStatus, errorThrown) {
            apex.debug.error(
                "PROC_SALARY failed",
                textStatus,
                errorThrown
            );

            apex.message.alert("The salary update failed.");
        }
    }
);
</code></pre>
<p>The important part is:</p>
<pre><code class="language-javascript">apex.server.process("PROC_SALARY", ...)
</code></pre>
<p>This calls an APEX Ajax Callback named <code>PROC_SALARY</code>.</p>
<p>We pass the employee ID using:</p>
<pre><code class="language-javascript">x01: employeeId
</code></pre>
<p>On the server side, APEX exposes this value through:</p>
<pre><code class="language-plsql">apex_application.g_x01
</code></pre>
<h2>3. Create the PL/SQL Ajax Callback</h2>
<p>Create an <strong>Ajax Callback</strong> process named:</p>
<pre><code class="language-text">PROC_SALARY
</code></pre>
<p>The PL/SQL code can look like this:</p>
<pre><code class="language-plsql">begin
    update oehr_employees
       set salary = salary * 2
     where employee_id = to_number(apex_application.g_x01);

    commit;

    htp.p('ok');
exception
    when others then
        rollback;
        apex_debug.error('PROC_SALARY failed: %s', sqlerrm);
        raise;
end;
</code></pre>
<p>The value passed from JavaScript in <code>x01</code> is available through:</p>
<pre><code class="language-plsql">apex_application.g_x01
</code></pre>
<p>We use it to identify the employee whose salary needs to be updated.</p>
<p>The callback sends a simple text response back to JavaScript:</p>
<pre><code class="language-plsql">htp.p('ok');
</code></pre>
<p>Because the JavaScript call specifies:</p>
<pre><code class="language-javascript">dataType: "text"
</code></pre>
<p>the returned value is available in the <code>success</code> function as <code>pData</code>.</p>
<h2>4. Refresh only the report</h2>
<p>If the server-side process completes successfully, we execute:</p>
<pre><code class="language-javascript">apex.region("myREPORT").refresh();
</code></pre>
<p>For this to work, set the Classic Report's <strong>Static ID</strong> to:</p>
<pre><code class="language-text">myREPORT
</code></pre>
<p>Only the report is refreshed.</p>
<p>The rest of the page remains unchanged.</p>
<p>The complete flow is therefore:</p>
<pre><code class="language-text">User clicks Salary
        ↓
Dynamic Action
        ↓
apex.server.process
        ↓
PROC_SALARY Ajax Callback
        ↓
UPDATE in Oracle Database
        ↓
Response returned to JavaScript
        ↓
Classic Report refresh
</code></pre>
<h2>Why use AJAX?</h2>
<p>The main advantage is that we do not need to submit and reload the entire page just to execute a small server-side operation.</p>
<p>This can provide a smoother user experience for operations such as:</p>
<ul>
<li><p>changing a value,</p>
</li>
<li><p>executing a small PL/SQL operation,</p>
</li>
<li><p>validating data,</p>
</li>
<li><p>retrieving server-side information,</p>
</li>
<li><p>refreshing part of a page,</p>
</li>
<li><p>triggering business logic from a user action.</p>
</li>
</ul>
<p>It also allows us to combine APEX's declarative development model with JavaScript when we need more control over the interaction.</p>
<h2>What changed since the original 2023 version?</h2>
<p>The core idea of the original article remains valid.</p>
<p><code>apex.server.process</code> is still a useful way to call server-side APEX processes from JavaScript.</p>
<p>However, I would implement the client-side part differently today.</p>
<p>My original example used JavaScript directly inside the report link. In modern APEX applications, I prefer separating markup from behavior and using Dynamic Actions or dedicated JavaScript code instead.</p>
<p>This makes the application easier to understand, maintain and change later.</p>
<p>Error handling is another area worth making explicit.</p>
<p>A real application should not assume that every AJAX request succeeds. Both the client and server side should handle unexpected errors appropriately.</p>
<h2>AJAX is not the same as background processing</h2>
<p>There is also an important distinction.</p>
<p>Although the PL/SQL process executes without a full page submit, this is still a request-response operation.</p>
<p>The browser sends the AJAX request and waits for the server-side process to finish.</p>
<p>For short operations, this is exactly what we want.</p>
<p>For genuinely long-running tasks — imports, large calculations, integrations or batch processing — a real background execution mechanism is usually more appropriate.</p>
<p>That may involve APEX background processing capabilities or database mechanisms such as <code>DBMS_SCHEDULER</code>.</p>
<p>So the question is not simply:</p>
<p><strong>How can I run PL/SQL in the background?</strong></p>
<p>A better question is:</p>
<p><strong>Does the user need to wait for the result, or should the work continue independently of the browser request?</strong></p>
<p>That distinction becomes increasingly important as APEX applications grow from simple pages into larger enterprise systems.</p>
<h2>Conclusion</h2>
<p>One of the strengths of Oracle APEX is that we can start with declarative development and add lower-level control only where we actually need it.</p>
<p><code>apex.server.process</code> provides a simple bridge between browser-side JavaScript and server-side PL/SQL.</p>
<p>For small interactive operations, it allows us to:</p>
<p><strong>JavaScript → PL/SQL → Oracle Database → refresh only what changed</strong></p>
<p>without submitting the whole page.</p>
<p>It is a small technique, but one I have used repeatedly in real APEX applications.</p>
]]></content:encoded></item><item><title><![CDATA[How to Generate a Database User Password with Special Characters?]]></title><description><![CDATA[At first glance, this doesn’t seem like a difficult task. Yet, I couldn’t find a simple and reliable solution.
Since I am developing an APEX application to manage multiple databases, I needed a functi]]></description><link>https://davidpataki.com/how-to-generate-a-database-user-password-with-special-characters</link><guid isPermaLink="true">https://davidpataki.com/how-to-generate-a-database-user-password-with-special-characters</guid><category><![CDATA[Oracle Database]]></category><category><![CDATA[PL/SQL]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Sun, 31 Aug 2025 18:44:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756665645231/f3df340c-e6f3-4488-9574-54f4d3945c6c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>At first glance, this doesn’t seem like a difficult task. Yet, I couldn’t find a simple and reliable solution.</p>
<p>Since I am developing an APEX application to manage multiple databases, I needed a function that could generate a new password for a user and send it to a given email address.</p>
<p>In my case, I am working with <strong>OCI Autonomous Transaction Processing (ATP)</strong> databases, where users are assigned to the <code>DEFAULT</code> profile:</p>
<pre><code class="language-sql">SELECT profile, resource_name, limit
FROM dba_profiles WHERE profile = 'DEFAULT' AND resource_type = 'PASSWORD';
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756664860548/b07f1224-0ca9-4e75-8653-5fabff333edf.png" alt="" style="display:block;margin:0 auto" />

<p>The password rules are validated by the <code>CLOUD_VERIFY_FUNCTION</code>:</p>
<pre><code class="language-sql">SELECT text
FROM dba_source WHERE name = 'CLOUD_VERIFY_FUNCTION' ORDER BY line;
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756664959425/e4c9947b-be21-44ee-a833-dac30d46cc90.png" alt="" style="display:block;margin:0 auto" />

<p>From the code, we can see that complexity is checked through the call: ORA_COMPLEXITY_CHECK(password, 12, null, 1, 1, 1, null);</p>
<p>This means the password must be at least 12 characters long and contain at least one lowercase letter, one uppercase letter, and one number.<br />But what about <strong>special characters</strong>?</p>
<p>The <code>DEFAULT</code> user profile does not enforce them, but for security reasons I wanted to ensure that generated passwords also contain at least one special character.</p>
<p>After checking the <code>ORA_COMPLEXITY_CHECK</code> function itself:</p>
<pre><code class="language-sql">SELECT text
FROM dba_source WHERE name = 'ORA_COMPLEXITY_CHECK' ORDER BY line;
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756665112857/7715ec8b-1a13-4783-834e-f7fb68a6c603.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>My Password Generator</h2>
<p>I created my own password generator function using the <code>DBMS_RANDOM</code> package:</p>
<pre><code class="language-sql">create function f_pwd_gen(p_length number default 20) return varchar2 as
    a number:=0;
    k number;
    i number;
    r varchar2(100); -- result
    v_check varchar2(100);
begin
    loop
      -- The password must begin with a character!
      a:=a+1; -- iteration counter
      r:=upper(dbms_random.string('u',1));
      v_check:='';
      
      for k in 2..least(p_length,100) loop -- max 100 chars
          i:=round(dbms_random.value(0,9));  
          if i between 0 and 3 then -- lower
            r:=r || lower(dbms_random.string('u',1));
            v_check:=v_check || 'L';
          elsif i between 4 and 6 then -- upper
            r:=r || upper(dbms_random.string('u',1));
            v_check:=v_check || 'U';              
          elsif i between 7 and 8 then -- number
            r:=r || lower(round(dbms_random.value(0,9)));
            v_check:=v_check || 'N';              
          else -- special
            r:=r || SUBSTR('#$_', dbms_random.value(1, 3), 1);
            v_check:=v_check || 'S';              
          end if;  
      end loop;  
      
      -- Replace potentially misleading characters
      r:=replace(r,'o','f');  
      r:=replace(r,'0','3');                
      r:=replace(r,'O','G');    
      r:=replace(r,'l','t');    

      exit when a&gt;100 
        or (instr(v_check,'L')&gt;0 and instr(v_check,'U')&gt;0 
        and instr(v_check,'N')&gt;0 and instr(v_check,'S')&gt;0 );
   end loop;   

   return r;
end;
</code></pre>
<p>At first, I tried including as many symbols as possible in the “special character” line. However, when setting the new password, I constantly received error messages.</p>
<hr />
<h2>The Real Issue</h2>
<p>Passwords are usually set with a command like:</p>
<pre><code class="language-sql">ALTER USER SCOTT IDENTIFIED BY fsd32fasSD_FS;
</code></pre>
<p>If you don’t wrap the password in quotes, the SQL parser interprets many special characters incorrectly. That’s why it may look like only <code>#</code>, <code>$</code>, or <code>_</code> are allowed.</p>
<p>✅ The fix is simple: <strong>enclose the password in double quotes</strong>. (Of course, I only realized this much later.)</p>
<pre><code class="language-sql">ALTER USER SCOTT IDENTIFIED BY "N3w!Pass@2025";
</code></pre>
<p>When quoted, Oracle accepts almost any character (except the double quote <code>"</code> itself and the null character).</p>
<p>⚠️ Be aware that some shells and tools (SQL*Plus, terminals, scripts) interpret certain characters (<code>!</code>, <code>&amp;</code>, <code>\</code>) before they reach the database. In those cases, escape them at the client level or use <code>EXECUTE IMMEDIATE</code> in PL/SQL to set the password.</p>
<hr />
<h2>Conclusion &amp; Best Practices</h2>
<p>Even though Oracle’s <code>ORA_COMPLEXITY_CHECK</code> function doesn’t require special characters by default, you can and should include them for stronger security. The key is to quote your password in the <code>ALTER USER</code> statement so all special characters are accepted.</p>
<p>If you’re building workflows in Oracle APEX (or any automation around database password resets), keep in mind:</p>
<ul>
<li><p><strong>Always quote the password</strong> in <code>ALTER USER</code>.</p>
</li>
<li><p>Test which characters your client environment accepts without extra escaping.</p>
</li>
<li><p>Replace ambiguous characters (<code>O</code>, <code>0</code>, <code>l</code>) to avoid confusion.</p>
</li>
<li><p>Consider sending passwords securely.</p>
</li>
<li><p>Require users to change their generated password upon first login.</p>
</li>
</ul>
<p>👉 By quoting the password properly, you can safely generate and use strong passwords containing a full range of special characters.</p>
]]></content:encoded></item><item><title><![CDATA[How I Prepared for the Oracle Cloud Infrastructure 2025 Certified Foundations Associate Exam]]></title><description><![CDATA[About a year ago, I started working more seriously with Oracle Cloud, and looking back, I honestly regret not taking the OCI Foundations Associate certification sooner. Preparing for an exam forces yo]]></description><link>https://davidpataki.com/how-i-prepared-for-the-oracle-cloud-infrastructure-2025-certified-foundations-associate-exam</link><guid isPermaLink="true">https://davidpataki.com/how-i-prepared-for-the-oracle-cloud-infrastructure-2025-certified-foundations-associate-exam</guid><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Oracle certification]]></category><category><![CDATA[OCI]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Sun, 24 Aug 2025 18:35:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1756060293600/6ae99835-df9a-48f2-8903-38c245aabfe1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>About a year ago, I started working more seriously with Oracle Cloud, and looking back, I honestly regret not taking the <a href="https://education.oracle.com/oracle-cloud-infrastructure-2024-foundations-associate/pexam_1Z0-1085-25"><strong>OCI Foundations Associate certification</strong></a> sooner. Preparing for an exam forces you to study systematically, and in my case that turned out to be one of the most valuable parts of the process. It gave me a broad, structured understanding of the different OCI components — something that months of reading documentation or solving “how do I fix this?” problems in real projects hadn’t fully delivered.</p>
<p>Of course, I didn’t start from scratch. As an active OCI user, I already had practical experience. But going through the official materials filled in many gaps and connected the dots between different services in a way that hands-on troubleshooting alone couldn’t.</p>
<hr />
<h2>From Books to On-Demand Learning</h2>
<p>Over the past ten years, I’ve taken several Oracle certifications, and the process has changed dramatically. For my very first exam, I ordered a book from Amazon, studied it cover to cover, and still passed only on the second attempt. At the time, official Oracle courses were out of reach — a full week, thousands of dollars in cost, and of course, mandatory travel. The exam itself meant going to a test center, emptying your pockets, and being watched by four cameras.</p>
<p>Fast forward to today: the process is <strong>simpler, faster, and more accessible</strong>. Many Oracle University courses and exams are free until October 31, 2025 in the <a href="https://education.oracle.com/race-to-certification-2025">Race to Certification 2025 program</a>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756059690562/c07b84b6-829d-4392-99fe-62be222c5c34.png" alt="" style="display:block;margin:0 auto" />

<p>The quality of the learning materials is excellent — well-paced, well-illustrated, and supported with practice questions.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756059768796/1e7cba6f-e528-4821-add3-cdb2f9a91e10.png" alt="" style="display:block;margin:0 auto" />

<p>I also appreciated that the same Oracle University content is available on <a href="https://www.linkedin.com/learning/oracle-cloud-infrastructure-foundations-associate-26285125"><strong>LinkedIn Learning</strong></a>. The platform’s transcript view made it easy to jump to exactly the right moment in each video, and with AI I could generate quick summaries and clarifications—even in Hungarian—when I wanted a different explanation. The courses are subtitled in <strong>30+ languages</strong>, which lowers the barrier for non-native speakers (even though the exam itself is in English). Combined with the clear pacing and visuals, that made my study sessions faster and far more focused.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756059409598/0b53d0dc-f7ba-4c6d-a219-091ffa2e9e05.png" alt="" style="display:block;margin:0 auto" />

<p>The training is subtitled in more than 30 languages, which makes it even more approachable globally.</p>
<hr />
<h2>Exam Details</h2>
<ul>
<li><p><strong>Exam Code:</strong> 1Z0-1085-25</p>
</li>
<li><p><strong>Format:</strong> 40 multiple-choice questions</p>
</li>
<li><p><strong>Duration:</strong> 60 minutes</p>
</li>
<li><p><strong>Passing Score:</strong> 65%</p>
</li>
<li><p><strong>My Score:</strong> 80% (completed in ~25 minutes)</p>
</li>
</ul>
<p>Each question has four possible answers, and there’s always exactly one correct choice. In my experience, at least half of the questions were very similar (sometimes identical) to the ones in the official practice test. The practice test is particularly useful because it shows you where you made mistakes — unlike the real exam, where you only see the final score.</p>
<p>Another big advantage: you get <strong>15 free attempts</strong> at the exam. That removes a lot of the pressure and gives you room to practice until you feel confident.</p>
<hr />
<h2>Final Thoughts</h2>
<p>If you’re already using OCI, I strongly recommend taking the <a href="https://mylearn.oracle.com/ou/learning-path/become-an-oci-foundations-associate-2025/148056">OCI Foundations Associate exam</a>. Not only will you gain a clear, structured view of the platform, but you’ll also be better equipped to explain OCI to colleagues, customers, and decision-makers. For me, the certification wasn’t just a badge — it was a way to step back from day-to-day problem solving and build a more complete mental model of Oracle Cloud.</p>
<p>I walked away with a stronger foundation, a certification to show for it, and plenty of motivation to continue down the OCI certification path.</p>
]]></content:encoded></item><item><title><![CDATA[Navigating the Cloud: My Transition to Oracle's Autonomous Transaction Database - Part 3]]></title><description><![CDATA[Since I want to migrate many APEX applications to the same Autonomus database, it is obvious that each system needs its own object storage for the migration. Moreover, it may be useful later to store ]]></description><link>https://davidpataki.com/navigating-the-cloud-my-transition-to-oracles-autonomous-transaction-database-part-3</link><guid isPermaLink="true">https://davidpataki.com/navigating-the-cloud-my-transition-to-oracles-autonomous-transaction-database-part-3</guid><category><![CDATA[OCI]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Oracle Autonomous Database]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Tue, 22 Apr 2025 11:17:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745320535931/4442739e-961e-4607-bee9-5aa59f98112c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since I want to migrate many <strong>APEX application</strong>s to the same <strong>Autonomus database</strong>, it is obvious that each system needs its own <strong>object storage</strong> for the migration. Moreover, it may be useful later to store images or generated files in a separate <strong>bucket</strong> instead of in the <strong>database</strong>.</p>
<p>The question is how to separate the objects of each system within a tenancy in the <strong>Oracle Cloud</strong>. Or how can we give them individual, external access? In OCI we can assign <strong>privilege</strong>s to registered <strong>users</strong>. However, we do not want each (technical) <strong>user</strong> to have access to the resources of another.</p>
<h1>Architecture</h1>
<p>In my architectural approach, a client has an <strong>APEX application</strong> (Application A). Each application has a separate <strong>workspace</strong> and a separate <strong>schema</strong>. It helps a lot to keep the architecture clean that each application, system, client, whatever you want to call it, is given an alias.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745319730125/796447c7-09fb-4ab3-9f1d-8226bade8c50.png" alt="" style="display:block;margin:0 auto" />

<p>For example, Global Network Application has the alias GN. So the <strong>schema</strong> name is GN_PROD, the <strong>workspace</strong> is GN_PROD_WKS, and the <strong>application</strong> alias is GN. And in the DEV environment, GN_DEV, GN_DEV_WKS.</p>
<p>Following the logic above, each system also gets its own <strong>compartment</strong> (in our case, GN_Compartment).</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1745320184405/080ef42b-6034-4026-b5d3-5cd6186b9125.png" alt="" style="display:block;margin:0 auto" />

<p>Here, the DEV and PROD environments share the <strong>OCI resource</strong>s. A <strong>bucket</strong> (GN_Bucket) is created under each <strong>compartment</strong>. The <strong>file</strong>s created by the live and development environments can be separated within the <strong>bucket</strong>.</p>
<h1>What about privilege management?</h1>
<p>In OCI, permission roles are managed by <strong>policies</strong>. I created this <strong>policy</strong> in the <strong>root compartment</strong>, in our case called GN_ADMIN_POLICY.</p>
<p>I also created a special <strong>user group</strong> to which I added the system administrators and the technical <strong>user</strong>. GN_ADMIN_POLICY has the following <strong>policy statement:</strong></p>
<p><code>Allow group GN_ADMIN_GROUP to manage all resources in compartment GN_compartment</code></p>
<p>This gives all members of GN_ADMIN_GROUP read and write access to GN_Bucket in GN_compartment.</p>
<h1>Creating a technical user</h1>
<p>In OCI, a <strong>user</strong> must have a unique <strong>email</strong> address. At least I did not find an alternative solution. For me, the problem was that as a Google Workspace subscriber, each new email address or user is a significant additional monthly cost.</p>
<p>Fortunately, Google allows up to 30 variations of an email address. So I didn't have to create the technical users as new Google users, that was enough in OCI.</p>
<p>Of course, there are many other combinations possible to separate permissions, but as a PROD and DEV <strong>ATP</strong> user, this seems to be the best solution.</p>
]]></content:encoded></item><item><title><![CDATA[Navigating the Cloud: My Transition to Oracle's Autonomous Transaction Database - Part 2]]></title><description><![CDATA[I've been subscribing to Oracle's cloud-based database, the Autonomous Transaction Database (ATP), for over a month now. Apart from minor problems, we've been steadily adding applications to the platf]]></description><link>https://davidpataki.com/navigating-the-cloud-part-2</link><guid isPermaLink="true">https://davidpataki.com/navigating-the-cloud-part-2</guid><category><![CDATA[OCI]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Oracle Autonomous Database]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Sat, 23 Nov 2024 20:50:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732390141196/98bd3e0e-f5f5-46ac-9845-574e609735c1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've been subscribing to Oracle's cloud-based database, the Autonomous Transaction Database (ATP), for over a month now. Apart from minor problems, we've been steadily adding applications to the platform.</p>
<p>The first major difficulty was understanding the administration. As database and APEX application developers, the four things we need to focus on most when it comes to administration are:</p>
<ul>
<li><p>Server</p>
</li>
<li><p>Database</p>
</li>
<li><p>APEX instance</p>
</li>
<li><p>APEX workspace and users</p>
</li>
</ul>
<h1>Server</h1>
<p>As I mentioned in the <a href="https://enrol.hashnode.dev/navigating-the-cloud-part-1">previous article</a>, as developers, we don't really want to be involved in administration. This is why using cloud-based services is a good choice. To get started, there is nothing extra to do other than subscribe. After registration, an Administrators group is created and we immediately become members of it.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732390732632/d9073dc3-2cca-4662-a5e3-c9e09f079d02.png" alt="" />

<p>The management and allocation of privileges is done through groups. The group can be found under <strong>Identity &amp; Security/Domains/Default domain/Groups</strong> where you can add users to the group.</p>
<p>And we need to assign policies to the groups. The policies contain the privileges themselves. Policies can be found under <strong>Identity &amp; Security/Policies</strong>.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732391220569/c71221c1-c977-4546-816f-3aa747f4d21e.png" alt="" style="display:block;margin:0 auto" />

<p>Of course, as I wrote, initially we get admin rights and we can do anything in the cloud. However, once we want to add more users and not with administrator rights, <a href="https://docs.oracle.com/en-us/iaas/Content/Identity/Concepts/policies.htm">we need more understanding</a>.</p>
<h1>Database administration</h1>
<p>By going into the <strong>Oracle Database/Autonomous Database</strong> menu, we have to click on our database - I only have one - and we are taken to the database administration.</p>
<p>Here, clicking on <strong>Database Actions/Database Users</strong> will bring up the default database users, including ADMIN.</p>
<p>Here it is important that Web access is enabled (it is enabled for ADMIN) so that we can open an SQL window.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732391669488/b12616ef-444a-4fee-87b7-bb44c70f7198.png" alt="" />

<p>The ADMIN user has the rights of the classic SYS user and is therefore the main administrator. It allows you to create and manage additional users and privileges.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732392051009/9706f5f9-b201-424d-a701-4aa5282dc6a3.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732392164039/ed4bba9d-0aeb-4de1-afc2-1226f589c097.png" alt="" style="display:block;margin:0 auto" />

<h1>APEX Instance</h1>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732392330365/89161ce1-ce01-4e77-be2e-c0b60c1889f6.png" alt="" style="display:block;margin:0 auto" />

<p>APEX instance administration can be accessed via the <strong>Database Actions/View all database actions/APEX</strong> menu.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732392470397/97ea78a7-d9e6-423f-9de1-f012562adedc.png" alt="" style="display:block;margin:0 auto" />

<p>In the cloud, the administration of APEX users is very different. After a few hours of trying, I managed to understand the logic of this. When creating a workspace, you have to specify whether you want to use an existing schema or create a new one.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732392855093/e832f117-9581-4ed2-9a05-4636fd0cc652.png" alt="" style="display:block;margin:0 auto" />

<h2>New Schema</h2>
<p>When creating a new schema, we do not have the option to specify its name.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732392935775/9d08cec0-243e-483e-a098-d9b9298658f9.png" alt="" style="display:block;margin:0 auto" />

<p>The logic surrounding the workspace username and password in Oracle's APEX can indeed be complex. Here's a simplified explanation:</p>
<ol>
<li><p><strong>Existing Database User</strong>:</p>
<ul>
<li><p>If the workspace username (e.g., DPATAKI) already exists as a database user, the workspace will link to this existing database user.</p>
</li>
<li><p>To log into the workspace, use the database password associated with this username.</p>
</li>
<li><p>The workspace password you set will be used for the APEX user within the applications created in the workspace.</p>
</li>
</ul>
</li>
<li><p><strong>New Database User</strong>:</p>
<ul>
<li><p>If the workspace username does not exist in the database, a new database user is created.</p>
</li>
<li><p>In this case, the database password and the APEX password will be the same as the one you set during workspace creation.</p>
</li>
</ul>
</li>
<li><p><strong>Privileges</strong>:</p>
<ul>
<li>A new user created by an APEX workspace in the database will not automatically have privileges to create connections.</li>
</ul>
</li>
</ol>
<p>This setup ensures that the database and APEX environments are securely linked while maintaining separate authentication mechanisms for database access and APEX application access.</p>
<h2>Existing Schema</h2>
<p>I prefer to create the schema first as a database administrator and here only the new workspace associated with it. The reason for this is that the naming conventions I use for schema names are very important to me.</p>
<p>The logic here is the same as in the previous point. The interesting thing is that the database user and the workspace username can be the same.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732393418634/c8c62432-24fd-4ef4-9d02-0e2e1de51108.png" alt="" style="display:block;margin:0 auto" />

<h1>APEX workspace and users</h1>
<p>It logically follows from the previous section that you can only access the APEX workspace with a database name and password. Let's say the login screen shows that this is the case, I just didn't notice it.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732394033890/b783cd40-40fc-4939-8ddf-003fb784b630.png" alt="" style="display:block;margin:0 auto" />

<p>In the APEX workspace, the three levels of privilege—Administrator, Developer, and User—function similarly in both on-premises and cloud environments.</p>
<p>However, in the cloud, when you add an Administrator or Developer to a workspace, a database schema is automatically created for them. This automatic creation of a schema can be confusing, but it is likely designed to ensure that each Administrator or Developer has a dedicated space for their work, enhancing security and organization.</p>
<p>On the other hand, creating a simple User does not result in a new schema; the User exists only within the APEX workspace, which simplifies user management for non-development roles.</p>
]]></content:encoded></item><item><title><![CDATA[Navigating the Cloud: My Transition to Oracle's Autonomous Transaction Database - Part 1]]></title><description><![CDATA[Over the past 15+ years, we have developed database applications in two distinct environments.
Our larger customers provide on-premise environments and handle their own database administration tasks. ]]></description><link>https://davidpataki.com/navigating-the-cloud-part-1</link><guid isPermaLink="true">https://davidpataki.com/navigating-the-cloud-part-1</guid><category><![CDATA[OCI]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Oracle Autonomous Database]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Thu, 17 Oct 2024 20:26:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729195992102/1ff42dbf-afbf-4095-ad8a-ec39274a6652.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the past 15+ years, we have developed database applications in two distinct environments.</p>
<p>Our larger customers provide <strong>on-premise</strong> environments and handle their own database administration tasks. For our smaller customers, we rely on an independent <strong>cloud provider for hosting</strong>, allowing us to focus on development.</p>
<p>Both solutions have their limitations.</p>
<p>In the second case, we also use Oracle XE, which is an extra limitation. Still, we were able to operate without Oracle Cloud Infrastructure for a very long time.</p>
<p>But because of a new project we had, I made the decision to go ahead with our own <strong>Autonomous Transaction Database</strong> (ATP) subscription.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729196528734/5227bb3e-f94b-46fc-8bda-bdba3fe8fc93.png" alt="" style="display:block;margin:0 auto" />

<p>This seems like a good decision for the following reasons:</p>
<ol>
<li><p>No need to handle maintenance.</p>
</li>
<li><p>Although it's not cheap, once we purchase the license, the cost of further growth is significantly lower.</p>
</li>
<li><p>Dynamic processor count and cheap storage space.</p>
</li>
<li><p>I can consolidate multiple Oracle XE databases under a single ATP subscription.</p>
</li>
<li><p>Scheduled backups and quick restoration.</p>
</li>
<li><p>Local (Hungarian) support.</p>
</li>
<li><p>Access to the entire ecosystem in the cloud.</p>
</li>
</ol>
<h2>The move</h2>
<p>However, the transition to OCI and learning how to use it were slower and more challenging than I expected. One thing that became clear was that it's better to work with Oracle through a <a href="https://www.oracle.com/cloud/#chat">key account manager</a>, as this provides <strong>better support</strong>. This process takes more time (for us, it was two weeks), and you need to pay <strong>in advance</strong> for about a year (5000 EUR + VAT). You can start the process on the Oracle website.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729196345413/72756087-48b5-47a3-88b2-b2875c1fbe2a.png" alt="" style="display:block;margin:0 auto" />

<p>Another important point is that it's not worth subscribing without immediately upgrading to a paid plan. Unfortunately, <strong>there was a data loss</strong> that support could not (or would not) resolve because the environment was free.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729196106585/3d1f68a3-c60e-483b-9792-c630af29d452.png" alt="" style="display:block;margin:0 auto" />

<p>When <a href="https://www.oracle.com/uk/cloud/costestimator.html">estimating the cost</a>, remember to <strong>select "license included"</strong> for the license type if you don't have your own license (BYOL option). This way, you won't face unexpected charges later. Currently, I'm looking at a cost of 500-600 EUR per month, which is worth it if I can move two or three clients. With the current provider, there is no license fee because they use Oracle XE, but there is a <strong>significant cost for support and operations.</strong></p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729196660801/c5e7ffda-9990-4868-af55-5b39cc7bc681.png" alt="" style="display:block;margin:0 auto" />

<p>In the next section, I will talk about database administration and how to manage users.</p>
]]></content:encoded></item><item><title><![CDATA[Testing Oracle's Select AI Capabilities]]></title><description><![CDATA[Oracle Cloud Infrastructure (OCI) provides a robust platform for deploying and managing applications. In this blog, we test the capabilities of Select AI with a sample application using Oracle's HR sc]]></description><link>https://davidpataki.com/testing-oracles-select-ai-capabilities</link><guid isPermaLink="true">https://davidpataki.com/testing-oracles-select-ai-capabilities</guid><category><![CDATA[#oracle-apex]]></category><category><![CDATA[AI]]></category><category><![CDATA[oracle-select-ai]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Sun, 26 May 2024 16:42:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/_tnDnmyFMrg/upload/9c82dcd3c965b1ea6067e8000f99153a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://www.oracle.com/cloud/">Oracle Cloud Infrastructure</a> (OCI) provides a robust platform for deploying and managing applications. In this blog, we test the capabilities of Select AI with a sample application using Oracle's HR schema.</p>
<p>I've seen several presentations on how Select AI works at various APEX conferences. However, they were very simple, mostly formulating queries on a table (in English) and getting answers (in SQL) using some kind of language model.</p>
<p>Basically, I am curious about three things:</p>
<ol>
<li><p><strong>How Select AI handles complex queries?</strong></p>
</li>
<li><p><strong>How different language models (Cohere, OpenAI) deal with complex queries?</strong></p>
</li>
<li><p><strong>How to integrate Select AI with an on premise application and what results are obtained with metadata and queries written in Hungarian?</strong></p>
</li>
</ol>
<p>In this article I will explore the first point using OpenAI's language model. For now, Select AI only works within OCI, so I have <a href="https://www.rittmanmead.com/blog/2023/11/autonomous-database-select-ai/">created an app</a> with the necessary settings where I can ask questions.</p>
<p>In the schema, I populated the HR schema tables using APEX Sample Datasets.</p>
<img src="https://lh7-us.googleusercontent.com/zGKEqmuOdM3spDEhfNQWe2oxqo6N8uCu1xP4yvvH8yd9l_VpcYEtrMaWAlTQRl64v-PdPpVuE-ufldBmKscKExhDdGeUE-QTZaYZTHr5Et_fe_b3ix4PiFTWKjL8ZoFkyN8gWpzMwN2wIky0q4BdNB4" alt="" />

<p>The HR schema data model looks like this:</p>
<img src="https://lh7-us.googleusercontent.com/LGI1yGDv3nLxxSSh-PZOldqbn1cRU_UW-Z_lRTv5BdSee53Ru6evtTUGPXeig-dUAf_uAr0qmqO6iHuzuOZE_ukPSe_j6BegajaG45G1Vh-bivbk97aqG2ro-MmhhsJ5UPxcQxv6W5gkz0y9nJb2Ol0" alt="" />

<h1>Start testing Select AI</h1>
<p>Let's start with a simple question:</p>
<blockquote>
<p><strong>"Show me the details of the employee with the highest salary."</strong></p>
</blockquote>
<img src="https://lh7-us.googleusercontent.com/vhjM-OvX9A-6wkGJ7Vfg42kguiHs2B3YI9HzwUTHOsV4HPDgAkr3WlNXDXNp2DRd8AVXhIbTqfWS9o2SxQvVuOaHYjJUWGJvMetlUmuxUeAL7yBoo87w9n3AjUjI6j1AImvuc5KNriMz1TKcq7SVCFo" alt="" />

<p>This solution may not be the most beautiful, so you can ask it to use an analytic function, for example.</p>
<blockquote>
<p><strong>"Show me the details of the employee with the highest salary. Use an analytic function in the solution."</strong></p>
</blockquote>
<pre><code class="language-plaintext">SELECT e.employee_id, e.first_name, e.last_name, e.salary
    FROM (
    SELECT employee_id, first_name, last_name, salary,
    RANK() OVER (ORDER BY salary DESC) AS salary_rank
    FROM employees) e
WHERE e.salary_rank = 1
</code></pre>
<p>Since I would like to look at the table connections, let's ask what the salaries look like by departments:</p>
<blockquote>
<p>"List the amount of salary per department!"</p>
</blockquote>
<pre><code class="language-plaintext">SELECT d.DEPARTMENT_NAME, SUM(e.SALARY) AS TOTAL_SALARY
FROM ENROLOCI.DEPARTMENTS d
    JOIN ENROLOCI.EMPLOYEES e ON d.DEPARTMENT_ID = e.DEPARTMENT_ID
GROUP BY d.DEPARTMENT_NAME
</code></pre>
<p>Let's go through the data model up to the highest aggregation, the regions.</p>
<blockquote>
<p>"List the amount of salary per location!"</p>
</blockquote>
<p>Error.</p>
<blockquote>
<p>"List the amount of salary per <strong>department</strong> and <strong>location</strong>!"</p>
</blockquote>
<pre><code class="language-plaintext">SELECT d.DEPARTMENT_NAME AS "Department", l.CITY AS "Location", 
        SUM(e.SALARY) AS "Total Salary"
FROM ENROLOCI.DEPARTMENTS d
    JOIN ENROLOCI.LOCATIONS l ON d.LOCATION_ID = l.LOCATION_ID
    JOIN ENROLOCI.EMPLOYEES e ON d.DEPARTMENT_ID = e.DEPARTMENT_ID
GROUP BY d.DEPARTMENT_NAME, l.CITY
</code></pre>
<p>After referring in the question to the table between location and salary, the department, we managed to get a good answer to the question.</p>
<blockquote>
<p>"List the salaries by country!"</p>
</blockquote>
<p><strong>Error.</strong></p>
<blockquote>
<p>"List the salaries by country! Use foreign keys!"</p>
</blockquote>
<p><strong>Error.</strong></p>
<p>(This model's maximum context length is 4097 tokens. However, you requested 4237 tokens (3213 in the messages, 1024 in the completion). Please reduce the length of the messages or completion.)</p>
<p>Let's try another way.</p>
<blockquote>
<p>List the sum of employees' salary by country! Use foreign keys!</p>
</blockquote>
<pre><code class="language-plaintext">SELECT COUNTRY.COUNTRY_NAME, SUM(EMPLOYEES.SALARY) AS TOTAL_SALARY
FROM ENROLOCI.COUNTRIES COUNTRY
    JOIN ENROLOCI.LOCATIONS LOCATION ON COUNTRY.COUNTRY_ID = LOCATION.COUNTRY_ID
    JOIN ENROLOCI.DEPARTMENTS DEPARTMENT ON LOCATION.LOCATION_ID = DEPARTMENT.LOCATION_ID
    JOIN ENROLOCI.EMPLOYEES EMPLOYEES ON DEPARTMENT.DEPARTMENT_ID = EMPLOYEES.DEPARTMENT_ID
GROUP BY COUNTRY.COUNTRY_NAME
</code></pre>
<p>Finally, there was no need to list the tables between <strong>salary</strong> and <strong>country</strong>. However, I had to specify that the <strong>salary belonged to the workers' table</strong> and instructed them to <strong>use the foreign keys</strong>.</p>
<blockquote>
<p>"List the sum of employees' salaries by region!"</p>
</blockquote>
<p>Interestingly, I didn't have to ask to use foreign keys here, I got the correct result anyway. I assume the <strong>AI has learned from your mistakes</strong>.</p>
<h1>Conclusion</h1>
<p>To be fair, the HR schema tables are very well populated with comments.</p>
<p>Let's look at the <strong>employees</strong> and <strong>departments</strong> tables for example:</p>
<pre><code class="language-plaintext">comment on table EMPLOYEES
  is 'employees table. Contains 107 rows. References with departments, 
jobs, job_history tables. Contains a self reference.';
</code></pre>
<pre><code class="language-plaintext">comment on table DEPARTMENTS
  is 'Departments table that shows details of departments where 
      employees work. Contains 27 rows references with locations, 
      employees, and job_history tables.';
</code></pre>
<p>The comment in the salary field is as follows:</p>
<pre><code class="language-plaintext">comment on column EMPLOYEES.salary
  is 'Monthly salary of the employee. Must be greater than zero 
      (enforced by constraint oehr_emp_salary_min)';
</code></pre>
<p>Of course, the number of questions is endless, with countless possibilities for testing. However, I think Select AI is a good solution to use, although the metadata descriptions need a lot of testing and tuning.</p>
<p>At the same time, I see Select AI as very promising in its ability to evolve.</p>
]]></content:encoded></item><item><title><![CDATA[Találkozások az APEX világában #JoelKallmanDay]]></title><description><![CDATA[Néhány éve igyekszem szorosabban figyelemmel követni, hogy mi történik az Oracle fejlesztők és azon belül is az APEX felhasználók népesebb táborában.
Október 11. már hét éve az Oracle fejlesztői közös]]></description><link>https://davidpataki.com/talalkozasok-az-apex-vilagaban-joelkallmanday</link><guid isPermaLink="true">https://davidpataki.com/talalkozasok-az-apex-vilagaban-joelkallmanday</guid><category><![CDATA[JoelKallmanDay]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[community]]></category><category><![CDATA[Hungarian]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Wed, 11 Oct 2023 04:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697004058630/5328bdc3-7a2c-43c4-8862-2b2c5594a979.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Néhány éve igyekszem szorosabban figyelemmel követni, hogy mi történik az Oracle fejlesztők és azon belül is az APEX felhasználók népesebb táborában.</p>
<p>Október 11. már hét éve az Oracle fejlesztői közösség napja, ilyenkor sokan igyekeznek posztolni olyan témákban, melyek a közösséghez kapcsolódnak. Két éve ez a nap Joel Kallman emlékére lett átnevezve, aki igazi úttörőként vett részt az Oracle Application Express (APEX) létrehozásában és fejlesztésében.</p>
<p>Sajnos személyesen nem találkozhattunk, de a Covid alatt számos online előadáson vehettem részt, ahol ő is az előadók között volt.</p>
<p>Én személy szerint is sokat kaptam az APEX fejlesztői közösségtől, külföldi útjaim során nagyon nyitott és támogató embereket ismerhettem meg. Olyanokat, akik lelkesednek a munkájukért, akik szeretik azt, amit csinálnak.</p>
<p>Higyjétek el, programozók, fejlesztők között ez közel sem mondható el mindenkiről. Sokan csak azért választották ezt a szakmát, hogy ne kelljen emberekkel beszélni, kommunikálni, a problémáikkal foglalkozni.</p>
<p>Remélem a különböző APEX konferencákon készített képeim is arról tanúskodnak, hogy az APEX fejlesztők nagyon nyitottak és támogatóak.</p>
<p>Ugyanakkor nemcsak külfölfön találkozhatsz velük, hanem már kis hazánkban is elkezdtünk szerveződni. A következő meetupunkra például <a href="https://www.meetup.com/apexbudapest/events/296551747">itt tudsz jelentkezni</a>.</p>
<p>A képek helyszínei sorrendben: London (UK), Maribor (SLO), Zeist (NL), Stockholm (S), Zagreb (HR), Oslo (N), Budapest (HU)</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696943859388/500242aa-d8da-42f6-a176-0f8cf66ec48f.jpeg" alt="London 2021" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696944149155/ce2e6ea3-bfb5-4efd-92f6-ae9a44113cf8.jpeg" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696944228116/3e2599d9-9de0-449c-a605-ac9bf824df31.jpeg" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696944461682/b05c811c-e69f-41ab-ba39-55d31cc41dd4.jpeg" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696944515688/154e240c-a56e-427a-8e02-6f0357ed10fa.jpeg" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696944806111/5a33f02e-8964-46f4-a21a-76a3e8c725d7.jpeg" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696944594577/e4e1c000-c123-4ea9-8f1f-2dd63272becf.jpeg" alt="" style="display:block;margin:0 auto" />

<p>Végül pedig egy interjú:</p>
<iframe height="611" width="504"></iframe>]]></content:encoded></item><item><title><![CDATA[PL/SQL futtatása a háttérben]]></title><description><![CDATA[Az APEX framework elég jól kiszolgál bennünket a deklaratív alkalmazásfejlesztés során. A page szerkesztőben "drag and drop" módszerrel felépítjük az oldalunkat, módosítjuk néhány tulajdonságát az ele]]></description><link>https://davidpataki.com/plsql-futtatasa-a-hatterben</link><guid isPermaLink="true">https://davidpataki.com/plsql-futtatasa-a-hatterben</guid><category><![CDATA[Oracle Database]]></category><category><![CDATA[PL/SQL]]></category><category><![CDATA[Hungarian]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Mon, 05 Jun 2023 13:29:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/UkBoArZ7dFE/upload/955346d64a7d2ddd16df21a4fbd97a03.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Az APEX framework elég jól kiszolgál bennünket a deklaratív alkalmazásfejlesztés során. A page szerkesztőben "drag and drop" módszerrel felépítjük az oldalunkat, módosítjuk néhány tulajdonságát az elemeknek, esetleg írunk néhány processt vagy validációt és kész is a működő oldalunk.</p>
<p>Az alap működés során azonban az oldalunkat minden <strong>Submit</strong> vagy <strong>Redirect</strong> után újra elkérjük a szervertől, tehát az egész oldalunk újraépül. Ilyenkor a kurzor pozíciók elveszhetnek és a felhasználói élmény is romlik.</p>
<p>Ebben a postban bemutatom a háttérben történő eljáráshívást (AJAX) az APEX környezetben.</p>
<p>A példánkban egy egyszerű <strong>Classic Report</strong> cellájának értékére kattintva szeretném a megjelenített értéket megduplázni.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685785789953/aaa4a035-2405-4fc9-bfc6-39289405c0ae.png" alt="" style="display:block;margin:0 auto" />

<p><strong>A megoldás menete a következő lesz:</strong></p>
<ol>
<li><p>Kattinthatóvá tesszük az értékeket</p>
</li>
<li><p>Kattintás esetén meghívásra kerül egy Javascript függvény</p>
</li>
<li><p>A függvény meghív egy <strong>PL/SQL Page process</strong>-t</p>
</li>
<li><p>Végrehajtjuk az érték duplázását egy SQL utasítással</p>
</li>
<li><p>Frissítjük a riportot az új eredménnyel</p>
</li>
</ol>
<p>A <strong>Classic Report</strong> most az SQL utasításunk eredményeképpen kapott <strong>Salary</strong> oszlopot jeleníti meg. Írjuk be az oszlop <strong>HTML Expression</strong> tulajdonságába a következőt:</p>
<pre><code class="language-xml">&lt;a href="javascript:onlcick=f_salary(#EMPLOYEE_ID#);"&gt;#SALARY#&lt;/a&gt;
</code></pre>
<p>Figyeljük meg, hogy a riportunkban a <strong>Salary</strong> oszlop kattinthatóvá válik. Kattintás esetén meghívja az <strong>f_salary()</strong> javascript függvényt, ami még nem létezik, ezért hozzuk létre az oldal tulajdonságai között a <strong>Function and Global Variable Declaration</strong> részben.</p>
<pre><code class="language-javascript">function f_salary(id) {
   console.log("id: " +id);
   apex.server.process('PROC_SALARY',
            {x01:id},
            {dataType: 'text',
                success: function(pData)
                            {
                                console.log("Eredmény: "+ pData );
                                apex.region("myREPORT").refresh();             
                            }
            }                
                        );
    };
</code></pre>
<p>A függvény bemenő paramétere az <strong>Employee_id</strong> oszlop értéke, erre majd az adat frissítésénel lesz szükségünk, hiszen innen tudjuk majd, hogy melyik dolgozó fizetésére történt a kattintás.</p>
<p>A <strong>console.log</strong> utasítással szövegeket tudunk a böngésző konzol ablakába kiíratni, aminek a megoldás szempontjából nincs jelentőssége, a hibakeresésnél azonban hasznos lehet tudni, hogy hol is járunk a futásban.</p>
<p>Az <strong>apex.server.process</strong> beépített javascript utasítás első paramétere az az oldal vagy applikáció szintű <strong>PL/SQL process</strong>, amit a javascript függvényünk meghív. Most csak egy paramétert adunk át, az <strong>X01</strong> pozícióban. A dataType a visszatérési érték típusát adja meg, amely alapesetben Json, de mi most csak egy karaktersorozatot várunk, ezért text. (A visszatérési értéknek a példánkban nincs jelentősége, csupán ez is kiíratásra kerül a konzolra.)</p>
<p>Ha sikeresen lefutott a háttérben a <strong>PROC_SALARY</strong> process, akkor az <strong>apex.region</strong>("myREPORT").refresh(); javascript utasítással frissítjük a riportunkat. A riportra egy azonosítóval hivatkozunk - esetünkben <strong>myREPORT</strong> - amit a <strong>Classic Report</strong> régió <strong>Static ID</strong> tulajdonságánál állítottunk be.</p>
<p>A PROC_SALARY eljárás kódja a következőképpen néz ki:</p>
<pre><code class="language-sql">begin
update oehr_employees set salary=salary*2 
where employee_id=apex_application.g_x01;
commit;
    htp.p('ok');
end;
</code></pre>
<p>Maga az eljárás az oldal AJAX Callback részénél került létrehozásra, mivel az nem kötődik az oldal valamely eseményéhez.</p>
<p>A Javascript, kliens oldali hívás paraméterét az <strong>apex_application.g_x01</strong> függvény adja vissza, így ezt fel tudjuk használni az SQL utasítás szűrési paramétereként.</p>
<p>A <strong>htp.p</strong> utasítással pedig visszatérési értéket adhatunk az AJAX call-nak.</p>
<p><strong>A kliens oldali kódok kis- és nagybetű érzékenyek, ha ebben hiba van, nem fog futni a kódunk!</strong></p>
<p>A megoldás kipróbálható az alábbi linken:</p>
<p><a href="https://apex.oracle.com/pls/apex/r/test_sqelme/enrolblog/home">https://apex.oracle.com/pls/apex/r/test_sqelme/enrolblog/home</a></p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685970788621/3cdf2674-e5e2-4ef9-990e-46374cccbaff.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[APEX meetup és fejlesztői közösség elindítása]]></title><description><![CDATA[Szeretném elindítani a magyarországi Oracle APEX fejlesztők illetve a téma iránt érdeklődők számára egy olyan szakmai közösségét, amely elég laza ahhoz, hogy merj kérdezni és elég professzionális ahho]]></description><link>https://davidpataki.com/apex-meetup-es-fejlesztoi-kozosseg-elinditasa</link><guid isPermaLink="true">https://davidpataki.com/apex-meetup-es-fejlesztoi-kozosseg-elinditasa</guid><category><![CDATA[Hungarian]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[community]]></category><dc:creator><![CDATA[David Pataki]]></dc:creator><pubDate>Wed, 17 May 2023 11:58:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697003594654/4afa3903-7f2d-469c-ab44-cefbf40fc2c5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Szeretném elindítani a magyarországi Oracle APEX fejlesztők illetve a téma iránt érdeklődők számára egy olyan szakmai közösségét, amely <strong>elég laza</strong> ahhoz, hogy merj kérdezni és <strong>elég professzionális</strong> ahhoz, hogy használható válaszokat kapjál.</p>
<p>Kezdő lépésként egy meetup-al indítanánk, ahol személyesen is meg tudunk ismerkedni.</p>
<p>A tervezett program:</p>
<ul>
<li><p>A classic riport rejtett lehetőségei</p>
</li>
<li><p>Hol teheted fel a kérdéseidet vagy hol oszthatod meg az ötleteid?</p>
</li>
<li><p>Milyen konferenciák és fórumok elérhetőek APEX témában?</p>
</li>
</ul>
<p>Előadó: Pataki Dávid, Enrol Consulting Kft.<br />Program:<br />17:30-18:00 gyülekezés<br />18:00-18:10 kahoot<br />18:10-19:00 előadás(ok)<br />19:00-19:30 Q&amp;A, ismerkedés</p>
<p><a href="https://www.meetup.com/apexbudapest/events/293254942/">Itt tudsz jelentkezni</a></p>
]]></content:encoded></item></channel></rss>