martes, 6 de enero de 2015

El uso de PL / SQL en Oracle E-Business Suite


Introducción al uso de PL / SQL en Oracle E-Business Suite

 

Puede usar los procedimientos PL / SQL como parte de una aplicación que se construye alrededor de Oracle E-Business Suite. Siguiendo los estándares de codificación, puede crear un procedimiento PL / SQL que se integra perfectamente con su solicitud y con Oracle E-Business Suite.
Podemos utilizar PL / SQL para:
  • Desarrollar extensiones basadas en procedimientosque serán utilizadas por nuestros formularios e informes de forma rápida y sencilla.
  • Modularizar el código de aplicación para acelerar el desarrollo y mejorar la mantenibilidad
  • Optimizar el código de aplicación para reducir el tráfico de red y mejorar el rendimiento general
Por ejemplo, para desarrollar una form siguiendo los estándares de Oracle E-Business Suite, Toda la lógica de negocio (manipulador de elementos, controlador de eventos y manejador de tablas) la tenemos que organizar en código PL/SQL. Pondremos muy poco código PL / SQL directamente en los eventos desencadenadores de forms ya que estos no representan un modelo lógico; son simplemente puntos de sucesos que Oracle Forms proporciona para invocar código procedimental. Si ponemos toda nuestra lógica de negocio en Paquetes PL/SQL,de esta forma aseguramos que nuestra aplicación es modular y además fácil de hacer mantenimiento.

Un ejemplo de lo que estamos hablando lo podemos ver en el formulario de OM "Pedidos rapidos" cuyo archivo fmb es "OEXOEORD.fmb"

No ubicamos en el bloke "ORDER" ubicamos el elemento "PRICE_LIST_MIR", en su evento "WHEN-VALIDATE-ITEM" se tiene la siguiente sentencia de codigo:

OE_ORDERS.Price_List('WHEN-VALIDATE-ITEM');


Claramente podemos ver que se hace un llamado al método "Price_List" el cual está contenido en el paquete "OE_ORDERS" este paquete lo pueden ver y analizar abriendo el archivo "OEXOEHDR.pll"


También podemos utilizar PL / SQL para desarrollar programas concurrentes o procedimientos almacenados que son llamados por los programas concurrentes. En general, cualquier programa concurrente puede ser desarrollado en PL / SQL.

Existen dos definiciones muy utilizadas, las cuales son:

Server-side(Del lado del servidor)

Del lado del servidor es un término usado para describir los procedimientos PL / SQL que se almacenan en una base de datos Oracle (en el servidor de base de datos). Procedimientos y funciones almacenados en la base de datos también se conocen como procedimientos almacenados y funciones, y también se pueden denominar como los procedimientos del lado del servidor de bases de datos.

Client-side (Del lado del cliente)

Del lado del cliente es un término usado para describir los procedimientos PL / SQL que se ejecutan en los programas que son clientes de la base de datos Oracle, como Oracle Forms, Oracle Reports y bibliotecas.

Normas de codificación PL/ SQL

Estas son las normas generales que debe seguir:

Usar siempre Paquetes

Procedimientos PL / SQL siempre deben definirse dentro de los paquetes. Crear un paquete para cada bloque de una forma u otra agrupación lógica de código.

Tamaño de Paquetes

En el lado del cliente (Oracle Forms)el código fuente PL / SQL de una unidad de programa y el código compilado en conjunto deben tener menos de 64 KB. (Una unidad de programa es una especificación de paquete, cuerpo o un procedimiento independiente.) Esto implica que el código fuente de una unidad de programa no puede exceder de 10K.

Si un paquete excede el límite de 10 km, se puede reducir el tamaño del paquete poniendo variables y procedimientos privados en uno o varios "paquetes privados." Por norma, sólo el paquete original debe acceder a las variables y procedimientos en un paquete privado. Si un procedimiento individual excede el límite de tamaño, debe separar el código en dos o más procedimientos.

Cuando un PL / SQL de Oracle Forms supera el límite de 64 K, Oracle Forms genera un error al compilar el paquete.

En el lado del servidor los paquetes no tiene límite de tamaño, pero cuando son utilizados por Oracle Forms se crea una copia local y e aquí cuando surgen los inconvenientes. Mantengan el número de procedimientos en un paquete de menos de 25 para evitar exceder el límite de 10 km.

Añadir nuevos procedimientos a los paquetes existentes

Al agregar nuevos procedimientos o funciones a los paquetes existentes (ya sea almacenado en la base de datos o en bibliotecas de Oracle Forms), debe por lo general a añadir al final del paquete (y especificación del paquete). Si agrega nuevos procedimientos en medio de la especificación del paquete, debe volver a generar cada formulario que hace referencia el paquete, o esos forms pueden obtener errores ORA-4062.

Uso de nombres de campo en el lado del cliente PL / Paquetes SQL

Siempre especifique nombres de campo completamente al incluir el nombre del bloque (es decir, en lugar de sólo poner FIELD_NAME ponga BLOCK.FIELD_NAME). Si especifica sólo el nombre del campo, Oracle Forms deben escanear a través de toda la lista de campos para cada bloque en intentando localizar su campo y comprobar si su nombre es ambiguo, lo que podría degradar el rendimiento de su forms. Si se incluye el nombre del bloque, Oracle Forms búsca sólo los campos en ese bloque y se detiene cuando encuentra una coincidencia. Por otra parte, si alguna vez agrega más bloques, su código existente continuara trabajando.

Nombres de campo en los parámetros de procedimiento

Cuando se pase campos como parámetros a un procedimiento almacenado, debe utilizarse la función 
COPY para actualizar los valores de campo en lugar de utilizar parámetros de tipo IN OUT u OUT. Este método evita que un campo se marquen como cambiado si está o no realmente modificado en su procedimiento. Cualquier parámetro declarado como OUT siempre se escribe cuando el procedimiento sale normalmente.

Por ejemplo, declarar un procedimiento de prueba (my_var VARCHAR2 IN) y llamarlo como prueba ('block.field') en lugar de declarar el procedimiento de prueba (my_var VARCHAR2 IN OUT) y llamarlo como prueba (: block.field).

Explícitamente asociar el nombre del parámetro y el valor con => cuando la lista de parámetros es mucha mejorar la legibilidad y asegurarse de que usted no está en "off" por un parámetro.

Utilizando DEFAULT

Utilizar DEFAULT en lugar de ": =" para asignar valores por defecto cuando declaren sus parámetros. DEFAULT es más preciso para valores por defecto.

Por el contrario, utilizar ": =" en lugar de DEFAULT al declarar valores para las variables constantes. 
Usando ": =" es más preciso constantes, los valores no se pueden sustituir.

Manipulación de NULL


Tenga cuidado al manipular los valores NULL en PL / SQL. Por ejemplo, si
a: = NULL y b: = NULL

La expresión (a = b) evalúa como FALSO. En cualquier expresión "=", donde uno de los términos es NULL, toda la expresión resolverá a FALSO.

