<?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[Santosh Panigrahi's blog]]></title><description><![CDATA[An experienced database professional with over 9 years of expertise in Oracle SQL, PL/SQL, Performance Tuning,  APEX, ORDS.]]></description><link>https://panigrahisantosh.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 14:23:23 GMT</lastBuildDate><atom:link href="https://panigrahisantosh.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[REST-Enabling the HR Schema in Oracle ORDS: A Complete Guide]]></title><description><![CDATA[Introduction
Oracle REST Data Services (ORDS) allows you to expose database objects as RESTful web services. In this guide, we will enable RESTful services for the HR schema and create a fully functional REST API that supports GET, POST, PUT, PATCH, ...]]></description><link>https://panigrahisantosh.com/rest-enabling-the-hr-schema-in-oracle-ords-a-complete-guide</link><guid isPermaLink="true">https://panigrahisantosh.com/rest-enabling-the-hr-schema-in-oracle-ords-a-complete-guide</guid><category><![CDATA[ords]]></category><category><![CDATA[authentication]]></category><category><![CDATA[OAuth2]]></category><category><![CDATA[REST API]]></category><dc:creator><![CDATA[Santosh Panigrahi]]></dc:creator><pubDate>Thu, 20 Mar 2025 14:22:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/hDyO6rr3kqk/upload/2ffc8dab5409e79505fa32363d15b690.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>Oracle REST Data Services (ORDS) allows you to expose database objects as RESTful web services. In this guide, we will enable RESTful services for the <strong>HR schema</strong> and create a <strong>fully functional REST API</strong> that supports <strong>GET, POST, PUT, PATCH, and DELETE</strong> operations for the <strong>Employees table</strong>.</p>
<p>This blog will take you through the <strong>end-to-end process</strong>, including:</p>
<ul>
<li><p>Enabling RESTful services for <strong>HR schema</strong></p>
</li>
<li><p>Creating a <strong>module</strong>, <strong>templates</strong>, and <strong>handlers</strong></p>
</li>
<li><p>Implementing all major <strong>HTTP methods</strong></p>
</li>
<li><p>Testing the APIs</p>
</li>
</ul>
<hr />
<h2 id="heading-1-enabling-restful-services-for-hr-schema"><strong>1. Enabling RESTful Services for HR Schema</strong></h2>
<p>Before creating RESTful endpoints, we must enable ORDS for the <strong>HR schema</strong>.</p>
<h3 id="heading-step-1-enable-ords-for-hr-schema"><strong>Step 1: Enable ORDS for HR Schema</strong></h3>
<p>Execute the following PL/SQL block in <strong>SQLcl or SQL*Plus</strong>:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">BEGIN</span>
        ORDS.ENABLE_SCHEMA(
        p_enabled =&gt; <span class="hljs-literal">TRUE</span>,
        p_schema =&gt; <span class="hljs-string">'HR'</span>,
        p_url_mapping_type =&gt; <span class="hljs-string">'BASE_PATH'</span>,
        p_url_mapping_pattern =&gt; <span class="hljs-string">'hr_api'</span>, <span class="hljs-comment">-- Base path for the schema</span>
        p_auto_rest_auth =&gt; <span class="hljs-literal">FALSE</span>  <span class="hljs-comment">-- Set to TRUE if authentication is required</span>
    );
    <span class="hljs-keyword">COMMIT</span>;
 <span class="hljs-keyword">END</span>;
/
</code></pre>
<p>✅ <strong>Now, the HR schema is REST-enabled!</strong> All endpoints will be accessible under <code>/ords/hr_api/</code>.</p>
<hr />
<h2 id="heading-2-creating-the-restful-api-module"><strong>2. Creating the RESTful API Module</strong></h2>
<p>A <strong>module</strong> acts as a logical container for multiple endpoints under a <strong>base path</strong>.</p>
<h3 id="heading-step-2-define-a-module-hrmodule"><strong>Step 2: Define a Module (</strong><code>hr_module</code>)</h3>
<pre><code class="lang-sql"> <span class="hljs-keyword">BEGIN</span>
        ORDS.DEFINE_MODULE(
        p_module_name =&gt; <span class="hljs-string">'hr_module'</span>,
        p_base_path =&gt; <span class="hljs-string">'employees/'</span>,  <span class="hljs-comment">-- Base path for all employee-related APIs</span>
        p_items_per_page =&gt; <span class="hljs-number">25</span>
    );
    <span class="hljs-keyword">COMMIT</span>;
 <span class="hljs-keyword">END</span>;
/
</code></pre>
<p>✅ <strong>All employee-related endpoints will be accessible under</strong> <code>/ords/hr_api/employees/</code>.</p>
<hr />
<h2 id="heading-3-creating-rest-endpoints-for-employees-table"><strong>3. Creating REST Endpoints for Employees Table</strong></h2>
<h3 id="heading-step-3-define-templates-and-handlers"><strong>Step 3: Define Templates and Handlers</strong></h3>
<h4 id="heading-get-fetch-all-employees"><strong>📌 GET - Fetch All Employees</strong></h4>
<pre><code class="lang-sql">    <span class="hljs-keyword">BEGIN</span>
        ORDS.DEFINE_TEMPLATE(
        p_module_name =&gt; <span class="hljs-string">'hr_module'</span>,
        p_pattern =&gt; <span class="hljs-string">''</span> <span class="hljs-comment">-- Base pattern: `/ords/hr_api/employees/`</span>
    );

    ORDS.DEFINE_HANDLER(
        p_module_name =&gt; 'hr_module',
        p_pattern =&gt; '',
        p_method =&gt; 'GET',
        p_source_type =&gt; ORDS.SOURCE_TYPE_QUERY,
        p_source =&gt; '<span class="hljs-keyword">SELECT</span> employee_id, first_name, last_name, job_id, salary <span class="hljs-keyword">FROM</span> hr.employees<span class="hljs-string">'
    );

    COMMIT;
END;
/</span>
</code></pre>
<p>✅ <strong>Access:</strong> <code>GET /ords/hr_api/employees/</code><br />✅ <strong>Returns:</strong> List of all employees in JSON format.</p>
<hr />
<h4 id="heading-get-fetch-a-single-employee-by-id"><strong>📌 GET - Fetch a Single Employee by ID</strong></h4>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    ORDS.DEFINE_TEMPLATE(
        p_module_name =&gt; <span class="hljs-string">'hr_module'</span>,
        p_pattern =&gt; <span class="hljs-string">'{employee_id}'</span> <span class="hljs-comment">-- `/ords/hr_api/employees/:employee_id`</span>
    );

    ORDS.DEFINE_HANDLER(
        p_module_name =&gt; 'hr_module',
        p_pattern =&gt; '{employee_id}',
        p_method =&gt; 'GET',
        p_source_type =&gt; ORDS.SOURCE_TYPE_QUERY,
        p_source =&gt; '<span class="hljs-keyword">SELECT</span> employee_id, first_name, last_name, job_id, salary 
                     <span class="hljs-keyword">FROM</span> hr.employees 
                     <span class="hljs-keyword">WHERE</span> employee_id = :employee_id<span class="hljs-string">'
    );

    COMMIT;
END;
/</span>
</code></pre>
<p>✅ <strong>Access:</strong> <code>GET /ords/hr_api/employees/101</code><br />✅ <strong>Returns:</strong> Employee details for <code>employee_id = 101</code>.</p>
<hr />
<h4 id="heading-post-insert-a-new-employee"><strong>📌 POST - Insert a New Employee</strong></h4>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    ORDS.DEFINE_TEMPLATE(
        p_module_name =&gt; <span class="hljs-string">'hr_module'</span>,
        p_pattern =&gt; <span class="hljs-string">''</span>
    );

    ORDS.DEFINE_HANDLER(
        p_module_name =&gt; 'hr_module',
        p_pattern =&gt; '',
        p_method =&gt; 'POST',
        p_source_type =&gt; ORDS.SOURCE_TYPE_PLSQL,
        p_source =&gt; '
            <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> hr.employees (employee_id, first_name, last_name, job_id, salary) 
            <span class="hljs-keyword">VALUES</span> (:employee_id, :first_name, :last_name, :job_id, :salary);
            <span class="hljs-keyword">COMMIT</span>;'
    );

    <span class="hljs-keyword">COMMIT</span>;
<span class="hljs-keyword">END</span>;
/
</code></pre>
<p>✅ <strong>Access:</strong> <code>POST /ords/hr_api/employees/</code><br />✅ <strong>Body (JSON Example):</strong></p>
<pre><code class="lang-plaintext">jsonCopyEdit{
    "employee_id": 999,
    "first_name": "John",
    "last_name": "Doe",
    "job_id": "IT_PROG",
    "salary": 6000
}
</code></pre>
<p>✅ <strong>Effect:</strong> Inserts a new employee.</p>
<hr />
<h4 id="heading-put-update-an-entire-employee-record"><strong>📌 PUT - Update an Entire Employee Record</strong></h4>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    ORDS.DEFINE_TEMPLATE(
        p_module_name =&gt; <span class="hljs-string">'hr_module'</span>,
        p_pattern =&gt; <span class="hljs-string">'{employee_id}'</span>
    );

    ORDS.DEFINE_HANDLER(
        p_module_name =&gt; 'hr_module',
        p_pattern =&gt; '{employee_id}',
        p_method =&gt; 'PUT',
        p_source_type =&gt; ORDS.SOURCE_TYPE_PLSQL,
        p_source =&gt; '
            <span class="hljs-keyword">UPDATE</span> hr.employees 
            <span class="hljs-keyword">SET</span> first_name = :first_name, last_name = :last_name, 
                job_id = :job_id, salary = :salary 
            <span class="hljs-keyword">WHERE</span> employee_id = :employee_id;
            <span class="hljs-keyword">COMMIT</span>;'
    );

    <span class="hljs-keyword">COMMIT</span>;
<span class="hljs-keyword">END</span>;
/
</code></pre>
<p>✅ <strong>Access:</strong> <code>PUT /ords/hr_api/employees/999</code><br />✅ <strong>Body (JSON Example):</strong></p>
<pre><code class="lang-plaintext">jsonCopyEdit{
    "first_name": "Jane",
    "last_name": "Doe",
    "job_id": "SA_REP",
    "salary": 7000
}
</code></pre>
<p>✅ <strong>Effect:</strong> Updates all fields of the employee.</p>
<hr />
<h4 id="heading-patch-partially-update-an-employee"><strong>📌 PATCH - Partially Update an Employee</strong></h4>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    ORDS.DEFINE_TEMPLATE(
        p_module_name =&gt; <span class="hljs-string">'hr_module'</span>,
        p_pattern =&gt; <span class="hljs-string">'{employee_id}'</span>
    );

    ORDS.DEFINE_HANDLER(
        p_module_name =&gt; 'hr_module',
        p_pattern =&gt; '{employee_id}',
        p_method =&gt; 'PATCH',
        p_source_type =&gt; ORDS.SOURCE_TYPE_PLSQL,
        p_source =&gt; '
            <span class="hljs-keyword">UPDATE</span> hr.employees 
            <span class="hljs-keyword">SET</span> salary = :salary 
            <span class="hljs-keyword">WHERE</span> employee_id = :employee_id;
            <span class="hljs-keyword">COMMIT</span>;'
    );

    <span class="hljs-keyword">COMMIT</span>;
<span class="hljs-keyword">END</span>;
/
</code></pre>
<p>✅ <strong>Access:</strong> <code>PATCH /ords/hr_api/employees/999</code><br />✅ <strong>Body (JSON Example):</strong></p>
<pre><code class="lang-plaintext">jsonCopyEdit{
    "salary": 8000
}
</code></pre>
<p>✅ <strong>Effect:</strong> Updates only the salary of the employee.</p>
<hr />
<h4 id="heading-delete-remove-an-employee"><strong>📌 DELETE - Remove an Employee</strong></h4>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    ORDS.DEFINE_TEMPLATE(
        p_module_name =&gt; <span class="hljs-string">'hr_module'</span>,
        p_pattern =&gt; <span class="hljs-string">'{employee_id}'</span>
    );

    ORDS.DEFINE_HANDLER(
        p_module_name =&gt; 'hr_module',
        p_pattern =&gt; '{employee_id}',
        p_method =&gt; '<span class="hljs-keyword">DELETE</span><span class="hljs-string">',
        p_source_type =&gt; ORDS.SOURCE_TYPE_PLSQL,
        p_source =&gt; '</span>
            <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">FROM</span> hr.employees <span class="hljs-keyword">WHERE</span> employee_id = :employee_id;
            <span class="hljs-keyword">COMMIT</span>;'
    );

    <span class="hljs-keyword">COMMIT</span>;
