domingo, 24 de junio de 2018

Escribiendo Código Flexible en Oracle Forms

Objetivos:



 Describir un Código Flexible.
 Indicar las ventajas de usar variables de sistema.
 Identificar los built-ins útiles en la codificación flexible.
 Escribir código dinámico mediante la referencia a objetos:
--Por ID interno.
--Indirectamente.
_________________________________________________________________________
¿Qué es el Código Flexible?
Código Flexible: es todo código que puede ser reutilizado en distintos escenarios. El código flexible a menudo es un código genérico que puede usar en cualquier módulo Form en una aplicación. Por lo general, incluye el uso de variables del sistema en lugar de nombres de objetos codificados.

¿Por qué escribir código flexible?
Escribir código flexible te brinda las siguientes ventajas:
 Es reutilizable.
 Es genérico.
 Evita nombres de objetos codificados.
 Es más fácil de mantener.
 Aumenta la productividad.
______________________________________________________________________________________
Uso de  Variables de Sistema para el Contexto Actual.
Variables del sistema para localizar el foco de entrada actual:
Variable de Sistema
Funcción
CURSOR_BLOCK
Contiene el Bloque que tiene el foco de entrada.
CURSOR_RECORD
Contiene el registro que tiene el foco de entrada.
CURSOR_ITEM
Contiene el Item y Bloque que tiene el foco de entrada.
CURSOR_VALUE
Contiene el valor del Item que tiene el foco de entrada.
Ejemplo:
IF :SYSTEM.CURSOR_BLOCK = 'ORDERS' THEN
GO_BLOCK('ORDER_ITEMS');
ELSIF :SYSTEM.CURSOR_BLOCK = 'ORDER_ITEMS' THEN
  GO_BLOCK('INVENTORIES');
ELSIF :SYSTEM.CURSOR_BLOCK = 'INVENTORIES' THEN
  GO_BLOCK('ORDERS');
END IF;
/*El ejemplo anterior muestra un código que podría colocarse en un Trigger When-Button-Pressed para permitir a los usuarios navegar a otro bloque en el Form. Verifica el nombre del bloque actual, luego navega a otro en función del resultado.*/

Nota: asegúrese de establecer la propiedad Mouse Navigate del botón en No; de lo contrario, SYSTEM.CURSOR_BLOCK siempre será el bloque en el que se encuentra el botón.

Variables del sistema para localizar el foco del Trigger.
System Variable
Function
TRIGGER_BLOCK
El bloque en el que estaba el foco de entrada cuando el Trigger se disparó inicialmente.
TRIGGER_RECORD
El número del registro que Forms está procesando.
TRIGGER_ITEM
El bloque y item en el que estaba el foco de entrada cuando el Trigger se disparó inicialmente.
El Uso de las Variables de Enfoque del Trigger.
Las variables para ubicar el foco del trigger son útiles para navegar de regreso al destino inicial una vez que se completa la ejecución del trigger . Por ejemplo, puede que durante la ejecución del trigger se requiere navegar a otros bloques, registros o items y así realizar acciones sobre ellos, y que después de la ejecución de dicho proceso se desee que el cursor retorne en la misma instancia inicial. Debido a que la navegación en el trigger se produce detrás de escenas, el usuario ni siquiera se dará cuenta.
Nota: la mejor manera de aprender sobre las variables del sistema es observar sus valores cuando se está ejecutando un Form. Puede examinar las variables del sistema utilizando el Depurador (Debugger).

Variables de sistema para determinar el estado actual del Form.
También puede usar las siguientes variables de sistema para realizar acciones de acuerdo al valor que estas contengan:
SYSTEM.RECORD_STATUS
SYSTEM.BLOCK_STATUS

SYSTEM.FORM_STATUS
Ejemplo:
BEGIN
ENTER;
IF :SYSTEM.BLOCK_STATUS = 'CHANGED' THEN
COMMIT_FORM;
END IF;
CLEAR_BLOCK;
END;
/*En el ejemplo anterior se valida si existen modificaciones en el bloque actual, si las hay se procede a guardar dichas modificaciones (COMMIT_FORM), posteriormente se procede a limpiar dicho bloque (CLEAR_BLOCK).*/
_________________________________________________________________________
El Uso Built-ins para codificación flexible.
Algunos de los Built-ins de Forms Builder proporcionan el mismo tipo de información que proporcionan las variables de sistema.

