miércoles, 11 de mayo de 2016

Parámetro de entrada y salida – PL/SQL

Parámetro de entrada y salida – PL/SQL:
Los parámetros de entrada y salida no son los parámetros de inicialización de la base de datos ORACLE. Los parámetros de entra y salida son utilizados mayormente en implementaciones de funciones, procedimientos almacenados o bloques de código bajo el lenguaje del PL/SQL, se considera que ambos parámetros (entra y salida) puedan realizar operaciones en el mismo bloque PL/SQL, es decir, si enviamos un parámetro de entrada hará que cumpla cierta operación y retornara los valores de salida de dicha operación procesada de acuerdo al parámetro de ingresado. Es de acuerdo al caso que nos presenta en la implementación.
Algo importante al definir los parámetros, es saber y considerar cuántos tipos de parámetro existe si solo hablamos de entrada y salida, en realidad mi determinación seria 3 tipos:

Parámetros:

IN – entrada
OUT – salida
IN OUT – entrada salida

Parámetro IN – entrada:
El comportamiento común de estés tipos de parámetros es estar siempre pendiente de recibir un dato para ser procesada según él dato. Acepta valores por defectos haciendo uso del operador de asignación (:=) o utilizando la palabra reservada DEFAULT.

Parámetro OUT – salida:
Los parámetros de salida inicialmente arrancan como NULL, es decir al iniciar el proceso el parámetro estará como nulo o en todo caso, puede tomar un valor inicial y ser cambio durante la ejecución del proceso; y al finalizar el proceso se encarga de tomar o asignar el último valor al parámetro de salida.

Parámetro IN OUT – entrada salida:
Los parámetros de entra salida comúnmente cumplen las 2 funcionalidades arriba mencionadas con la diferencia de que si no defines un valor de entra te retornará el valor nulo o según la condición del proceso que está realizando (Ver el ejemplo, líneas abajo) o caso contrario mostrará el valor de entrada según definido inicialmente.

Ejemplo:

Para el siguiente ejemplo planteare el siguiente caso:
Nos piden mostrar los registros EMPLOYEE_ID, MANAGER_ID, DEPARTMENT_ID de cualquiera de los empleados según el EMPLOYEEID, así mismo, debemos mostrar el campo DEPARTMENT_NAME sólo cuando el DEPARTMENT_ID sea igual a 50; además nos piden mostrar la fecha actual de ejecución del proceso y mostrar opcionalmente el mes actual en texto o en todo caso mostrara el mensaje definido - MES NO DEFINIDO (cuando el parámetro sea vacío u otro mes diferente al actual).
/*Se recomienda leer y considerar todos los comentarios detallados, 
  para su mayor entendimiento de la solución del caso propuesto */
CREATE OR REPLACE PROCEDURE Demo_DataInOutEmployees(
  --Parámetro de 
  p_EMPLOYEEID        IN NUMBER,--Entrada
  pou_EMPLOYEE_ID     OUT EMPLOYEES.EMPLOYEE_ID%TYPE,--Salida
  pou_MANAGER_ID      OUT EMPLOYEES.MANAGER_ID%TYPE,--Salida   
  pou_DEPARTMENT_ID   OUT EMPLOYEES.DEPARTMENT_ID%TYPE,--Salida  
  pou_DEPARTMENT_NAME OUT DEPARTMENTS.DEPARTMENT_NAME%TYPE,--Salida
  pou_DAY_CONSULT     OUT DATE,--Salida
  pou_MONTH_TEXT      IN OUT VARCHAR2--Entrada Salida
)
AS
BEGIN
      --@1 Inicio primer bloque - Recuperar datos de la tabla employees
      BEGIN
        pou_EMPLOYEE_ID :=100;--Por default, pero, puede ser cambando según el 
                              --proceso (según el select que nos retorna) 
        SELECT EMPLOYEE_ID, 
              MANAGER_ID,   
              DEPARTMENT_ID,
              SYSDATE(),
              CASE 
                  --WHEN TO_CHAR(TO_DATE('11/05/2016'),'MM') = '05' THEN 'MAYO'
                  --La condición del proceso a realizar es, que sí ingresamos 05 (referencia 
                  --al mes de MAYO) nos debería pintar como respuesta MAYO, caso contrario el
                  --mensaje NO ES EL MES ACTUAL
                  WHEN TO_CHAR(TO_DATE('11/05/2016'),'MM') = pou_MONTH_TEXT THEN 'MAYO'
                  ELSE 'MES NO DEFINIDO' END MES
        INTO  pou_EMPLOYEE_ID,
              pou_MANAGER_ID,
              pou_DEPARTMENT_ID,
              pou_DAY_CONSULT,
              pou_MONTH_TEXT
        FROM EMPLOYEES WHERE EMPLOYEE_ID = p_EMPLOYEEID;
      EXCEPTION
        WHEN no_data_found THEN
          pou_EMPLOYEE_ID:=NULL;
          pou_MANAGER_ID:=NULL;
          pou_DEPARTMENT_ID:=NULL;
      END;
      --@1 Final primer bloque - Recuperar datos de la tabla employees
      
      --@2 Inicio segundo bloque - Recuperar el DEPARTMENT_NAME. 
      --Solo sí el pou_DEPARTMENT_ID sea 50, caso contrario devolver CERO (0).
      --Considerando: Que sí el pou_DEPARTMENT_ID sea 50 y no se encuentra data
      --el parametro de salida devolvera null
      BEGIN
        if (pou_DEPARTMENT_ID = 50) THEN
            BEGIN
              SELECT  DEPARTMENT_NAME
              INTO    pou_DEPARTMENT_NAME
              FROM    DEPARTMENTS WHERE DEPARTMENT_ID=pou_DEPARTMENT_ID;
            EXCEPTION
              WHEN no_data_found THEN
                pou_DEPARTMENT_NAME:=NULL;--Null, no hay data a pesar de ser pou_DEPARTMENT_ID = 50
            END;
        ELSE
          begin
            pou_DEPARTMENT_NAME:=0;--0, diferente - pou_DEPARTMENT_ID != 50
          end;
        end if;
      end;      
      --@2 Inicio segundo bloque - Recuperar el DEPARTMENT_NAME- 
      
      --Pasar los datos recuperados a los parámetros de tipo OUT - Salida
      pou_EMPLOYEE_ID     :=pou_EMPLOYEE_ID;
      pou_MANAGER_ID      :=pou_MANAGER_ID;
      pou_DEPARTMENT_ID   :=pou_DEPARTMENT_ID;
      pou_DEPARTMENT_NAME :=pou_DEPARTMENT_NAME;
      pou_DAY_CONSULT     :=pou_DAY_CONSULT;
      pou_MONTH_TEXT      :=pou_MONTH_TEXT;