Por esta razón, para comprobar si un valor es igual a NULL, debe utilizar el operador "is" en su lugar. 
Si usted está comparando dos valores y cualquiera de los valores podría ser igual a NULL, debe escribir la expresión de esta manera:
((a = b) or ((a is null) and (b is null))

Variables globales

Oracle Forms Developer y PL / SQL soporta diferentes tipos de variables globales:

 

Oracle Forms Global: una variable declarada en el pseudo-bloque "global" de un formulario
PL / SQL paquete global: Variables globales definidas en la especificación de un paquete
Oracle Forms Parámetro: una variable creada en el Diseñador de formularios de Oracle como un parámetro

La siguiente tabla muestra las características de cada tipo de variable, y le permite seleccionar el tipo más adecuado para su código.


comportamiento Oracle Forms Global PL/SQL Package Global Oracle Forms Parameter 
Puede ser creado en tiempo de diseño  Y Y 
Puede ser creado en tiempo de ejecuciónY     
Accesible a través de todas las formasY     
Accesible desde bibliotecas conectadasY (1) Y 
Soporta específicos tipos de datos(2) Y Y 
Por defecto es declarativa    Y 
Se puede hacer referencia indirectaY   Y 
Puede ser especificado en la línea de comandos    Y 
Deben borrarse para recuperar memoriaY     
Puede ser utilizado en cualquier 
Código de Oracle Forms
Y   Y 

 

(1) Una variable de definida en un paquete de un form no es visible desde sus bibliotecas adjuntas; una variable definida en una biblioteca adjunto es visible en el form. (Una variable Global definida en un form es visible a todas las bibliotecas adjuntas)
(2) Siempre CHAR (255).

Base de Datos Lado del Cliente Vs Lado del Servidor

El rendimiento es un aspecto crítico de cualquier aplicación. Debido a que las idas y vueltas por la red son muy costosas en un entorno típico de cliente-servidor, reducir al mínimo el número de rotaciones es clave para asegurar un buen rendimiento.

Usted debe decidir si sus procedimientos PL / SQL residen en el servidor o en el cliente basado en lo que resulte ser el menor número de rotaciones de la red. Aquí hay algunas pautas:

Los procedimientos se llaman en Oracle Forms empotrados, deben residir en el cliente.

Procedimientos que hacen referencia directamente a campos, ya sea como: block.field o vía NAME_IN / COPY, deben residir en el cliente.

Si un procedimiento contiene tres o más sentencias SQL, o se vuelve muy complicado, el procedimiento generalmente pertenece en el servidor.

Los procedimientos que se ejecutan sin ninguna sentencia SQL y que no necesitan acceso de base de datos deben residir donde sea necesario.

Si un procedimiento se llama desde el servidor, debe residir en el servidor.

Si un procedimiento se llama desde el cliente y el servidor, se debe definir en ambos lugares, a menos que el procedimiento sea muy complicado y el doble mantenimiento sea muy costoso. En este último caso, el procedimiento debe residir en el servidor.

Formato de Código PL/SQL

Dentro de un paquete se deben definir primeramente las variables privadas, a continuación los procedimientos privados, y finalmente procedimientos públicas.

Siempre termine los procedimientos y paquetes con la declaración "end <name>" donde <name> es el nombre del procedimiento o paquete para ayudar a delinear procedimientos.
A continuación una sentencia SQL:
ejemplo

DECLARE
CURSOR employees IS
SELECT empno
FROM emp
WHERE deptno = 10
AND ename IN ('WASHINGTON', 'MONROE')
AND mgr = 2701;

Utilice "- -" para inicializar un comentario, comentarios de varias líneas se pueden hacer utilizando "/ * ... * /".

Utilice minúsculas y mayúsculas para mejorar la legibilidad del código (PL / SQL mayúsculas y minúsculas). A modo de orientación, utilice mayúsculas para las palabras reservadas y minúsculas para todo lo demás.

Evite por cualquier motivo el anidamiento de la sentencia IF-THEN-ELSE.En su lugar utilise IF-THEN-ELSIF.

Ejemplo: código con mal estilo

IF ... THEN ... ELSE
       IF ... THEN ... ELSE
               IF ... THEN ... ELSE
               END IF
       END IF
END IF;

Ejemplo: Código con buen estilo

IF ... THEN ...
ELSIF ... THEN ...
ELSIF ... THEN ...
ELSIF ... THEN ...
ELSE ...
END IF;

Sólo crear bloques PL / SQL (BEGIN / END pares) dentro de un procedimiento cuando sea necesario atrapar capturar excepción procedente de la manipulación de datos.

Manejo de excepciones

Para el manejo de excepciones, utilice los siguientes consejos.

Errores en Oracle Forms PL / SQL

Si se produce un fallo en Oracle Forms PL / SQL y desea detener el procesamiento, utilice 
FND_MESSAGE para mostrar un mensaje de error, a continuación, suba FORM_TRIGGER_FAILURE para detener el procesamiento:

IF (error_condition) THEN
        fnd_message.set_name(appl_short_name,
        message_name);
        fnd_message.error;
        RAISE FORM_TRIGGER_FAILURE;
END IF;

Tenga en cuenta que FORM_TRIGGER_FAILURE hace que el proceso se detenga de forma silenciosa.

Los errores en procedimientos almacenados

Si se produce un fallo en un procedimiento almacenado y desea detener el procesamiento, utilice el procedimiento FND_MESSAGE.SET_NAME para configurar un mensaje y APP_EXCEPTION.RAISE_EXCEPTION para detener el procesamiento:

IF (error_condition) THEN
      fnd_message.set_name(appl_short_name,
      message_name);
      APP_EXCEPTION.RAISE_EXCEPTION;
END IF;

El formulario que invoca al procedimiento almacenado no deberá hacer nada para controlar este error 

El código en el trigger ON-ERROR del formulario automáticamente detecta el error del procedimiento almacenado, recuperara y mostrara el mensaje.

Importante: Por motivos de rendimiento, los paquetes del lado del servidor deben devolver un return_code para todos los retornos esperados, como no_rows. Sólo excepciones inesperadas deben procesarse con un manejador de excepciones.

Probando FORM_SUCCESS, FORM_FAILURE y FORM_FATAL

Al probar FORM_SUCCESS, FORM_FAILURE o FORM_FATAL tenga en cuenta que sus valores pueden ser modificados por un código empotrado en otro evento que se dispara. Por ejemplo, considere el siguiente código:

GO_ITEM('emp.empno');
IF FORM_FAILURE THEN
RAISE FORM_TRIGGER_FAILURE;
END IF;

El GO_ITEM causa otros factores desencadenantes que se disparar, como WHEN-NEW-ITEM-INSTANCE. Aunque el GO_ITEM puede fallar, el último evento disparado puede tener éxito, lo que significa que FORM_FAILURE es falso. El siguiente ejemplo evita este problema.

GO_ITEM('EMP.EMPNO');
IF :SYSTEM.CURSOR_ITEM != 'EMP.EMPNO' THEN
   - No hay necesidad de mostrar un error, porque las formas de Oracle
   - Ya debe haber informado de un error debido a
   - Alguna otra condición que causó el GO_ITEM
   - A fallar.
RAISE FORM_TRIGGER_FAILURE;
END IF;

Evite RAISE_APPLICATION_ERROR

 
No utilice RAISE_APPLICATION_ERROR. Por que entra en conflicto con el esquema utilizado para procesar excepciones del lado del servidor.

Directrices para código SQL

Siga estas directrices para todo código SQL:
  • Utilice " select from DUAL " en vez de " select from SYS.DUAL ". No utilice SYSTEM.DUAL.
  • Todas las declaraciones SELECT deben usar un cursor explícito. Sentencias SELECT implícitos en realidad causan 2 ejecuciones: una para obtener los datos, y una para comprobar si la excepción TOO_MANY_ROWS. Esto se puede evitar utilizando un cursor explícito.
  • Un SELECT que no devuelve ninguna fila lanza la excepción NO_DATA_FOUND. Un INSERT, UPDATE o DELETE que no afecte a ninguna fila no lanza una excepción. Es necesario comprobar explícitamente el valor de SQL% NOTFOUND para comprobar que no dio error en ninguna fila.
  • Para controlar las excepciones NO_DATA_FOUND, se debe escribir un manejador de excepciones. No codificar declaraciones COUNT para detectar la existencia de filas, a menos que esa es su única preocupación.
  • Al comprobar el valor de un campo o variable PL / SQL en un literal, hacer la comprobación en el código PL / SQL, no en una cláusula WHERE. Usted puede ser capaz de evitar que el código SQL este incompleto.
Triggers en Forms

Siga estas reglas generales para disparadores en sus formularios.

Estilo de Ejecución

El "estilo ejecución" para todos los disparadores a nivel de block o en el en un campo debe ser Override o Before. En general utilice el estilo Before .La excepción es si usted tiene una llamada a un  flexfield en el evento POST-QUERY a nivel de formulario, pero se reestablece el estado de consulta del bloque en el evento POST-QUERY a nivel de bloque. En ese caso, el nivel de bloque POST-QUERY debe utilizar Estilo Ejecución Before.

Propiedades de eventos de  teclado (KEY- Trigger Properties)

Establezca la propiedad " Show Keys " a True para todos KEY- triggers de su código, excepto las que está deshabilitando (que debe tener " Show Keys " establecidos en Falso). Ponga siempre la propiedad  " Show Keys Description "  a NULL.

WHEN-CREATE-RECORD en modo Consulta dinámica 


El evento WHEN-CREATE-RECORD se dispara incluso cuando el bloque no permite inserciones. Si tiene lógica en este evento puede que tenga que comprobar si el bloque permite insertar , para verificar si el bloque permite inserciones debe consultar la variable insert-allowed la cual si está en false no dejara insertar información:

IF GET_ITEM_PROPERTY('<BLOCK>', INSERT_ALLOWED) = FALSE THEN

null;
ELSE
<your logic here>;
END IF;

Recursos

En el PC hay un límite en el número de widgets  disponibles  (elementos de texto y elementos de la pantalla no son los widgets reales de Windows, son propios de Oracle Forms ). Cada casilla de verificación, elemento de la lista, y el grupo de objetos en su forma consume estos recursos.

Si un widget  esta sobre un lienzo oculto, los recursos que consume son liberados. Puede liberar recursos ocultando explícitamente un lienzo para que no aparezca en la pantalla. Un lienzo no visible no consume recursos junto con todo los elementos que contiene, hasta que es mostrado en pantalla.

Recuerde que Oracle Forms navega hacia el primer elemento editable cuando se está iniciando la aplicación, esto crea el lienzo y todos sus widgets para el primer bloque de navegación.


Comprobación de la disponibilidad de recursos

Para comprobar la disponibilidad de recursos de MS Windows antes de realizar alguna acción, utilice la siguiente utilidad:

if get_application_property(USER_INTERFACE) =
'MSWINDOWS' then
       if (FND_UTILITIES.RESOURCES_LOW) then
             FND_MESSAGE.SET_NAME('FND', 'RESOURCES_LOW');
                if (FND_MESSAGE.QUESTION('Do Not Open', 'Open','', 1) =1) then
                     raise FORM_TRIGGER_FAILURE;
                end if;
       end if;
end if;

 
Reemplazos en Oracle Forms

Estas normas requieren que ciertos complementos integrados tengan que evitarse por completo, otras rutinas o "envolturas" serán llamadas en su lugar. Para muchos complementos empotrados existen múltiples métodos de invocación. Se puede obtener un comportamiento estándar haciendo uso de los complementos integrados. Para algunos eventos empotrados hay conductas estándar en la Suite de Oracle E-Business que se invoca llamando APP_STANDARD.EVENT.

No utilice CALL_FORM

No utilice este de Oracle Forms:

VariableDescription
CALL_FORMEste metodo es incompatible con OPEN_FORM, que es utilizado por las rutinas de Oracle E-Business Suite.
Debe utilizar FND_FUNCTION.EXECUTE en lugar de cualquier llamada a CALL_FORM u OPEN_FORM siempre que necesite para abrir un formulario mediante programación. La utilización de FND_FUNCTION.EXECUTE le permite abrir formularios sin pasar de lado el api de seguridad de Oracle E-Business Suite, y además se encarga de encontrar la ruta del directorio correcto para el formulario.

 

Oracle Forms Integrados Reemplazados con AppCore
En AppCore existen rutinas equivalentes a las existentes en Oracle Forms, las cuales proporcionan funcionalidad adicional:

VariableDescripción
EXIT_FORMLas formularios de Oracle E-Business Suite tienen un procesamiento especial de salida. No llame directamente a EXIT_FORM; en su lugar siempre llame a do_key ('EXIT_FORM').
Para salir de la totalidad de Oracle E-Business Suite, primero debe convocar:


copy('Y','GLOBAL.APPCORE_EXIT_FLAG');

luego invoque:


do_key('exit_form');
SET_ITEM_ PROPERTYSe debe reemplazar con APP_ITEM_PROPERTY.SET_ PROPERTY y APP_ITEM_PROPERTY.SET_ VISUAL_ATTRIBUTE. Estas rutinas de AppCore establecen las propiedades de forma estándar en Oracle E-Business Suite y cambian el comportamiento de la propagación. Algunas propiedades utilizan el nativo de Oracle Forms SET_ITEM_PROPERTY.
GET_ITEM_ PROPERTYUtilize APP_ITEM_PROPERTY.GET_PROPERTY para obtener propiedades especificas en Oracle E-Business Suite. En otros casos utilize el integrado a Oracle Forms.
OPEN_FORMUtilize FND_FUNCTION.EXECUTE. Esta rutina es necesaria para las funciones de seguridad.
Tanto OPEN_FORM y FND_ FUNCTION.EXECUTE causan los eventos POST-RECORD y POST-BLOCK.
CLEAR_FORMUtilize do_key('clear_form'). Esta rutina lanza la excepción FORM_TRIGGER_FAILURE si existe un registro invalido.
COMMITUtilize do_key('commit_form'). Esta rutina lanza la excepcion FORM_TRIGGER_FAILURE si existe un registro invalido.
EDIT_FIELD/ EDIT_ TEXTITEMUtilize do_key('edit_field'). Esta rutina aumenta el calendario cuando el elemento actual es una fecha.
VALIDATEUtilize APP_STANDARD.APP_VALIDATE. Esta rutina se desplaza hasta cualquier elemento que provoca un fallo de navegación.


Advertencia: APP_STANDARD.APP_VALIDATE requiere cumplir con los estándares de codificación.

 
Codificación de artículos, eventos y Manejadores de Tabla

Es normal utilizar manipuladores de eventos para ejecutar todo el código necesario para validar un artículo o para garantizar el correcto comportamiento en una situación en particular.

Los Manipuladores sirven para centralizar el código por lo que es fácil de leer y trabajar. Una forma típica de realizar esto con un paquete para cada bloque, y un paquete para el propio formulario. 

Coloque el código dentro de los procedimientos (manipuladores) que pertenecen a cada paquete, los cuales tendrán un evento asociado. Cuando un controlador involucra múltiples bloques o responde a nivel de formulario, colóquelo en el paquete del formulario.

Hay diferentes tipos de procedimientos para los diferentes tipos de código, como los manipuladores de elementos, controladores de eventos y manejadores de tablas. La mayor parte del código reside en estos procedimientos, aparte de las llamadas a ellos, usted debe minimizar la utilización de código dentro de los eventos de formulario.

Manipuladores de artículos

Los manipuladores de artículo son procedimientos que contienen toda la lógica utilizada para la validación de un artículo en particular. Un paquete de controlador de elemento contiene todos los procedimientos de validación de los artículos en un bloque o forma.

Los paquetes son generalmente el nombre de su bloque o formulario, mientras que los procedimientos tienen el nombre de su elemento en particular.

Por ejemplo, el bloque EMP incluye los artículos EMPNO, ENAME y Job. El EMP (paquete correspondiente) contiene procedimientos nombrados EMPNO, ENAME, y JOB, por lo que es fácil de localizar el código asociado con un elemento determinado.

Un manejador elemento siempre toma un parámetro llamado EVENTO de tipo VARCHAR2, que suele ser el nombre del disparador llamado por el gestor de artículo.

Argumentos comúnes para Manipuladores de artículo

Los argumentos comunes de los eventos y la lógica asociada son:

VariableDescripción
PRE-RECORDRestablece los atributos de un artículo para un nuevo registro. Típicamente es utilizado por rutinas de APPCORE para habilitar y des-habilitar campos dependientes. También podemos utilizar WHEN-NEW-RECORD-INSTANCE para algunos casos donde se necesario restringirnos a rutinas de Oracle Forms.
INITInicializa el artículo.
VALIDATEValida el articulo y establece los atributos del articulo dinámicamente.

 

El Evento INIT

INIT es la abreviatura de "inicialización" y es una directiva para inicializar el artículo. INIT indica al manejador elemento examinar y restablecer de forma dinámica los valores predeterminados a cada uno de los elementos del formulario. Este evento se espera por muchas rutinas AppCore.

El caso más común es cuando un elemento depende de otro elemento. Cada vez que los elementos maestros cambian en su manejador maestro WHEN-VALIDATE-ITEM el método INIT es llamado.

El Evento VALIDATE

Este seudo-evento se utiliza con muchas rutinas AppCore donde el artículo es validado. Utilice este evento en lugar de WHEN-VALIDATE-ITEM, WHEN-CHECKBOX- CHANGED, WHEN-LIST-CHANGED, o WHEN-RADIO- CHANGED (cualquiera de los cuales podría utilizarse también).

Formato para el controlador de Artículo

Un controlador típico de un artículo tiene el siguiente formato:

procedure ITEM_NAME(event VARCHAR2) IS
            IF (event = 'WHEN-VALIDATE-ITEM') THEN
                  -- validate the item
           ELSIF (event = 'INIT') THEN
                 -- initialize this dependent item
          ELSIF (event in ('PRE-RECORD', 'POST-QUERY')) THEN
                -- etc.
         ELSE fnd_message.debug('Invalid event passed to item_name: ' || EVENT);
         END IF;
END ITEM_NAME;

Consejo: Recuerde que escribir un manejador de artículo no es todo el proceso; también debe codificar un disparador para cada evento que se encarga de llamar al manejador del artículo. Si lo que codificado no está sucediendo, lo primero que debe hacer es comprobar si su controlador es invocado en el evento del artículo.

Codificación de controladores de eventos

Los controladores de eventos encapsulan lógica que se refiere a varios artículos, es más fácil centralizar el código en torno a un evento en lugar de hacerlo de forma individual. Como desarrolladores debemos determinar cuándo un controlador de eventos es más fácil de leer que un conjunto de manipuladores de elementos.

Comportamientos cruzados de artículos muy complejos pertenecen al controlador de eventos, mientras que los comportamientos de un solo artículo pertenecen a los manipuladores de elementos.

Por ejemplo, es posible codificar un controlador de eventos para poblar muchos artículos en POST-QUERY. En lugar de escribir manejadores de elementos para cada uno de los artículos, usted podría encapsular toda la lógica en un solo controlador de eventos.

Desde un controlador de eventos se maneja sólo un evento, que no necesita parámetros. De hecho, no debería tener ningún parámetro.

Los controladores de eventos llevan el nombre de los eventos, sustituyen guiones por subrayado (por ejemplo, el controlador de eventos PRE-QUERY es PRE_QUERY).

Controladores de eventos Comúnes

VariableDescripción
PRE_QUERYRellena los artículos con valores necesarios para recuperar los registros apropiados.
POST_QUERYRellena artículos que no pertenecen a la tabla.
WHEN_CREATE _RECORDRellena los valores por defecto (cuando utilizar la propiedad de valor por defecto es insuficiente)
WHEN_ VALIDATE_ RECORDValida las relaciones complejas inter-elementos.

 

Codificación de Manipuladores de Tabla

Un manejador de tabla es un paquete de servidor o de cliente que proporciona una API para esa tabla. 

Manejadores de tablas se utilizan para insertar, actualizar, eliminar , bloquear un registro o para verificar si un registro de otra tabla hace referencia a un registro en esta tabla.

Dado que la mayoría de los formularios de Oracle E-Business Suite se basan en vista, estos manejadores de tablas son necesarias para manejar las interacciones con las tablas debajo de las vistas.

La siguiente tabla contiene algunos o todos de los siguientes procedimientos para los manipuladores:

VariableDescripción
CHECK_ UNIQUECompruebe si hay valores duplicados en columnas únicas.
CHECK_ REFERENCESCompruebe la integridad referencial
INSERT_ROWInserta una fila en la tabla
UPDATE_ROWActualiza una fila de la tabla
DELETE_ROWElimina una fila de la tabla
LOCK_ROWBloquea una fila en la tabla

 

INSERT_ROW, UPDATE_ROW, DELETE_ROW y LOCK_ROW se utilizan comúnmente para reemplazar en Oracle Forms el procesamiento de transacciones en los eventos ON-INSERT, ON-UPDATE, ON-DELETE, y ON-LOCK.

En el procedimiento controlador INSERT_ROW, si se permite que una columna de clave principal pueda ser NULL, recuerde agregar "OR (primary_key IS NULL AND X_col IS NULL)" a la cláusula WHERE de la instrucción SELECT ROWID.

En el procedimiento controlador LOCK_ROW, si a una columna no se le permite ser NULL, retire la instrucción "OR (RECINFO.col IS NULL AND X_col IS NULL)" de la instrucción condicional IF.

Además, dado que Oracle Forms pone espacios finales a los valores de cada campo consultado. Dado que el procedimiento almacenado LOCK_ROW no elimina los espacios finales, la comparación en este caso (poco frecuente) siempre falla. Usted puede utilizar RTRIM para quitar espacios finales si es necesario.

Interactuando en una segunda tabla

Para realizar una acción en otra tabla, se debe llamar al controlador apropiado de la tabla en lugar de realizar la acción directa.

Por ejemplo, para realizar una eliminación en cascada, llame al manejador DELETE_ROWS de al tabla detalle (que acepta la clave principal del maestro como parámetro) en lugar de realizar el borrar directamente en el controlador DELETE_ROW de la tabla maestra.

Ejemplo Cliente-Side Controlador de Tabla

El siguiente es un ejemplo de un manejador de tablas de cliente que proporciona INSERT_ROW, UPDATE_ROW, DELETE_ROW y procedimientos LOCK_ROW para la tabla EMP. Codificar el manejador de tabla del lado del cliente directamente en su formulario.

Especificaciones del paquete que podría codificar para el bloque EMP

PACKAGE EMP IS


        PROCEDURE Insert_Row;


        PROCEDURE Lock_Row;


        PROCEDURE Update_Row;


        PROCEDURE Delete_Row;


END EMP;


Cuerpo del paquete que podría codificar para el bloque EMP

PACKAGE BODY EMP IS


PROCEDURE Insert_Row IS


        CURSOR C IS
               SELECT
                        rowid
               FROM EMP


               WHERE empno =:EMP.Empno;


BEGIN


INSERT
        INTO EMP(

                            empno,ename,job,mgr,hiredate,sal,
                            comm,deptno
                           )
         VALUES(

                          :EMP.Empno,:EMP.Ename,:EMP.Job,:EMP.Mgr,:EMP.Hiredate,
                          :EMP.Sal,:EMP.Comm,:EMP.Deptno
                         );


OPEN C;

FETCH C INTO
:EMP.Row_Id;

          if(C%NOTFOUND)then
              CLOSE C;

              Raise NO_DATA_FOUND;
          end if;
CLOSE C;
END Insert_Row;


PROCEDURE Lock_Row IS

Counter NUMBER;

CURSOR C IS

                       SELECT empno,ename,job,mgr,hiredate,sal,comm,deptno
                                    FROM EMP
                       WHERE
                                     rowid :EMP.Row_Id

                       FOR UPDATE of Empno NOWAIT;

Recinfo C%ROWTYPE;


BEGIN

     Counter := 0;

LOOP
BEGIN

           Counter := Counter 1;


OPEN C;


FETCH C INTO Recinfo;


        if(C%NOTFOUND)then

              CLOSE C;
              FND_MESSAGE.Set_Name('FND','FORM_RECORD_DELETED');
              FND_MESSAGE.Error;
              Raise FORM_TRIGGER_FAILURE;

       end if;
CLOSE C;
if((Recinfo.empno =:EMP.EmpnoAND ((Recinfo.ename =:EMP.EnameOR ((Recinfo.ename IS NULL) AND (:EMP.Ename IS NULL))) AND ((Recinfo.job :EMP.Job) OR ((Recinfo.job IS NULL) AND (:EMP.Job IS NULL))) AND (Recinfo.mgr =:EMP.MgrOR ((Recinfo.mgr IS NULL) AND (:EMP.Mgr IS NULL))) AND ((Recinfo.hiredate :EMP.HiredateOR ((Recinfo.hiredate IS NULL) AND (:EMP.Hiredate IS NULL))) AND ((Recinfo.sal =:EMP.SalOR ((Recinfo.sal IS NULL) AND (:EMP.Sal IS NULL))) AND ((Recinfo.comm :EMP.CommOR ((Recinfo.comm IS NULL) AND (:EMP.Comm IS NULL))) AND (Recinfo.deptno =:EMP.Deptno))then
      return;
else
         FND_MESSAGE.Set_Name('FND','FORM_RECORD_CHANGED');
         FND_MESSAGE.Error;
         Raise FORM_TRIGGER_FAILURE;
end if;

EXCEPTION When APP_EXCEPTIONS.RECORD_LOCK_EXCEPTION then

IF(C% ISOPEN)THEN

    close C;
END IF;

APP_EXCEPTION.Record_Lock_Error(Counter);

END;

end LOOP;


END Lock_Row;


PROCEDURE Update_Row IS


BEGIN


UPDATE EMP

                       SET empno =:EMP.Empno,
                               ename =:EMP.Ename,
                               job=:EMP.Job,
                               mgr =:EMP.Mgr,
                               hiredate =:EMP.
                               Hiredate,sal =:EMP.Sal,
                               comm =:EMP.Comm,
                               deptno =:EMP.Deptno
                       WHERE rowid=:EMP.Row_Id;


if(SQL%NOTFOUND)then

      Raise NO_DATA_FOUND;
end if;


END Update_Row;


PROCEDURE Delete_Row IS


BEGIN


DELETE  FROM EMP

                 WHERE rowid=:EMP.Row_Id;


if(SQL%NOTFOUND)then

    Raise NO_DATA_FOUND;
end if;


END Delete_Row;

END EMP;

Ejemplo: Controlador de tabla de lado del servidor

El siguiente es un ejemplo de un controlador de tabla del lado del servidor que proporciona métodos INSERT_ROW, UPDATE_ROW, DELETE_ROW y LOCK_ROW para la tabla EMP. Consiste de un paquete en el formulario y un paquete el servidor de base de datos. El paquete del formulario llama el paquete del servidor y pasa todos los valores de campo como argumentos.

Especificaciones del paquete que se podría codificar para el bloque EMP en el Formulario

PACKAGE EMP IS


      PROCEDURE Insert_Row;


      PROCEDURE Update_Row;


      PROCEDURE Lock_Row;


      PROCEDURE Delete_Row;

END EMP;


Cuerpo del paquete que podría codificar para el bloque EMP en el formulario

PACKAGE BODY EMP IS

PROCEDURE Insert_Row IS

BEGIN

          EMP_PKG.Insert_Row(

                                                 X_Rowid =>:EMP.Row_Id,
                                                 X_Empno =>:EMP.Empno,
                                                 X_Ename =>:EMP.Ename,
                                                 X_Job =>:EMP.Job,
                                                 X_Mgr =>:EMP.Mgr,
                                                 X_Hiredate =>:EMP.Hiredate,
                                                 X_Sal =>:EMP.Sal,
                                                 X_Comm =>:EMP.Comm,
                                                 X_Deptno =>:EMP.Deptno);
END Insert_Row;



PROCEDURE Update_Row IS

BEGIN

EMP_PKG.Update_Row(

                                          X_Rowid =>:EMP.Row_Id,
                                          X_Empno =>:EMP.Empno,
                                          X_Ename =>:EMP.Ename,
                                          X_Job =>:EMP.Job,
                                          X_Mgr =>:EMP.Mgr,
                                          X_Hiredate =>:EMP.Hiredate,
                                          X_Sal =>:EMP.Sal,
                                          X_Comm =>:EMP.Comm,
                                          X_Deptno =>:EMP.Deptno);
END Update_Row;



PROCEDURE Delete_Row IS

BEGIN

                    EMP_PKG.Delete_Row(:EMP.Row_Id);

END Delete_Row;



PROCEDURE Lock_Row IS

          Counter Number;

BEGIN

          Counter :=0;
           LOOP   
           BEGIN
                 Counter := Counter +1;

                 EMP_PKG.Lock_Row(
                                                       X_Rowid =>:EMP.Row_Id,
                                                       X_Empno =>:EMP.Empno,
                                                       X_Ename =>:EMP.Ename,
                                                       X_Job =>:EMP.Job,
                                                       X_Mgr =>:EMP.Mgr,
                                                       X_Hiredate =>:EMP.Hiredate,
                                                       X_Sal =>:EMP.Sal,
                                                       X_Comm =>:EMP.Comm,
                                                       X_Deptno =>:EMP.Deptno);

            return;


            EXCEPTION 
When APP_EXCEPTIONS.RECORD_LOCK_EXCEPTION then

               APP_EXCEPTION.Record_Lock_Error(Counter);


            END;


             end LOOP;

END Lock_Row;

END EMP;


Especificaciones del paquete para el manejador de la tabla del lado del servidor (script SQL)

SET VERIFY OFF

DEFINE PACKAGE_NAME="EMP_PKG"

WHENEVER
SQLERROR
EXIT FAILURE ROLLBACK;

CREATE
or
REPLACE
PACKAGE &PACKAGE_NAME as



/* Poner cualquier información de cabecera (como $ Header $) aquí.
Debe ser escrito en la definición del paquete para que el
  información de cabecera estará disponible en el propio paquete.
  Esto hace que sea más fácil identificar versiones de los paquetes durante
  actualizaciones. */




PROCEDURE Insert_Row(

                                             X_Rowid INOUT VARCHAR2,
                                             X_Empno NUMBER,
                                             X_Ename VARCHAR2,
                                             X_Job VARCHAR2,
                                             X_Mgr NUMBER,
                                             X_Hiredate DATE,
                                             X_Sal NUMBER,
                                             X_Comm NUMBER,
                                             X_Deptno NUMBER
                                             );

PROCEDURE Lock_Row(

                                             X_Rowid VARCHAR2,
                                             X_Empno NUMBER,
                                             X_Ename VARCHAR2,
                                             X_Job VARCHAR2,
                                             X_Mgr NUMBER,
                                             X_Hiredate DATE,
                                             X_Sal NUMBER,
                                             X_Comm NUMBER,
                                             X_Deptno NUMBER
                                             );

PROCEDURE Update_Row(

                                               X_Rowid VARCHAR2,
                                               X_Empno NUMBER,
                                               X_Ename VARCHAR2,
                                               X_Job VARCHAR2,
                                               X_Mgr NUMBER,
                                               X_Hiredate DATE,
                                               X_Sal NUMBER,
                                               X_Comm NUMBER,
                                               X_Deptno NUMBER
                                               );




PROCEDURE Delete_Row(X_Rowid VARCHAR2);

END &PACKAGE_NAME;

/

show errors
package &PACKAGE_NAME

SELECT to_date('SQLERROR')
       FROM user_errors

   WHERE name='&PACKAGE_NAME' AND type 'PACKAGE'
/

commit;

exit;

El cuerpo del paquete para el manejador de la tabla del lado del servidor (script SQL)

SET VERIFY OFF

DEFINE PACKAGE_NAME="EMP_PKG"

WHENEVER
SQLERROR
EXIT FAILURE ROLLBACK;

CREATE
or
REPLACE
PACKAGE
BODY &PACKAGE_NAME as



/* Poner cualquier información de cabecera (como $ Header $) aquí.
  Debe ser escrito en la definición del paquete por lo que el
  información de cabecera está disponible en el propio envase.
  Esto hace que sea más fácil identificar versiones de los paquetes durante
  actualizaciones. */


PROCEDURE Insert_Row(

                                             X_Rowid IN OUT VARCHAR2,
                                             X_Empno NUMBER,
                                             X_Ename VARCHAR2,
                                             X_Job VARCHAR2,
                                             X_Mgr NUMBER,
                                             X_Hiredate DATE,
                                             X_Sal NUMBER,
                                             X_Comm NUMBER,
                                             X_Deptno NUMBER
                                             )
IS


CURSOR C IS
                      SELECT rowid FROM emp

                                      WHERE empno = X_Empno;


BEGIN


INSERT
INTO emp(
empno,ename,job,mgr,hiredate,sal,comm,deptno)
VALUES(X_Empno,X_Ename,X_Job,X_Mgr,X_Hiredate,X_Sal,X_Comm,X_Deptno);

OPEN C;


FETCH C INTO X_Rowid;


    if(C%NOTFOUND)then

            CLOSE C;

            Raise NO_DATA_FOUND;
    end if;


CLOSE C;


END Insert_Row;


PROCEDURE Lock_Row(

                                             X_Rowid VARCHAR2,
                                             X_Empno NUMBER,
                                             X_Ename VARCHAR2,
                                             X_Job VARCHAR2,
                                             X_Mgr NUMBER,
                                             X_Hiredate DATE,
                                             X_Sal NUMBER,
                                             X_Comm NUMBER,
                                             X_Deptno NUMBER
                                             )
IS


CURSOR C IS

                       SELECTFROM emp
                        WHERE rowid= X_Rowid
                       FOR UPDATE of Empno NOWAIT;

Recinfo C%ROWTYPE;
BEGIN


OPEN C;


FETCH C INTO Recinfo;

     if(C%NOTFOUND)then
          CLOSE C;

          FND_MESSAGE.Set_Name('FND','FORM_RECORD_DELETED');
          APP_EXCEPTION.Raise_Exception;

     end if;


CLOSE C;


     if(
(Recinfo.empno = X_Empno)AND((Recinfo.ename = X_Ename)OR((Recinfo.ename IS NULL)AND(X_Ename IS NULL)))AND((Recinfo.job= X_Job)OR((Recinfo.job IS NULL)AND(X_Job IS NULL)))AND((Recinfo.mgr = X_Mgr)OR((Recinfo.mgr IS NULL)AND(X_Mgr ISNULL)))AND(
(Recinfo.hiredate = X_Hiredate)OR((Recinfo.hiredate IS NULL)AND(X_Hiredate IS NULL)))AND((Recinfo.sal = X_Sal)OR((Recinfo.sal IS NULL)AND(X_Sal IS NULL)))AND((Recinfo.comm = X_Comm)OR((Recinfo.comm IS NULL)AND(X_Comm IS NULL)))AND(Recinfo.deptno = X_Deptno))then
    return;

else


     FND_MESSAGE.Set_Name('FND','FORM_RECORD_CHANGED');

     APP_EXCEPTION.Raise_Exception;
end if;


END Lock_Row;


PROCEDURE Update_Row(

                                               X_Rowid VARCHAR2,
                                               X_Empno NUMBER,
                                               X_Ename VARCHAR2,
                                               X_Job VARCHAR2,
                                               X_Mgr NUMBER,
                                               X_Hiredate DATE,
                                               X_Sal NUMBER,
                                               X_Comm NUMBER,
                                               X_Deptno NUMBER
                                               )
IS


BEGIN


UPDATE emp

                   SET

                          empno = X_Empno,
                          ename = X_Ename,
                          job= X_Job,
                          mgr = X_Mgr,
                          hiredate = X_Hiredate,
                          sal = X_Sal,
                          comm = X_Comm,
                          deptno = X_Deptno
WHERE
                          rowid= X_Rowid;


if(SQL%NOTFOUND)then

   Raise NO_DATA_FOUND;
end if;


END Update_Row;


PROCEDURE Delete_Row(X_Rowid VARCHAR2)
IS


BEGIN


DELETE
FROM emp


WHERE
rowid
= X_Rowid;


if
(SQL%NOTFOUND)
then


Raise
NO_DATA_FOUND;


end
if;


END Delete_Row;


END &PACKAGE_NAME;

/

show errors package body &PACKAGE_NAME
SELECT to_date('SQLERROR'FROM user_errors
WHERE name='&PACKAGE_NAME' AND type ='PACKAGE BODY'
/

commit;

exit;









Creación de Objetos de Base de Datos en EBS


En esta ocasión hablaremos de cómo crear tablas y adicionar las columnas necesarias.

Uso del Optimizador Cost-Based de Oracle

Oracle E-Business Suite utiliza la Optimización Base-Costo (CBO) en lugar de la de optimización basada en reglas (RBO) utilizada en versiones anteriores. Todo nuevo código debe ser escrito para tomar ventaja de la optimización.

Seguimiento de los cambios con registros históricos (OMS)

La función Historial Record (OMS) reporta información sobre quién creó o actualizo filas en las tablas de Oracle E-Business Suite.
Si agrega columnas especiales de la OMS a las tablas y la lógica de la OMS a los formularios y procedimientos almacenados, los usuarios pueden realizar un seguimiento de los cambios realizados en sus datos. Al observar columnas de la OMS, los usuarios pueden diferenciar entre los cambios realizados por las formas y los cambios realizados por los programas concurrentes.
Usted puede representar cada una de las columnas de OMS como campos ocultos en cada bloque de sus formularios (que corresponden a las columnas de la OMS en cada tabla subyacente). Estos campos son llenados invocando a FND_STANDARD.SET_WHO en los eventos PRE-UPDATE y PRE-INSERT.

Cómo añadir columnas Histórico de Registro

La siguiente tabla muestra las columnas estándar utilizados para Historial (OMS), los atributos de la columna y descripciones, las fuentes de los valores de esas columnas. Establezca las columnas CREATED_BY y CREATION_DATE sólo cuando se inserta una fila (utilizando FND_STANDARD.SET_WHO de un formulario).

Nombre de ColumnaTipoNull?Foreign Key?DescripcionValor
CREATED_BYNUMBER(15)NOT NULLFND_ USERUsuario que creo el registroTO_NUMBER (FND_ PROFILE. VALUE ('USER_ID'))
CREATION_ DATEDATENOT NULL  Fecha de creación de la filaSYSDATE
LAST_ UPDATED_BYNUMBER(15)NOT NULLFND_ USERUsuario que actualizo el registroTO_NUMBER (FND_ PROFILE. VALUE ('USER_ID'))
LAST_UPDATE_ DATEDATENOT NULL  Fecha de la Ultima actualizaciónSYSDATE
LAST_UPDATE_ LOGINNUMBER(15)  FND_ LOGINSProporciona acceso a la información sobre el sistema operativo de inicio de sesión del usuario que la última actualización de cada filaTO_NUMBER (FND_ PROFILE. VALUE ('LOGIN_ ID'))

Cualquier tabla que pueda ser actualizada por un programa concurrente también necesita columnas adicionales. La siguiente tabla muestra las columnas, los atributos de columna, descripciones, y las fuentes de los valores de esas columnas.

Nombre de ComunaTipoNull?Foreign Key to Table?Descripción
REQUEST_IDNUMBER(15)  FND_ CONCURRENT_ REQUESTSID del concurrente con el cual el registro fue credo o actualizado
PROGRAM_ APPLICATION_ IDNUMBER(15)  FND_ CONCURRENT_ PROGRAMSId de programa con el cual el registro fue cread o actualizado
PROGRAM_IDNUMBER(15)  FND_ CONCURRENT_ PROGRAMSId de programa con el cual el registro fue cread o actualizado
PROGRAM_ UPDATE_DATEDATE  PROGRAM_ UPDATE_ DATEFecha de creación o actualización

Utilizar controladores de eventos con el Código de Registro de Historial en los formularios

Algunas operaciones que se deben realizar en el momento de realizar el commit no parecen estar diseñadas para un manejador de tabla. Por ejemplo, los controladores de eventos son preferibles a los manejadores de tablas para establecer información histórica de un registro, o la determinación de un número secuencial. La lógica de estas operaciones se puede almacenar en un PRE_INSERT y / o controlador de eventos PRE_UPDATE, PRE-INSERT y PRE_UPDATE son llamados a nivel de bloque cuando se disparan las inserciones o actualizaciones.

Clases de propiedad para los campos de la OMS

Aplicar la clase de propiedad CREATION_OR_LAST_UPDATE_DATE al campo CREATION_DATE en el formulario y LAST_UPDATE_DATE respectivamente. Estas clases de propiedad establecen los atributos correctos para estos campos, incluyendo el tipo de datos y el 
ancho.

Tablas sin Información Histórica

Para los bloques que están basados en una tabla que no tienen columnas de información Historia, se debe deshabilitar el menú> ABOUT_THIS_RECORD (todos los demás casos se tratan mediante el control de menú por defecto), para ello se debe colcar en el evento WHEN-NEW-BLOQUE-INSTANCIA a nivel de bloque las siguientes líneas:

app_standard.event('WHEN-NEW-BLOCK-INSTANCE');
app_special.enable('ABOUT', PROPERTY_OFF);

Declaración de Restricciones en Oracle

En esta sección trataremos sobre las restricciones y permisos de base de datos y cuando utilizar cada función con las tablas personalizadas dentro de Oracle E-Business Suite.
Cualquier restricción que se asocia con una tabla debe ser duplicada en un formulario para que el usuario recibe retroalimentación inmediata si la restricción es viola.
Advertencia: No debe crear restricciones adicionales sobre las tablas de Oracle E-Business Suite, ya que puede afectar negativamente en las actualizaciones de Oracle E-Business Suite. Si crea limitaciones adicionales, es posible que necesite desactivarlas antes de actualizar Oracle E-Business Suite.

NOT NULL

Utilice siempre que sea apropiado. Declarar los campos correspondientes dentro de las formas de Oracle como "Requerido" = True.

DEFAULT

En general, no use esta función debido a problemas de bloqueo potenciales con Oracle Forms. Es posible que pueda utilizar esta función con las tablas que no son utilizados por las formas (por ejemplo, los utilizados por programas por lotes).

UNIQUE

La restricción "unique" impide la duplicación de claves alternas (no primarias), es decir, especifica que dos registros no puedan tener el mismo valor en un campo. Se permiten valores nulos.
Se pueden aplicar varias restricciones de este tipo a una misma tabla, y pueden aplicarse a uno o varios campos que no sean clave primaria.
Se emplea cuando ya se estableció una clave primaria (como un número de legajo) pero se necesita asegurar que otros datos también sean únicos y no se repitan (como número de documento).
La sintaxis general es la siguiente:

alter table NOMBRETABLA
add constraint NOMBRERESTRICCION
unique (CAMPO);

CHEQUE

La restricción "check" especifica los valores que acepta un campo, evitando que se ingresen valores inapropiados.
La sintaxis básica es la siguiente:

alter table NOMBRETABLA
add constraint NOMBRECONSTRAINT
check CONDICION;

Esto no suele ser un problema, ya que los factores desencadenantes de bases de datos Oracle E-Business Suite raramente deben ser desactivados. Algunos factores desencadenantes (como eventos de alerta) se desactivan antes de una actualización y re-activados al final de la actualización.
Se desaconseja el uso de triggers de base de datos.

PRIMARY KEY

Definir una clave principal para todas las tablas.

Cascade Delete and Foreign Key Constraint

No utilice el declarativa Cascade Delete or the Foreign Key Constraint en la definición de las tablas. Eliminar en cascada no funciona a través de bases de datos distribuidas, por lo que debe programar la lógica de eliminación en cascada.

Para llevar a cabo una verificación de la integridad referencial, cree un / SQL procedimiento almacenado PL que cuyo argumento sea la clave primaria y que lance una excepción si la supresión de la fila podría causar un error de integridad referencial.

LONG, LONG RAW y RAW Datatypes

No utilice estos tipos de datos en su lugar utilice : VARCHAR2(2000) en la declaración de las columnas

Uso de palabras Reservas en Columnas

Si una tabla contiene como nombre de columna una palabra reservada de PL/SQL o de Oracle Forms, se deberá crear una vista sobre esta tabla en la cual se pondrá un alias a estas columnas.

Views

En general, los bloques complejos se basan en las Vistas mientras que los bloques de configuración simples se basan en tablas. Las ventajas de utilizar vistas son:
  • El tráfico de red se reduce al mínimo, porque todas las claves externas se des normalizan en el servidor
  • No es necesario codificar ninguna lógica en POST-QUERY para rellenar los campos que no son de Base de datos
  • No es necesario codificar ninguna lógica en PRE-QUERY para implementar consulta por ejemplo para los campos que no son de base de datos
También debe basar sus listas de valores (LOV) en vistas. Esto le permite centralizar y compartir definiciones LOV. Una vista LOV suele ser más simple que una vista de bloque, ya que incluye menos columnas no normalizadas, y contiene sólo las filas válidas de datos.

Definir vistas para mejorar el rendimiento

Siempre que el rendimiento es un problema y su Tabla tiene las claves externas, debe definir una Vista con el objetivo de mejorar el rendimiento. Las vistas permiten una única sentencia SQL procesar las claves externas, reduciendo análisis sintácticos por el servidor, y reduciendo el tráfico de red.

Definir vistas para Impulsa la modularidad

Cualquier objeto disponible en la base de datos promueve la modularidad y reutilización, porque todo código del lado del cliente o del servidor puede acceder a él.
Las vistas son muy deseables porque:
  • Aceleran el desarrollo, ya que los desarrolladores pueden construir en ella lógica encapsulada
  • Ellas modula rizan código, a menudo lo que significa que una corrección o mejora pueden realizarse en una sola ubicación
  • Reducen el tráfico de red
  • A menudo son útiles para la presentación de informes u otras actividades
  • Pueden ser parcheado con facilidad y de forma centralizada en un sitio de cliente
Cuando no crear una Vista

Si la vista contiene una sola sentencia SQL NO se debería crear una vista.
Si la vista será utilizada por un solo procedimiento almacenado NO se debería crear, ya que esto aumenta la carga de mantenimiento debido a que tanto el código que contiene la sentencia de SQL y la vista debe ser mantenida.

ROW_ID primera columna

La primera columna de la vista debe ser la pseudo-columna ROWID de la tabla raíz, y la vista debe crear un alias a ROW_ID. Su vista, entonces debe incluir todas las columnas de la tabla raíz, incluyendo las columnas de la OMS, y debe des normalizar la información de las claves externas.
Consejo: Sólo tiene que incluir la columna ROWID si la vista es utilizada en un bloque de Oracle Forms. El campo de Oracle Forms correspondiente a la pseudo-columna ROW_ID debe utilizar la clase de propiedad ROW_ID.

Cambiar el Modo Clave (Block Key Mode)


En Oracle Forms, es necesario cambiar la propiedad Modo Clave (Block Key Mode) a "No Actualizable (Non-Updatable)" que no pueden actualizarse y asi de esta forma Fomrs no hara referencia por defecto a ROWID para bloques basados en vista. Especifique a nivel de ITEM la propiedad Clave Primaria (Primary Key) en True.
Por ejemplo, un punto de vista basado en la tabla EMP tiene las columnas row_id, EMPNO, Ename, deptno y DNAME. Establezca la propiedad Tecla de modo de bloque EMP_V a que no pueden actualizarse, y establezca la propiedad de clave principal de EMPNO en True.
Si el bloque se basa en una tabla, el Modo Clave (Block Key Mode) debe ser único.

Código desencadenantes de Inserción, Actualización, eliminación y bloqueo

Si el bloque se basa en una vista, se debe codificar los eventos ON-INSERT, ON-UPDATE ON-DELETE y ON-LOCK para insertar, actualizar, eliminar y bloquear la tabla raíz en lugar de la vista.

Vistas de una sola Tabla

Las Vistas individuales de una sola Tabla no necesitas los factores desencadenantes de inserción, actualización, supresión y bloqueo. El ajuste Modo Clave debe estar en "Unico". Las vistas de una sola tabla no requieren una columna ROW_ID.

Caracteres especiales

No utilice la función CHR () (se utiliza para definir un carácter por su número ASCII) en el lado del servidor. Esto causa problemas con las plataformas de servidor que utilizan EBCDIC, como MVS.

Secuencias

En esta sección trataremos sobre las normas para la creación y el uso de secuencias.

Crear Secuencias de Uso Individual

Use cada secuencia para suministrar valores de identificación únicos para una columna de una tabla.

No limite el alcance de su Secuencias

No debe crear secuencias que se envuelven con la opción CICLO o que tienen un MAXVALUE especificado. El rango total de la secuencia es tan grande que los límites superiores realista nunca se encuentran.

En general, no diseñar secuencias que se envuelven o tengan rangos limitados.

Tipo de Datos Para Almacenar Secuencias

Utilice un tipo de datos NUMBER para almacenar valores de secuencia dentro de PL / SQL.

No utilice la Tabla FND_UNIQUE_IDENTIFIER_CONTROL

No confíe en la tabla FND_UNIQUE_IDENTIFIER_CONTROL para suministrar valores secuenciales. Utilice una secuencia o en su lugar el paquete de numeración secuencial. La tabla FND_UNIQUE_IDENTIFIER_CONTROL es obsoleta y no debe tener ninguna fila para los objetos de su producto.

Además, no cree versiones específicas de la aplicación de la tabla FND para reemplazar la tabla FND_UNIQUE_IDENTIFIER_CONTROL.

API para el Registro de Tablas

Usted puede registrar sus tablas de aplicaciones personalizadas mediante una rutina de PL / SQL utilizando el paquete AD_DD.

Flexfields y Alerta Oracle son las únicas características o productos que dependen de esta información. Por lo tanto, sólo es necesario registrar esas tablas (y todas sus columnas) que se utilizarán con flexfields o Alerta Oracle.

También puede utilizar la API AD_DD para eliminar el registro de la tablas y columnas de Oracle Application Object Library , en caso de que más tarde tenga que modificar las tablas.

Si altera la tabla más adelante, entonces tiene que modificar el registro de la tabla dentro del EBS. Para modificar un registro primero debe eliminar el registro, a continuación volver a registrar la tabla o columna. Primero de debe eliminar el registro columna, luego el registro de la tabla.


Debe incluir las llamadas a las rutinas de registro de tabla en una secuencia de comandos PL / SQL. Aunque creamos nuestras tablas en nuestro propio esquema de aplicación, debemos ejecutar los procedimientos AD_DD contra el esquema APPS. Se debe confirmar los cambios para que tomen efecto.


El API AD_DD no comprueba la existencia de la tabla registrada o columna en el esquema de base de datos, pero sólo actualiza las tablas de AOL requeridos. Debe asegurarse de que existen las tablas y columnas registradas en realidad y tienen el mismo formato que el definido mediante la API AD_DD.


Procedimientos en el paquete AD_DD

procedure register_table (
                                         p_appl_short_name in varchar2
                                         p_tab_name in varchar2
                                         p_tab_type in varchar2
                                         p_next_extent in number default 512
                                         p_pct_free in number default 10
                                         p_pct_used in number default 70);

procedure register_column(
                                           p_appl_short_name in varchar2,
                                           p_tab_name in varchar2,
                                           p_col_name in varchar2,
                                           p_col_seq in number,
                                           p_col_type in varchar2,
                                           p_col_width in number,
                                           p_nullable in varchar2,
                                           p_translate in varchar2,
                                           p_precision in number default null,
                                           p_scale in number default null);

procedure register_primary_key(
                                                     p_appl_short_name in varchar2,
                                                     p_key_name in varchar2,
                                                     p_tab_name in varchar2,
                                                     p_description in varchar2,
                                                     p_key_type in varchar2,
                                                     p_audit_flag in varchar2,
                                                     p_enabled_flag in varchar2);

procedure update_primary_key(
                                                   p_appl_short_name in varchar2,
                                                   p_key_name in varchar2
                                                   p_tab_name in varchar2,
                                                   p_description in varchar2 default null,
                                                   p_key_type in varchar2 default null,
                                                   p_audit_flag in varchar2 default null,
                                                   p_enabled_flag in varchar2 default null);

procedure register_primary_key_column(
                                                                  p_appl_short_name in varchar2,
                                                                  p_key_name in varchar2,
                                                                  p_tab_name in varchar2,
                                                                  p_col_name in varchar2,
                                                                  p_col_sequence in number);

procedure delete_primary_key_column(
                                                                p_appl_short_name in varchar2,
                                                                p_key_name in varchar2,
                                                                p_tab_name in varchar2,
                                                                p_col_name in varchar2 default null);

procedure delete_table(
                                     p_appl_short_name in varchar2,
                                     p_tab_name in varchar2);

procedure delete_column(
                                         p_appl_short_name in varchar2,
                                         p_tab_name in varchar2,
                                         p_col_name in varchar2);


VariableDescription
p_appl_short_ nameEl nombre corto de la aplicación propietaria de la tabla(por lo general la aplicación personalizada).
p_tab_nameEl nombre de la tabla (en letras mayúsculas).
p_tab_typeUse 'T' si es una tabla de transacciones (casi todas las tablas de aplicación), o 'S' para una tabla "datos semilla" (utilizado sólo por Oracle productos E-Business Suite).
p_pct_freeEl porcentaje de espacio de cada uno de los elementos de la tabla, reservada para futuras actualizaciones de la tabla (1-99). La suma de p_pct_free y p_pct_used debe ser inferior a 100.
p_pct_usedPorcentaje mínimo de espacio utilizado en cada uno de los elementos de la tabla (1-99). La suma de p_pct_free y p_pct_used debe ser inferior a 100.
p_col_nameEl nombre de la columna (en letras mayúsculas).
p_col_seqEl número de secuencia de la columna en la tabla (el orden en que la columna aparece en la definición de la tabla).
p_col_typeEl tipo de columna ('NUMBER', 'VARCHAR2', 'DATE', etc.).
p_col_widthEl tamaño de la columna (un número). Utilice 9 de columnas de tipo DATE, 38 para las columnas numéricas (a menos que tenga un ancho específico).
p_nullableUtilice 'N' si la columna es obligatorio o 'Y' si la columna permite valores nulos.
p_translateUse 'Y' si los valores de las columnas serán traducidos para un lanzamiento de productos de Oracle E-Business Suite (utilizado sólo por Oracle productos E-Business Suite) o 'N' si los valores no están traducidos (la mayoría de las columnas de la aplicación).
p_next_extentEl siguiente tamaño de extensión, en kilobytes. No incluya la 'K'.
p_precisionEl número total de dígitos de un número.
p_scaleEl número de dígitos a la derecha del punto decimal en un número.


Ejemplo del uso del paquete AD_DD
He aquí un ejemplo de cómo utilizar el paquete AD_DD para registrar una Tabla flexfield y sus columnas:
--REGISTRAMOS LA TABLA
execute ad_dd.register_table('FND','CUST_FLEX_TEST','T',8,10,90);

--REGISTRAMOS SUS COLUMNAS
execute ad_dd.register_column('FND','CUST_FLEX_TEST','APPLICATION_ID',1,'NUMBER',38,'N','N');

execute ad_dd.register_column('FND','CUST_FLEX_TEST','ID_FLEX_CODE',2,'VARCHAR2',30,'N','N');

execute ad_dd.register_column('FND','CUST_FLEX_TEST','LAST_UPDATE_DATE',3,'DATE',9,'N','N');

execute ad_dd.register_column('FND','CUST_FLEX_TEST','LAST_UPDATED_BY',4,'NUMBER',38,'N','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','UNIQUE_ID_COLUMN',5,'NUMBER',38,'N','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','UNIQUE_ID_COLUMN2',6,'NUMBER',38,'N','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','SET_DEFINING_COLUMN',7,'NUMBER',38,'N','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','SUMMARY_FLAG',8,'VARCHAR2',1,'N','N');

execute ad_dd.register_column('FND','CUST_FLEX_TEST','ENABLED_FLAG',9,'VARCHAR2',1,'N','N');

execute ad_dd.register_column('FND','CUST_FLEX_TEST','START_DATE_ACTIVE',10,'DATE',9,'N','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','END_DATE_ACTIVE',11,'DATE',9,'N','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','SEGMENT1',12,'VARCHAR2',60,'Y','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','SEGMENT2',13,'VARCHAR2',60,'Y','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','SEGMENT3',14,'VARCHAR2',60,'Y','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','SEGMENT4',15,'VARCHAR2',60,'Y','N');


execute ad_dd.register_column('FND','CUST_FLEX_TEST','SEGMENT5',16,'VARCHAR2',60,'Y','N');

Bueno amigos eso es todo, gracias.








File sharing system in PHP free code (Veno File Manager v4.2.7)

  File sharing system in PHP free code (Veno File Manager v4.2.7) Download: veno-file-manager-v427 File sharing system in PHP free code ===...