Algunos Built-ins:
 GET_APPLICATION_PROPERTY
 GET_FORM_PROPERTY
 GET_BLOCK_PROPERTY
 GET_RELATION_PROPERTY
 GET_RECORD_PROPERTY
 GET_ITEM_PROPERTY
 GET_ITEM_INSTANCE_PROPERTY
 GET_LOV_PROPERTY
 GET_RADIO_BUTTON_PROPERTY
 GET_MENU_ITEM_PROPERTY
 GET_CANVAS_PROPERTY
 GET_TAB_PAGE_PROPERTY
 GET_VIEW_PROPERTY
 GET_WINDOW_PROPERTY
 SET_APPLICATION_PROPERTY
 SET_FORM_PROPERTY
 SET_BLOCK_PROPERTY
 SET_RELATION_PROPERTY
 SET_RECORD_PROPERTY
 SET_ITEM_PROPERTY
 SET_ITEM_INSTANCE_PROPERTY
 SET_LOV_PROPERTY
 SET_RADIO_BUTTON_PROPERTY
 SET_MENU_ITEM_PROPERTY
 SET_CANVAS_PROPERTY
 SET_TAB_PAGE_PROPERTY
 SET_VIEW_PROPERTY
 SET_WINDOW_PROPERTY

Algunos Explicaciones:
 GET_APPLICATION_PROPERTY  devuelve información sobre la aplicación Forms actual.

Ejemplo:
BEGIN
:GLOBAL.username := GET_APPLICATION_PROPERTY(USERNAME);
:GLOBAL.o_sys := GET_APPLICATION_PROPERTY(OPERATING_SYSTEM);
END;
/*El ejemplo anterior captura el nombre de usuario y la información del sistema operativo.*/

Nota: GET_APPLICATION_PROPERTY devuelve información sobre la aplicación Forms que se ejecuta en el nivel medio (Servidor Forms). Si necesita información sobre la máquina cliente, puede usar los JavaBean.

 GET_BLOCK_PROPERTY devuelve información sobre un bloque específico.

Ejemplo: 
...GET_BLOCK_PROPERTY('blockname',top_record)...
/*Este ejemplo muestra como determinar el registro actual que está visible en la primera línea (superior) de un bloque.*/

 GET_ITEM_PROPERTY devuelve información sobre un item especificado.

Ejemplo: 
DECLARE cv_name varchar2(30);
BEGIN
cv_name := GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM,item_canvas);
...
/*Este ejemplo muestra como determinar el Canvas que contiene el Item donde radica el foco de entrada.*/


SET_ITEM_INSTANCE_PROPERTY modifica la instancia del item en cuestión cambiando la propiedad especificada.

Ejemplo: 
BEGIN
SET_ITEM_INSTANCE_PROPERTY(:SYSTEM.CURSOR_ITEM, VISUAL_ATTRIBUTE, CURRENT_RECORD, 'VA_CURR');
END;
/*El anterior ejemplo establece el atributo visual en VA_CURR para el registro actual del item en cuestión.*/

• SET_MENU_ITEM_PROPERTY modifica las propiedades dadas de un elemento de menú.

Ejemplo: 
SET_MENU_ITEM_PROPERTY ('FILE.SAVE', ENABLED, PROPERTY_TRUE);
/*El ejemplo muestra como habilitar el Item SAVE.*/
.
SET_TAB_PAGE_PROPERTY establece las propiedades de la página de pestañas de la página de lienzo de pestañas especificada.

Ejemplo:
DECLARE
tbpg_id  TAB_PAGE;
BEGIN
tbpg_id := FIND_TAB_PAGE('tab_page_1');
IF GET_TAB_PAGE_PROPERTY(tbpg_id, enabled) = 'FALSE' THEN
SET_TAB_PAGE_PROPERTY(tbpg_id, enabled,property_true);
END IF;
END;
/*El anterior ejemplo evalúa el estado de la pestaña 'tab_page_1' y en caso de estar inhabilitada procede a habilitarla.*/
_________________________________________________________________________
Haciendo Referencia a Objetos por el ID Interno.
Forms Builder asigna un ID a cada objeto creado. El ID de objeto es un valor interno que nunca se muestra. Puede obtener la ID de un objeto mediante el uso de los built-ins FIND_objectFIND_object requiere un nombre de objeto que recibe como parámetro.

