application 11g plsql oracle11g oracle-apex

plsql - 11g - Application Express: Bloque PL/SQL anónimo y variables de vinculación



oracle apex version (2)

Tengo un problema que vincula el valor de un elemento de página a una variable declarada en un proceso de bloque PL / SQL anónimo.

El problema es que el elemento de página (: P4550_REQUESTOR) no se completa con un valor hasta que se cumple un condicional. Parece que el proceso de bloqueo PL / SQL vincula la variable a un valor vacío tan pronto como se carga la página, a pesar de que el proceso no se activa hasta que se ha hecho clic en un botón específico.

Aquí está mi código:

DECLARE v_email_to app_user.email%type; v_requestor VARCHAR2(15); BEGIN v_requestor := :P4550_REQUESTOR; BEGIN SELECT email INTO v_email_to FROM app_user WHERE userid = v_requestor; END; SEND_APEX_MAIL ( v_email_to, ''Your vacancy request has been rejected.'' || chr(10) || ''Emailed to: '' || v_email_to || chr(10) || ''Requestor: '' || v_requestor, ''Vacancy Request Rejected'' ); END;

¿Alguien tiene alguna idea sobre esto?

El bloque funciona bien si codigo un valor a v_requestor. Si trato de obtener el valor de P4550_REQUESTOR después de que la página se haya cargado, está vacío. Después de hacer clic en el botón Editar, P4550_REQUESTOR se rellena.

** ** MÁS DETALLES ** **

P4550_REQUESTOR es un elemento de página que reside dentro de la región de Solicitud de vacante que solo se muestra cuando se cumple un condicional. Específicamente, el condicional es un botón de edición asociado a una fila de la tabla que se crea en la carga de la página. Al hacer clic en el botón de edición, se muestra la región de detalles y se completan los elementos de la página asociados.

Los valores de elemento de página en la región de Solicitud de vacante se rellenan a través de un acceso de fila automatizado que se activa después del encabezado.

P4550_REQUESTOR tiene un tipo de fuente de columna DB.

El proceso que activa el código anterior está configurado para disparar al enviar: después de los cálculos y las validaciones

Si registro el valor de P4550_REQUESTOR cuando la página se carga, muestra nulo. Si registro el valor después de hacer clic en el botón editar, obtengo el valor esperado de la cadena.


Control de flujo de procesos en Oracle APEX

(Esto es realmente útil para pensar en otras disciplinas y entornos de programación).

Problema definido

El problema es que el elemento de página (: P4550_REQUESTOR) no se completa con un valor hasta que se cumple un condicional. Parece que el proceso de bloqueo PL / SQL vincula la variable a un valor vacío tan pronto como se carga la página, a pesar de que el proceso no se activa hasta que se ha hecho clic en un botón específico.

La declaración del problema reformulada en la terminología de Apex y presentada en la forma de una pregunta real:

  1. Hay una REPORT REGION en la página que contiene el resultado de una referencia directa a una tabla de datos / vista. Este informe es administrado por un proceso de Apex llamado "Búsqueda automatizada" y se inicia automáticamente al cargar los encabezados de página.
  2. Hay un FORM ITEM en una página que se llena condicionalmente mediante una selección de BUTTON ITEM realizada por el usuario. El BUTTON ITEM es parte de los resultados del informe.
  3. Hay múltiples elementos de botón. Cada uno está asociado con un valor para cada registro de informe.
  4. Si el usuario no selecciona el BUTTON ITEM de la REPORT REGION , el FORM ITEM permanece sin asignar y contiene un valor "nulo".

Hay un bloque de código PL / SQL definido que se configura para ejecutarse cuando se presiona un elemento SUBMIT BUTTON (también en la misma página). ¿Por qué mi bloque de código (proceso de página definido) se ejecuta con un valor nulo cuando se desencadena sin primero presionar primero un BUTTON ITEM desde la REPORT REGION ?

Diseño de programa impulsado por eventos para programadores de procedimientos

La respuesta no es obvia si piensas bajo el paradigma de un lenguaje de procedimiento. Sin zambullirme en una conferencia sobre el tema, aquí hay un diseño visual del espacio problemático del PO que preparé para ilustrar cómo el problema puede hacerse más obvio:

Este es mi diseño de página Apex en implementación. Es lo suficientemente genérico como para usarlo como plantilla para otros diseños de Apex. No hay flechas de flujo en este diagrama porque es un sistema con estado. Una cosa hace que ocurra otra cosa y así sucesivamente ... pero no siempre, y no todas al mismo tiempo.

Casos de uso para los diseños de página de la interfaz de usuario de Apex

Intente recorrer algunos casos de uso para comprender cómo funcionan juntos los elementos desglosados ​​en el diagrama. Cada usuario puede tomar cualquier número de combinaciones de clics e interacciones, pero hay una característica común:

  1. Todos ingresan las mismas condiciones inicializadas en la carga de la página.
  2. Todos abandonan la página al: navegar en otro lugar o mediante el evento de botón ENVIAR.

Usar el caso n. ° 1

  1. El usuario elige {MyPage:SQLReport:ThisButton} de uno de los registros en {MyPage:SQLReport}
  2. De acuerdo con {MyPage:SQLReport:ThisButton} #3 , el valor asociado entre el registro del informe y el elemento del botón se pasa a: {MyPage:HTML-Region:ThisItem}
  3. El estado del elemento de formulario se ha actualizado y cambiado desde el valor nulo inicial.
  4. El usuario selecciona el botón {MyPage:HTML-Region:ThisSubmit} para informar al sistema que continúe.
  5. El botón de enviar ejecuta el bloque de procedimiento de PL / SQL definido: {MyPage:RunCodeBlock}