END Demo _DataInOutEmployees;

Consideración:
La palabra reservada para la implementación de parámetros de entrada es IN y se declara en la cabecera o al principio de una función, procedimiento almacenado o bloque acompañado de un tipo de dato, no se considera la longitud de data (ejemplo – varchar2(50), numeric(5)… no es considerado). Las mismas consideraciones se tienen con los parámetros OUT e IN OUT.

miércoles, 4 de mayo de 2016

Convertir expresión con TO_NUMBER - PL/SQL

Función TO_NUMBER():
Se encarga de convertir una expresión (expr) en un valor de tipo de dato NUMBER. Es decir el valor de la expresión (expr) puede ser un valor de tipo de dato  CHAR, VARCHAR2, NCHAR, NVARCHAR2 o BINARY_DOUBLE.

Sintaxis.

TO_NUMBER(expr [, fmt [,nlsparam ] ])

Ejemplo:

Convertir la expresión de tipo de dato VARCHAR2, haciendo uso de la función TO_NUMBER().
DECLARE
      pVARCHAR2 VARCHAR2(50) := '59300.65';--Considerar la cantidad de enteros y decimales en la entrada de datos, es decir si
                                                    --la entrada contiene 5 enteros y 2 decimales (ejemplo - 59300.65 cincuenta y nueve mil 
                                                    --trecientos con sesenta y cinco), nuestro dato de salida debe soporta la longitud de
                                                    --5 enteros y 2 decimas (ejemplo de retorno, '99999.99')
      pNUMBER NUMBER ;
      pNUMBER2 NUMBER; 
BEGIN           
      pNUMBER := TO_NUMBER(pVARCHAR2,'999999999999999999.99');--Incluye los decimales... ejmplo 59300,65
      pNUMBER2:= TO_NUMBER(pVARCHAR2,'999999999999999999D99');--Excluye los decimales...  ejemplo 5930065       
      
      DBMS_OUTPUT.PUT_LINE('Conversion usando punto : ' || pNUMBER);
      DBMS_OUTPUT.PUT_LINE('Conversion usando la letra D : ' || pNUMBER2);
END;
Para poder convertir una expresión en cualquier parte de nuestra implementación sería lo optimo crear una función que realice todo esta conversión, y hacer referencia a dicha función creada.
CREATE OR REPLACE FUNCTION FN_FORMATEO_EXPRESION(
       pVARCHAR2 IN VARCHAR2
) 
RETURN NUMBER IS
  pNUMBER NUMBER;
BEGIN
  pNUMBER := TO_NUMBER(pVARCHAR2 ,'99999999999.99');
  
  RETURN pNUMBER ;
END FN_FORMATEO_EXPRESION;

Validar la función creada:
SELECT MI_ESQUEMA.FN_FORMATEO_EXPRESION('59300.65') FROM DUAL;
Consideraciones:
- Puedes especificar una expresión de tipo BINARY_FLOAT. Sin embargo, no tiene relevancia en hacerlo porque un tipo float solo puede ser interpretado por su presentación interna.
- No es compatible con los datos CLOB directamente. Sin embargo, CLOB se pueden pasar como argumentos a través de la conversión de datos implícita.
- El argumento nlsparam, en esta función tiene el mismo propósito que en la función TO_CHAR(). Además puedes dar el formato (fmtde la mascará haciendo uso de la función TO_CHAR().
- La función NVL() se puede utilizar a partir de Oracle 10g y Oracle 11g.