Los valores de retorno de FIND_object (los ID de objeto) son de un tipo específico. Los tipos de ID de objeto están predefinidos en Forms Builder. Hay un tipo diferente para cada objeto.

¿Por Qué usar Identificadores de Objetos?
• Mejora del rendimiento (Forms busca el objeto una sola vez al llama al built-in FIND_object para obtener el ID. Cuando se refiere a un objeto por nombre en un trigger, Forms debe buscar la ID del objeto cada vez).
• Permite escribir un código más genérico y a la vez más dinámico.
• Permite probar si existe un objeto (usando la función ID_NULL y FIND_object).

Tipos de Objetos FIND_object: 
Object Class
Subprogram
Return Type
Alertas
FIND_ALERT
ALERT
Bloques
FIND_BLOCK
BLOCK
Canvas
FIND_CANVAS
CANVAS
Editores
FIND_EDITOR
EDITOR
Forms
FIND_FORM
FORMMODULE
Items
FIND_ITEM
ITEM
LOVs
FIND_LOV
LOV
Relaciones
FIND_RELATION
RELATION
Vistas
FIND_VIEW
VIEWPORT
Windows
FIND_WINDOW
WINDOW
Las Variables para Identificadores de Objetos.
Para usar un ID de objeto, primero debe asignarlo a una variable. La variable debe ser declarada del mismo tipo que la ID del objeto.

El siguiente ejemplo usa el buil-int FIND_ITEM para asignar el ID del item que tiene el foco de entrada a la variable id_var.
DECLARE 
 
id_var item;0
BEGIN
 
id_var := FIND_ITEM(:SYSTEM.CURSOR_ITEM);
. . .
END;

Una vez que asigna un ID de objeto a una variable en un trigger o unidad de programa PL/SQL, puede usar esa variable para hacer referencia al objeto, en lugar de referirse al objeto por su nombre.

Los ejemplos siguientes muestran que puede pasar tanto el nombre de item como su ID al built-in  SET_ITEM_PROPERTY. Las siguientes llamadas son lógicamente equivalentes:
SET_ITEM_PROPERTY('ORDERS.order_id',position,50,35);

SET_ITEM_PROPERTY(id_var,position,50,35);
Puede usar identificadores de objetos o nombres de objetos en la misma lista de argumentos, siempre que cada argumento individual se refiera a un objeto distinto.

Sin embargo, no puede usar un ID de objeto y un nombre de objeto para formar un nombre compuesto (nombre_de_bloque.nombre_de_elemento). La siguiente llamada es ilegal:
GO_ITEM(block_id.'item_name');
Nota: Es recomendable usar los built-ins FIND_object solo cuando se refiera a un objeto más de una vez en el mismo Trigger o unidad de programa PL/SQL.
_________________________________________________________________________
ID de Objetos fuera del Bloque PL/SQL Inicial.
Hemos visto como hacer referencia a los ID de objeto dentro de un trigger o unidad de programa mediante variables PL/SQL. Puede hacer referencia a estas variables PL/SQL solo en el bloque PL/SQL actual; sin embargo, puede aumentar el alcance de un ID de objeto.

Para hacer referencia a una ID de objeto fuera del bloque PL/SQL inicial, debe convertir el ID a un formato numérico utilizando una extensión .id para su variable PL/SQL declarada, y luego asignarla a una variable global.

Ejemplo:
En el siguiente ejemplo se asigna la ID del objeto a una variable local de PL/SQL (item_var) inicialmente, luego a una variable global (global.item):
DECLARE
item_var item;
BEGIN
item_var := FIND_ITEM(:SYSTEM.CURSOR_ITEM);
:GLOBAL.item := item_var.id;
END;

Ahora puede pasar la variable global dentro de la aplicación. Para poder reutilizar la ID del objeto, debe volver a convertirla a su tipo de datos original.