Usar el caso n. ° 2

  1. El usuario ingresa la página y revisa los resultados que se muestran en la región {MyPage:SQLReport} .
  2. El usuario decide que no es necesaria ninguna entrada adicional y luego selecciona el botón {MyPage:HTML-Region:ThisSubmit} para informar al sistema que continúe.
  3. (una nota: el estado del elemento del formulario {MyPage:HTML-Region:ThisItem} no se ha cambiado desde el valor nulo inicial en este punto ... después de que se haya seleccionado el botón de envío)
  4. El botón de enviar ejecuta el bloque de procedimiento de PL / SQL definido: {MyPage:RunCodeBlock}

Usar el caso n. ° 3

  1. El usuario elige {MyPage:SQLReport:ThisButton} de uno de los registros en {MyPage:SQLReport}
  2. De acuerdo con {MyPage:SQLReport:ThisButton} #3 , el valor asociado entre el registro del informe y el elemento del botón se pasa a: {MyPage:HTML-Region:ThisItem}
  3. El estado del elemento de formulario se ha actualizado y cambiado desde el valor nulo inicial.
  4. El usuario elige {MyPage:SQLReport:ThisButton} de una selección diferente de uno de los registros en {MyPage:SQLReport} .
  5. De acuerdo con {MyPage:SQLReport:ThisButton} #3 , el valor asociado entre el registro del informe y el elemento del botón se pasa a: {MyPage:HTML-Region:ThisItem}
  6. El estado del elemento del formulario se ha actualizado y cambiado desde el valor inicial almacenado en el paso (2).
  7. El usuario selecciona el botón {MyPage:HTML-Region:ThisSubmit} para informar al sistema que continúe.
  8. El botón de enviar ejecuta el bloque de procedimiento de PL / SQL definido: {MyPage:RunCodeBlock}

La diferencia entre cada caso debe ilustrar por qué el valor dependiente ( ThisItem , o más específicamente, el elemento de página P4550_REQUESTOR ) es nulo en un caso de uso contra el otro.

Construyendo una Implementación Física (Una Página Apex)

La tabla que usé se llama STAR_EMPS. Es similar a la tabla EMP pero tiene solo tres columnas: ename, deptno y salario. Aunque no es muy importante, este es el conjunto de datos que solía poblar STAR_EMPS:

Usé una tabla simple de dos columnas llamada STAR_EMPS_LOG para capturar el resultado de una llamada de procedimiento ejecutada con éxito. Usted podría lograr lo mismo con solo una columna, pero yo quería una identificación secuencial para rastrear el orden en que se registró cada evento, para ejecutar múltiples casos de prueba. El procedimiento es uno de varios procesos definidos que se conservan en esta página:

contenido en: {MyPage: RunCodeBlock} está debajo:

DECLARE -- output from this procedure will be recorded in the star_emps_log -- table. {MyPage:RunCodeBlock} mycelebrity star_emps.ename%TYPE:= :P17_CELEBRITY_NAME; mylogmessage star_emps_log.log_message%TYPE; BEGIN -- Conditional; changes message based on the value set for the -- page item. if mycelebrity is null then mylogmessage:= ''No button was pressed on the previous page.''; else mylogmessage:= ''The user selected: '' || mycelebrity || '' from the report list.''; end if; -- populate value from the page item. INSERT INTO star_emps_log (log_message) VALUES (mylogmessage); commit; END;

Así es como se configuró el diseño de la página:

  1. Como en su ejemplo, hice una región {MyPage: SQLReport} con sus elementos de apoyo. El Informe SQL representa una consulta dirigida a la tabla de datos fuente.
  2. {MyPage: Form} se ha cambiado el nombre a {MyPage: HTML-Region}.
  3. {MyPage: SQLReport} se define mediante una consulta SQL, también hay una columna simulada para usar como marcador de posición para colocar los botones "editar".
  4. {MyPage: SQLReport: ThisButton} Las especificaciones de los botones se detallan a través de esto:

Los procesos de la página TWO: PROCESS y BRANCH deben estar vinculados con la misma configuración que hace referencia a un BUTTON triggering Item.

Casos de prueba de interfaz de usuario

Ejecute los tres escenarios sugeridos para comenzar. Verifique que el sistema esté interpretando las solicitudes correctamente. Así es como se ve el diseño de la página:

Los dos procesos en el sistema tienen una definición que no fue mencionada en discusiones previas que pueden resolver nuestro problema original:

Algunos pensamientos de despedida

Es una buena cosa que este sea un caso trivial una vez analizado. El método de diagramación descrito aquí debería escalar a otras aplicaciones Apex de complejidad variable. Existe una considerable utilidad al alejarse del código, restringir la terminología e intentar describir sistemas y procesos sin código real. Asegúrese de compartir cualquier historia si este enfoque ayuda con sus propios desafíos de diseño de Oracle Apex.

¡Adelante!


La respuesta original y detallada parece complicar demasiado el problema. El manual de conceptos de estado de la sesión cubre este comportamiento de manera más sucinta.

En caso de que P4550_REQUESTOR sea un elemento normal creado a partir de un asistente, el uso de: P4550_REQUESTOR devolverá un valor en los procesos que ejecutan la publicación de envíos porque el proceso de envío mueve los valores en el navegador al estado de la sesión.

Si P4550_REQUESTOR se procesa condicionalmente, siempre será nulo y no estoy seguro de qué pasaría si intentaste configurarlo, probablemente depende de cómo.

En una nota similar, si usaste & P4550_REQUESTOR. para parametrizar el proceso, se enfrentaría al comportamiento descrito originalmente (y haría el código menos seguro)