<span class="hljs-keyword">END</span>;
/
</code></pre>
<p>✅ <strong>Access:</strong> <code>DELETE /ords/hr_api/employees/999</code><br />✅ <strong>Effect:</strong> Removes employee with <code>employee_id = 999</code>.</p>
<hr />
<h2 id="heading-testing-the-rest-api"><strong>Testing the REST API</strong></h2>
<p>Once everything is set up, test the APIs using:</p>
<ul>
<li><p><strong>Postman</strong></p>
</li>
<li><p><strong>cURL</strong></p>
</li>
<li><p><strong>Web browser (for GET requests)</strong></p>
</li>
</ul>
<hr />
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this guide, we:<br />✔ Enabled RESTful services for <strong>HR schema</strong><br />✔ Created an <strong>ORDS module (</strong><code>hr_module</code>)<br />✔ Implemented <strong>GET, POST, PUT, PATCH, and DELETE</strong> requests<br />✔ Provided <strong>real examples with HR schema</strong></p>
<p>Now, you have a fully functional REST API for managing employees! 🚀</p>
<h2 id="heading-securing-ords-rest-apis-with-basic-authentication-in-apex"><strong>Securing ORDS REST APIs with Basic Authentication in APEX</strong></h2>
<p>By default, ORDS allows anonymous access if <code>p_auto_rest_auth</code> is set to <code>FALSE</code>. However, for security, we should enable <strong>authentication</strong> using APEX <strong>roles and privileges</strong>.</p>
<hr />
<h2 id="heading-1-enable-authentication-for-hr-schema"><strong>1. Enable Authentication for HR Schema</strong></h2>
<p>Modify the <code>ORDS.ENABLE_SCHEMA</code> command to <strong>force authentication</strong>:</p>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.ENABLE_SCHEMA(
        p_enabled =&gt; TRUE,
        p_schema =&gt; 'HR',
        p_url_mapping_type =&gt; 'BASE_PATH',
        p_url_mapping_pattern =&gt; 'hr_api',
        p_auto_rest_auth =&gt; TRUE  -- Enforce authentication
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ Now, authentication is required for all endpoints.</p>
<hr />
<h2 id="heading-2-create-an-apex-user-for-api-access"><strong>2. Create an APEX User for API Access</strong></h2>
<ol>
<li><p>Log in to <strong>APEX Administration</strong>.</p>
</li>
<li><p>Navigate to <strong>Manage Users and Groups</strong> → <strong>Create User</strong>.</p>
</li>
<li><p>Provide a <strong>Username</strong>, <strong>Password</strong>, and assign <strong>RESTful Service</strong> role.</p>
</li>
<li><p>Save the user.</p>
</li>
</ol>
<p>✅ The user can now authenticate with <strong>Basic Authentication (username &amp; password).</strong></p>
<hr />
<h2 id="heading-3-create-an-ords-role-and-privilege"><strong>3. Create an ORDS Role and Privilege</strong></h2>
<p>To enforce API access restrictions, define a <strong>role</strong> and <strong>privilege</strong> in ORDS.</p>
<h3 id="heading-step-1-create-a-role-hrapirole"><strong>Step 1: Create a Role (</strong><code>hr_api_role</code>)</h3>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.CREATE_ROLE(
        p_role_name =&gt; 'hr_api_role'
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ <code>hr_api_role</code> is now available in ORDS.</p>
<hr />
<h3 id="heading-step-2-assign-the-role-to-apex-users"><strong>Step 2: Assign the Role to APEX Users</strong></h3>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.GRANT_ROLE(
        p_role_name =&gt; 'hr_api_role',
        p_grantee =&gt; 'APEX_REST_PUBLIC_USER'
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ Now, the APEX user must authenticate to access the API.</p>
<hr />
<h3 id="heading-step-3-create-a-privilege-and-assign-the-role"><strong>Step 3: Create a Privilege and Assign the Role</strong></h3>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.DEFINE_PRIVILEGE(
        p_privilege_name =&gt; 'hr_api_access',
        p_role =&gt; 'hr_api_role',
        p_description =&gt; 'Access to HR API endpoints'
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ The privilege <code>hr_api_access</code> is linked to <code>hr_api_role</code>.</p>
<hr />
<h3 id="heading-step-4-secure-the-api-endpoints"><strong>Step 4: Secure the API Endpoints</strong></h3>
<p>Modify the existing <strong>ORDS module</strong> to enforce authentication.</p>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.DEFINE_MODULE(
        p_module_name =&gt; 'hr_module',
        p_base_path =&gt; 'employees/',
        p_items_per_page =&gt; 25,
        p_status =&gt; 'PUBLISHED',
        p_comments =&gt; 'HR Employees API'
    );

    -- Secure the module with the privilege
    ORDS.DEFINE_MODULE_PRIVILEGE(
        p_module_name =&gt; 'hr_module',
        p_privilege_name =&gt; 'hr_api_access'
    );

    COMMIT;
END;
/
</code></pre>
<p>✅ Now, all requests to <code>/ords/hr_api/employees/</code> require <strong>authentication</strong>.</p>
<hr />
<h2 id="heading-4-testing-secure-api-with-authentication"><strong>4. Testing Secure API with Authentication</strong></h2>
<p>Now, if you try to access the API <strong>without authentication</strong>, you will get:</p>
<pre><code class="lang-plaintext">jsonCopyEdit{
    "error": "401 Unauthorized"
}
</code></pre>
<h3 id="heading-use-basic-authentication-in-postman-or-curl"><strong>Use Basic Authentication in Postman or cURL:</strong></h3>
<h4 id="heading-postman"><strong>Postman:</strong></h4>
<ol>
<li><p>Go to <strong>Authorization</strong> tab → Select <strong>Basic Auth</strong>.</p>
</li>
<li><p>Enter <strong>APEX username &amp; password</strong>.</p>
</li>
<li><p>Send the request.</p>
</li>
</ol>
<h4 id="heading-curl"><strong>cURL:</strong></h4>
<pre><code class="lang-plaintext">bashCopyEditcurl -u apex_user:your_password -X GET https://yourserver/ords/hr_api/employees/
</code></pre>
<p>✅ <strong>Now, only authenticated users can access the HR API.</strong></p>
<hr />
<h2 id="heading-conclusion-1"><strong>Conclusion</strong></h2>
<p>✔ Enforced authentication using <strong>ORDS roles and privileges</strong><br />✔ Restricted API access to <strong>APEX users</strong><br />✔ Secured all <strong>RESTful endpoints</strong></p>
<h2 id="heading-oauth2-and-jwt-authentication-in-ords-oracle-rest-data-services"><strong>OAuth2 and JWT Authentication in ORDS (Oracle REST Data Services)</strong></h2>
<p>When exposing Oracle database objects as RESTful services using <strong>ORDS</strong>, securing them with <strong>OAuth2 and JWT (JSON Web Token)</strong> is recommended for better security and control. Below, I’ll explain both authentication methods and provide <strong>detailed implementation steps</strong>.</p>
<hr />
<h1 id="heading-1-oauth2-authentication-in-ords"><strong>1. OAuth2 Authentication in ORDS</strong></h1>
<h2 id="heading-step-1-enable-oauth2-in-ords"><strong>Step 1: Enable OAuth2 in ORDS</strong></h2>
<p>To use OAuth2, ensure <strong>ORDS is configured for OAuth2</strong>.<br />Run the following command in SQL Developer (as <code>ORDS_METADATA</code> user):</p>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.ENABLE_SCHEMA(
        p_enabled =&gt; TRUE,
        p_schema =&gt; 'HR',
        p_url_mapping_type =&gt; 'BASE_PATH',
        p_url_mapping_pattern =&gt; 'hr_api',
        p_auto_rest_auth =&gt; TRUE
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ This enforces authentication for all endpoints under <code>hr_api/</code>.</p>
<hr />
<h2 id="heading-step-2-create-an-oauth2-client"><strong>Step 2: Create an OAuth2 Client</strong></h2>
<p>Run the following command to create an OAuth2 client in ORDS:</p>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.CREATE_OAUTH_CLIENT(
        p_name            =&gt; 'hr_client',
        p_grant_type      =&gt; 'client_credentials',
        p_owner           =&gt; 'HR',
        p_description     =&gt; 'HR API OAuth2 Client'
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ This creates an OAuth2 client (<code>hr_client</code>) with <strong>client credentials</strong> authentication.</p>
<hr />
<h2 id="heading-step-3-get-the-client-secret"><strong>Step 3: Get the Client Secret</strong></h2>
<p>Run the following query to retrieve the <strong>client secret</strong>:</p>
<pre><code class="lang-plaintext">sqlCopyEditSELECT name, client_id, client_secret FROM user_ords_clients;
</code></pre>
<p>✅ Note the <strong>client_id</strong> and <strong>client_secret</strong>, as they will be used for authentication.</p>
<hr />
<h2 id="heading-step-4-obtain-an-access-token"><strong>Step 4: Obtain an Access Token</strong></h2>
<p>Use <code>curl</code> or <strong>Postman</strong> to request an <strong>OAuth2 access token</strong>:</p>
<pre><code class="lang-plaintext">bashCopyEditcurl -X POST https://yourserver/ords/hr/oauth/token \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "grant_type=client_credentials" \
    -d "client_id=hr_client" \
    -d "client_secret=your_client_secret"
</code></pre>
<p>✅ This returns a response like:</p>
<pre><code class="lang-plaintext">jsonCopyEdit{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "token_type": "bearer",
    "expires_in": 3600
}
</code></pre>
<p>🔹 <strong>Use this</strong> <code>access_token</code> in API requests.</p>
<hr />
<h2 id="heading-step-5-use-access-token-for-api-calls"><strong>Step 5: Use Access Token for API Calls</strong></h2>
<p>Once you have the access token, send API requests using <strong>Bearer Token Authentication</strong>:</p>
<pre><code class="lang-plaintext">bashCopyEditcurl -X GET https://yourserver/ords/hr_api/employees/ \
    -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni..."
</code></pre>
<p>✅ Now, access is granted only if a <strong>valid token</strong> is provided.</p>
<hr />
<h1 id="heading-2-jwt-authentication-in-ords"><strong>2. JWT Authentication in ORDS</strong></h1>
<p>Instead of OAuth2, you can use <strong>JWT (JSON Web Token)</strong> authentication for a <strong>stateless</strong> and <strong>secure API</strong>.</p>
<h2 id="heading-step-1-enable-jwt-authentication"><strong>Step 1: Enable JWT Authentication</strong></h2>
<p>Run the following command to enable JWT authentication in ORDS:</p>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.ENABLE_SCHEMA(
        p_enabled =&gt; TRUE,
        p_schema =&gt; 'HR',
        p_url_mapping_type =&gt; 'BASE_PATH',
        p_url_mapping_pattern =&gt; 'hr_api',
        p_auto_rest_auth =&gt; TRUE
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ This ensures that JWT is required for API access.</p>
<hr />
<h2 id="heading-step-2-create-a-jwt-based-role-and-privilege"><strong>Step 2: Create a JWT-Based Role and Privilege</strong></h2>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.CREATE_ROLE('hr_jwt_role');
    COMMIT;
END;
/
</code></pre>
<p>Then, create a <strong>privilege</strong> that requires a JWT:</p>
<pre><code class="lang-plaintext">sqlCopyEditBEGIN
    ORDS.DEFINE_PRIVILEGE(
        p_privilege_name =&gt; 'hr_jwt_access',
        p_role =&gt; 'hr_jwt_role',
        p_description =&gt; 'Access to HR API via JWT'
    );
    COMMIT;
END;
/
</code></pre>
<p>✅ Now, only users with valid JWT tokens can access the API.</p>
<hr />
<h2 id="heading-step-3-obtain-a-jwt-token"><strong>Step 3: Obtain a JWT Token</strong></h2>
<ol>
<li><p>Create a <strong>JWT provider</strong> (e.g., Keycloak, Auth0, Oracle IDCS).</p>
</li>
<li><p>Use the <strong>client_id</strong> and <strong>client_secret</strong> to request a JWT.</p>
</li>
<li><p>ORDS will validate the JWT token before granting access.</p>
</li>
</ol>
<p>Example JWT token request:</p>
<pre><code class="lang-plaintext">bashCopyEditcurl -X POST https://your-auth-server/oauth/token \
    -H "Content-Type: application/json" \
    -d '{
        "grant_type": "password",
        "client_id": "your_client_id",
        "client_secret": "your_client_secret",
        "username": "your_username",
        "password": "your_password"
    }'
</code></pre>
<p>✅ This returns a JWT token similar to OAuth2.</p>
<hr />
<h2 id="heading-step-4-use-jwt-for-api-calls"><strong>Step 4: Use JWT for API Calls</strong></h2>
<pre><code class="lang-plaintext">bashCopyEditcurl -X GET https://yourserver/ords/hr_api/employees/ \
    -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni..."
</code></pre>
<p>✅ ORDS verifies the JWT and grants or denies access.</p>
<hr />
<h1 id="heading-conclusion-2"><strong>Conclusion</strong></h1>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Authentication Type</td><td>Use Case</td></tr>
</thead>
<tbody>
<tr>
<td><strong>OAuth2</strong></td><td>Best for applications needing <strong>token expiration &amp; refresh</strong> (e.g., external apps).</td></tr>
<tr>
<td><strong>JWT Authentication</strong></td><td>Best for <strong>stateless</strong> APIs with third-party authentication providers (e.g., Auth0, Keycloak).</td></tr>
</tbody>
</table>
</div><p>✅ <strong>OAuth2</strong> is ideal for external applications.<br />✅ <strong>JWT</strong> is best for <strong>microservices &amp; secure APIs</strong>.</p>
]]></content:encoded></item><item><title><![CDATA[Learn the Basics: How to Get Started with the APEX Animal Shelter App]]></title><description><![CDATA[This is a beginner's app designed to help understand how an app works, not a fully developed Apex app for production, with non-normalized tables, sample data, and suboptimal relationships, intended solely for learning purposes on what, when, and how ...]]></description><link>https://panigrahisantosh.com/little-lives-big-impact-an-apex-animal-shelter-solution</link><guid isPermaLink="true">https://panigrahisantosh.com/little-lives-big-impact-an-apex-animal-shelter-solution</guid><category><![CDATA[ords 24]]></category><category><![CDATA[Animal Shelter]]></category><category><![CDATA[Apex]]></category><category><![CDATA[ords]]></category><dc:creator><![CDATA[Santosh Panigrahi]]></dc:creator><pubDate>Tue, 18 Mar 2025 15:23:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742310951695/e2e25533-171a-4c64-83f2-0c5e3734fec8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><mark>This is a beginner's app designed to help understand how an app works, not a fully developed Apex app for production, with non-normalized tables, sample data, and suboptimal relationships, intended solely for learning purposes on what, when, and how to do basic things in Apex.</mark><strong><mark>This blog is a continuation of my previous blog: "</mark></strong><a target="_blank" href="https://panigrahisantosh.com/apex-ords-and-tomcat-installation"><strong><mark>APEX, ORDS, and TOMCAT INSTALLATION</mark></strong></a><strong><mark>." If you haven’t checked that out, I recommend reviewing it also first for a smoother setup experience.</mark></strong></p>
<p><strong>Disclaimer:</strong> This blog is inspired by the <strong>J Kreie Database</strong> YouTube channel (<a target="_blank" href="http://www.youtube.com/@databasetopics">www.youtube.com/@databasetopics</a>) <a target="_blank" href="https://youtube.com/playlist?list=PL1MJdy9N8XJLLs-4IGpEPet-7MJf4HUic&amp;feature=shared">video playlist</a>. It is created <strong>solely for informational and personal reference purposes</strong>. I highly suggest going through this playlist before reading this blog, where Kreie has explained everything in a crystal clear manner. The content has been adapted for my own learning and documentation. If you find it helpful, that's great—but please note that this is not an official guide. Always refer to the original source for authoritative information.</p>
<h3 id="heading-create-animalshelter-schema-and-required-db-objects-in-demo-pdb"><mark>Create ANIMAL_SHELTER schema and required DB objects in DEMO PDB</mark></h3>
<ul>
<li><p>Download resources: <a target="_blank" href="https://drive.google.com/drive/folders/1NzeOPTnrq2nd9GkjEHdI_p4TBQ8foxWC">Google Drive Link</a></p>
</li>
<li><p>Create tablespace named <strong>APEX</strong> (skip if already exists): SQL</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">create</span> <span class="hljs-keyword">tablespace</span> apex <span class="hljs-keyword">datafile</span> <span class="hljs-string">'E:\app\oradata\ORCL\demo\apex.dbf'</span> <span class="hljs-keyword">size</span> <span class="hljs-number">300</span>m <span class="hljs-keyword">autoextend</span> <span class="hljs-keyword">on</span> <span class="hljs-keyword">next</span> <span class="hljs-number">10</span>m;
</code></pre>
<p>  Update <code>create_schema.sql</code> with your prefered password and tablespace name to <code>APEX</code></p>
</li>
<li><p>Connect to <code>SYS@DEMO</code> and run <code>@create_schema.sql</code> (DEMO is PDB here).</p>
</li>
<li><p>Verify user ANIMAL_SHELTER created from dba_users.</p>
</li>
<li><p>Modify <code>@create_animal_shelter_tables.sql</code> by changing tablespace name to <code>APEX</code> for all create table statement.</p>
</li>
<li><p>Verify all require tables are created and empty:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> ZIPS;
  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> PERSONS;
  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> EMPLOYEES;
  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> ANIMALS;
  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> TRANSACTIONS;
  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> ACTIVITIES;
</code></pre>
<h3 id="heading-create-animal-shelter-workspace-and-require-user-accounts-for-application"><mark>Create ANIMAL SHELTER workspace and require user accounts for application</mark></h3>
<p>  Login to <strong>ADMIN@INTERNAL</strong> workspace at <a target="_blank" href="http://localhost:8080/ords">localhost:8080/ords</a>.</p>
<p>  Create a workspace called "<strong>Animal Shelte</strong>r" by clicking "<strong>Create Workspace</strong>" or <strong>managing workspaces → create workspace</strong>. For "Reuse existing schema," select Yes, and for "Schema Name," choose ANIMAL_SHELTER. On the next page, enter the admin name as <strong>AS_ADMIN</strong> and fill the necessary details to create the workspace.</p>
<p>  <strong>Note:</strong> INTERNAL is the main workspace, and you should use <strong>ADMIN@INTERNAL</strong> for overall administration of APEX, such as creating and managing other workspaces. Typically, for development or admin tasks, we log in to a specific workspace. workspace contains all the design elements for the web application in this project. It's always a good idea to add a description for the workspace.</p>
</li>
<li><p>Click on <strong>Manage Workspaces -&gt; Manage Workspace to Schema Assignments</strong> to check if the new workspace appears.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478568094/b57df2bf-fe18-44bb-b3c3-66cf2c0ab8a9.png" alt class="image--center mx-auto" /></p>
<p>  Similarly, click on <strong>Manage Developers and Users</strong> to confirm the admin user AS_ADMIN is created.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478620801/83777bad-f060-4f1b-81ac-aaa0291d9dca.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Now, log in to the new <strong>Animal Shelter workspace</strong> as the workspace administrator <strong>AS_ADMIN</strong> to create <strong>two types of accounts: i. Developer and ii. Regular User</strong>.</p>
<p>  To create an account, select <strong>Manage Users and Groups from the dropdown → Create User → Fill in all details</strong>. For the name, use <strong>AS_DEVELOPER</strong> (make sure the schema is ANIMAL_SHELTER). Select No for "User is Workspace Administrator" and Yes for "User is a Developer." For this exercise, set "Require change of password" to No, though typically it is set to Yes. → Click on Create and Create Another → Create user <strong>AS_USER</strong> (make sure to select No for both "Is admin" and "Is dev"). (Note: The email doesn't need to be valid, but it is mandatory.)</p>
</li>
<li><p>Verify all these 3 users created (manage users and groups → Users).</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478870510/fdc0ed12-4986-4521-8a79-f9f399ab1b15.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-use-sql-workshop-in-apex-to-run-scripts-that-insert-data-into-tables"><mark>Use SQL Workshop in APEX to run scripts that insert data into tables</mark></h3>
<p>  Now log in to the Animal Shelter workspace with the developer account to view an overview of the Animal Shelter APEX WS, including the App Builder, SQL Workshop, Team Development, and Gallery. Run scripts to populate tables and perform other necessary tasks. Verify the created or modified objects from the object browser.</p>
</li>
<li><p>Log in as_developer to Workspace -&gt; SQL Workshop -&gt; SQL Scripts -&gt; upload -&gt; choose file -&gt; upload. Select all files that start with insert_data (Warning: don't run them yet; they need to be run in order).</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479018304/18126fff-08e9-4ecf-93c4-fc7e15b420b3.png" alt class="image--center mx-auto" /></p>
<p>  Before choosing the order for inserts, check the ERD to find tables that are on the "one" side of a relationship. In this case, the ZIPS table is populated first, followed by the others in this order: zip -&gt; persons -&gt; employees -&gt; animals -&gt; transactions -&gt; activities. For activities, import from the ACTIVITIES_DATA.csv file using <strong>SQL Workshop -&gt; Utilities -&gt; Data Workshop -&gt; Load data</strong>.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479164703/ee2e41b7-fbf3-4c94-83d2-fc38f192a7b7.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479110614/4f114165-93d4-4fa8-ac4b-84c78e200229.png" alt class="image--center mx-auto" /></p>
<p>  While running, we expect 2 errors for <code>insert_data_transaction</code>. You can find this order at the end of <code>drop_animal_shelter_db.sql</code> (it's reversed in this file since they are delete statements). You can refer to <code>ANIMAL_SHELTER@DEMO.pdf</code> for the ERD, or alternatively, you can get it from SQL Developer by going to File -&gt; Data Modeler -&gt; Import -&gt; Data Dictionary, and so on.</p>
<h3 id="heading-create-an-application-with-application-builder-add-a-logo-amp-create-a-simple-form"><mark>Create an application with Application Builder. Add a logo &amp; Create a simple form. .</mark></h3>
</li>
<li><p>Log in again as AS_DEVELOPER and create an application called <strong>Daily Operations</strong> from the App Builder. Go to <strong>App Builder -&gt; Create Application -&gt; Choose required details</strong> (let's keep everything as default for this app, like Theme as Standard Vita, Navigation side menu, Authentication as Application Express Accounts, etc.). Now run the application with the required credentials.</p>
<p>  Note: When APEX creates an application, it generates a Global Page, home page, login page, and others in recent versions.</p>
</li>
<li><p>Now, try to change the title bar image . From the developer toolbar, click on <strong>Application -&gt; Shared Components -&gt; under the Files and Reports section, click Static Application Files -&gt; Create File -&gt; drag and drop the file Animal_Shelter_text.jpg</strong> for the title logo. Once uploaded, <strong>copy the reference</strong> for the uploaded image file, which is usually like <strong>#APP_FILES#Animal_Shelter_text.jpg</strong>.</p>
<p>  Now go back to <strong>Shared Components</strong> -<strong>&gt; From User Interface, select User Interface Attributes -&gt; check for the menu Logo and select the Image tab -&gt; replace the text for the label Logo with the one you just copied #APP_FILES#Animal_Shelter_text.jpg -&gt; Apply Changes -&gt; Run Application</strong>.</p>
<p>  <strong>#APP_FILES#</strong> indicates where to find the image within the workspace itself.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479314767/84d8f202-cd2f-408f-8950-3d9ad47fee45.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Now we can add components like a form, IR, CR, or IG to the page. To create a form, find a table that shows a lot of relevant information on its own, such as "persons" or "animals," rather than "transactions" or "activities."</p>
<p>  To create a page and add a component to it, <strong>go to the Dev toolbar and select Application -&gt; Create Page -&gt; choose the Interactive Grid component -&gt; enable form -&gt; fill in the required details -&gt; next, select PK -&gt; Create Page</strong>.</p>
<p>  Below is a screenshot showing the application page with a form and a classic report. The Interactive Grid is named <strong><em>List of Animals</em></strong> and the form is named <strong><em>Animal Info.</em></strong> Now, we'll use the form to add a new record for Rocky and see it in the report as Animal ID 10075.</p>
<p>  Note: A report displays, filters, and sorts data, while a form creates and modifies data, and in IG you can edit records inline without a form if it's not enabled, but in IR you must use a form to edit records.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477124465/792de347-0579-4312-8c49-4539bb6634dc.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477740823/2b698758-5073-49b1-a2d8-a5a285b09123.png" alt class="image--center mx-auto" /></p>
<p>  To see Animal ID column in report we have to below change</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477972879/982fdb2e-b444-448b-ac60-22320dda6712.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477981228/3bd83fe9-4ea9-4f69-ba20-32dee87d3d7a.png" alt class="image--center mx-auto" /></p>
</li>
<li><h3 id="heading-page-designer-show-pk-in-a-form-see-source-of-a-item-create-lookup-table"><mark>Page Designer. Show PK in a form. See source of a Item. Create lookup table</mark></h3>
</li>
<li><p>In the page designer, there are three sections: Rendering, Layout, and Properties, with the Layout section, known as the canvas, being where we actually work. When you select a component in rendering, you can view its corresponding item properties in the item section and the page layout in the layout or canvas section.</p>
<p>  [Page designer from APEX 19.1]</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742395317279/ce781d24-f79e-4c2f-a6ed-c329a8af5458.png" alt class="image--center mx-auto" /></p>
<p>  [Page designer from APEX 24.2]</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742395671802/4319ebdb-f4f6-4b2a-86d2-b14750fc3952.png" alt class="image--center mx-auto" /></p>
<p>  Normally, you don't see the PK in a form because the PK attribute item property is set to hidden, but you can make it visible by selecting Display Only. It's also recommended to change the label name from "New" to something more appropriate and meaningful, like "Animal ID (PK)," otherwise the disabled PK field will display with the label "New" inside, as shown in the third screenshot.</p>
<p>  [After label change]</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477702704/2d5afbda-b2f0-44d1-91e2-2cce96928c8f.png" alt class="image--center mx-auto" /></p>
<p>  [See source of selected Item]</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742397286206/cb23f604-6ede-4303-9c36-a504b5bbea7e.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Sometimes we need to provide an input list to ensure that people don't add animals incorrectly or modify their classification over time. Mistakes can happen, such as entering the wrong value, using incorrect casing, or omitting spaces, which makes list and column values inconsistent. We want data entry to be uniform and efficient wherever possible. To achieve this, we should use a lookup table to provide a dropdown list when someone wants to enter a new animal. Let's create a lookup table for this purpose.</p>
</li>
<li><p>To create a lookup table, go to the object browser, select the Animal table, click "Create Lookup Table" under the column section's more dropdown, select the column DOM_BREED and create on lookup table, and a new lookup table named DOM_BREED_LOOKUP will be automatically created to store a unique list of values from the selected column. You can also make the change by modifying the displayed script.</p>
<p>  <em>A lookup table serves as a "master list" to find a business key value, like "DOM_BREED," in exchange for its identifier, such as the id column, for use in another table's foreign key column.</em></p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742397855444/d8b7717d-22ac-4402-a0f4-fe61c0537d87.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742398153602/f74bcf65-49a0-48ea-871b-a0d559f3221e.png" alt class="image--center mx-auto" /></p>
<p>  The following SQL commands were executed behind the scenes to create the lookup table.</p>
</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> <span class="hljs-string">"DOM_BREED_LOOKUP"</span> (
    <span class="hljs-string">"DOM_BREED_ID"</span><span class="hljs-built_in">number</span> <span class="hljs-keyword">generated</span> <span class="hljs-keyword">by</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">on</span> <span class="hljs-literal">null</span> <span class="hljs-keyword">as</span> <span class="hljs-keyword">identity</span>,
    <span class="hljs-string">"DOM_BREED"</span>   <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">4000</span> <span class="hljs-keyword">byte</span>) <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>,
    <span class="hljs-keyword">constraint</span> <span class="hljs-string">"DOM_BREED_LOOKUP_PK"</span> primary <span class="hljs-keyword">key</span> (<span class="hljs-string">"DOM_BREED_ID"</span>)
);

<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> <span class="hljs-string">"DOM_BREED_LOOKUP"</span> (<span class="hljs-string">"DOM_BREED"</span>)
<span class="hljs-keyword">select</span> <span class="hljs-keyword">distinct</span> <span class="hljs-string">"DOM_BREED"</span>
<span class="hljs-keyword">from</span> <span class="hljs-string">"ANIMALS"</span>
<span class="hljs-keyword">where</span> <span class="hljs-string">"DOM_BREED"</span> <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>;

<span class="hljs-keyword">alter</span> <span class="hljs-keyword">table</span> <span class="hljs-string">"ANIMALS"</span> <span class="hljs-keyword">add</span> <span class="hljs-string">"DOM_BREED_ID"</span> <span class="hljs-built_in">number</span>;

<span class="hljs-keyword">update</span> <span class="hljs-string">"ANIMALS"</span> x
<span class="hljs-keyword">set</span> <span class="hljs-string">"DOM_BREED_ID"</span> = (<span class="hljs-keyword">select</span> <span class="hljs-string">"DOM_BREED_ID"</span> <span class="hljs-keyword">from</span> <span class="hljs-string">"DOM_BREED_LOOKUP"</span> <span class="hljs-keyword">where</span> <span class="hljs-string">"DOM_BREED"</span> = x.<span class="hljs-string">"DOM_BREED"</span>);

<span class="hljs-keyword">alter</span> <span class="hljs-keyword">table</span> <span class="hljs-string">"ANIMALS"</span> <span class="hljs-keyword">drop</span> <span class="hljs-keyword">column</span> <span class="hljs-string">"DOM_BREED"</span>;

<span class="hljs-keyword">alter</span> <span class="hljs-keyword">table</span> <span class="hljs-string">"ANIMALS"</span>
<span class="hljs-keyword">add</span> <span class="hljs-keyword">constraint</span> <span class="hljs-string">"ANIMALS_DOM_BREED_FK"</span>
<span class="hljs-keyword">foreign</span> <span class="hljs-keyword">key</span> (<span class="hljs-string">"DOM_BREED_ID"</span>)
<span class="hljs-keyword">references</span> <span class="hljs-string">"DOM_BREED_LOOKUP"</span>(<span class="hljs-string">"DOM_BREED_ID"</span>);
</code></pre>
<p>You can now verify that the new table DOM_BREED_LOOKUP has been created, the column DOM_BREED has been dropped from the ANIMALS table, and a new foreign key column DOM_BREED_ID has replaced it with values from the new lookup table's ID.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742398802172/6b0e707a-0eb4-4f33-9a40-a09ea9a01675.png" alt class="image--center mx-auto" /></p>
<p>However, after creating the lookup table, the application may start to break. To fix this, quickly edit from the dev toolbar, then in the report page designer, go to the report element properties. In the source, select the source and add the <code>dom_breed_id</code> column in the SQL query, which was added to the table, and remove any reference to the <code>dom_breed</code> column. Alternatively, you can select the source as a table again and choose the Animal table to resolve this error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742399352346/e10984da-46dd-4783-b2e5-37521e304d72.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-display-a-picture-in-a-form-edit-link-between-report-and-form"><strong><mark>Display a picture in a form. Edit link between report and form.</mark></strong></h3>
<p>Add a BLOB animal_pic column to the Animals table by selecting the Animal table in the object browser and clicking on Add column in the right pane.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742489448149/4382c7ab-4209-4347-a23b-fee1478cb716.png" alt class="image--center mx-auto" /></p>
<p>But you see adding this column doesn’t change anything in report but in form it is there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742490602316/cadcdf0d-da95-4616-86b1-0169fbd4bc82.png" alt class="image--center mx-auto" /></p>
<p>Now let's delete the form that we originally had (Animal Info form page #3).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742490723095/5be11e1d-f462-465f-b5af-b77b38e5235e.png" alt class="image--center mx-auto" /></p>
<p>confirm</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742490752040/bd615de4-2e5a-44b8-a505-bb54e83f5095.png" alt class="image--center mx-auto" /></p>
<p>create a new page again</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742490775196/6b00ae8d-0490-4fe4-ad7a-b1089769e3bd.png" alt class="image--center mx-auto" /></p>
<p>Deliberately give page#4 to break the functionality as page 4 is not available</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742491026991/5169c843-15c5-4591-b964-46157404f740.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742492338290/5ef51083-4cd8-47b6-98da-1c1fbf1fe6a9.png" alt class="image--center mx-auto" /></p>
<p>now run application directly as modal dialog can’t be run directly</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742491270003/75225b29-7052-4cf8-9415-538a6b0493ef.png" alt class="image--center mx-auto" /></p>
<p>Now, if I run the application and try to click on create form or edit any record in the report, I get a page not available error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742491405300/6fba83ae-d1cb-4cb0-999d-9712307a137b.png" alt class="image--center mx-auto" /></p>
<p>To fix this, go back to the report page, do a quick edit, and set the target to the correct newly created page #4, and also change the name in set items to P4_ANIMAL_ID and click ok and you see application works well but in report when you click create you still get same error as previous page 103 is already deleted.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742493418312/242d7034-f99c-4f3c-a6ef-5e006ecd8d51.png" alt class="image--center mx-auto" /></p>
<p>Now lets try to upload a image to newly create blob column</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742493821695/20b618c8-f042-48bf-8847-cb93da4f3f00.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742493836641/6d5fbd91-fb7e-4678-b2d4-6ad139fd8b35.png" alt class="image--center mx-auto" /></p>
<p>After uploading, you can see the image, but to view the blob content, add a page item in page #4 for the Animal Data form, and we won't use the existing ANIMAL_PIC column to display animal photos since it only allows browsing and uploading.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742494057233/5c984bfc-e66b-47ea-b52d-beb61f58396d.png" alt class="image--center mx-auto" /></p>
<p>rename new page item to P4_PIC and select type as Display image</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742494277770/28ed7e82-602e-4384-9456-2e35f065c6a1.png" alt class="image--center mx-auto" /></p>
<p>Now scroll to source section and select the form for source and select column which you want to display</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742494366105/5ee3e169-b66c-471a-a0d5-cb5afff1d68d.png" alt class="image--center mx-auto" /></p>
<p>Now when you will edit a form for a row you can see pic you had added already added.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742495031743/c3894388-9fbb-4008-92d3-e39bd53d1ef9.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-create-static-and-dynamic-lovs-in-shared-components-use-them-in-a-form"><strong><mark>Create static and dynamic LOVs in Shared Components. Use them in a form.</mark></strong></h3>
<p>Copy the <strong>Animal Data form page (Page #4)</strong> to create a new form page called <strong>Animal Data LOVs (Page #5)</strong>, where users can input data using a dropdown select list or Popup LOV. DOn’t associate this page with navigation entry yet.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742623382759/e60becec-2b31-4afb-ab28-f4fb2f81d5f0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742623423645/eca70fd5-7408-4fa4-a59a-e54652d6ed67.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742623847934/428b6377-0600-42ce-94b6-6c6aae3b877d.png" alt class="image--center mx-auto" /></p>
<p>Now are next idea is to create static/dynamic lovs for each column based on the requirement. LOVs help prevent errors in data entry. There are two types of LOVs: Static and Dynamic. Static LOVs do not change over time and only developers can modify them. Dynamic LOVs, on the other hand, come from distinct column values and can change as users update them since these dynamic values are auto-populated. Static values will appear in shared component LOV lists, whereas dynamic values will not.</p>
<p>here is Animal table column for which we will be creating LOVs</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742624084623/cec746d8-0cc7-4fc7-870e-13e88d78b114.png" alt class="image--center mx-auto" /></p>
<p>To create LOV go to Shared Component → Under Other Components select List of Values → Create →<br />Note - You have already DOM_BREED_LOOKUP.DOM_BREED local lov already created as part of lookup table creation from Animals.DOM_BREED column</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742624381629/78be4bbc-d8a6-409c-a295-01061fff1a2d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742624488243/ce293306-f3e4-4235-9adc-3ddbc57e605b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742624723668/f4d233a9-f311-4112-b73e-f57b4664b1d7.png" alt class="image--center mx-auto" /></p>
<p>The Display Value is what you see in the application dropdown, and the Return Value is the corresponding value that will be saved in the database table column. Now lets LOVs for other column as well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742625013552/073be84a-11ee-4dd2-b2f8-8e961fc704a5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742625339998/91b126cc-185c-42db-92f1-40de7ea72a54.png" alt class="image--center mx-auto" /></p>
<p>Now let's create DOMINANT BREED dynamic LOVs like the one automatically created by APEX during the lookup table creation from dom-Breed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742625526133/53a3559c-5f78-4669-8ea1-8bd647ec75f9.png" alt class="image--center mx-auto" /></p>
<p>Either make source type as SQL Query or Table like below</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742625827093/e39cae20-a466-4ec8-bc56-7bcae5e4e925.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742625932849/709d452a-0c46-4599-8364-2f660947cc75.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742625952251/d36c7150-ce47-4643-a411-dd9f690ccade.png" alt class="image--center mx-auto" /></p>
<p>This will create local LOV.</p>
<p>Return to the page designer and change the column items' identification type attributes to either a select list or Popup LOV and change List of Value attribute for same selected column item.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742626264553/5a83eff7-b0a5-409f-98e6-fbd4b493b4a6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742626343670/5777ada9-38bc-43b9-a51c-c2f643719bdd.png" alt class="image--center mx-auto" /></p>
<p>Now if we run application we see for the newly created almost all filed is either select list or popup LOV. now lets create a lookup for status field.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742627077019/e17a545c-0538-49bf-8ac6-58c6e52139e6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742627120539/eb812fd6-08ff-4178-8ac5-6c3d66b36e17.png" alt class="image--center mx-auto" /></p>
<p>Once done, you may see a "page not available" and "status invalid identifier" error. To fix this, change the source to status_id instead of status. Then, change the column type to a select list and set the source to the newly created animal status LOV.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742628016323/2b64978d-1014-442e-b85e-415bb197dfdc.png" alt class="image--center mx-auto" /></p>
<p>Keep in mind that when you run the application and click the edit icon for a row in the list of animals report page, it will open the original form without LOVs. To fix that go to report page designer #2 and change target attribute to page #5 from page #4 to map to newly created form with LOVs .</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742628887895/576b754f-eebe-4270-8478-8b1bba07c45b.png" alt class="image--center mx-auto" /></p>
<p>Now, run the application and try to edit a row in the report using the newly created form page with LOVs; if you see an error for status invalid identifier, change the source for status to STATUS_ID for page #5, just as you did for page #4 previously. Now all should be good.</p>
<p>Below are the pages and LOVs we have created so far.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742629150919/00d82806-12c8-4763-8be5-d2831989c6fb.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742629162000/88085a38-0c6a-4ed9-ba61-84e08d08f103.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-add-data-to-a-static-or-dynamic-lov-clean-the-data-and-prevent-inconsistent-entries-in-the-future-by-enforcing-lowercase-in-a-form"><strong><mark>Add data to a static or dynamic LOV, clean the data, and prevent inconsistent entries in the future by enforcing lowercase in a form.</mark></strong></h3>
<p>To add or modify LOV -</p>
<p>Developer can go to shared component → select LOV → either Add Row or Edit</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742640908357/fd6f1d7e-d32f-4776-bf68-cb0a450e0250.png" alt class="image--center mx-auto" /></p>
<p>For Dynamic LOV, we can create a form for each lookup table. Users can add to the list by using the form<br />Lets create a interactive report and enable form there like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742641584001/f078701c-8c63-47ea-abb5-a4d176c146ca.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742641648255/1acb5e59-fd7b-4b91-acb8-95662b1fccf3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742641657180/b2d60e08-f4fb-4141-8a52-2fc586542f33.png" alt class="image--center mx-auto" /></p>
<p>From this Status Item Report we will try to insert a new status deceased</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742641748684/a9fee89a-2564-425d-ab78-846bbec2dc63.png" alt class="image--center mx-auto" /></p>
<p>You can check the new addition from the forms you had created earlier or from List of Animals page</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742641833421/6a881b12-df86-47ad-b50a-a80699decbee.png" alt class="image--center mx-auto" /></p>
<p>Just as side Note if you want to bring Animal Data form page to Home in navigation menu. then go to shared component →</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742642315632/235f18cb-6a6a-4491-b880-0ae8db1ca70d.png" alt class="image--center mx-auto" /></p>
<p>Now see Animal Data is not in Home</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742642365334/a97f7040-b29d-439b-a866-caffb73ed864.png" alt class="image--center mx-auto" /></p>
<p>Chnage parent List entry to Home and Apply Changes</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742642431933/3111360f-2cc6-42df-9eb8-1a68dfdc3f49.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742642491913/a9f9fe8e-18eb-4675-b8fb-aade9d33e842.png" alt class="image--center mx-auto" /></p>
<p>Returning to the project, you may notice that the color values of Animals are inconsistent, appearing in all lowercase, uppercase, and camel case in different places.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742642710923/634a28bf-e984-437f-ba14-a81e9ad9dd67.png" alt class="image--center mx-auto" /></p>
<p>Now to ensure data is consistent irrespective of the case it was entered. go to for page (page#5 in our case), right click on column for which you want to make thinks consitent(in our case primary_colour would be in small case)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742643054086/5bfdc54a-7f49-4217-afcb-8a725baae6b3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742643132388/194e07c5-535b-425c-a6ab-75d733daf09d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742643254207/0503076d-f660-40bb-aacf-19c47297090d.png" alt class="image--center mx-auto" /></p>
<p>Returning to the project, you might see that the color values of Animals are inconsistent, showing up in lowercase, uppercase, and camel case in various places.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742643504059/a06c0ec0-4a92-458c-943a-96905d12a103.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742643520142/6c95ac5b-d029-470e-856f-f17302edf5f4.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-correct-a-target-page-change-the-layout-of-page-items-in-a-form"><strong><mark>Correct a target page. Change the layout of page items in a form</mark></strong></h3>
<p>If you see a "Page isn’t available" error when clicking the create button on the interactive grid list of animals, go to the page designer, click on the CREATE button in the rendering section, and change the target properties on the right to page #4 as shown below; this will solve the page not available problem.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742622389466/b02ad520-d9c7-4544-83a9-8aded401cd3a.png" alt class="image--center mx-auto" /></p>
<p>To Create a form lookup table for Dominant Breed - Lets create a interactive report for this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742644330751/050cd2fa-ab25-48db-8e70-e248604aa07f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742644468080/dcb48188-9a76-4257-8c7c-632b3c3b6b00.png" alt class="image--center mx-auto" /></p>
<p>(Change column Dom Breed ID from hidden to plain text or display if not appear default in form)<br />Now lets go and add “American Blue Heeler “</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742644655353/8a6b0d12-79ee-4d24-af73-badc5e349346.png" alt class="image--center mx-auto" /></p>
<p>We know APEX is a responsive design tool, so pages in the application will adjust their display based on the device being used. Now, go back to the List of Animals Report and change the layout of the form. Instead of having a wide column field for each column, change the layout to a two-column page so that two fields will appear in a single row, except for the last two audit columns.</p>
<p>Before Layout change</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742645274254/f7ee0c34-cc9a-4f47-ab49-dc93179faa94.png" alt class="image--center mx-auto" /></p>
<p>Now to change layout select column in page designer (page #5) → go to layout section</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742645498450/0a77ff40-ca69-4aab-8322-90d5f6cf06c8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742645628888/d0170ce0-7914-4c78-b49b-75e18b323485.png" alt class="image--center mx-auto" /></p>
<p>Let Start new Row enable for P5_ANIMAL_ID. and observe how layout chnage when you make start new row to NO for P5_CATEGORY.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742645842489/917fee1f-4845-49fe-b669-8b82245c65b7.png" alt class="image--center mx-auto" /></p>
<p>You can also see the column span set to Automatic below the enabled New column in Layout. To explain what column span is, APEX views any display screen in 12 units, so if you want to change the width of some fields relative to others, you can adjust this column span value. For example, if you set it to 6, then both columns in a single row will have equal width in a form, and if you set one to 8 and the other to 4, the one set to 8 will be larger, and the one set to 4 will be smaller.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742645879078/94610077-90be-42da-9396-eee74efb19cd.png" alt class="image--center mx-auto" /></p>
<p>Now if i set Animal Id column span as 4 in form it willl apear something like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742646233076/0f777e10-6f7a-4b62-953a-0e20e1e7fe7c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742646246494/c68a6fc0-9908-4a29-bd11-c34dfae0c415.png" alt class="image--center mx-auto" /></p>
<p>Let's disable "start a new row" for every alternate item so 2 fields appear in a single row in the UI form, and ensure audit columns appear last by assigning them a sequence value greater than the last column, in this case, P5_PIC.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742646646719/934746b5-36b5-42f1-8078-7d627489b3fb.png" alt class="image--center mx-auto" /></p>
<p>To display 2 fields in a single row when 3 or 4 fields appear, set the column span value to 6, resulting in the final layout after the change.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742646827373/76395389-c889-4346-9ec3-ce94a0cc3411.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742646869552/6445b020-fdb9-450b-ac52-ed5b8a44e685.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-change-navigation-menu-add-a-hierarchy-create-2nd-application-copy-a-page"><strong><mark>Change navigation menu. Add a hierarchy. Create 2nd application. Copy a page</mark></strong></h3>
<p>Reorganize and group navigation items. Before this create 3 more landing pages (like page #1), all will be blank pages.</p>
<p>Lets create Animal Page #10 and keepp that at the same level of Home(No parent selected in Parent navigation menu entry)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742649629530/bdbbf564-1a56-4fac-8fcb-073cfdb7ba4c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742649643622/f77e25cd-2ef4-4bbd-8c87-f21e2794e240.png" alt class="image--center mx-auto" /></p>
<p>Now similarly Create 2 more blank pages People and Data Maintenance. and the purpose of these blank pages to provide that top level groupings where other navigation items can be put together like in Home.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742649823892/623cf8d3-9a9f-4f6f-84c0-4f1e5ae7994a.png" alt class="image--center mx-auto" /></p>
<p>Now in Animal Page we’ll create new component and/or region</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742650123293/f54d37a5-04b7-42cd-950e-0bd64f6ff4d4.png" alt class="image--center mx-auto" /></p>
<p>Change Name to Animals and add details to Source</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742650416490/ab9d3871-f660-40d4-b267-fa89f405aa2a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742650449294/4cce1afa-e313-45fc-a6fa-67900782ab21.png" alt class="image--center mx-auto" /></p>
<p>Now add 4 new pics to shared components → Files → Static Workspace Files (As we might need to add those files in some other applications in single workspace as well)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742653297051/3403e21f-bc3c-4115-bfa3-15ccae248a07.png" alt class="image--center mx-auto" /></p>
<p>Copy animal page reference and paste in source section along with existing text as HTML</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"#WORKSPACE_FILES#animal_page.jpg"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Reports and Forms for Animal Data (Transactions, activities and Animal Records) are listed here.<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742652648055/79ce65c1-a6dc-4960-b017-fae5f785abe4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742652659959/55710dd2-bc98-4ccc-9a8e-5ab7daf4090d.png" alt class="image--center mx-auto" /></p>
<p>do same for people and Data Maintenance page</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742653701906/53edd7f0-4070-428f-96d2-f7e42378a7ca.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742653711978/ac107b5f-7482-4ef4-b1f1-b18eba73302b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742653430163/b45dd11a-031b-4a39-9c31-951a72e362bc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742653465247/71cea330-2241-4b0a-9c8d-4df5e3425ffd.png" alt class="image--center mx-auto" /></p>
<p>Once done with these goto shared components → navigation and Search → navigation menu → click on the name Navigation Menu.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742653868084/88145d7e-3d52-44e5-8d41-e75773dcc490.png" alt class="image--center mx-auto" /></p>
<p>here notice column parent entry the entry for which parent entry are Home they are listed under Homem menu. We’ll now move status item report and dominant breed report under data maintenance by assigning Data Maintenance as parent</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742654109922/586f78d4-7bf3-436c-8ccb-0562e25dc3d2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742654182183/2d5b7b64-0623-47b0-95f5-4627bffe2427.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742654236201/2f891094-b1fc-44ca-921b-2cf00bac1431.png" alt class="image--center mx-auto" /></p>
<p>Now switch List Of Animalsand Animal Data to Animals Menu</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742654369320/a980266c-1af9-48a4-a1fa-c9374787d6e6.png" alt class="image--center mx-auto" /></p>
<p>Animal Data id old form which we created to enter animals’ data w/o any select list or popup LOV.<br />Now lets create other application .</p>
<p>Click on Home icon on designer de tool bar and create Application from app builder</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742654625322/41c09394-3f6b-4f36-a599-fdb0a9acde51.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742654700524/4f31ee9e-93b0-4a91-9f66-3ed40d950aa1.png" alt class="image--center mx-auto" /></p>
<p>No copy Animal Shelter pic reference you had uploaded to workspace files and go to application (App 102) → shared component → Application definition under Application Logic → under user interface and paste image reference in logo URL</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655054141/9c1de350-a5fc-47bd-b704-f0b9323e6f8c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655088185/32e519cc-19b3-4505-b384-97cdc3af7687.png" alt class="image--center mx-auto" /></p>
<p>Now lets copy few pages from other application to this new one.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655213621/61faf9c0-304c-473d-8b29-14e5c169eb5e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655235745/e8a332ae-3dcf-480f-a52a-35b1fb2683ed.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655325333/654e3dde-a33b-40e7-9040-274625557e09.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655468336/38fc39a9-fe46-4dc1-b04a-a5f87610ba8d.png" alt class="image--center mx-auto" /></p>
<p>Now the first thing we’lll copy are all 3 parent pages for navigation menu we created newly )Animals, People and Data Maintenance).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655738547/51c5dbde-c94a-43f3-85af-9bb1ff0d05a7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655747207/4f9f5519-eac8-48b8-b4ed-73dd590cf29f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655811243/0d5ac365-92ab-4269-824d-c79d35ff7e6a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655824808/00382078-649e-4316-ae27-3b78e6f0c47a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742655859081/251f7459-bae3-414f-a85d-341b2ac272a9.png" alt class="image--center mx-auto" /></p>
<p>Similarly copy the remaining 2 pages People and Data Maintenance (ensure page numers are same)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742656625518/e4869f5f-d04d-4e73-b20b-1dde880be781.png" alt class="image--center mx-auto" /></p>
<p>Observe I have copied as <strong>Data Entry Support</strong> Not <strong>Data Maintenance</strong> just to show they don’t have to same when copy. If you have already copied, you can rename it from shared component navigation menu.</p>
<p>Now lets copy in status report and form to Data Data Entry Support</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657033909/37498b6a-bfeb-4fb4-9a41-136b83c2146f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657083729/fc4fc4be-7879-4660-95f8-6aefa8243f53.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657143790/12daff12-2e5f-4369-bf97-5750b601775e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657150495/abfd64c9-b68e-4142-962d-5477d5f9d262.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657241865/5f079593-ea12-4a74-9e36-2875a3387d57.png" alt class="image--center mx-auto" /></p>
<p>But if you click on edit icon here you get page not available error message. To fix that we to copy the corresponding for as well. also ensure page numbers are same else you have to fix the target properties.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657299745/acabf8b0-cbf5-4758-986d-d3ae2d21c7cc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657445045/38ccba28-07e4-4644-8b54-aaf8ffaf3e97.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657501872/6b2b6876-e53a-466a-a837-871bfb16baa8.png" alt class="image--center mx-auto" /></p>
<p>click next next Finish</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657546073/3da67deb-07a6-43db-85a8-d9e964f1904f.png" alt class="image--center mx-auto" /></p>
<p>Now we can see form opening on clicking edit icon in Page #7</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657609737/d542b81c-7226-4939-9244-666f66d64156.png" alt class="image--center mx-auto" /></p>
<p>Now Lets do the same thing for Dominant Breed Report and put under Data Entry Support</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657730767/5816035d-57db-44b9-8e35-1c839418b425.png" alt class="image--center mx-auto" /></p>
<p>Now copy corresponding form also to avoid page not available error. don’t create navigation entry for this form page you are copying for dominant breed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657853296/9cf0b302-79d6-47c5-8820-971ba0eef227.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742657916529/fd973440-4737-4b37-acf7-91368f59e4d2.png" alt class="image--center mx-auto" /></p>
<p>Now Lets move the navigation pane from the side to the top. Go to shared componenets → User Interface Attributes → Either Under Show All or from direct Navigation Menu tab change Position to Top from Side.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742658188415/4b121c49-b6cb-47c5-ba35-761dbe7c3e56.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742658312663/ed85ab01-eef4-48c3-a02b-b7927eed182b.png" alt class="image--center mx-auto" /></p>
<p>Observe images are also coming fine as they were uploaded at workspace levell not application level.</p>
<p><strong><em>Note We could use one application for development/ testing and move pages to the second application once they have been approved.</em></strong></p>
<h3 id="heading-sql-code-concatenates-columns-in-a-dynamic-lov-apex-writes-lov-sql-code"><strong><mark>SQL code concatenates columns in a dynamic LOV. APEX writes LOV SQL code</mark></strong></h3>
<p>Before continuing, let's review our progress so far. We’ll treat <strong>Daily Operations</strong> as our <strong>DEV</strong> environment and <strong>AS Operations</strong> as our <strong>PROD</strong> environment</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742658850090/debcebd6-24b1-4bd3-9144-ba3ff0d7a900.png" alt class="image--center mx-auto" /></p>
<p>So far, we have created lookup tables only for the Animals tables; let's create more lookup tables for the remaining ones using the object browser and add unique constraints where needed.</p>
<p>For Activities, we need to create two dynamic LOVs: one for categories and another for sub-categories. For transactions, we need to create dynamic LOVs for transaction type, Client ID, Pers ID, and Animal ID. Except for transaction type, we don't need any lookup tables for the remaining three attributes as they are derived from existing tables. For the persons table, we need a dynamic LOV for ZIP code, which doesn't require a lookup table as it is already referenced in the ZIP table. For the Employees table, we need two static LOVs for STATUS and ROLE, and one dynamic LOV for Supervisor ID. No new lookup table is required for the Employees table lookup tables.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742699350571/f41c87a5-b5cb-4886-b184-31df38940ac8.png" alt class="image--center mx-auto" /></p>
<p>For Veterinarian return value should be VET not VOL (typo)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742699512720/e849ee25-a8f5-4645-bae7-9e4cce167cfa.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742699536300/7d7ca29e-2bf0-472a-a66d-53fdca886611.png" alt class="image--center mx-auto" /></p>
<p>After creating the sub-category lookup table, we'll add one column for the category to it, as we'll use this later to create a hierarchy of choices in an LOV.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742699805574/d0637897-27f2-491b-82a3-5f5f88795e64.png" alt class="image--center mx-auto" /></p>
<p>We have 2 category present in our DB</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742699947637/f6e4c543-b07e-4096-81a6-692a75550374.png" alt class="image--center mx-auto" /></p>
<p>So let's manually map each subcategory to these 2 categories.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742700015283/6aed5135-78fd-4cd6-86a4-e7f7650698fc.png" alt class="image--center mx-auto" /></p>
<p>Now update manually the correpending categorory</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742701089373/fa60edb3-e361-4fb6-81d5-813a4fa383d3.png" alt class="image--center mx-auto" /></p>
<p>Let's delete the row for vaccinations because we already have a similar subcategory called vaccination.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742701117672/cb5bcd06-470e-4219-97d9-bbb56d0893a1.png" alt class="image--center mx-auto" /></p>
<p>Update subcategory id to 3 where it was 1</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742701678126/ed6eeff4-f96b-42a0-9e98-604d2718ba86.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742701850604/22a7b216-e054-45f2-8650-0bce7144fda1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742701855867/cc1504ac-d3ff-4222-9791-25e13ab11664.png" alt class="image--center mx-auto" /></p>
<p>Now add 1 unique constraint to Subcategory field to avoid duplicate entry</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742702413080/1a635075-2dab-4cdb-ac42-684f910421e4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742702448479/68f09197-a6ae-4c5a-8055-7e3350b0d658.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742702567135/877eceb4-fc9b-408a-9dec-a8579dd16059.png" alt class="image--center mx-auto" /></p>
<p>Now similarly create unique constraint to remaining lookup tables created</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742702713941/f6d5a9b1-b177-438d-a0ab-f24b0615dcb6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742702757320/167d8c48-45e4-4a9f-94df-5cd8637f76ee.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742702800968/9aa85638-2e0a-4ed1-b8af-51ccd8a4a6f5.png" alt class="image--center mx-auto" /></p>
<p>Let's go to the Daily Operations application to create some LOVs from shared components, and copy-paste these codes wherever needed to create dynamic LOVs.</p>
<pre><code class="lang-sql"><span class="hljs-comment">--category_list</span>
instead of SQL query <span class="hljs-keyword">select</span> <span class="hljs-keyword">source</span> <span class="hljs-keyword">as</span> CATEGORY_LOOKUP -&gt; display:<span class="hljs-keyword">CATEGORY</span> <span class="hljs-keyword">and</span> -&gt; <span class="hljs-keyword">RETURN</span>: CATEGORY_ID

<span class="hljs-comment">--subcategory_list</span>
instead <span class="hljs-keyword">of</span> <span class="hljs-keyword">SQL</span> <span class="hljs-keyword">query</span> <span class="hljs-keyword">select</span> <span class="hljs-keyword">source</span> <span class="hljs-keyword">as</span> SUBCATEGORY_LOOKUP -&gt; display:SUBCATEGORY <span class="hljs-keyword">and</span> -&gt; <span class="hljs-keyword">RETURN</span>: SUBCATEGORY_ID

<span class="hljs-comment">--client_list</span>
<span class="hljs-keyword">select</span> lname || <span class="hljs-string">', '</span> || fname || <span class="hljs-string">': '</span> || pers_ID <span class="hljs-keyword">as</span> display, 
   pers_id <span class="hljs-keyword">as</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">from</span> persons <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> <span class="hljs-number">1</span>;  

<span class="hljs-comment">--emp_list</span>
<span class="hljs-keyword">select</span> lname || <span class="hljs-string">', '</span> || fname || <span class="hljs-string">': '</span> || persons.pers_ID <span class="hljs-keyword">as</span> display, 
   persons.pers_id <span class="hljs-keyword">as</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">from</span> persons <span class="hljs-keyword">inner</span> <span class="hljs-keyword">join</span> employees
  <span class="hljs-keyword">on</span> persons.pers_id = employees.pers_id <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> <span class="hljs-number">1</span>;  

<span class="hljs-comment">--zip_list</span>
<span class="hljs-keyword">select</span> zip || <span class="hljs-string">', '</span> || city || <span class="hljs-string">', '</span> || state <span class="hljs-keyword">as</span> display,    zip_id <span class="hljs-keyword">as</span> <span class="hljs-keyword">return</span>
<span class="hljs-keyword">from</span> zips <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> <span class="hljs-number">1</span>;  

<span class="hljs-comment">--animal_list</span>
<span class="hljs-keyword">select</span> <span class="hljs-keyword">name</span> || <span class="hljs-string">', '</span> || dom_breed || <span class="hljs-string">': '</span> || animal_id <span class="hljs-keyword">as</span> display,
  animal_id <span class="hljs-keyword">as</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">from</span> animals <span class="hljs-keyword">inner</span> <span class="hljs-keyword">join</span> dom_breed_lookup
  <span class="hljs-keyword">on</span> animals.dom_breed_id = dom_breed_lookup.dom_breed_id
<span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> <span class="hljs-keyword">name</span>;
</code></pre>
<p>Below are the LOVs that we have created so far which we will use in future activities</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742704591289/278dc3b5-cf67-4d0e-b7dc-cb3cefa1346e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-put-navigation-buttons-at-the-top-amp-bottom-of-a-report-change-an-lov-to-radio-group"><strong><mark>Put navigation buttons at the top &amp; bottom of a report. Change an LOV to radio group.</mark></strong></h3>
<p>Let's modify the report and form for ANIMALS by adding the record navigation feature to the top of the page, so we don't have to scroll down to access additional records.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742717579356/9404923d-46a8-4cfd-9bb2-84a5f6db05b5.png" alt class="image--center mx-auto" /></p>
<p>If you don't see navigation arrows, you can enable them by going to actions → Format → Rows per page → 50.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742719046564/765a0949-d5d7-452b-9937-e060ebc373b2.png" alt class="image--center mx-auto" /></p>
<p>if you don’t see Rows per page option under Format then you can go to page designer and chnage Pagination type attribute to Page and enable Show total count to see total no records in the report</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742719168802/b5a193cf-10ed-4714-986d-33d9df3ec435.png" alt class="image--center mx-auto" /></p>
<p>Now to get this navigation in the top of page along with bottom you can do like this in APEX version older than 20. but for 20+ version I don’t see this option. still searching :)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742720125408/5cc0d6d6-ef13-48c7-861c-781130b7b3c0.png" alt class="image--center mx-auto" /></p>
<p>Modify the display of few LOVs to radio group from select list. Go to Page #5 form LOVs designer → change type to Radio Group.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742720491835/f8eb95b1-bec7-408b-a6ae-149df871d0cd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742720504200/afe08bec-debb-470b-a404-df45b61a943a.png" alt class="image--center mx-auto" /></p>
<p>Change the Number of Columns under settings to 3 to prevent options from appearing vertically, and disable Display Null Value to avoid showing null values as radio button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742720653142/731e48eb-b739-4de0-a923-0fab0aa8e484.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742720667127/e3f87886-b6a5-45b8-aa67-2bfcbb95b669.png" alt class="image--center mx-auto" /></p>
<p>Note : To select multiple values. insted of radio group you can choose check list or shuttle.</p>
<p>Now Similary you cange Housetrained from select list to radio grup.You can chnage for status and SP_NE by holding ctrl button and change type to radio group. they both share common lov properties.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721089018/ba85b2db-08aa-4e91-9329-2403336855d6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721113520/f3688073-b454-440d-969f-045235650a29.png" alt class="image--center mx-auto" /></p>
<p>Now lets copy List of Animals report (Page #2) and corresponding form with LOVs(page #5) to PROD (AS Operations). Click on any page then copy page#2 and #5 from DEV Daily Operations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721366923/60de8906-8d8c-47a8-88f5-cb55e4ba0bb4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721404348/067edef1-655a-4a94-a95c-e750799743dd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721492402/580a7fdd-7da3-4ed5-a233-822abbf6a52e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721560998/15748d6a-cfad-45fb-ab54-3fffc1cb55be.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721583182/c125a0cb-dab8-496f-b8e8-4c7214a6cd1b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721591966/75b4dd27-768b-4550-8008-ec5e65ec2937.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721641932/405a2c92-94d2-4b42-bb6d-4204167d9909.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721651122/1483fee3-99e0-4376-9adf-e7d921951a8a.png" alt class="image--center mx-auto" /></p>
<p>But if you click on edit option of any record you will get page not available error. To fix that we need to copy the form page as well from DEV application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721795522/8a55b162-1f8f-426d-97a4-b081f7a8ae5e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721919502/4b33373f-1e4c-432c-b42e-1e664ce13ca6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721930834/a81c71c0-e0e6-4fc3-9c66-1667dc944a8e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742721951496/e7e98110-61ec-4c80-901d-05ceb8ec7f87.png" alt class="image--center mx-auto" /></p>
<p>Copy all LOVs for this page to PROD. select Copy drop down.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722098368/0cb8862c-ef8f-4008-a096-8cff8d8a7dc9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722126782/6b0609a2-007f-479b-91bd-c86892f30366.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722134222/47d45571-4fb5-4bfb-a90a-72eedf5ef15d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722174408/e812ea75-dfe4-474c-bc3a-d58a3fc82440.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722214011/a297b5be-518e-4c18-9f5d-97af476742b1.png" alt class="image--center mx-auto" /></p>
<p>You can verify the copied LOVs as well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722254770/960fb6ea-73f1-43de-af33-e83b9edfacab.png" alt class="image--center mx-auto" /></p>
<p>After copying the report and form from DEV (Daily Operations) to PROD (AS Operations), all LOVs, which didn't exist in the PROD app before, are copied along with the form and report pages.</p>
<p>[Before Copy of Report and Form page from daily Operations to AS Operations]</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742717311188/c564f60b-4de0-4e49-8641-f8d40268096b.png" alt class="image--center mx-auto" /></p>
<p>Log in as an end user to see how the application looks, because if you try to log in as a developer or admin, you won't be able to access the page and will see a message instead saying only allowed to change password, so make sure to use the correct URL. <a target="_blank" href="http://localhost:8080/ords/r/animal_shelter/as-operations/">http://localhost:8080/ords/r/animal_shelter/as-operations/</a>. In older versions you had to copy url till page number like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722928989/a9f42e87-1c8b-44c0-95fb-b9a5425f27ea.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722665933/0cb81aae-5e43-4584-a5cd-f826b48634b7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722770241/34cb82c3-707e-4874-a767-d476c282360a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742722802259/236e7ab8-afce-4870-b589-f92d530d8306.png" alt class="image--center mx-auto" /></p>
<p>As a normal end user, you won't see the dev designer toolbar.</p>
<p><strong><mark>Create a master-detail form (2 tables) and simple form (1 table)</mark></strong></p>
<p>Before starting on master details, create a model excluding lookup tables, as they are only meant for data entry consistency and will clutter the model, making it less succinct. For reference during model import, in SQL Developer's data dictionary, you can check and drop lookup tables, then click on merge and rearrange tables so they look better in the data model.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742827265759/2f29b3c6-e734-4399-950d-d596b629d48e.png" alt class="image--center mx-auto" /></p>
<p>Normally, a single table has a simple form, but there can be situations where two tables are linked, with one as the master and the other as the detail, or main and subform. Let's look at the data model to discuss when to create a simple form and when to create a master-detail or main-subform. This decision depends on whether the tables are dependent or independent. Sometimes, data in one table depends on another table, like in a strong entity 1-1 relation where a foreign key is usually a unique key constraint. We’ll create a simple form for "PERSON" and a master-detail form for "PERSON_EMPLOYEES." Tables like "Animals" and "Persons" are candidates for simple forms as they are independent and not linked to transactions or activities. Remember, you are not limited to one form per table; you might create two or more forms for a table. For dependent tables (weak entities), consider using a master-detail form, such as for "Animal-Transactions" and "Animal-Activities."</p>
<p>Login to Animal Shelter workspace AS_DEVELOPER → Daily Operation App(DEV APP)<br />Lets create a simple interactive report form on persons.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742828126534/bba897c1-7406-4f56-8936-745f9138c9fc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742828248400/ef045645-e60d-45cf-bf07-f717d7d9cdb1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742828462924/54a950fa-32ed-4bf2-93bc-b8b887b8e08e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742828483073/f4720ee7-fc22-4ed2-be6f-5ed005201e54.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742828562662/f92fa83d-04ec-4ddf-bdb2-f2eac4741f12.png" alt class="image--center mx-auto" /></p>
<p>Click on any edit icon you’ll see form Person Data</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742828594358/aaec2261-36cc-4a19-b4e2-2e6b650bb9a5.png" alt class="image--center mx-auto" /></p>
<p>Modify the form to adjust multiple fields in 1 row. For audit keys Data created and modified make the type to Display only as they’ll be populated through triggers.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742829082317/7a110b13-98e7-42b1-b250-02d8f651d7e4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742829098062/d04355e7-3d06-44e4-80d6-415678ffa0f1.png" alt class="image--center mx-auto" /></p>
<p>For ZIP use POPUP LOV</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742829312155/c31c9527-560b-4922-b443-c9f438329846.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742829329939/e000eb0e-ea14-4e53-84b3-09013e9b6dcb.png" alt class="image--center mx-auto" /></p>
<p>Now, Person Data is a simple form, a single page that interacts with one table for adding and maintaining data; let's look at the master-detail form.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742829544590/6fe0edc9-1fc0-4fa4-94b3-1d6b021b0887.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742829606826/c870dadc-2d12-4153-8732-72c68fdd8dc6.png" alt class="image--center mx-auto" /></p>
<p>you will get 3 types of master detail style (Stacked, Side by Side and Drill Down). We’ll not be using Stacked that is we can do , but here we’ll see and create Side by side and Drill Down example</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742829574213/45594928-f439-4f07-91a9-062a4de6d88d.png" alt class="image--center mx-auto" /></p>
<p>Lets create side by side master detail page. Create anavigation mentry for that as we’re going to do this more than once.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742830268746/a052bcbf-5d68-43d6-b264-a5be57b24e82.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742830507336/d82ec47d-b0d6-4621-bace-ce4c870e207a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742830869399/0f36bccf-b7f8-443b-a561-f9bc208f637e.png" alt class="image--center mx-auto" /></p>
<p>Run to see if a person is employee and if not a employee.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742831045869/bf3248ff-6c4f-46b1-89e1-18cf1f81a787.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742831082733/524c2897-40f8-4a18-8ba8-7612d948537a.png" alt class="image--center mx-auto" /></p>
<p>Lets modify the master-detail page to have the ability to serch by id along with name. for example if you wil search 90117 or 90151 you’ll not see any record.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742831502036/f0cbd052-50b2-44c6-8938-832bb523cb1b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742831560489/4a998243-ba19-43ea-92a4-8d9e9f226e58.png" alt class="image--center mx-auto" /></p>
<p>Lets modify the page to incorporate this modification sech by id. From page select Master record and modify SQL Query under source.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742831838312/cb22884b-982c-43ac-8847-f22eeaaf8c10.png" alt class="image--center mx-auto" /></p>
<p>post change</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742831988525/9fb0887d-a892-4d8b-b78c-6fb035a37ee9.png" alt class="image--center mx-auto" /></p>
<p>You can see 3 pages created beacuse of 1 master details page. we created page#15 but page #25 and #26 created automatically 1 for master and other for detail. Here the report page is of type classic report.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742834627567/2f5a2a1f-c84d-4a00-b525-b7ed893e7a89.png" alt class="image--center mx-auto" /></p>
<p>Now create 1 more master detail form type drill down. lets number it 16.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742832106503/d1069401-21cf-4b4e-960e-8968ce5ab2ec.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742832351451/dc0161e1-7687-4226-a47b-8967d0a54fca.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742832457187/cd032f85-af3e-486d-b095-1b4fa18b5daa.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742832764715/898fdbc8-5264-47f7-8ebc-bb177087056b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742832781066/1e7d8491-278b-4059-a860-8d595bc4751c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742835062550/f03d9ef1-2006-48ef-bf5c-c533e4ee328c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742835158171/a0a32021-0c32-4c92-881a-dc1580ae5439.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742835165111/fae8b5e0-9a5d-403a-a88a-eded472f7fa1.png" alt class="image--center mx-auto" /></p>
<p>Lets make ID columns visible in the master-detail as well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742833133776/add91baa-c36b-41d6-a26b-52dc388b91ce.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742833414304/fd4cd905-16b3-4905-8912-b7297db318b0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742833429966/1602c23f-1ca7-411f-a79f-1f00f15a08ae.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742833188818/01100817-30fa-4859-ba82-e4485de70052.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742833210239/b5badb26-83ce-4303-a6af-1fcaa97471ae.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742833524802/d8f42eb2-1b70-4937-9745-348b81720c96.png" alt class="image--center mx-auto" /></p>
<p>For the drill-down report page, which is an interactive report, we don't need to add search by ID like we did for the side-by-side master-detail type, where the report page was a classic report requiring the search by ID feature.</p>
<h3 id="heading-add-column-to-table-amp-page-item-to-form-edit-sql-to-filter-rows-shown-in-a-form"><strong><mark>Add column to table &amp; page item to form. Edit SQL to filter rows shown in a form.</mark></strong></h3>
<p>Pages created so far for Daily Operations (DEV APP) include the drill-down type page #16 IR and page #17 form.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742836307881/25ffb2be-def1-4d04-9b95-b05343bbbc91.png" alt class="image--center mx-auto" /></p>
<p>Now let's add and update the column in APEX object browser, then include it as a page item in the APEX form. For that from the previous master-details page we created, if we don't want to show information about people who have left or passed away, we don't delete them from the database; instead, we flag those records as inactive. Let's add a status column in the Persons table where the values can be Active(A) or Inactive(I), similar to the status column in the Employees table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742906431020/f0ae1363-38d5-4ae0-b38d-fde404b0e9b6.png" alt class="image--center mx-auto" /></p>
<p>update all perosns to Active (A). Lets now update PERS_ID 90001 PERS_STATUS to Inactive(I)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742906577450/53796c46-fbb0-498d-954c-e67fbe4818c9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742906972926/45ab8444-fb56-4cde-8fde-8eead45c39b1.png" alt class="image--center mx-auto" /></p>
<p>Now idea is to show 120 records in form not the 1 which status we made Inactive(I). so edit the sql from page designer and add require filter condition</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742907273237/d4c23970-0948-401e-9dab-510ee230966f.png" alt class="image--center mx-auto" /></p>
<p>verify from UI</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742907353979/f6c05347-286d-428d-806a-af11c489036e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742907378027/97b2ba61-5b56-4e1b-aa5a-fd9b5e3eeede.png" alt class="image--center mx-auto" /></p>
<p>Now lets come back to People → Report List of Persons. In the form you don’t get field/label to chnage newly added column. so to add that to the form create a page item for pers_status.</p>
<p>Before change</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742907637766/521a15b0-b5f7-49d5-ba10-8bfd29b36f21.png" alt class="image--center mx-auto" /></p>
<p>After change</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742907724491/437e85ac-cfd6-4d1e-9af1-372fd5d0684f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742907886742/8d12933f-7d63-4649-a88d-4a6c5b74d979.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742908009119/cead6eb4-90cd-45a5-a85c-59940ebadf4b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742908039366/d9a42b61-e414-4c66-a5f2-6ac9df6cae63.png" alt class="image--center mx-auto" /></p>
<p>Now lets have a LOV for Pers Status. Create</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742908338591/311cbead-89f6-43f0-8492-d037e2f5f01b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742908514134/aaf9cc86-55d9-47ae-a54a-52efa54a764f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742908588657/b89a27d1-8e50-46e2-a647-af914a6c8c30.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742908717554/3a474a30-3b25-4a3f-98ff-ce4594fbbcb0.png" alt class="image--center mx-auto" /></p>
<p>Now Select the drill-down report under home and change pagination attributes in the page designer to display page navigation above the report page too.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909018960/126c4111-7ada-4b3a-a82b-e72d4725ff03.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909052341/1386b3ee-cb02-4662-92ed-f14fd58b98c5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909282928/884eb486-74f2-4816-9912-8545b257cd63.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909296675/d2e7f8c6-92f3-4412-9b98-fb04a1738ed2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909316420/c530a4fa-8824-42a9-ab35-b9d1924e8852.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909352484/920e5576-e37f-44ce-9a4e-9e8232d811b9.png" alt class="image--center mx-auto" /></p>
<p>Now lets display 15 rows per page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909508114/f02d8549-a08b-421f-8ef7-d4b40e8aeb49.png" alt class="image--center mx-auto" /></p>
<p>Now edit the form page desiner to display 3 fields in 1 line</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909721833/d35266b0-c51c-4203-9344-bb02fcceac54.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742909774307/a70740be-9afa-4f2e-a501-230fdc71043b.png" alt class="image--center mx-auto" /></p>
<p>Finally we can edit the details directly in the report as it is a interactive grid, unlike a classic report in a side-by-side master-details page.</p>
<h3 id="heading-correct-code-for-an-lov-add-lovs-to-master-detail-add-data-to-form"><strong><mark>Correct code for an LOV. Add LOVs to master-detail. Add data to form.</mark></strong></h3>
<p>Back to Animal Shelter data model we see zip table has PK on ZIP column rather ZIP_ID like all other tables inthe schema. Now we will chnage zip_id to zipp in zip_list lov</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742985988466/7cb3d395-a752-4403-9c85-444819a9f4f1.png" alt class="image--center mx-auto" /></p>
<p>Now from application of you see zip is souced from zip_id. so lets chnage that to zip_list lov.<br />Before</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986146711/e818cce5-199f-4d61-b9ef-e712a600c8f7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986187340/521ccb36-077d-4c68-ac71-56809512e906.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986216443/8ac3d556-1871-403a-94f9-77a91e5f18e3.png" alt class="image--center mx-auto" /></p>
<p>Now lets display/add Pers_Status column to the master form.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986425218/52f5818c-fb0f-4bbd-9da5-9464e22e530d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986493884/15735fec-36eb-47a9-9531-931328237621.png" alt class="image--center mx-auto" /></p>
<p>Chnage source and sequence so that it appear next to phone no</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986599917/5767db07-cc07-4a3c-a244-691ad98f4298.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986616343/614ceb44-36fa-4f22-8392-7fba1d417c32.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986712445/040d95fd-661a-4cb9-99e0-b44d9d23e22e.png" alt class="image--center mx-auto" /></p>
<p>Lets hide those audit columns as they are auto populated through triggers.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986788542/6972f977-01e8-4445-a245-c5ab55da1e9a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742986913899/97198b5c-6517-4231-bf4e-c281126183c1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991065364/af9eebb1-4847-44da-a82a-f0245a3f0dd5.png" alt class="image--center mx-auto" /></p>
<p>To see single row view</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991181320/eda073e1-ef16-49dc-b196-b3d063aa9e95.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991185635/53197ccd-c5ad-418d-8a8c-6979635daa7f.png" alt class="image--center mx-auto" /></p>
<p>you can click on edit and edit the fields inline</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991233835/73ee8d92-4090-4b8d-b486-55fdbacb3e3d.png" alt class="image--center mx-auto" /></p>
<p>Now lets hide audit columns here and add lovs for status, role and supv id</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991422826/1afe44d6-be82-46ff-aaca-1357e280ed35.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991557707/40edf9f9-6495-4147-8938-e267ababe2a8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991594375/a108cd35-7ae2-4bf3-ab15-2a1d9f520ff8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991638899/a7d11875-f873-4421-82bb-724ec2087996.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991746596/05cea3a5-7f29-467b-9615-4ba6a87bb324.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991754246/676cbbd0-6c4c-43b7-b03e-4e32aaf942c7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742991760674/aee46214-6501-47a1-bec1-2a8ae945ead2.png" alt class="image--center mx-auto" /></p>
<p>You can disbale null value in page designer under column → List of Values to hide null values for selected list. now chnage to single row view and verify if good to edit</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742992029299/1848a962-3085-4cfc-a41c-335c62efcb4f.png" alt class="image--center mx-auto" /></p>
<p>But here the issue is that the supervisor list includes all Veterinarians and Volunteers and also possibly inactive, so we need to automatically exclude them from the select list. For that we need to update the LOV for this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742992545600/de645de7-a66d-4154-bca7-caf8232381e1.png" alt class="image--center mx-auto" /></p>
<p>here this extra filter willl only include active one but don’t exclude vol and vets. so as a best practice no need to edit existing emp_list lov and copy emp_list LOV to create a new SUPV_LIST and edit to add extra filter condition.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742992871962/3d983a7e-0dab-4266-b145-70afc791640c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993106848/9c1c4da2-c028-4dc9-a163-822779bcb629.png" alt class="image--center mx-auto" /></p>
<p>Now change SUPV_ID LOV value to SUPV_LIST from EMP_LIST</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993227377/a54b8441-7635-4016-aa5d-d4c8a4563d5c.png" alt class="image--center mx-auto" /></p>
<p>now you will only see active supervisors</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993369685/148c7ef8-161b-4164-a2e3-2bd12b5f3dd0.png" alt class="image--center mx-auto" /></p>
<p>Now lets create data(person).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993438577/c5d4ddfe-3dfb-4578-9ac6-fa114b203790.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993633803/5c510625-cf95-4987-b0bd-e35af453e6c6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993638659/fdbaf6c1-1873-473e-a05e-7bf26891aab1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993686330/a5277c0e-0106-4959-9774-c5a3f5ed02a9.png" alt class="image--center mx-auto" /></p>
<p>Now lets add a row for Felipe in Employees table</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993746765/52653134-2005-4571-a879-4e5eb257090a.png" alt class="image--center mx-auto" /></p>
<p>click on Add Row</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993829427/77e8ef1a-5b6b-42b0-8f66-1b503e7a2c8a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993843248/e19ea86f-2906-4034-9bc2-ba13064c48de.png" alt class="image--center mx-auto" /></p>
<p>Hide Emp ID</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742993961841/40523e14-3f99-4769-aa49-2ca272a4dadc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742994002633/fe3eda3e-6a4a-4662-9e98-0cc2ccc060bf.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742994145146/e2e7b768-ccec-4910-8bb7-d83aa05e1aa1.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-use-update-to-clean-data-add-a-unary-relationship-to-a-table-remove-a-column"><strong><mark>Use UPDATE to clean data. Add a unary relationship to a table. Remove a column.</mark></strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743000187376/f637bf8f-62e5-414f-ad6c-48b93f87c055.png" alt class="image--center mx-auto" /></p>
<p>Lets add couple of Animals to List of Animals</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743001813658/b716aa53-ecbb-409e-8215-f9474a2286d8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743001976576/084fe950-fd8d-4c0d-907d-523a83be4526.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743002272444/a6085df3-217b-449c-807c-44913057f143.png" alt class="image--center mx-auto" /></p>
<p>Lets update all Dog to Canine. <code>update animals set category = ‘Canine’ where category = ‘Dog‘; —52 rows updated</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743002691036/c329fff9-34d9-4208-bf7d-43ce33cef059.png" alt class="image--center mx-auto" /></p>
<p>Now lets create fk(SUPV_ID_EMP_CONS_FK) on supv_id to reference emp_id in same employees table</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743002989339/41a8fb1b-e50b-4ea3-a6cd-1d67f3c34579.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003009705/4c4a562d-5884-4f38-90b6-bfb1ba3cf64d.png" alt class="image--center mx-auto" /></p>
<p>Just for sake of this constraint creation sucessful we can delete supv_id of the person we created Felipe.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003325602/140be9d7-9b68-4d93-b47a-2f6fd6ebc1a9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003354025/b2e425b7-e3f5-491c-88c4-7ce182db3b20.png" alt class="image--center mx-auto" /></p>
<p>Now go to SUPV_LIST and modify query to get return value, so that going forards correct value get stored on selecting values from select list LOVs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743005471341/b92b865b-d6f8-46fb-b78e-d1663acc3fa8.png" alt class="image--center mx-auto" /></p>
<p>Now let's drop the ZIP_ID column from the ZIP table since we already have a meaningful unique ZIP column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003822673/212cdc0d-0309-4c06-97f5-32aba8a55208.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743003868317/5f0063b3-afa3-4be9-bfcf-e5a063b8fa2e.png" alt class="image--center mx-auto" /></p>
<p>Finally, after completing all these steps, reimport the data model to see the removal of the zip_id column and the new hierarchical/unary relationship.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743004541960/ab7a760f-a0f4-4637-97a0-902e525777fd.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-create-interactive-report-and-grid-format-phone-display-with-lov"><strong><mark>Create interactive report and GRID. Format phone display with LOV.</mark></strong></h3>
<p>Copy ZIP_LIST lov to create a new city_state_zip_list</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743005627389/e364beb2-56f2-4b2e-a6f3-b54b6d85fb35.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743005760320/0dd2753d-8c6b-4b7d-8cb8-f5aa58db9391.png" alt class="image--center mx-auto" /></p>
<p>Pages till now</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743005835021/08aa3dae-5c13-4be8-86db-4b7724b1a61b.png" alt class="image--center mx-auto" /></p>
<p>Now lets create a interactive report page</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743005855003/62ecff9d-b9d4-4179-bfb1-a89bdaeb98fb.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743006455848/5a5e0241-a5d9-4e1a-bf5e-63a5749b79c0.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> PERSONS.PERS_ID,
       PERSONS.FNAME,
       PERSONS.MNAME,
       PERSONS.LNAME,
       PERSONS.ADDR,
       PERSONS.ZIP,
       PERSONS.PHONE_NUM,
       EMPLOYEES.STATUS,
       EMPLOYEES.ROLE,
       EMPLOYEES.SUPV_ID,
       EMPLOYEES.BEGIN_DATE,
       EMPLOYEES.END_DATE,
       PERSONS.DATE_CREATED,
       PERSONS.DATE_MODIFIED
  <span class="hljs-keyword">FROM</span> PERSONS <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> EMPLOYEES <span class="hljs-keyword">ON</span> (PERSONS.PERS_ID = EMPLOYEES.PERS_ID)
 <span class="hljs-keyword">WHERE</span> EMPLOYEES.STATUS = <span class="hljs-string">'Active'</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743006497992/9c65c601-d4b9-4152-8276-e825c3811871.png" alt class="image--center mx-auto" /></p>
<p>Now let's display the city_state_zip LOV instead of only the zip on the newly created UI interactive report.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743006644946/3d18885a-92bf-41f3-b2cb-99e00b438cc1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743006654996/8fec4eba-0c35-4778-ab4e-ff4d8ab5a15f.png" alt class="image--center mx-auto" /></p>
<p>Now we’ll display a formatted phone number. for that we will create a dynamic LOV from scratch.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743006780768/f3313a9a-8187-4a3e-ac5c-063158d495d3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007467697/90f26d57-700d-4204-94c3-7397152ba2c1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007499204/b642e079-1c5c-4b01-8fa4-caf3ce1d9942.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007544523/c1edd56a-374a-4cc3-aa80-92a6fa0c7fbc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007564036/5af47715-7dbd-42eb-912e-7f534f1c440c.png" alt class="image--center mx-auto" /></p>
<p>We can filter in IR also. We see 2 emp and 2 vol</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007662600/545b4166-8342-4eb9-8814-376e95c43ea6.png" alt class="image--center mx-auto" /></p>
<p>We can download this report with the formatting intact and only the selected records displayed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007698601/0affd669-6a81-4b6e-9ad2-fac7a30ea96d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007749832/70af1ad3-5f3e-4bcf-bfd5-84dc84bf85f2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007762400/eea7590d-06c5-4fc3-a4d4-e1ddd69ec62f.png" alt class="image--center mx-auto" /></p>
<p>In the downloaded report, the ZIP and PHONE_NUM are formatted even if the database values are not, making the download feature very sophisticated and useful.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743007927739/4ad3b2ac-06d7-439e-9a1f-23eb89221ac0.png" alt class="image--center mx-auto" /></p>
<p>Now let's create an interactive Grid without using SQL, as updatable SQL is somewhat complex and an advanced topic.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008225473/ca0d200b-c893-4cc6-bfab-856f30fcfeea.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008388720/cafc96fb-e976-4c71-a882-946882b8ce46.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008401409/2a3cbf66-1401-42ea-9d84-f88284247980.png" alt class="image--center mx-auto" /></p>
<p>while running the app if you get below error then fix the reference of D.ZIP_ID lov</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008534336/855ad0a2-807d-418c-ab1a-0bcceb6ba303.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008579375/ee9bb88e-04ab-44ec-a78a-6378668951bf.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008597858/8656c83a-62fb-4aba-bece-7f2599c6a239.png" alt class="image--center mx-auto" /></p>
<p>This IG is similar to IR but includes row actions on the left for adding and deleting rows, and allows inline field editing if the edit option was enabled during page creation; if not, you can edit by going to single row view → edit.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008923359/9658493d-0613-49e0-b762-8891bbccf272.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743008899373/393d0258-ef6b-448b-9a8e-d5e118505aae.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-unique-constraint-on-2-columns-add-computation-to-a-page-item-in-form"><strong><mark>Unique constraint on 2 columns. Add computation to a page item in form.</mark></strong></h3>
<p>Let’s modify DOM_BREED column of lookup table DOM_BREED_LOOKUP and add a column ANIMAL_CATEGORY VARCHAR2(15)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743048049390/cc5c7ddd-989e-4736-b29d-f583ce76c0bf.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743048186791/2bfc2676-f1f0-461b-998c-f6988507b8e9.png" alt class="image--center mx-auto" /></p>
<p>Now lets drop constraint DOM_BREED_LOKKUP_UNIQ.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743048442477/1a6ab593-aab6-4171-b2c4-e24bd85c82ed.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743048556527/e3d2029a-e510-45a8-a546-7f65c8b53dbf.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743048736080/1ae565af-d7c4-41ec-be19-d7f204ffc3fa.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743048772210/92a23d16-519f-4cf7-b650-78c1b567fcee.png" alt class="image--center mx-auto" /></p>
<p>Now that we have populated animal_category column, lets create check constraint on animal_category saying column can’t be NULL and create composite unique key constraint for DOM_BREED and ANIMAL_CATEGORY.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743048930002/aa2f2d6a-fd61-4d07-bb2e-fbde48c7913b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743049012752/e317b953-5689-4875-b4bc-b19cac55c958.png" alt class="image--center mx-auto" /></p>
<p>update DOM_BREED and ANIMAL_CATEGORY to UPPER case.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743049266232/245f9add-bda2-47e4-8517-6a8ab12a31b0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743049322680/69d0c475-ad7c-4bd5-a058-a66b7038d6b3.png" alt class="image--center mx-auto" /></p>
<p>Now Change ANIMAL_CATEGORY LOV RETURN value to be in UPPER case(edited manually)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743049522071/1f3620f9-f3f6-45df-8166-96d0101af490.png" alt class="image--center mx-auto" /></p>
<p>Now lets change case of CATEGORY to upper case to make things consistent</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743049738230/a553d1f8-c6af-4da3-a579-ae57bde27a09.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743049820463/95e4dbd3-6f71-4072-a672-0ae7097c87d6.png" alt class="image--center mx-auto" /></p>
<p>Lets delete page Dominant Breed Report and its corresponding form page (#8 and #9)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743049865830/51548eef-8009-4277-9e7a-86ad67d15250.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743050053466/82ff2707-a7ee-4555-ae95-6bb57596bda2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743050097794/094ae973-72db-410a-8a64-17a91c439728.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743050121924/26e6cdde-85d6-465a-9bb2-1ec57d0a606e.png" alt class="image--center mx-auto" /></p>
<p>Now add the page from scratch</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743050433459/7ee619cf-17df-40d8-9b5a-6a83a13950c2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743050447656/ff4f9325-99f4-4abc-b77e-4f7d49747dbd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743050484045/79dd9b27-c6c7-425c-8bca-805c74dbbdee.png" alt class="image--center mx-auto" /></p>
<p>Please note that if you want to change the target of a menu item, you can do it from the shared component menu and update the target.</p>
<p>Now edit the form page layout to see and enter all field details in a single line.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743051137500/a89dab45-fa59-44d6-bc80-c4c5865d3d84.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743051152356/45bafd3c-cbc2-4538-9d7b-cd1b373c425c.png" alt class="image--center mx-auto" /></p>
<p>now bring Animal Category label before Dom Breed</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743051283085/b28f1f58-ae5c-4156-b0b9-b773dab41278.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743051841753/b1201f41-667a-420c-88d0-2b30d6671c3b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743051899779/8af758c2-e94d-4dae-a9b5-90569131d4f4.png" alt class="image--center mx-auto" /></p>
<p>Entering the same values will cause a unique constraint violation error, but entering DOM BREED in lowercase will succeed incorrectly; to fix this, change the animal category to a select list and source it from the animal category LOV you created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743051999896/806ad358-f3c0-42b6-b022-a9e50d228c14.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052075936/c623c27d-9424-469a-aa12-25fa8a433a8d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052243490/f89c09fa-839d-4986-9ce9-676dbdf3a195.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052262136/d15b34b4-e269-4456-8765-55af0a6568ec.png" alt class="image--center mx-auto" /></p>
<p>For DOM BREED lets create a computation</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052311001/0844d8a1-92a9-435e-bcbe-0416a327c81d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052427043/dd1bb138-cd4a-43b6-969a-b86da13ade73.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052510619/66ea310e-07ea-4cac-b416-82e117d11bf2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052525014/38c72f8a-5576-4c41-832a-a82cd8abaf74.png" alt class="image--center mx-auto" /></p>
<p>now delete old record for calico</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743052594777/c75e93dc-8dcc-4c71-8e6a-c6f2083aee94.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-cascading-lovs-selection-in-one-sets-the-list-in-other-create-after-update-triggers"><strong><mark>Cascading LOVs: selection in one sets the list in other. Create after-update triggers.</mark></strong></h3>
<p>Lets edit the form page so that when category selected then corresponding Dom Breed should appear in Dom Breed Id field</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743167560253/946e86f1-576f-4bb4-8447-264c95e5de6d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743167629186/cc9e7277-8837-458d-ae23-b7e1cde738bf.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743167882582/fb7b1cd1-8582-422f-9720-e3f570115f27.png" alt class="image--center mx-auto" /></p>
<p>Now, if you run the application and select the category Feline, you will only see the DOM Breed that corresponds to FELINE, and it works the same for others.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743168261629/25d47c1c-03d4-414f-b616-b8cee51d57e2.png" alt class="image--center mx-auto" /></p>
<p>Now lets create a editable interactive grid Animal Grid</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743168763173/6d9200cd-4b4a-4c33-b904-58d52aa0df91.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743168775415/6b298af8-9bbf-4f6e-9ba1-48cbc9c96a52.png" alt class="image--center mx-auto" /></p>
<p>Now rename Dom Breed ID to Dom Breed and bring that to after Category column heading</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743168861415/b50c27e7-020b-47ce-baea-586abc2d4650.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743168896329/22efe48d-5be5-4a09-9092-f30802686f6a.png" alt class="image--center mx-auto" /></p>
<p>use up arrow in column section to get dom breed below category</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743168977341/ca52a715-46cc-4390-a63e-197cfddcb8ed.png" alt class="image--center mx-auto" /></p>
<p>In the page designer, change the category type to a select list, source it from Animal_category LOV, use dom_breed as the source SQL statement, and update Parent columns and Items to submit under cascading List Of Values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743169291888/b5172325-ed08-460e-9a33-631cb0891dde.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> DOM_BREED <span class="hljs-keyword">as</span> DISPLAY,
    DOM_BREED_ID <span class="hljs-keyword">as</span> <span class="hljs-keyword">RETURN</span> 
 <span class="hljs-keyword">from</span> DOM_BREED_LOOKUP 
 <span class="hljs-keyword">where</span> ANIMAL_CATEGORY = :<span class="hljs-keyword">CATEGORY</span>
 <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> DISPLAY
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743169449921/9b2838c4-a8d9-4162-b8c5-6e140512135e.png" alt class="image--center mx-auto" /></p>
<p>Now, in the grid report, when you click to populate Dom Breed, you'll only see the breeds that match the selected category, such as Feline.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743169725789/5492ce6b-3330-45b1-91cd-00232e0a9c2a.png" alt class="image--center mx-auto" /></p>
<p>Now, let's execute the script <code>triggers_before_update.sql</code> from the downloaded folder to create before-update triggers for each table (except lookup tables) that will populate the <code>date_modified</code> audit column whenever these tables are updated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743170029239/894e3b76-1301-4e33-ab2e-146b209bcb05.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743170069902/b58162c8-67c9-4c93-8814-54b4889ce6d3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743170012181/7268497f-e66c-4526-87dc-68ce6d27e89e.png" alt class="image--center mx-auto" /></p>
<p>Now, when we edit anything, the DATE_MODIFIED column is automatically filled due to the before trigger action.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743170252223/be7bacaa-0782-4a4a-8f4f-cc86f218ec6f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743170267557/c54c7a00-237a-41c6-a29f-997d1b76f625.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-create-a-button-and-dynamic-action-in-a-form-to-calculate-age"><strong><mark>Create a button and dynamic action in a form to calculate age.</mark></strong></h3>
<p>Lets bring Chip No, Est DOB, Est Age in one line in report so that some space will be there for a button to be created to calculate age.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743246762326/1e5915ce-6c9d-4229-8565-d0b7564802fc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743246795854/1476e8ce-4601-478b-bdb3-b7e59ef5a5ee.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743247010325/04e7c36d-5bc1-4bac-921e-02c9222ecb17.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743247117154/32153bea-432c-400a-8ca5-5d2270d9f397.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743247200949/c6faf6f8-20fa-4599-8aff-bc1d79771ddc.png" alt class="image--center mx-auto" /></p>
<p>Now lets add a dynamic action for this newly created column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743247249412/c212b48e-7496-4959-8ab1-02d5519eb7e6.png" alt class="image--center mx-auto" /></p>
<p>Do these require field value changes for the new button's dynamic action.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743248020666/32150a05-4e7b-403a-9f4f-3e3c0ace9037.png" alt class="image--center mx-auto" /></p>
<p>Verify this by changing Est DOB and notice that the change is reflected in the Est Age field, as we set the affected elements to P5_EST_AGE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743248350769/8a1eb041-349a-474b-8c69-171eff3c9a59.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743248369684/058b632c-bb6e-4fe8-8005-ed2bd76dc1d3.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-create-page-groups-to-organize-the-application-web-pages"><strong><mark>Create page groups to organize the application web pages.</mark></strong></h3>
<p>Page groups used to organize pages, including a group for pages that may be deleted later.</p>
<p>We’ll group the web pages based on the purpose within the overall application. so we’re going to have groupings based on the parent pages those are just the landing pages that you see when you click on navigation area if you click on Animals then you see an introductory or parent page before you select a particular report or form for animals . so Lets have Group parent pages, Animals, People, Maintenance, Other.</p>
<p>We’ll start by creating another form and report for data maintenance. Lets create a Interactive Report.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743251899168/e570de1b-ffab-4c0a-b100-21e0b94755b5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743251909547/ed0c7bc6-f3e8-4f86-b001-e4b993d345c9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252004701/adaa8c32-76bb-4a0d-ae25-ccf61c3ccbba.png" alt class="image--center mx-auto" /></p>
<p>Now Lets create Interactive report page for subcategory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252226736/8902700f-022c-4acd-86e7-5968f35bfe09.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252235735/e1994705-c596-41f6-b100-f3293466cc5c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252249925/39de8b66-9fd5-427b-8226-7a746ff333a2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252259939/897cf387-1faa-443d-b06f-e5b36ad3443a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252643854/d2de90d7-f19f-4f5e-ae5b-7546717ec75a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252673674/f5f317b7-dd35-46e8-acd4-4441d8f30b8d.png" alt class="image--center mx-auto" /></p>
<p>Now lets organize these pages. Goto Utilities → Page Groups → Create and then create groups based on requirement.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252798077/e1930811-93a2-41dd-8a49-a13590096291.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252812936/c0981cb6-4eb7-4dc8-bfd3-b78e1b4798fb.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252832661/6ecceb60-5ced-4d9a-bb9a-bb99d773d983.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743252985798/e12f9ec6-bff1-4ad9-98ee-08cb15cea93f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743253013819/a4c4d7ff-2d28-4b01-ba8d-2c2543243e45.png" alt class="image--center mx-auto" /></p>
<p>Similarly create other groups Animals, People, Maintenance, Other.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743253165860/4f63a9ae-f146-45e4-915d-faa5127c2d61.png" alt class="image--center mx-auto" /></p>
<p>Now let’s do Page Group Assignments by clicking on Page Group Assignments or from page designer pages. In page designer assign page group for page List of Animals report page. save and verify same from Page Group Assignments section in Page Group.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743253350607/5c45d50b-1844-4328-8b68-99c499704f21.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743253426195/126455ee-beea-4596-939d-b1b600858e40.png" alt class="image--center mx-auto" /></p>
<p>Now go to Up and note down each page number, then decide which pages you want to put under each page group. For Animals, use pages 10, 2, 5, 4, 8. For People, use pages 11, 13, 14, 15, 26, 16, 17, 19, 20, 25. For Data Maintenance, use pages 12, 6, 7, 9, 29, 21, 22, 23, 24. and rest all assign to Other Page Group.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743256113434/3e7d7a49-d3d7-4c0b-9dc7-488474df3ce5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743256437115/af1e36d4-0ec6-42c8-aed2-9fcbd1e66eb5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743256447115/fa64fe64-0182-4f32-ad27-aad4cfeabd55.png" alt class="image--center mx-auto" /></p>
<p>Now to see pages by groupings click on Pages by Page Group.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743257108669/b20e248b-32e3-4782-bdce-6eccd0f21f37.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743257114631/b33d000b-dd0e-4d53-9ca1-de37c6c030ee.png" alt class="image--center mx-auto" /></p>
<p>Now return to the application page and search by typing the page group, as shown in the example where we searched for Other.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743257212071/4f2e94b0-60e4-4c97-a43c-b24d90cb5677.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743257370604/32fcaf5f-7223-46a3-9a1d-094da6e081b3.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-look-at-the-3-layout-options-for-master-detail-forms"><strong><mark>Look at the 3 layout options for master-detail forms.</mark></strong></h3>
<p>We will create master-detail forms for Activities and transactions related to Animals.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258124302/590575e0-571c-4d88-a4a3-d5efb6c59806.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258157835/92a8f37e-faf6-4a35-bd9d-4ef603650ebb.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258238876/5ae02bd0-3ed2-4191-a4a2-b34a950ee222.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258258812/be7b0710-a5d7-4929-adf8-2a262bedad76.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258450670/ecf0cb78-8698-4047-a97b-f3c4bdc84cef.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258459216/d95c9f66-1257-4309-9f01-5558ba22f7f0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258474425/f0f4d732-507b-4ab3-9016-a1b478786bac.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258497920/332db3fe-cb1b-4afa-aa57-c22f6041dbc5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258615276/d0de40f1-0965-42f2-8f1d-ef5bc13386fd.png" alt class="image--center mx-auto" /></p>
<p>Selecting an animal from the master report shows the related transactions on the details page, and for a better view, we can change the Type attribute under pagination to Page and set rows per page to 5 to see both master and details on one page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258963011/fa080b0a-4fb0-4208-84ab-9a9c553ee122.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743258975159/41b965de-d835-42b5-9eda-048dc84b4c42.png" alt class="image--center mx-auto" /></p>
<p>Let's change the headings and identification type of Dom Breed Id and Status ID to select lists.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259232633/a4df20ef-9b45-4ac4-b874-560baf1c724a.png" alt class="image--center mx-auto" /></p>
<p>Now lets create a master-details report for Animal Activities. Plan is to see both transactions and activities for selected Animals.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259492047/35752681-4c97-47f3-9340-5b33d3d68428.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259512776/90220167-f634-4e73-9935-3f7f2dd6d4fd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259653874/a74d0c6d-dd02-44d2-9a08-4cc099b72763.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259761731/00afabc0-8185-490f-8f59-4d97ff66893c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743259775844/5331c1af-c998-4633-9082-324f2e9c8623.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260049079/823d1113-534e-44f7-9554-f85ea540d620.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260191696/d2cd8bfd-7ffc-41ba-bdd3-025b21da12f2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260411796/814bd7f4-c207-457c-9bca-8bfe081e3746.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260423714/5954eceb-1582-4265-a40d-e6f563aaac24.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260080946/a10dc2a1-4371-4adc-bb30-9d3c2e42f8f9.png" alt class="image--center mx-auto" /></p>
<p>Now let's create a drill-down master-details report page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260506123/14326675-a798-4652-9ce9-0b0806755ad2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260619175/fa7eb67c-b32c-4d91-a2a7-703e9005767c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260669392/33207028-2712-404e-97aa-39d8a41263a9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260835260/56fc288a-c228-454a-a28d-227725538383.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260857760/befb9f13-4bcc-4fd9-b21b-80bd8d05f152.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260954312/3f491af5-c03d-43db-8e4a-54a993039313.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260976151/b4e412cf-d4e6-4b7b-b4fb-80c3fb15fba0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743260983665/3d539e27-945a-43e6-91b1-25213444a2e0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743261468327/b9d91243-332c-43a8-83ea-39d7596caf2a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743261495319/ab03d79d-c981-4166-b04b-b28ab77920f3.png" alt class="image--center mx-auto" /></p>
<p>Lets add a page item to see animal pic which will enhance visibility for single row edit for.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743261808457/8b260584-dcc6-4cdf-9a31-d05ab868f528.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743261827302/782d145e-54e9-47d5-9415-ce20dddaee70.png" alt class="image--center mx-auto" /></p>
<p>If you get an error saying "column ambiguously defined," try debugging by enabling debug mode to check the debug info, or delete the ANIMAL_PIC item as it might duplicate the newly created item P34_PICTURE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743263926671/5369bd28-48c5-4b7a-98a9-fe80fcbe5363.png" alt class="image--center mx-auto" /></p>
<p><strong>THE END</strong></p>
<h2 id="heading-faqhttpsdrivegooglecomdrivefolders1nzeoptnrq2nd9gkjehdip4tbq8foxwc"><a target="_blank" href="https://drive.google.com/drive/folders/1NzeOPTnrq2nd9GkjEHdI_p4TBQ8foxWC">FAQ</a></h2>
<ol>
<li><p><strong>How to enable RESTful services in ORDS?</strong><br /> <a target="_blank" href="https://panigrahisantosh.com/rest-enabling-the-hr-schema-in-oracle-ords-a-complete-guide">You can refer to this blog for the answer.</a></p>
</li>
<li><p><strong>How can you debug an Apex app?</strong></p>
<p> Enable debug mode from the dev toolbar to view debug info, or add a message and check the SQL right after it in the debug info to help, as shown in the example below.</p>
<p> <code>APEX_DEBUG.ENABLE(apex_debug.c_log_level_info);</code><br /> <code>apex_debug.message(p_message =&gt; 'Santosh Panigrahi enabled Debug. SQL below:');</code><br /> <code>apex_debug.message(p_message =&gt; v_sq1) ;|</code></p>
</li>
</ol>
<p>You can also refer this video <a target="_blank" href="https://youtu.be/VVr8dybBeuE">APEX_DEBUG</a> from ERPStuff</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[Must Read Articles from different developers]]></title><description><![CDATA[Learn Oracle APEX – 15+ sources to speed up your learning process
https://oracle-base.com/articles/misc/apex-tips-basic-apex-management
https://www.rebellionrider.com/how-to-uninstall-oracle-database-19c/
https://www.rebellionrider.com/how-to-install...]]></description><link>https://panigrahisantosh.com/must-read-articles-from-different-developers</link><guid isPermaLink="true">https://panigrahisantosh.com/must-read-articles-from-different-developers</guid><category><![CDATA[oracle advance concepts]]></category><category><![CDATA[partition]]></category><dc:creator><![CDATA[Santosh Panigrahi]]></dc:creator><pubDate>Wed, 18 Dec 2024 18:34:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Oaqk7qqNh_c/upload/ab8bbd843ee50ab1efaa481edd418108.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://pretius.com/blog/learn-oracle-apex-15-sources-to-speed-up-your-learning-process/">Learn Oracle APEX – 15+ sources to speed up your learning process</a></p>
<p><a target="_blank" href="https://oracle-base.com/articles/misc/apex-tips-basic-apex-management">https://oracle-base.com/articles/misc/apex-tips-basic-apex-management</a></p>
<p><a target="_blank" href="https://www.rebellionrider.com/how-to-uninstall-oracle-database-19c/">https://www.rebellionrider.com/how-to-uninstall-oracle-database-19c/</a></p>
<p><a target="_blank" href="https://www.rebellionrider.com/how-to-install-oracle-database-19c-on-windows-10/">https://www.rebellionrider.com/how-to-install-oracle-database-19c-on-windows-10/</a></p>
<p><a target="_blank" href="https://www.rebellionrider.com/how-to-find-out-the-sid-and-db-home-in-oracle-database/">https://www.rebellionrider.com/how-to-find-out-the-sid-and-db-home-in-oracle-database/</a></p>
<p><a target="_blank" href="https://danischnider.wordpress.com/2022/07/02/housekeeping-in-oracle-how-to-get-rid-of-old-data/"><strong>Housekeeping in Oracle: How to Get Rid of Old Data</strong></a></p>
<p><a target="_blank" href="https://www.thatjeffsmith.com/archive/2023/09/ords-101-enabling-oracle-schemas-for-https-rest/">https://www.thatjeffsmith.com/archive/2023/09/ords-101-enabling-oracle-schemas-for-https-rest/</a></p>
<p><a target="_blank" href="https://oracle-base.com/articles/misc/oracle-rest-data-services-ords-rest-enabled-sql">https://oracle-base.com/articles/misc/oracle-rest-data-services-ords-rest-enabled-sql</a></p>
]]></content:encoded></item><item><title><![CDATA[APEX, ORDS, and TOMCAT INSTALLATION]]></title><description><![CDATA[In this guide, I'll walk you through the installation process of Oracle Application Express (APEX), Oracle REST Data Services (ORDS), and Tomcat in Windows.
Following a step-by-step approach, we'll ensure a clean setup for all components.
Prerequisit...]]></description><link>https://panigrahisantosh.com/apex-ords-and-tomcat-installation</link><guid isPermaLink="true">https://panigrahisantosh.com/apex-ords-and-tomcat-installation</guid><category><![CDATA[apex, ords, tomcat, rest, installation]]></category><dc:creator><![CDATA[Santosh Panigrahi]]></dc:creator><pubDate>Tue, 06 Feb 2024 09:07:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/MNd-Rka1o0Q/upload/7a9b25894f3a3a64f4609cb36ac17093.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this guide, I'll walk you through the installation process of Oracle Application Express (APEX), Oracle REST Data Services (ORDS), and Tomcat in Windows.</p>
<p>Following a step-by-step approach, we'll ensure a clean setup for all components.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<h3 id="heading-oracle-database-installation">Oracle Database Installation</h3>
<ul>
<li><p>Make sure Java is installed on your machine. if not install same (preferably &gt;= <strong>jdk17</strong>)</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707293028076/e2ee2206-585e-495d-a68a-6fbf7dc50212.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Ensure Oracle DB is installed (Version: <strong>19c</strong> in our case).</p>
</li>
<li><p>Check Oracle DB version:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">SELECT</span> banner <span class="hljs-keyword">FROM</span> v$<span class="hljs-keyword">version</span>;

  Output

  BANNER
  <span class="hljs-comment">--------------------------------------------------------------------------------</span>
  Oracle Database 19c Enterprise Edition <span class="hljs-keyword">Release</span> <span class="hljs-number">19.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span> - Production
</code></pre>
</li>
<li><p>Install Any IDE of your choice such as <strong>SQL Developer</strong> or <strong>TOAD</strong>.</p>
</li>
<li><p>Data modeling software (<strong>optional</strong>). SQL Developer can be used for ERD visualization.</p>
</li>
</ul>
<h3 id="heading-uninstall-apex-if-already-installed">Uninstall APEX (if already installed) :</h3>
<ul>
<li><pre><code class="lang-sql">  <span class="hljs-comment">-- Check APEX Version from APEX_RELEASE Table:</span>
  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> APEX_RELEASE;

  <span class="hljs-comment">-- Check APEX Installation Status from DBA_REGISTRY Table:</span>
  <span class="hljs-comment">-- If APEX is installed, you should see a row with COMP_ID as 'APEX'</span>

  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> DBA_REGISTRY <span class="hljs-keyword">WHERE</span> COMP_ID = <span class="hljs-string">'APEX'</span>;
</code></pre>
</li>
<li><p>If you see any row indicating APEX is already installed, change the working directory to APEX using <code>cd apex</code>. Start SQL*Plus and connect to the pluggable database where APEX is installed as SYS, specifying the SYSDBA role, and execute <code>@apxremov.sql</code>. Then exit SQL*Plus and reconnect before attempting a new install using <code>apexins.sql</code>.</p>
</li>
</ul>
<h3 id="heading-fresh-apex-installationhttpsapexoraclecomenlearndocumentation"><a target="_blank" href="https://apex.oracle.com/en/learn/documentation/">Fresh APEX Installation:</a></h3>
<ol>
<li><p>Download and unzip APEX from <a target="_blank" href="http://www.oracle.com/technetwork/developer-tools/apex/downloads/index.html">Oracle's official website</a>.</p>
</li>
<li><p>This will create a folder named '<strong>apex24_2</strong>', and you should navigate to the 'apex' folder using <code>cd apex</code>.</p>
</li>
<li><p>Start SQL*Plus and make sure you connect to your PDB, not the "root" of the container database, since APEX should not be installed there.</p>
<pre><code class="lang-sql">
 sqlplus / as sysdba

 <span class="hljs-comment">--create PDB named DEMO</span>
 <span class="hljs-keyword">create</span> <span class="hljs-keyword">pluggable</span> <span class="hljs-keyword">database</span> demo <span class="hljs-keyword">admin</span> <span class="hljs-keyword">user</span> demo_admin <span class="hljs-keyword">identified</span> <span class="hljs-keyword">by</span> &lt;<span class="hljs-keyword">password</span> <span class="hljs-keyword">for</span> pdb&gt; <span class="hljs-keyword">file_name_convert</span>=(<span class="hljs-string">'pdbseed'</span>, <span class="hljs-string">'demo'</span>);

 <span class="hljs-comment">-- Chnage container to created DEMP pdb</span>
 <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">SESSION</span> <span class="hljs-keyword">SET</span> <span class="hljs-keyword">CONTAINER</span> = DEMO;

 <span class="hljs-comment">-- Create APEX tablespace</span>
 <span class="hljs-keyword">create</span> <span class="hljs-keyword">tablespace</span> apex <span class="hljs-keyword">datafile</span> <span class="hljs-string">'E:\app\oradata\ORCL\demo\apex.dbf'</span> <span class="hljs-keyword">size</span> <span class="hljs-number">300</span>m <span class="hljs-keyword">autoextend</span> <span class="hljs-keyword">on</span> <span class="hljs-keyword">next</span> <span class="hljs-number">10</span>m;

 <span class="hljs-comment">-- Install APEX lowcode environment</span>
 @apexins.sql APEX APEX TEMP /i/

 Note only for runtime environment run @apxrtins.sql. usually in PROD environment.
 <span class="hljs-comment">-- Alternatively, utilize the below command:</span>
 sqlplus sys@//localhost:port/pdb as sysdba @apexins sysaux sysaux temp /i/
</code></pre>
<p> <strong>This will take some time</strong>.....  </p>
</li>
<li><p>Upon execution of the <code>apexins.sql</code> or <code>apxrtins.sql</code> , a log file generated in the apex directory, adhering to the format <code>installYYYY-MM-DD_HH24-MI-SS.log</code>. In the event of a successful installation, the log file will display the message: "<strong><em>Thank you for installing Oracle APEX. Oracle APEX is installed in the APEX_240200 schema"</em></strong></p>
</li>
</ol>
<p>    Note that few errors in log does not necessarily indicate a failed installation.  </p>
<ol start="5">
<li><p><strong>Unlocking the</strong> <a target="_blank" href="https://medium.com/@techtutorsti/apex-public-user-f06073ffa914#:~:text=Configuration%20with%20ORDS%3A%20The%20APEX_PUBLIC_USER,the%20database%20through%20web%20services."><strong>APEX_PUBLIC_USER</strong></a> <strong>Account:</strong></p>
<pre><code class="lang-sql"> <span class="hljs-keyword">alter</span> <span class="hljs-keyword">user</span> apex_public_user <span class="hljs-keyword">identified</span> <span class="hljs-keyword">by</span> <span class="hljs-keyword">oracle</span> <span class="hljs-keyword">account</span> <span class="hljs-keyword">unlock</span>;
</code></pre>
</li>
<li><p>Execute <code>@apxchpwd.sql</code> to configure and update the instance administrator username and password. Ensure to provide a robust password; otherwise, the script will prompt repeatedly until a strong password is provided and the process is successful.  </p>
</li>
<li><p>To check instance administrator user (default ADMIN ) details -</p>
<pre><code class="lang-sql"> <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> APEX_240200.WWV_FLOW_FND_USER;
</code></pre>
 <div data-node-type="callout">
 <div data-node-type="callout-emoji">💡</div>
 <div data-node-type="callout-text">Let's take a quick look at the "WWV_FLOW" tables:</div>
 </div>

<p> The "WWV" prefix stands for "Web Warrior Virtual." It's a common naming style in Oracle APEX, used for internal components and objects.</p>
<p> When you install Oracle APEX, a user is created (like APEX_230200, which can change with different versions). This user holds the "WWV_FLOW" tables, which store important metadata and runtime data for APEX apps. For example:</p>
<ul>
<li><p>WWV_FLOW_USERS: Stores user information for APEX. Example query: SELECT * FROM APEX_230200.WWV_FLOW_USERS;</p>
</li>
<li><p>WWV_FLOW_SESSION: Keeps track of session details for APEX apps. Example query: SELECT * FROM APEX_230200.WWV_FLOW_SESSION;</p>
</li>
<li><p>WWV_FLOW_FILES: Manages files related to APEX apps. Example query: SELECT * FROM APEX_230200.WWV_FLOW_FILES;</p>
</li>
</ul>
</li>
<li><h3 id="heading-apex-installation-verification">APEX Installation Verification</h3>
<ul>
<li><p>Check APEX installation:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> DBA_REGISTRY <span class="hljs-keyword">WHERE</span> COMP_ID = <span class="hljs-string">'APEX'</span>;
  If APEX is installed, you should see a row <span class="hljs-keyword">with</span> COMP_ID <span class="hljs-keyword">as</span> <span class="hljs-string">'APEX'</span>.
</code></pre>
</li>
<li><p>Check APEX release version:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> APEX_RELEASE;
</code></pre>
</li>
<li><p>Verify instance administrator user:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> APEX_240200.WWV_FLOW_FND_USER;
</code></pre>
</li>
<li><p>Prevent <strong>ADMIN</strong> from changing the password on first login:</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">UPDATE</span> APEX_240200.WWV_FLOW_FND_USER <span class="hljs-keyword">SET</span> CHANGE_PASSWORD_ON_FIRST_USE=<span class="hljs-string">'N'</span>;
</code></pre>
</li>
</ul>
</li>
</ol>
<p>    <strong><mark>Now let's move to ORDS installation.</mark></strong></p>
<h3 id="heading-first-uninstall-ords-if-already-installed">First Uninstall ORDS (if already installed):</h3>
<h3 id="heading-ords-installation-official-getting-startedhttpsdocsoraclecomendatabaseoracleoracle-rest-data-services244indexhtml">ORDS Installation: (<a target="_blank" href="https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/24.4/index.html">Official Getting Started</a>)</h3>
<ol>
<li><p>Verify if ORDS already installed <code>ords --version</code></p>
</li>
<li><p>To uninstall ORDS run : <code>ords uninstall</code></p>
</li>
<li><p>Now download the latest ORDS, unzip it, and navigate to the ords directory using <code>cd E:\ords\</code>.</p>
</li>
<li><p>Add ords bin to the environment PATH; otherwise, you will need to use the absolute path to run ords.</p>
</li>
<li><p>Create a system environment variable <strong>ORDS_CONFIG</strong> and assign it a folder that will be used for ORDS configuration (ensure this folder is not inside ords directory). for use ORDS_CONFIG = E:\ord_config</p>
</li>
<li><p>Lets install in standalone mode ( interactively) : <code>ords install</code><br /> <strong>Note : during installation in option #9 for apex static file path give //(double slash in path separator) insted of /(single slash) else / will not be interpreted correctly and merged to a single string.</strong></p>
</li>
<li><p>After installation validate the version -<code>ords --version</code></p>
</li>
<li><p><code>SELECT * FROM DBA_USERS WHERE USERNAME LIKE '%ORDS%'</code></p>
<p> ORDS_PUBLIC_USER<br /> ORDS_METADATA<br /> ORDSYS</p>
</li>
<li><p>To start <code>ords serve</code></p>
</li>
<li><p>That's it!! You should now be able to login <a target="_blank" href="http://localhost:8080/ords/">http://localhost:8080/ords/</a>  </p>
<p>The structure of the link to the Oracle APEX Administration Services is as follows: <a target="_blank" href="http://localhost:8080/ords/apex_admin">http://localhost:8080/ords/apex_admin</a>  </p>
<p>The structure of the link to the Oracle APEX development environment is as follows: <a target="_blank" href="http://localhost:8080/ords/apex">http://localhost:8080/ords/apex</a>  </p>
<p><strong>Workspace:</strong> internal<br /><strong>Username:</strong> admin<br /><strong>Password:</strong> &lt;passwd you had provided&gt;</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680796697102/ef9416cc-060e-43ec-ab56-40a22e3226c8.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt="APEX Login Page" /></p>
</li>
<li><p>Now, the challenge is that we need to manually start ORDS using the "<em>ords serve</em>" command every time we want to use APEX. To solve this, we should deploy the ords.war file into Tomcat, so ORDS starts automatically when Tomcat initializes during a system reboot. <strong>Let's explore the process of installing and configuring Tomcat for ORDS deployment.</strong></p>
</li>
<li><p>Download and set up <a target="_blank" href="https://tomcat.apache.org/download-90.cgi">Tomcat</a>, configuring it to utilize port 8080</p>
</li>
<li><p>Visit <a target="_blank" href="http://localhost:8080/">http://localhost:8080/</a> to ensure Apache Tomcat is up and running.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707292753506/dcddaf4b-969b-4535-865e-22393f6f9904.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Copy apex images folder as i <strong>(~\apex\images)</strong> to Tomcat webapps folder <strong>(C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps\i)</strong></p>
</li>
<li><p>Copy the <strong>ords.war</strong> file to the Tomcat webapps directory <strong>(~\webapps)</strong>, and note that you can rename it to any name you choose, but you must use the same name after host:port.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707293173734/c660cc61-ec76-4f54-9419-3cdfeadde7f8.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Restart the ORDS application from the Apache server .</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707293229181/7f75269e-214e-486f-b679-48d1ff6b2356.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Set the system environment variable JAVA_TOOL_OPTIONS to -Dconfig.url=E:\app\config_ords -Xms1024M -Xmx1024M (representing the ORDS Config path).</p>
</li>
<li><p>Modify the Apache Tomcat service startup type to Automatic and reboot the machine. Following this, everything should be operational.</p>
</li>
<li><p>If a 503 error (Service Unavailable) or ORA-28000 error occurs, unlock the following accounts:</p>
<ul>
<li><p>APEX_REST_PUBLIC_USER</p>
</li>
<li><p>APEX_INSTANCE_ADMIN_USER (ignore if an error occurs for this user)</p>
</li>
<li><p>APEX_PUBLIC_USER</p>
</li>
<li><p>APEX_LISTENER</p>
</li>
</ul>
</li>
<li><p>Now you can always access Apex at <a target="_blank" href="http://localhost:8080/ords">http://localhost:8080/ords</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707292491998/5c55962d-a82a-46a2-9f15-db0ef2d93b82.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<h2 id="heading-some-valuable-links-for-additional-information">Some valuable links for additional information:</h2>
<ul>
<li><p>To delve deeper into ORDS installation and configuration, consult the Oracle <a target="_blank" href="https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/23.4/ordig/installing-and-configuring-oracle-rest-data-services.html#GUID-B6661F35-3EE3-4CB3-9379-40D0B8E24635">Oracle ORDS official Quick Start Guide</a></p>
</li>
<li><p>For further exploration of ORDS details and resources, visit the <a target="_blank" href="https://www.oracle.com/database/technologies/appdev/rest.html">official Oracle Page</a> dedicated to ORDS.</p>
</li>
<li><p>If you're interested in installing ORDS on Tomcat for Linux systems (ORDS Version 22.1 onward), you can find guidance <a target="_blank" href="https://oracle-base.com/articles/misc/oracle-rest-data-services-ords-installation-on-tomcat-22-onward">here</a>.</p>
</li>
<li><p>Similarly, for Windows users looking to install ORDS on Tomcat, refer to this resource <a target="_blank" href="https://oracle-base.com/articles/misc/oracle-rest-data-services-ords-installation-on-tomcat-windows">here</a>.</p>
</li>
<li><p>For older version ords install you can refer to <a target="_blank" href="https://joelkallman.blogspot.com/2017/05/apex-and-ords-up-and-running-in2-steps.html">this</a> or watch this short <a target="_blank" href="https://youtu.be/amF01SpNLUo">video</a>.</p>
</li>
</ul>
<h2 id="heading-faq">FAQ</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>How to create a pdb?</strong></div>
</div>

<p>Example : create pluggable database demo admin user demo_admin identified by &lt;password for pdb&gt; file_name_convert=('pdbseed', 'demo');</p>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">show</span> <span class="hljs-keyword">user</span> con_name
<span class="hljs-keyword">USER</span> <span class="hljs-keyword">is</span> <span class="hljs-string">"SYS"</span>

CON_NAME
<span class="hljs-comment">------------------------------</span>
CDB$ROOT
<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">show</span> pdbs

    CON_ID CON_NAME                       <span class="hljs-keyword">OPEN</span> <span class="hljs-keyword">MODE</span>  <span class="hljs-keyword">RESTRICTED</span>
<span class="hljs-comment">---------- ------------------------------ ---------- ----------</span>
         <span class="hljs-number">2</span> PDB$<span class="hljs-keyword">SEED</span>                       <span class="hljs-keyword">READ</span> <span class="hljs-keyword">ONLY</span>  <span class="hljs-keyword">NO</span>
         <span class="hljs-number">3</span> ORCLPDB                        <span class="hljs-keyword">READ</span> WRITE <span class="hljs-keyword">NO</span>
<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">create</span> <span class="hljs-keyword">pluggable</span> <span class="hljs-keyword">database</span> demo <span class="hljs-keyword">admin</span> <span class="hljs-keyword">user</span> demo_admin <span class="hljs-keyword">identified</span> <span class="hljs-keyword">by</span> &lt;<span class="hljs-keyword">password</span> <span class="hljs-keyword">for</span> pdb&gt; <span class="hljs-keyword">file_name_convert</span>=(<span class="hljs-string">'pdbseed'</span>, <span class="hljs-string">'demo'</span>);

Pluggable database created.

SQL&gt; <span class="hljs-keyword">show</span> pdbs

    CON_ID CON_NAME                       <span class="hljs-keyword">OPEN</span> <span class="hljs-keyword">MODE</span>  <span class="hljs-keyword">RESTRICTED</span>
<span class="hljs-comment">---------- ------------------------------ ---------- ----------</span>
         <span class="hljs-number">2</span> PDB$<span class="hljs-keyword">SEED</span>                       <span class="hljs-keyword">READ</span> <span class="hljs-keyword">ONLY</span>  <span class="hljs-keyword">NO</span>
         <span class="hljs-number">3</span> ORCLPDB                        <span class="hljs-keyword">READ</span> WRITE <span class="hljs-keyword">NO</span>
         <span class="hljs-number">4</span> DEMO                           <span class="hljs-keyword">READ</span> WRITE <span class="hljs-keyword">NO</span>
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>How to create a tablespace?</strong></div>
</div>

<p>Before creating tablespace - check if OMF is enabled for your database,<br /><code>SELECT name, value FROM v$parameter WHERE name = 'db_create_file_dest';</code></p>
<p>If the query returns a not null value for 'db_create_file_dest', OMF is enabled,<br /><code>create tablespace apex datafile size 200M autoextend on next 10m maxsize unlimited;</code></p>
<p>If it returns a null value for 'db_create_file_dest', OMF is not enabled,<br /><code>create tablespace apex datafile 'E:\app\oradata\ORCL\demo\apex.dbf' size 300m autoextend on next 10m;</code></p>
<p>that parameter names and values may vary based on the Oracle Database version and configuration.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Difference between a Full and runtime apex environment installation?</strong></div>
</div>

<p>Full Development Environment:</p>
<p>Comprehensive Toolset: Equipped with Application Builder, SQL Workshop, and Team Development, empowering developers with robust capabilities for application creation, customization, and collaborative development.</p>
<p>Development Lifecycle Hub: Serves as the central workspace for iterative prototyping, extensive testing, and meticulous debugging, facilitating efficient application development from inception to deployment readiness.</p>
<p>To install the Full Development Environment, execute the following command:</p>
<pre><code class="lang-sql">@apexins.sql tablespace_apex tablespace_files tablespace_temp images
</code></pre>
<p>Parameters:</p>
<ul>
<li><p><code>tablespace_apex</code>: Name of the tablespace for the Oracle APEX application user.</p>
</li>
<li><p><code>tablespace_files</code>: Name of the tablespace for the Oracle APEX files user.</p>
</li>
<li><p><code>tablespace_temp</code>: Name of the temporary tablespace or tablespace group.</p>
</li>
<li><p><code>images</code>: Virtual directory for Oracle APEX images.</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-sql">@apexins.sql SYSAUX SYSAUX TEMP /i/
</code></pre>
<p>If encountering the error SP2-0310: unable to open file "apexins.sql", exit SQL*Plus and ensure the working directory is correctly set to the installation file location.</p>
<p>Runtime Environment:</p>
<p>Production Deployment Hub: Exclusively focused on deploying and serving APEX applications to end-users, ensuring seamless user experiences and optimal application performance.</p>
<p>Secure Execution Realm: Stripped of development tools, it prioritizes application security, scalability, and resource optimization, safeguarding production environments while granting controlled access to application functionalities and underlying database assets.</p>
<p>To install the Runtime Environment, execute the following command:</p>
<pre><code class="lang-sql">@apxrtins.sql tablespace_apex tablespace_files tablespace_temp images
</code></pre>
<p>Parameters:</p>
<ul>
<li><p><code>tablespace_apex</code>: Name of the tablespace for the Oracle APEX application user.</p>
</li>
<li><p><code>tablespace_files</code>: Name of the tablespace for the Oracle APEX files user.</p>
</li>
<li><p><code>tablespace_temp</code>: Name of the temporary tablespace or tablespace group.</p>
</li>
<li><p><code>images</code>: Virtual directory for Oracle APEX images.</p>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-sql">@apxrtins.sql SYSAUX SYSAUX TEMP /i/
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Which users were created during apex installations?</strong></div>
</div>

<p>During Oracle APEX installation, several database accounts are created to manage different aspects of the application:</p>
<ul>
<li><p>APEX_240200: Owns the Oracle APEX schema and metadata.</p>
</li>
<li><p>FLOWS_FILES: Owns the uploaded files within Oracle APEX.</p>
</li>
<li><p>APEX_PUBLIC_USER: A minimally privileged account utilized for Oracle APEX configuration with ORDS. In upgrades, it is created if absent.</p>
</li>
<li><p>Additional accounts:</p>
<ul>
<li><p>APEX_REST_PUBLIC_USER: Used for invoking RESTful Services definitions stored in Oracle APEX.</p>
</li>
<li><p>APEX_LISTENER: Used to query RESTful Services definitions stored in Oracle APEX.</p>
</li>
</ul>
</li>
</ul>
<hr />
]]></content:encoded></item><item><title><![CDATA[Easy Setup: Oracle 23ai Free Database, APEX, ORDS and  sqlCL in Docker]]></title><description><![CDATA[In this guide, I will walk you through the process of setting up Oracle 23ai Free Database, Oracle APEX (Application Express), ORDS (Oracle REST Data Services) and oracle sqlCL in a Docker container. The VM Appliance comes preloaded with these tools,...]]></description><link>https://panigrahisantosh.com/easy-setup-oracle-23ai-free-database-apex-ords-and-sqlcl-in-docker</link><guid isPermaLink="true">https://panigrahisantosh.com/easy-setup-oracle-23ai-free-database-apex-ords-and-sqlcl-in-docker</guid><category><![CDATA[oracle23c docker, apex, ords]]></category><dc:creator><![CDATA[Santosh Panigrahi]]></dc:creator><pubDate>Sat, 03 Feb 2024 17:05:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/xG8IQMqMITM/upload/f1aab1e03fe2b26f7db6f73feacddb75.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this guide, I will walk you through the process of setting up Oracle 23ai Free Database, Oracle APEX (Application Express), ORDS (Oracle REST Data Services) and oracle sqlCL in a Docker container. The VM Appliance comes preloaded with these tools, but this guide focuses on the Docker environment for flexibility and ease of use.</p>
<p>Step 1: Install Docker Ensure you have Docker installed on your system. You can check the version or install Docker using the following commands:</p>
<pre><code class="lang-bash">docker version / docker --version
<span class="hljs-comment"># OR</span>
sudo yum install docker -y
</code></pre>
<p>Step 2: Pull and Run Oracle 23ai Free Database Container Pull the Oracle 23ai Free Database Docker image and run it with specific port mappings to avoid conflicts:</p>
<pre><code class="lang-bash">docker pull container-registry.oracle.com/database/free:latest
docker run -d -it --name 23aifree -p 8521:1521 -p 8500:5500 -p 8023:8080 -p 9043:8443 -p 9922:22 -e ORACLE_PWD=oracle container-registry.oracle.com/database/free:latest
docker <span class="hljs-built_in">exec</span> -it 23aifree /bin/bash
</code></pre>
<p>Step 3: Setup Oracle APEX Inside the container, download and install Oracle APEX:</p>
<pre><code class="lang-bash">curl -o apex-latest.zip https://download.oracle.com/otn_software/apex/apex-latest.zip
unzip apex-latest.zip
rm apex-latest.zip
<span class="hljs-built_in">cd</span> apex
</code></pre>
<p>Step 4: Configure Oracle APEX Allow the Oracle Database to settle, then open SQL*Plus and set the PDB:</p>
<pre><code class="lang-bash">sqlplus / as sysdba
ALTER SESSION SET CONTAINER = FREEPDB1;
@apexins.sql SYSAUX SYSAUX TEMP /i/
ALTER USER APEX_PUBLIC_USER IDENTIFIED BY oracle ACCOUNT UNLOCK;
@apxchpwd.sql
<span class="hljs-built_in">exit</span>
</code></pre>
<p>Step 5: Set Up ORDS and Java Install necessary tools, create folders, and configure ORDS:</p>
<pre><code class="lang-bash">mkdir /home/oracle/software
mkdir /home/oracle/software/apex
mkdir /home/oracle/software/ords
mkdir /home/oracle/scripts
cp -r /home/oracle/apex/images /home/oracle/software/apex

su
dnf update -y
dnf install sudo -y
dnf install nano -y

nano /etc/sudoers
<span class="hljs-comment"># Add 'Defaults !lecture' in Defaults section</span>
<span class="hljs-comment"># This is to supress banner message</span>
<span class="hljs-comment"># Add 'oracle ALL=(ALL) NOPASSWD: ALL' at the end</span>
<span class="hljs-comment"># This is to add oracle user in sudoes list </span>
<span class="hljs-comment"># so that user oracle can execute sudo command without password</span>

dnf install java-17-openjdk -y
java -version

mkdir /etc/ords
mkdir /etc/ords/config
mkdir /home/oracle/logs
chmod -R 777 /etc/ords

yum-config-manager --add-repo=http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64
dnf install ords -y
<span class="hljs-built_in">export</span> _JAVA_OPTIONS=<span class="hljs-string">"-Xms512M -Xmx512M"</span>
ords --config /etc/ords/config install

<span class="hljs-comment"># Follow the configuration steps</span>
Installation Type &gt; Choose option [2] Enter
Connection Type &gt; Choose option [1] Enter
host name &gt; Enter
listen port &gt; Enter
service name &gt; FREEPDB1
administrator username &gt; SYS
password &gt; oracle
default tablespace &gt; Enter
temp tablespace &gt; Enter
features &gt; Enter
Start ORDS &gt; [1] Enter &lt;-- Standalone Mode
protocol &gt; [1] &lt; http
port &gt; [1] &lt;-- 8080
Static Resources &gt; /home/oracle/software/apex/images
</code></pre>
<p>ORDS will then be configured. It will take 1-2 mins. You should now see below.</p>
<p>Oracle REST Data Services version : 23.1.0.r0861423 Oracle REST Data Services server info: jetty/10.0.12 Oracle REST Data Services java info: OpenJDK 64-Bit Server VM 17.0.6+10-LTS</p>
<p>you can now check <a target="_blank" href="http://localhost:8023/ords/">http://localhost:8023/ords/</a> in the browser for the apex.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1680796697102/ef9416cc-060e-43ec-ab56-40a22e3226c8.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Step 6: Create Startup and Shutdown Scripts.</p>
<p>Create scripts for starting, stopping, and to auto-start ORDS:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create an ORDS startup script</span>
nano /home/oracle/scripts/start_ords.sh
<span class="hljs-comment"># Paste in the script</span>
<span class="hljs-built_in">export</span> ORDS_HOME=/usr/<span class="hljs-built_in">local</span>/bin/ords
<span class="hljs-built_in">export</span> _JAVA_OPTIONS=<span class="hljs-string">"-Xms512M -Xmx512M"</span>
LOGFILE=/home/oracle/logs/ords-`date +<span class="hljs-string">"%Y"</span><span class="hljs-string">"%m"</span><span class="hljs-string">"%d"</span>`.<span class="hljs-built_in">log</span>
nohup <span class="hljs-variable">${ORDS_HOME}</span> --config /etc/ords/config serve &gt;&gt; <span class="hljs-variable">$LOGFILE</span> 2&gt;&amp;1 &amp; <span class="hljs-built_in">echo</span> <span class="hljs-string">"View log file with : tail -f <span class="hljs-variable">$LOGFILE</span>"</span>

<span class="hljs-comment"># Create a stop_ords.sh file</span>
nano /home/oracle/scripts/stop_ords.sh
<span class="hljs-comment"># Paste in the script</span>
<span class="hljs-built_in">kill</span> `ps -ef | grep [o]rds.war | awk <span class="hljs-string">'{print $2}'</span>`

<span class="hljs-comment"># create script to start ords automatically when image runs</span>
nano /opt/oracle/scripts/startup/01_auto_ords.sh
<span class="hljs-comment"># Paste this in the script</span>
sudo sh /home/oracle/scripts/start_ords.sh
<span class="hljs-built_in">exit</span>
</code></pre>
<p>Step 7: Final Steps and Enjoy.</p>
<p>Exit the Docker container, restart the container, and access APEX, and install sqlCL if needed:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">exit</span>
docker restart 23aifree
<span class="hljs-comment"># Wait 60 seconds and access APEX at localhost:8023/ords/apex</span>
<span class="hljs-comment"># Workspace &gt; INTERNAL</span>
<span class="hljs-comment"># Username &gt; ADMIN</span>
<span class="hljs-comment"># Password &gt; The Complex Password</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707068782918/767d9a13-9a5f-472f-ad2b-ff511758af9d.png" alt class="image--center mx-auto" /></p>
<p>Now you can also install sqlCL if you want -</p>
<pre><code class="lang-bash">dnf install sqlcl -y
<span class="hljs-comment"># check if sqlcl installed properly</span>
<span class="hljs-comment"># sql sys/oracle as sysdba</span>
SQL&gt; <span class="hljs-built_in">help</span>
SQL&gt; <span class="hljs-built_in">exit</span>
</code></pre>
<p><strong>Bonus</strong>: Commit, Tag, and Push Docker Image Optionally, if you want to save your setup:</p>
<pre><code class="lang-bash">docker commit 23aifree apex:latest
docker tag apex:latest panigrahisantosh/apex:latest
docker push panigrahisantosh/apex:latest

<span class="hljs-comment"># Note : Here panigrahisantosh is my docker hub username.</span>
<span class="hljs-comment"># you can replace this with username.</span>
<span class="hljs-comment"># Finally as this new image is in docker hub. you can always pull and use -</span>
&gt; docker pull panigrahisantosh/apex:latest
</code></pre>
<p>Conclusion: Following this comprehensive guide will enable you to run Oracle 23ai Free Database with APEX and ORDS in a Docker container, providing a flexible and scalable environment for your development needs. Enjoy the seamless integration of these powerful tools and enhance your database development experience.</p>
]]></content:encoded></item><item><title><![CDATA[Oracle Database 23ai New Features and Enhancements]]></title><description><![CDATA[SELECT without FROM DUAL
Oracle Database 23ai, you can use SELECT without specifying dual table.
SELECT sysdate, 'Hello World' ; output : 30-JAN-24 Hello World
Use column alias in GROUP BY and HAVING
You can use column aliases and position numbers in...]]></description><link>https://panigrahisantosh.com/oracle-database-23c-new-features-and-enhancements</link><guid isPermaLink="true">https://panigrahisantosh.com/oracle-database-23c-new-features-and-enhancements</guid><category><![CDATA[oracle23c]]></category><category><![CDATA[Developer]]></category><category><![CDATA[23c - New Features]]></category><category><![CDATA[What’s new in Oracle Database 23c]]></category><dc:creator><![CDATA[Santosh Panigrahi]]></dc:creator><pubDate>Mon, 29 Jan 2024 18:30:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/k2jksaz9oWg/upload/d9ae1019132381dbb81e6c8132c92b40.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-select-without-from-dual">SELECT without FROM DUAL</h3>
<p>Oracle Database 23ai, you can use <code>SELECT</code> without specifying <code>dual</code> table.</p>
<p><code>SELECT sysdate, 'Hello World' ;</code> output : <code>30-JAN-24 Hello World</code></p>
<h3 id="heading-use-column-alias-in-group-by-and-having">Use column alias in GROUP BY and HAVING</h3>
<p>You can use column aliases and position numbers in GROUP BY and HAVING clauses.</p>
<pre><code class="lang-sql"><span class="hljs-comment">/* GROUP BY on expression alias */</span>
<span class="hljs-keyword">SELECT</span> department_id <span class="hljs-keyword">AS</span> did, <span class="hljs-keyword">SUM</span>(salary) <span class="hljs-keyword">AS</span> xyz <span class="hljs-keyword">FROM</span> employees <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> did;

<span class="hljs-comment">/* GROUP BY on expression position number */</span>
<span class="hljs-keyword">SELECT</span> department_id <span class="hljs-keyword">AS</span> did, <span class="hljs-keyword">SUM</span>(salary) <span class="hljs-keyword">AS</span> xyz <span class="hljs-keyword">FROM</span> employees <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> <span class="hljs-number">1</span>;

<span class="hljs-comment">/* ORA-00979: "DEPARTMENT_ID": must appear in the GROUP BY clause or be used in an aggregate function 00979. 00000 - "not a GROUP BY expression" Cause:
Action: Error at Line: 37 Column: 5 */</span>

<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">SESSION</span> <span class="hljs-keyword">SET</span> group_by_position_enabled = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">SELECT</span> department_id <span class="hljs-keyword">AS</span> did, <span class="hljs-keyword">SUM</span>(salary) <span class="hljs-keyword">AS</span> xyz <span class="hljs-keyword">FROM</span> employees <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> <span class="hljs-number">1</span>;
</code></pre>
<h3 id="heading-if-exists-and-if-not-exists-in-ddl">IF EXISTS and IF NOT EXISTS in DDL</h3>
<p>Introduces new clauses (<code>IF EXISTS</code> and <code>IF NOT EXISTS</code>) in DDL statements to handle scenarios where objects may or may not exist, providing more control.</p>
<ul>
<li><pre><code class="lang-sql">                        <span class="hljs-keyword">drop</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">exists</span> boolean_table ;
                        <span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">exists</span> boolean_table (val <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">10</span>), flag <span class="hljs-built_in">boolean</span>) ;
</code></pre>
</li>
</ul>
<p>Note IF NOT EXISTS and REPLACE are mutually exclusive for any DDL. You will encounter ORA-11541 if try to achieve the same.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707200535708/12bb2cec-e7a6-4ecf-a191-607f5871dfd7.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-pgql-property-graph-query-language">PGQL (Property Graph Query Language)</h3>
<p>PGQL is a graph query language built on top of SQL, bringing graph pattern matching capabilities to existing SQL users as well as to new users who are interested in graph technology but who do not have an SQL background.</p>
<p><a target="_blank" href="https://pgql-lang.org/">PGQL | Property Graph Query Language (</a><a target="_blank" href="http://pgql-lang.org">pgql-lang.org</a><a target="_blank" href="https://pgql-lang.org/">)</a></p>
<p><a target="_blank" href="https://pgql-lang.org/spec/2.0/">PGQL 2.0 Specification | Property Graph Query Language (</a><a target="_blank" href="http://pgql-lang.org">pgql-lang.org</a><a target="_blank" href="https://pgql-lang.org/spec/2.0/">)</a></p>
<h3 id="heading-value-constructor">Value Constructor</h3>
<p>Allows grouping multiple rows of data in a single DML or SELECT statement.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707321114265/d3b5a771-5ae8-4b57-bdf9-4e3c8bd8e9b9.png" alt class="image--center mx-auto" /></p>
<ul>
<li><pre><code class="lang-sql">                        <span class="hljs-comment">/*Multi insert using VALUE constructor*/</span>
                        <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span>
                        (<span class="hljs-string">'false'</span> , <span class="hljs-literal">false</span>),
                         (<span class="hljs-string">'False'</span> , <span class="hljs-literal">False</span>),
                         (<span class="hljs-string">'FALSE'</span> , <span class="hljs-literal">FALSE</span>), 
                         (<span class="hljs-string">'f'</span>,<span class="hljs-string">'f'</span>),(<span class="hljs-string">'0'</span>,<span class="hljs-number">0</span>);

                       <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> boolean_table;                        
                       <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span>  (<span class="hljs-keyword">values</span> (<span class="hljs-string">'Santosh'</span> , <span class="hljs-number">1</span>),
                       (<span class="hljs-string">'Panigrahi'</span> , <span class="hljs-number">1</span>), (<span class="hljs-string">'Trainer'</span> , <span class="hljs-number">3</span>)) t1 (dsc, <span class="hljs-keyword">id</span>);

                        <span class="hljs-keyword">WITH</span> T (C1, C2, C3) <span class="hljs-keyword">AS</span>
                        (
                        <span class="hljs-keyword">values</span> (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>),
                        (<span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span> ),
                        (<span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>)

                        ) <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> t;
                        <span class="hljs-comment">/*
                        C1    C2    C3
                        0    1    2
                        3    4    5
                        6    7    8
                        */</span>
</code></pre>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707321254991/e7bb6132-bcd5-4811-a685-7fa9c3f2133d.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-returning-clause-for-merge-and-also-returning-old-column-value-for-update">RETURNING clause for MERGE and also returning OLD column value for UPDATE</h3>
<ul>
<li>Enables the use of <code>RETURNING</code> clause with the <code>MERGE</code> statement and introduces the ability to access the original column value (<code>OLD</code> column_name) after an <code>UPDATE</code> statement. If you've used PL/SQL, you might recognize this feature. Now, it's available in SQL too. It lets you retrieve affected rows after a DML operation, perform calculations on affected columns, and access both old and new values.</li>
</ul>
<pre><code class="lang-sql">SQL&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> employees <span class="hljs-keyword">where</span> employee_id = <span class="hljs-number">100</span>;

   EMPLOYEE_ID FIRST_NAME    LAST_NAME    EMAIL    PHONE_NUMBER    HIRE_DATE               JOB_ID        SALARY    COMMISSION_PCT    MANAGER_ID    DEPARTMENT_ID
______________ _____________ ____________ ________ _______________ _______________________ __________ _________ _________________ _____________ ________________
           100 Steven        King         SKING    515.123.4567    17-JUN-2003 00:00:00    AD_PRES        24000                                               90

SQL&gt; <span class="hljs-comment">-- We will check returning cluse functionaly to return old and new values.</span>
SQL&gt; <span class="hljs-comment">-- before 23ai we can get new value using return clause and both old and new using pl/sql construct.</span>
SQL&gt; variable l_id number
SQL&gt; variable l_new_sal number
SQL&gt; variable l_old_sal number
SQL&gt; <span class="hljs-keyword">EXECUTE</span> :l_id := <span class="hljs-number">100</span>;

PL/SQL procedure successfully completed.

SQL&gt; <span class="hljs-keyword">UPDATE</span> employees <span class="hljs-keyword">set</span> salary=salary*<span class="hljs-number">2</span> <span class="hljs-keyword">where</span> employee_id = <span class="hljs-number">100</span>
  <span class="hljs-number">2</span>* <span class="hljs-keyword">RETURNING</span> <span class="hljs-keyword">new</span> salary <span class="hljs-keyword">INTO</span> :l_new_sal;

1 row updated.

SQL&gt; PRINT l_new_sal

 L_NEW_SAL
<span class="hljs-comment">----------</span>
     48000

SQL&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> employees <span class="hljs-keyword">where</span> employee_id = <span class="hljs-number">100</span>;

   EMPLOYEE_ID FIRST_NAME    LAST_NAME    EMAIL    PHONE_NUMBER    HIRE_DATE               JOB_ID        SALARY    COMMISSION_PCT    MANAGER_ID    DEPARTMENT_ID
______________ _____________ ____________ ________ _______________ _______________________ __________ _________ _________________ _____________ ________________
           100 Steven        King         SKING    515.123.4567    17-JUN-2003 00:00:00    AD_PRES        48000                                               90

SQL&gt; roll
<span class="hljs-keyword">Rollback</span> complete.
<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> employees <span class="hljs-keyword">where</span> employee_id = <span class="hljs-number">100</span>;

   EMPLOYEE_ID FIRST_NAME    LAST_NAME    EMAIL    PHONE_NUMBER    HIRE_DATE               JOB_ID        SALARY    COMMISSION_PCT    MANAGER_ID    DEPARTMENT_ID
______________ _____________ ____________ ________ _______________ _______________________ __________ _________ _________________ _____________ ________________
           100 Steven        King         SKING    515.123.4567    17-JUN-2003 00:00:00    AD_PRES        24000                                               90

SQL&gt; <span class="hljs-keyword">UPDATE</span> employees <span class="hljs-keyword">set</span> salary=salary*<span class="hljs-number">2</span> <span class="hljs-keyword">where</span> employee_id = <span class="hljs-number">100</span>
  <span class="hljs-number">2</span>* <span class="hljs-keyword">RETURNING</span> <span class="hljs-keyword">old</span> salary <span class="hljs-keyword">INTO</span> :l_old_sal;

1 row updated.

SQL&gt; PRINT

      L_ID
<span class="hljs-comment">----------</span>
       100
 L_NEW_SAL
<span class="hljs-comment">----------</span>
     48000
 L_OLD_SAL
<span class="hljs-comment">----------</span>
     24000

SQL&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> employees <span class="hljs-keyword">where</span> employee_id = <span class="hljs-number">100</span>;

   EMPLOYEE_ID FIRST_NAME    LAST_NAME    EMAIL    PHONE_NUMBER    HIRE_DATE               JOB_ID        SALARY    COMMISSION_PCT    MANAGER_ID    DEPARTMENT_ID
______________ _____________ ____________ ________ _______________ _______________________ __________ _________ _________________ _____________ ________________
           100 Steven        King         SKING    515.123.4567    17-JUN-2003 00:00:00    AD_PRES        48000                                               90

SQL&gt; roll
<span class="hljs-keyword">Rollback</span> complete.
<span class="hljs-keyword">SQL</span>&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> employees <span class="hljs-keyword">where</span> employee_id = <span class="hljs-number">100</span>;

   EMPLOYEE_ID FIRST_NAME    LAST_NAME    EMAIL    PHONE_NUMBER    HIRE_DATE               JOB_ID        SALARY    COMMISSION_PCT    MANAGER_ID    DEPARTMENT_ID
______________ _____________ ____________ ________ _______________ _______________________ __________ _________ _________________ _____________ ________________
           100 Steven        King         SKING    515.123.4567    17-JUN-2003 00:00:00    AD_PRES        24000                                               90

SQL&gt;
</code></pre>
<h3 id="heading-better-error-messages-to-explain-why-a-statement-failed-to-execute">Better error messages to explain why a statement failed to execute</h3>
<p>Enhances error messages to provide more detailed and helpful explanations for failed SQL statements.</p>
<h3 id="heading-developer-role-dbdeveloperrole">Developer Role (DB_DEVELOPER_ROLE)</h3>
<p>Introduces a simplified way to grant necessary privileges for database development roles, reducing the need for manual role assignments.</p>
<pre><code class="lang-sql"><span class="hljs-comment">-- Instead of grant connect, resource to &lt;developer user&gt;</span>
exec DBMS_DEVELOPER_ADMIN.GRANT_PRIVS(developer user);
</code></pre>
<h3 id="heading-javascript-stored-procedures">JavaScript Stored Procedures</h3>
<p>Based on the Multi-Language Engine (MLE) powered by GraalVM, Oracle Database 23ai allows the definition of stored procedures written in JavaScript.</p>
<h3 id="heading-sql-domains">SQL Domains</h3>
<p>In Oracle Database 23ai, domains can be defined as database objects– as shown below – and when a column is defined, it can be linked to a domain definition. This is a potentially useful piece of metadata. But it is more than that: the check constraint defined against the domain is inherited by the column. The display format and order by expression can be used in query statements through the new functions DOMAIN_DISPLAY and DOMAIN_ORDER.</p>
<h3 id="heading-update-and-delete-records-based-on-a-join-condition">Update and Delete records based on a join condition</h3>
<p>Provides a more elegant syntax for updating records based on a join condition, simplifying complex updates. Does not support ANSI syntax you can not mention the keywords JOIN and ON clause with this feature.</p>
<p><strong>Use Case</strong>: the ability to copy values from a temporary table or a staging table into a main table by using ETL. We might also want to aggregate child totals into a parent row. We might also want to remove or change</p>
<ul>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707321856557/78b12cdd-b443-4a50-b40d-7156d470d609.png" alt class="image--center mx-auto" /></p>
</li>
<li><pre><code class="lang-sql">                        <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> employees <span class="hljs-keyword">where</span> employee_id=<span class="hljs-number">200</span>;

                        <span class="hljs-keyword">UPDATE</span> employees e
                        <span class="hljs-keyword">SET</span>
                            e.department_id = <span class="hljs-number">270</span>
                        <span class="hljs-keyword">FROM</span>
                            departments d
                        <span class="hljs-keyword">WHERE</span>
                                e.department_id = d.department_id
                            <span class="hljs-keyword">AND</span> e.employee_id = <span class="hljs-number">200</span>; <span class="hljs-comment">-- This will update department_id from 10 to 270</span>

                        <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> employees <span class="hljs-keyword">where</span> employee_id=<span class="hljs-number">200</span>;
</code></pre>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707322181822/1e9cc629-336d-4b43-9447-d16bc9bc994a.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-schema-level-privileges">Schema Level Privileges</h3>
<p>Allows granting access on all objects in a schema with a single statement, simplifying privilege management. The ability to grant access on allobjects in an schema in a single statement For example <code>GRANT SELECT ANY TABLE ON SCHEMA TO &lt;user name&gt;</code></p>
<h3 id="heading-ability-to-define-4096-columns-in-a-table">Ability to define 4096 columns in a table</h3>
<p>In Oracle Database 23ai, it is possible to define up to 4096 columns in a table, catering to scenarios where a large number of columns are needed, such as in machine learning models.</p>
<h3 id="heading-boolean-data-type">BOOLEAN Data Type</h3>
<p>Introduces the BOOLEAN data type for column definitions, allowing testing on boolean values directly in the WHERE clause without explicitly comparing to TRUE.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707320538763/21a6abf2-8ba8-4e03-bd1e-65b04b26316f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707320559241/a7e2ac4a-f40d-4599-b3de-2a2eb85a21d9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707320719463/cefe6007-1784-4d29-971a-f4ffa19995aa.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-sql"><span class="hljs-comment">/*BOOLEAN*/</span>

<span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> boolean_table (val <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">10</span>), flag <span class="hljs-built_in">boolean</span>) ;

<span class="hljs-comment">-- True</span>
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'true'</span> , <span class="hljs-literal">true</span> );
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'True'</span> , <span class="hljs-literal">True</span> );
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'TRUE'</span> , <span class="hljs-literal">TRUE</span> );
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'yes'</span>,<span class="hljs-string">'yes'</span> );
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'l'</span>, <span class="hljs-number">1</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'t'</span>,<span class="hljs-string">'t'</span> );
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'ON'</span>,<span class="hljs-string">'ON'</span> );

<span class="hljs-comment">-- False</span>
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'false'</span> , <span class="hljs-literal">false</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'False'</span> , <span class="hljs-literal">False</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'FALSE'</span> , <span class="hljs-literal">FALSE</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'f'</span>,<span class="hljs-string">'f'</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'0'</span>,<span class="hljs-number">0</span>);
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'OFF'</span>,<span class="hljs-string">'OFF'</span> );