Ejemplo:
El siguiente ejemplo muestra la conversión de la variable global a su tipo original de datos variables PL/SQL:
DECLARE
item_var item;
BEGIN
item_var.id := TO_NUMBER(:GLOBAL.item);
GO_ITEM(item_var);
END;
_________________________________________________________________________
Haciendo Referencia a Items Indirectamente.
Al hacer referencia indirectamente a los item, puede escribir un código más genérico y reutilizable. Usando variables en lugar de nombres de item reales, puede escribir una unidad de programa PL/SQL para usar cualquier item cuyo nombre esté asignado a la variable indicada.

Puede hacer referencia indirecta a los item con los built-ins NAME_IN y COPY.

Nota: utilice referencias indirectas cuando cree procedimientos y funciones en un módulo de librería, ya que las referencias directas no se pueden resolver.

Usando el Built-in NAME_IN.
La función NAME_IN devuelve el valor contenido de la variable indicada. Las siguientes sentencias son equivalentes. La primera usa una referencia directa a customer.name, mientras que la segunda usa una referencia indirecta:
IF :CUSTOMERS.cust_last_name = 'Welles'...
En una librería, puede evitar esta referencia directa al usar:
IF NAME_IN('CUSTOMERS.cust_last_name') = 'Welles'...
El valor de retorno de NAME_IN siempre es una cadena de caracteres. Para usar NAME_IN para un item tipo fecha o numérico, convierta la cadena al tipo de datos deseado con la función de conversión adecuada. Por ejemplo:
date_var := TO_DATE(NAME_IN('ORDERS.order_date'));

Usando el Built-in COPY.
El built-in COPY  asigna un valor indicado a una variable o item especifico. A diferencia de la sentencia de asignación estándar de PL/SQL, usar COPY le permite hacer referencia indirectamente al item cuyo valor se está configurando.
Ejemplo:
COPY('Welles','CUSTOMERS.cust_last_name');

Usando NAME_IN y COPY.
Utilice los built-ins COPY y NAME_IN para asignar indirectamente un valor a un item cuyo nombre se almacena en una variable global.
Ejemplo:
COPY('Welles',NAME_IN('global.customer_name_item'));
_________________________________________________________________________
Resumen.
En esta publicación, debes haber aprendido que:
 El código flexible es un código genérico reutilizable que puede usar en cualquier módulo Forms de una aplicación.
 Con las variables del sistema, puede:
---Realizar acciones condicionalmente en función de la ubicación actual (SYSTEM.CURSOR_ [RECORD | ITEM | BLOCK]).
---Utilizar el valor de un item sin conocer su nombre (SYSTEM.CURSOR_VALUE).
---Navegar a la ubicación inicial después de que se complete la ejecución de un trigger: (SYSTEM.TRIGGER_ [RECORD ITEM BLOCK]).
---Realizar acciones condicionalmente en función del estado del COMMITSYSTEM. [RECORD BLOCK| FORM] _STATUS.
 Los built-ins [GET | SET] _ <object> _PROPERTY son útil en la codificación flexible.
 El código que hace referencia a los objetos es más eficiente y genérico:
---Por ID interno: use FIND_ <object> built-ins.
---Indirectamente: usando lost built-ins COPY y NAME_IN incorporados.
_________________________________________________________________________
Fuente: Oracle Forms Developer 10g: Build Internet Applications.

jueves, 31 de mayo de 2018

El Procesamiento de Transacciones en Oracle Forms (Parte 2)

Objetivos:

 Complementar el procesamiento de transacciones.
 El uso de Variables de Sistema en conjunto con los Triggers Transaccionales.
 Implementar la Matriz DML.

Nota: esta publicación es la continuación de El Procesamiento de Transacciones en Oracle Forms (Parte 1), de modo que es recomendable tener los conocimientos expuestos ahí para una mejor comprensión de lo aquí expuesto.
______________________________________________________________________________________
Anulando el Procesamiento Transaccional Predeterminado.
En publicaciones anteriores hemos visto que algunos Triggers Commit se pueden usar para reemplazar las sentencias DML predeterminadas que Forms emite durante el procesamiento Commit. Puede utilizar varios otros Triggers para anular el procesamiento predeterminado de transacciones en Forms.

Triggers Transaccionales.
Todos los Triggers  que están relacionados con el acceso a una fuente de datos se denominan Triggers Transaccionales. Los Triggers Commit forman un subconjunto de ellos. Otros ejemplos incluyen Triggers  que se activan durante el inicio de sesión y cierre de sesión o durante consultas realizadas en el origen de datos.

Trigger
Do-the-Right-Thing Built-In
On-Check-Unique
CHECK_RECORD_UNIQUENESS
On-Column-Security
ENFORCE_COLUMN_SECURITY
On-Commit
COMMIT_FORM
On-Rollback
ISSUE_ROLLBACK
On-Savepoint
ISSUE_SAVEPOINT
On-Sequence-Number
GENERATE_SEQUENCE_NUMBER


Nota: Estos Triggers están destinados a ser utilizados cuando se conecta a fuentes de datos que no sean Oracle.

Triggers Transaccionales para iniciar y cerrar sesión.
Trigger
Do-the-Right-Thing Built-In
Pre-Logon
-
Pre-Logout
-
On-Logon
LOGON
On-Logout
LOGOUT
Post-Logon
-
Post-Logout
-
Usos de Triggers Transaccionales.
• Los Triggers transaccionales, excepto los Triggers Commit, están destinados principalmente a acceder a determinadas fuentes de datos distintas de Oracle.
• Los Triggers transaccionales de inicio de sesión y cierre de sesión también se pueden usar con las bases de datos de Oracle para cambiar las conexiones en tiempo de ejecución.
______________________________________________________________________________________
Forms con fuentes de datos distintas a Oracle.
Existen dos formas de ejecutar Forms con fuentes de datos distintas de Oracle:
 Use los productos Oracle Transparent Gateway.
 Escriba un conjunto apropiado de Triggers Transaccionales.

Conectando con Open Gateway:
Cuando se conecta a una fuente de datos que no sea Oracle con un producto Open Gateway, debe tener en cuenta estas propiedades transaccionales:
 La propiedad del Módulo Forms Cursor Mode.
 La propiedad del Módulo Forms Savepoint Mode.
 La propiedad de Bloque Key Mode.
 La propiedad de Bloque Locking Mode.

Puede configurar estas propiedades para especificar cómo Forms debe interactuar con el origen de datos. La configuración específica depende de las capacidades de la fuente de datos.

Usando Triggers Transaccionales.
Si no existen controladores Open Gateway para su origen de datos, debe definir Triggers Transaccionales. A partir de estos Triggers, debe llamar programas 3GL que implementan el acceso a la fuente de datos.

Propiedad Bloque de Base de Datos (Database Data Block).
Esta propiedad (de bloque) identifica un bloque como un bloque de control transaccional; es decir, un bloque de control que debe tratarse como un bloque de tabla base. Al establecer esta propiedad en Sí, se asegura que los Triggers Transaccionales dispararán para el bloque, aunque no sea un bloque de tabla base. Si establece esta propiedad en Sí, debe definir todos los Trigger transaccionales On-Event, de lo contrario recibirá un error durante la generación del Form.
______________________________________________________________________________________
Obteniendo y configurando el Estado del Commit (Commit Status).
Si desea procesar un registro en su Form, resulta útil saber si el mismo fue cambiado o está tal cual en la base de datos. Puede usar built-ins y variables de sistema para obtener esta información.

¿Cuál es el estado (Commit Status) de un registro?
El estado de un registro de un bloque de base de datos determina cómo se procesará durante el siguiente proceso de Commit. Por ejemplo, el registro se puede insertar, actualizar o no procesar en absoluto.