<span class="hljs-comment">-- NULL test</span>
<span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> boolean_table <span class="hljs-keyword">values</span> (<span class="hljs-string">'null'</span>, <span class="hljs-literal">null</span> );

<span class="hljs-comment">-- Test</span>
<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> boolean_table;
<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> boolean_table <span class="hljs-keyword">where</span> flag;
<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> boolean_table <span class="hljs-keyword">where</span> <span class="hljs-keyword">not</span> flag;
<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> boolean_table <span class="hljs-keyword">where</span> flag <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>;
</code></pre>
<h3 id="heading-asynchronous-transaction">Asynchronous Transaction</h3>
<p>Oracle Database 23ai introduces a new feature called Asynchronous Transactions, which allows multiple transactions to concurrently update a numeric column marked as reservable[4]. This feature increases developer productivity by enabling REST API applications to take advantage of Transactional Event Queues (TxEventQ) to handle application and data events[3].</p>
<p>Key features of Asynchronous Transactions in Oracle Database 23ai include:</p>
<ul>
<li><p><strong>Lock-free reservations</strong>: A numeric column marked as reservable allows multiple transactions to concurrently update the value[4].</p>
</li>
<li><p><strong>Transactional Event Queues (TxEventQ)</strong>: This feature enables Oracle Database to handle application and data events, making it suitable for use in Machine Learning applications and other data-intensive applications[3].</p>
</li>
<li><p><strong>Asynchronous programming and Oracle Database pipelining</strong>: These features remove performance bottlenecks and enhance overall responsiveness, making it easier for developers to incorporate them into their existing applications[5].</p>
</li>
</ul>
<p>Asynchronous Transactions in Oracle Database 23ai can be used in various scenarios, such as repetitive batch operations, looping through sets of records for updates, and inserts with a commit for each set of records[3]. This feature can help improve application performance and developer productivity by allowing multiple transactions to concurrently update a numeric column marked as reservable[4].</p>
<pre><code class="lang-sql"><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">exists</span> tbl_async
(
id_number <span class="hljs-built_in">integer</span> primary <span class="hljs-keyword">key</span>,
val <span class="hljs-built_in">NUMBER</span>(<span class="hljs-number">5</span>, <span class="hljs-number">2</span>) RESERVABLE
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">into</span> tbl_async <span class="hljs-keyword">VALUES</span>
(<span class="hljs-number">1</span>, <span class="hljs-number">18.20</span>),
(<span class="hljs-number">2</span>, <span class="hljs-number">20.21</span>),
(<span class="hljs-number">3</span>, <span class="hljs-number">24.22</span>) ,
(<span class="hljs-number">4</span>, <span class="hljs-number">25.24</span>);

<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> tbl_async <span class="hljs-keyword">WHERE</span> id_number = <span class="hljs-number">1</span>;
<span class="hljs-keyword">UPDATE</span> tbl_async <span class="hljs-keyword">SET</span> val = val + <span class="hljs-number">10</span> <span class="hljs-keyword">WHERE</span> id_number = <span class="hljs-number">1</span>;
<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> tbl_async <span class="hljs-keyword">WHERE</span> id_number = <span class="hljs-number">1</span>; <span class="hljs-comment">-- Here val is still 18.20 beacuse transaction is not yet COMMIT and table column define as RESERVABLE</span>
<span class="hljs-keyword">commit</span>; 
<span class="hljs-keyword">drop</span> <span class="hljs-keyword">table</span> tbl_async; <span class="hljs-comment">-- was giving error initially don't know why it is now not throwing any</span>
NOTE : You can not <span class="hljs-keyword">DROP</span> <span class="hljs-keyword">or</span> <span class="hljs-keyword">MOVE</span> <span class="hljs-keyword">tables</span> <span class="hljs-keyword">with</span> RESERVABLE columns. <span class="hljs-keyword">to</span> <span class="hljs-keyword">drop</span> the <span class="hljs-keyword">table</span> you have <span class="hljs-keyword">to</span> <span class="hljs-keyword">modify</span> <span class="hljs-keyword">column</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">NOT</span> RESERVABLE
<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> tbl_async <span class="hljs-keyword">MODIFY</span> val <span class="hljs-keyword">not</span> RESERVABLE;
</code></pre>
<h3 id="heading-blockchain-tables">Blockchain Tables</h3>
<p>Oracle Database 23ai provides support for blockchain tables or insert only table, allowing the use of crypto-secure methods to protect data from tampering or deletion by external hackers</p>
<h3 id="heading-sql-transpiler">SQL transpiler</h3>
<p>These enhancements contribute to improving the functionality, usability, and expressiveness of Oracle Database 23ai. till now what I understand is any plsql construct if possible can be converted to SQL format. wip..</p>
<h3 id="heading-foor-and-ceil-on-dates">FOOR and CEIL on dates</h3>
<pre><code class="lang-sql"><span class="hljs-comment">-- find the upper/lower bound values for datetime</span>
<span class="hljs-comment">-- and interval values in given time</span>
<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">SYSDATE</span>, <span class="hljs-keyword">FLOOR</span> (<span class="hljs-keyword">SYSDATE</span>, <span class="hljs-string">'IYYY'</span>), <span class="hljs-keyword">CEIL</span> (<span class="hljs-keyword">SYSDATE</span>, <span class="hljs-string">'IYYY'</span>) <span class="hljs-keyword">FROM</span> DUAL;
<span class="hljs-comment">/*
SYSDATE        FLOOR(SYSDATE,'IYYY')    CEIL(SYSDATE,'IYYY')
1/30/2024   12:36:27 PM    1/1/2024    12/30/2024
*/</span>
</code></pre>
<h3 id="heading-default-on-null-for-update-statement">DEFAULT ON NULL FOR UPDATE Statement</h3>
<p>In Oracle 23ai, a powerful new feature has been introduced - the DEFAULT ON NULL option for the UPDATE statement. This eliminates the need for triggers that were previously used to achieve similar functionality. While the INSERT statement already had this feature, it's now extended to cover updates as well. Let's dive into a practical example:</p>
<pre><code class="lang-sql"><span class="hljs-comment">-- Creating a table with the DEFAULT ON NULL feature</span>
SQL&gt; <span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> demo_t (
  <span class="hljs-number">2</span>  <span class="hljs-keyword">id</span> <span class="hljs-built_in">number</span>,
  <span class="hljs-number">3</span>  ename <span class="hljs-built_in">varchar2</span>(<span class="hljs-number">100</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">ON</span> <span class="hljs-literal">NULL</span> <span class="hljs-keyword">for</span> <span class="hljs-keyword">insert</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-string">'missing name'</span>
  <span class="hljs-number">4</span>* );

<span class="hljs-comment">-- Inserting values into the table</span>
SQL&gt; <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> demo_t <span class="hljs-keyword">values</span> (<span class="hljs-number">1</span>, <span class="hljs-keyword">default</span>);
SQL&gt; <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> demo_t <span class="hljs-keyword">values</span> (<span class="hljs-number">2</span>, <span class="hljs-keyword">default</span>);

<span class="hljs-comment">-- Checking the contents of the table</span>
SQL&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> demo_t;

   ID ENAME
_____ _______________
    1 missing name
    2 missing name

<span class="hljs-comment">-- Updating the value and observing changes</span>
SQL&gt; <span class="hljs-keyword">update</span> demo_t <span class="hljs-keyword">set</span> ename = <span class="hljs-string">'Check for null'</span> <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span>=<span class="hljs-number">1</span>;
SQL&gt; <span class="hljs-keyword">update</span> demo_t <span class="hljs-keyword">set</span> ename = <span class="hljs-literal">null</span> <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span>=<span class="hljs-number">1</span>;

<span class="hljs-comment">-- Verifying the final results</span>
SQL&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> demo_t;

   ID ENAME
_____ _______________
    1 missing name
    2 missing name
</code></pre>
<pre><code class="lang-sql"><span class="hljs-comment">-- Creating a table with GENERATED BY DEFAULT ON NULL</span>
SQL&gt; <span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> t1 (c1 <span class="hljs-built_in">number</span>, c2 <span class="hljs-built_in">number</span> <span class="hljs-keyword">generated</span> <span class="hljs-keyword">by</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">on</span> <span class="hljs-literal">null</span> <span class="hljs-keyword">for</span> <span class="hljs-keyword">insert</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">update</span> <span class="hljs-keyword">as</span> <span class="hljs-keyword">identity</span>);

<span class="hljs-comment">-- Inserting values into the table</span>
SQL&gt; <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t1(c1) <span class="hljs-keyword">values</span>(<span class="hljs-number">10</span>);
SQL&gt; <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> t1(c1) <span class="hljs-keyword">values</span>(<span class="hljs-number">11</span>);

<span class="hljs-comment">-- Updating and observing changes</span>
SQL&gt; <span class="hljs-keyword">update</span> t1 <span class="hljs-keyword">set</span> c1=<span class="hljs-number">3</span> <span class="hljs-keyword">where</span> c1=<span class="hljs-number">10</span>;
SQL&gt; <span class="hljs-keyword">update</span> t1 <span class="hljs-keyword">set</span> c1=<span class="hljs-number">4</span>, c2 = <span class="hljs-literal">NULL</span> <span class="hljs-keyword">where</span> c1=<span class="hljs-number">11</span>;

<span class="hljs-comment">-- Verifying the final results</span>
SQL&gt; <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> t1;

   C1    C2
_____ _____
    3     1
    4     3
</code></pre>
<p>These enhancements streamline your SQL operations, providing more concise and efficient ways to handle default values on null conditions during both insertions and updates. Oracle 23ai continues to pave the way for improved database management.</p>
<h3 id="heading-annotations-define-metadata-for-database-objects">Annotations – define metadata for database objects</h3>
<p>Introduces annotations for defining metadata on various database objects like tables, views, columns, indexes, PL/SQL program units, and materialized views.<br />Annotations simplify sharing application metadata with external applications by allowing the addition of metadata on database objects. This metadata can include instructions on how to display, format, mask, and hide/unhide column values.</p>
<p>The functionality of Annotations is comparable to Java Annotations, providing benefits such as sharing application metadata across different modules and microservices, improving SQL code maintenance, and enhancing the developer experience.</p>
<p>An example demonstrates the use of annotations in creating a table named "departments_demo," where annotations are applied to different columns. For instance, the department_id column is annotated to be displayed as "Dept ID" and marked as an identity column, while the manager_id column is annotated to be displayed as "Manager ID" with a UI_Hidden annotation.</p>
<p>create table departments_demo<br />( department_id NUMBER ANNOTATIONS (Identity, Display 'Dept ID', Group 'Dept Info'),<br />department_name varchar2(25) ANNOTATIONS(Display 'Dept Name', Group 'Dept Info'),<br />manager_id NUMBER ANNOTATIONS (Display 'Manager ID', Group 'Dept Info', UI_HIDDEN) )<br />ANNOTATIONS (Display 'Department Table', SINCE_APPLICATION_VERSION '1.0.1');</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707198976559/ae866345-7c42-4e71-a7ba-d2843fa5eafd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707199005078/fbc5c50b-6053-47a7-8226-f5f142da15d8.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-aggregation-over-interval-types">Aggregation over INTERVAL types</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707321556930/240c39b6-8cdb-4ab4-a924-104926e307f3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707321627094/2d938723-6a8c-4a6d-901f-732456376b2f.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-json-schema-support">JSON Schema Support</h3>
<p>what is JSON schema support? Well, it lets us define the rules, also known as the allowed properties for JSON documents. And we can do this either using the IS JSON constraint. Or we can do validations as well with a PL/SQL utility function. And of course, the benefits are that it helps us avoid errors in production that we might have missed in development.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707361078151/f835d06d-3088-4d3e-a3d6-bf335ec0749e.png" alt class="image--center mx-auto" /></p>
<p>We are doing a validation-- you'll notice the IS JSON VALIDATE keywords. And what we're doing here is we are defining the rules of the data coming into that column. You'll notice that a type is an object, and the minimum properties have to be 2.</p>
<p>Now let's take a look at a simple validation using what we call shorthand syntax where we don't have to use the constraint keyword like we did before. You'll notice that we have the same CREATE TABLE statement with json_tab being the name of the table. But this time, you'll notice that we don't have a constraint keyword. We have a jval column of the JSON type. And you'll notice that we've included the VALIDATE USING clause.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707361440036/85977003-0538-4557-b0d7-a0f86d4daeea.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707361568298/818130b7-26cd-4338-b209-2a4b76126199.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707361598373/053d43f5-0b65-4241-9079-879537d2065b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707362712834/ac84ecbf-5638-48f5-b9d3-e3d320818bd9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707361734680/31eb45c4-4d2d-4dc2-982a-b7b8835d484a.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-soda-enhancements">SODA Enhancements</h3>
<h3 id="heading-enhancement-to-jsontransform">Enhancement to JSON_TRANSFORM</h3>
<p>Version 23ai introduces significant enhancements to JSON_TRANSFORM, including support for right-hand-side path expressions, nested paths, and arithmetic operations. JSON_TRANSFORM now serves as the primary operator for modifying JSON data and supports sorting arrays. These enhancements increase update capabilities, establish parity with other systems like MongoDB, and enable declarative transformations without procedural language changes, reducing I/O.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707365257246/e133b0c8-dfa7-410f-9365-1e6c6533e54b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-comparing-and-sorting-json-datatypes">Comparing and Sorting JSON Datatypes</h3>
<p>In 23ai, comparing and sorting JSON data types is now possible, building on the introduction of the JSON data type in 21C. This functionality extends to various SQL clauses including WHERE, ORDER BY, and GROUP BY. The benefits include enhanced SQL and JSON programming capabilities, avoidance of unexpected data type conversion issues, and alignment with features offered by non-Oracle systems, thereby providing a similar capability in 23ai.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707365546437/9dd66b82-affd-4eb8-a36b-ddd35b868be0.png" alt class="image--center mx-auto" /></p>
<p>Another 23ai examples -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707365722913/6d358775-3adb-467a-a80a-1fd40cf811e9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707365789401/f045a846-7b01-40e9-82eb-42d13d172b21.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707365856898/05197731-5e7e-43a4-a7d2-78628de68e46.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707365917117/1639542f-fe04-4e15-9c61-78b535110c91.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-predicates-for-jsonvalue-and-jsonquery">Predicates for JSON_VALUE and JSON_QUERY</h3>
<p>In 23ai, predicates for JSON value and JSON query have been enhanced, allowing developers to utilize conditional logic within path expressions. Multiple predicates are now supported for all path expressions, expanding the capabilities beyond the previous limitation to only one predicate.</p>
<p>Furthermore, a passing clause has been introduced, enabling the use of bind variables to hold path expressions and literals. This feature is supported in <em>JSON_QUERY, JSON_VALUE, JSON_TRANSFORM, and JSON_EXISTS.</em></p>
<p>The benefits of these enhancements include improved power and flexibility for developers working with SQL and JSON, better compatibility with operations from other SQL and JSON databases, and the ability to execute more complex queries compared to previous versions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707366803650/e32b85c1-c5e4-4435-95f8-7cd4be01e41a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707367067609/c64836f3-1b87-4729-a2f2-1ec348e95074.png" alt class="image--center mx-auto" /></p>
<p>In the above example, we created jtab table with a JSON column ('J'). Three phone numbers (work, home, mobile) are inserted as an array. Using the passing clause, we then searched for the work number using JSON query predicates.</p>
<h3 id="heading-json-relational-duality-view">JSON-Relational Duality View</h3>
<p>In 23ai, <strong>JSON-Relational Duality</strong> View feature addresses challenges in storing data by bridging the gap between different data representation methods. Traditionally, data is stored in various formats such as object databases, object-relational databases, or document databases, which can pose challenges for complex applications and evolving data structures.</p>
<p>The object-relational impedance mismatch arises when applications manipulate data differently from relational databases. However, JSON-Relational Duality View tackles this mismatch by integrating relational database structures with JSON data. Relational databases store data in normalized tables, avoiding redundant copies and enabling flexible querying, joining, and updating through normalization principles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707369810663/7bd0357f-9257-4e88-a697-9a15b2488f75.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707369882542/2007eb7f-5670-408f-8bce-2d27885d8358.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707370858133/059bd982-04a4-4b1b-9582-7a31be7d56ea.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-introduction-of-data-quality-operators">Introduction of data quality operators</h3>
<p><strong>fuzzy_match</strong> and <strong>phonic_encode</strong> using different algorithms.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707386367080/35dd0beb-0a78-4688-b0ae-434987419e61.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-json-materialized-views-enhancements">JSON Materialized Views Enhancements</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707386438013/d28ad9de-177f-42da-8813-22f31c2f65c1.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-vectorized-query-processing">Vectorized Query Processing</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707471105124/a18f4a49-e319-4285-b2a5-224f469a37d4.png" alt class="image--center mx-auto" /></p>
<p>In 23ai, vectorized query processing is a feature that enhances in-memory performance by leveraging the in-memory deep vectorization framework introduced in previous versions of the database. It automatically improves performance without requiring any special changes to SQL queries, as the usage is determined by the database.</p>
<p>To check if vectorized query processing was used, one can utilize SQL Monitor. However, there are some restrictions associated with this feature, such as no support for bushy joins, parallel query hash-hash plan support, or left semi/outer support for non-root right-deep joins. Additionally, there are aggregation restrictions, including limitations on using the same column as grouping columns and aggregation columns, and limited expression support for aggregation, which only allows arithmetic expressions on numeric data type columns.</p>
<p>Furthermore, aggregation is supported by single table PCODE but not HPK for SQL, and functions like CASE, COALESCE, DECODE, NVL, and DISTINCT have restrictions. Deduplication per IMCU is currently supported, and ordering is possible on the column from the last probe table with the rank with the ORDER BY clause.</p>
<h3 id="heading-staging-tables">Staging Tables</h3>
<p>In Oracle 23ai, staging tables are introduced for optimized data loading into data warehouses. They can be created as new tables or by altering existing ones. Staging tables bypass the recycle bin and have restrictions such as no data compression. After data loading, they are truncated or deleted.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707473136401/1307a7f3-0bfa-4b56-9e94-f8b6d9d1f38d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707473080482/ff84cc03-0570-4bca-9003-7de93fae5fb1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707473048396/33d99abf-c3c1-46a1-bbf4-8c478a966fb1.png" alt class="image--center mx-auto" /></p>
<p>If you want to revert the stagging table to the original (not stagging) then you can ALTER TABLE in the same way this example</p>
<p><code>ALTER TABLE stagging_table NOT FOR STAGGING.;</code></p>
<h3 id="heading-lpct-for-materialized-view-refresh-and-staleness-tracking">LPCT for Materialized View Refresh and Staleness Tracking</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707474535996/6b6482c2-8e97-4248-be42-5e6e8dc65e85.png" alt class="image--center mx-auto" /></p>
<p>This operates at the level of logical granularity and gives you the flexibility to align the boundaries of logical partitions with the business rules and with the changes applied to tables. This optimizes MV for partial query rewrite. It also optimizes incremental refresh, without the overhead of MV log.</p>
<h3 id="heading-sysdate-and-systimestamp"><strong>SYSDATE and SYSTIMESTAMP</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707570107186/9e9c16dc-2dce-4fa6-a421-1c60195c4160.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1707570288771/3ebb8c0e-8998-4313-b821-366998719ad9.png" alt class="image--center mx-auto" /></p>
<p>Some of the ppt slides and snippets are from <a target="_blank" href="https://mylearn.oracle.com/ou/course/oracle-database-23c-new-features-for-developers">oracle-database-23ai-new-features-for-developers</a> course**.**</p>
]]></content:encoded></item></channel></rss>