Los Valores de SYSTEM.RECORD_STATUS:
Valor
Descripción
NEW
Indica que el registro se ha creado, pero que ninguno de sus Items se ha cambiado aún (es posible que el registro se haya llenado con los valores predeterminados).
INSERT
Indica que uno o más items en un registro recién creado han sido cambiados (El registro se procesará como una inserción durante el próximo proceso de confirmación (Commit) si su bloque tiene el estado CHANGED; ver más adelante. Tenga en cuenta que cuando cambia un item de control de un registro con estado en NEW , el estado del registro también se convierte en INSERT).
QUERY
Indica que el registro corresponde a una fila de la base de datos, pero que ninguno de sus items han sido cambiados.
CHANGED
Indica que se han cambiado uno o más item de un registro extraído de la base de datos (el registro se procesará como una actualización (o eliminación) durante el siguiente proceso de confirmación).
Los Valores de SYSTEM.BLOCK_STATUS:
Valor
Descripción
NEW
Indica que todos los registros del bloque tienen el estado NEW (Tenga en cuenta que un bloque de tabla base con el estado NEW también puede contener registros con el estado INSERT causado por el cambio de items de control).
QUERY
Indica que todos los registros del bloque tienen el estado QUERY si el bloque es de base de datos (un bloque de control tiene el estado QUERY si contiene al menos un registro con el estado INSERT).
CHANGED
Indica que el bloque contiene al menos un registro con el estado INSERT CHANGED si el bloque es un bloque de tabla base (El bloque se procesará durante el próximo proceso de confirmación. Tenga en cuenta que un bloque de control no puede tener el estado CHANGED).
Los Valores de SYSTEM.FORM_STATUS:
Valor
Descripción
NEW
Indica que todos los bloques del Form  tienen el estado NEW.
QUERY
Indica que al menos un bloque del Form tiene el estado QUERY y todos los otros bloques tienen el estado NEW.
CHANGED
Indica que al menos un bloque del Form tiene el estado CHANGED.
El uso de built-ins para obtener el Estado del Commit.
Las variables de sistema SYSTEM.RECORD_STATUS y SYSTEM.BLOCK_STATUS se aplican al registro y al bloque donde está ubicado el cursor. Puede usar built-ins para obtener el estado de otros bloques y registros.

Built-ins

Descripción

GET_BLOCK_PROPERTY
Use la propiedad STATUS para obtener el estado del bloque especificado.
GET_RECORD_PROPERTY
Use la propiedad STATUS para obtener el estado del registro especificado de algún bloque.
SET_RECORD_PROPERTY
Establezca la propiedad STATUS del registro especificado en el bloque especificado con una de las siguientes constantes:
·         NEW_STATUS
·         INSERT_STATUS
·         QUERY_STATUS
·         CHANGED_STATUS
Sintaxis
 GET_BLOCK_PROPERTY  ('BLOCK',   PROPERTY);
 GET_RECORD_PROPERTY  ( RECORD_NUMBER,   'BLOCK',   PROPERTY);
 SET_RECORD_PROPERTY  ( RECORD_NUMBER,   'BLOCK',   PROPERTY,   'VALUE');

Ejemplo:
Si el tercer registro del bloque ORDERS es un registro de base de datos modificado, establezca el estado nuevamente en QUERY.

BEGIN
  IF GET_RECORD_PROPERTY(3, '
ORDERS',status)= 'CHANGED' 
  THEN
  SET_RECORD_PROPERTY(3, 
'ORDERS', status,  
                        
query_status);
  END IF;
END;
Advertencias:
 No confunda el estado de confirmación (COMMIT STATUS) con el estado de validación.
 El estado de confirmación se actualiza durante la validación.
______________________________________________________________________________________
Matriz DML (Array DML).

Procesamiento Matriz
El procesamiento  matriz es una opción en Forms Builder que altera la forma en que se procesan los registros. El comportamiento predeterminado de Forms es procesar los registros de uno en uno. Al habilitar el procesamiento matriz, puede procesar grupos de registros a la vez, reduciendo el tráfico en la red y, por lo tanto, aumentando el rendimiento. Esto es especialmente importante en las aplicaciones web. Con el procesamiento matriz, una estructura (una matriz) que contiene múltiples registros se envía o se devuelve desde el servidor para su procesamiento.

Forms Builder permite extraer un conjunto de registros en forma de matriz y a su vez permite procesarlos en forna de DML matriz. Tanto para consultas como para operaciones DML, puede determinar el tamaño de la matriz para así optimizar el rendimiento según sus necesidades.

El procesamiento de matriz está disponible para consultas y operaciones DML en bloques basados en tablas de base de datos, vistas, procedimientos y subconsultas; no es compatible con bloques basados en Triggers Transaccionales.

Efecto de la Matriz DML en Triggers Transaccionales.
Con DML Array Size establecido en 1, los Triggers Pre-InsertPre-UpdatePre-Delete disparan por cada registro nuevo, modificado y eliminado; se emite el DML y se dispara el Post-trigger para ese registro.

Con DML Array Size configurado en un número mayor a 1, son disparados los triggers Pre- para todas las filas nuevas, modificadas y eliminadas; todas las sentencias DML se emiten y todos los triggers Post- se activan.

Si cambia 100 filas y DML Array Size es 20, obtendrá 100 Pre-triggers, 5 matrices de 20 sentencias DML y 100 Post-triggers.
______________________________________________________________________________________
Cómo Implementar la Matriz DML.
1. Para establecer preferencias:
--Seleccione Editar> Preferencias.
--Haga clic en la pestaña Runtime.
--Seleccione la casilla Procesamiento de Matrices.
2. Para establecer propiedades:
--En el Navegador de objetos, seleccione el nodo Bloques de datos.
--Seleccione el Bloques de datos en question y despliegue sus propiedades (F4).
--En la categoría de Advanced Database, establezca la propiedad DML Array Size en un número que represente la cantidad de registros a ser procesados en forma de matriz. También puede configurar esta propiedad mediante programación.

Nota: Cuando la propiedad DML Array Size es mayor que 1, debe especificar la clave principal. El KEY MODE aún puede ser UNIQUE.

El servidor de Oracle usa ROWID para identificar la fila, excepto después de una inserción matriz. Si actualiza un registro en la misma sesión que lo insertó, el servidor bloquea el registro utilizando la clave principal.
______________________________________________________________________________________
Resumen.
En esta publicación en conjunto con El Procesamiento de Transacciones en Oracle Forms (Parte 1), debes haber aprendido a:
 Aplicar cambios a la base de datos, Forms emite los posting y los commits.
 La secuencia de eventos del Commit:
1. Se Valida el Form.
2. Se Procesan los puntos de rescate.
3. Se disparan los Triggers Pre-.
4. Se Validan los bloques en orden secuencial.
5. Se ejecutan los DML:
--Secuencia al eliminar registros: Se dispara el Pre-Delete; Se elimina el registro o se dispara el On-Delete; Se dispara el Post-Delete.
--Secuencia al insertar registros: Se copia el valor del Item; Se dispara el Pre-Insert; Se verifica la singularidad del registro; Se inserta el registro o se dispara el On-Insert; Se dispara el Post-Insert.
--Secuencia al  actualizar registros: Se dispara el Pre-Update; Se verifica la singularidad del registro; Se actualiza el registro o se activa el On-Update; Se dispara el Post-Update.
6. Se dispara el Trigger Post-Forms-Commit.
Si la operación actual es COMMIT, entonces:
7. Emite la sentencia SQL-COMMIT.
8. Se Dispara el Trigger Post-Database-Commit.
 Puede complementar el procesamiento de transacciones con Triggers:
--Pre-Commit: se dispara una vez si se realizan cambios en el Form.
--[Pre | Post] - [Update| Insert | Delete].
--On - [Update| Insert | Delete]: Se dispara por cada registro, reemplazando el DML predeterminado. Realiza las funciones predeterminadas con Built-ins: [UPDATE|INSERT|DELETE]_RECORD.
 Utilizar el Trigger Pre-Insert para asignar números de secuencia a los registros a medida que se aplican a las tablas.
 Verificar o cambiar el estado de confirmación (Commit):
GET_BLOCK_PROPERTY, [GET | SET]_RECORD_STATUS
–:SYSTEM.[FORM | BLOCK | RECORD]_STATUS Usar Triggers Transaccionales para anular o añadir funcionalidad al procesamiento predeterminado del Commit.
 El uso de la Matriz DML para reducir los viajes de ida y vuelta en la red con la propiedad de bloque DML Array Size.
______________________________________________________________________________________
Fuente: Oracle Forms Developer 10g: Build Internet Applications.