Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Oracle
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 14-12-2021
jofemalo73 jofemalo73 is offline
Registrado
 
Registrado: dic 2021
Posts: 2
Poder: 0
jofemalo73 Va por buen camino
Llamar a una función/procedimiento de BBDD desde Delphi

Buenas,

Al final me he decidido por este hilo, espero no haberme equivocado.

- Oracle Database 11g Release 11.2.0.4.0 - 64bit Production
- Delphi Versión 7 (Build 4.453)

Tengo un paquete de base de datos donde he definido varias funciones, las funciones devuelven un tipo personalizado.
Este tipo personalizado se encuentra en la sección de la especificación del paquete de Oracle.

Código SQL [-]
  -- Estructura Operación
  TYPE TOperacion IS RECORD 
      (operacion_id        acceso.via_operacion.ope_id%TYPE,                       -- Identificador de la Operación.
       operacion_desc      acceso.via_operacion.ope_descripcion%TYPE,              -- Descripción de la Operación.
       valor               acceso.via_valor.val_id%TYPE);                          -- Valor de la Operación (0:Sin permiso - 1:Con permiso).

  TYPE TaTOperacion IS TABLE OF TOperacion INDEX BY PLS_INTEGER;
  

  -- Estructura Criterio
  TYPE TCriterio IS RECORD 
      (criterio_id         acceso.via_criterio.cri_id%TYPE,                        -- Identificador del Criterio.
       criterio_desc       acceso.via_criterio.cri_descripcion%TYPE,               -- Descripción del Criterio.
       operacion           TaTOperacion);                                          -- Lista de operaciones asociadas al Criterio.       

  TYPE TaTCriterio IS TABLE OF TCriterio INDEX BY PLS_INTEGER;
  
  
  -- Estructura Permisos
  TYPE TPermisos IS RECORD 
      (usuario             acceso.usuarios.nusuario%TYPE,                          -- Identificador del usuario.
       usuario_desc        acceso.usuarios.desusu%TYPE,                            -- Nombre del usuario.
       servicio_id         acceso.area.area%TYPE,                                  -- Identificador del Servicio.
       servicio_desc       acceso.area.texto%TYPE,                                 -- Descripción del Servicio.
       puesto_id           acceso.rh_puestos_trabajo.ptr_puesto%TYPE,                -- Identificador del Puesto.
       puesto_desc         acceso.rh_puestos_trabajo.ptr_descripcion%TYPE,           -- Descripción del Puesto.
       criterio            TaTCriterio);                                           -- Lista de criterios.


Existe una función que devuelve un tipo TPermisos, debido al fracaso (que ahora comentaré), convertí esta función en un procedimiento donde uno de los parametros fuera de salida y del tipo TPermisos.

Desde Delphi he intentado llamar a la función y al procedimiento, sin exito.

He usado el componente TOraStoredProc (este es un ejemplo pero he hecho varias pruebas distintas):

Código SQL [-]
  OraStoredProc1.StoredProcName := 'ACCESO.PCK_VISIBILIDAD_ACCESO.PRC_PERMISO';   // FNC_PERMISO
  OraStoredProc1.Params.CreateParam(ftInteger, 'pi_usuario', ptinput);
  OraStoredProc1.Params.CreateParam(ftADT, 'po_permiso', ptoutput);  // ftUnknown  // ftReference // ftArray // ftTypedBinary // ftCursor // ftVariant
  OraStoredProc1.Prepare;
  OraStoredProc1.ParamByName('pi_usuario').Value := 322;
  OraStoredProc1.Execute;

¿Cual es el problema?
En el primer parámetro de CreateParam se define el tipo del parámetro, y el tipo viene definido por TFieldType.

Código SQL [-]
  TFieldType = (ftUnknown, ftString, ftSmallint, ftInteger, ftWord,
    ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime,
    ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic, ftFmtMemo,
    ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar, ftWideString,
    ftLargeint, ftADT, ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob,
    ftVariant, ftInterface, ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd);

No consigo encontrar la forma de encontrar un tipo que se trague la estructura que he definido en la especificación del paquete de Oracle.
"El error que da es que el número de argumentos o tipo es erroneo".
El número de argumentos no es, hay dos parámetros, uno de entrada y otro de salida, el tipo del primero es ftInteger, y el tipo del segundo ... he probado con varios tipos y nada.

No sé si se os ocurre como hacerlo o si lo hariais de otra manera.

Espero haberme explicado, si no ha quedado claro preguntarme que intentaré ser más claro.

Gracias de antemano.
Responder Con Cita
  #2  
Antiguo 14-12-2021
cloayza cloayza is offline
Miembro
 
Registrado: may 2003
Ubicación: San Pedro de la Paz, Chile
Posts: 933
Poder: 23
cloayza Tiene un aura espectacularcloayza Tiene un aura espectacular
Estimado jofemalo73: En primer lugar no soy experto en Oracle, pero a su comentario...

Cita:
No consigo encontrar la forma de encontrar un tipo que se trague la estructura
Creo que no lo encontrará.

En una primera revisión lo que se ocurre es que genere una consulta/vista/procesimiento almacenado, que le devuelva lo siguiente:
Código SQL [-]
SELECT 
  U.usuario             -- Identificador del usuario.
  U.usuario_desc           -- Nombre del usuario.

  A.servicio_id            -- Identificador del Servicio.
  A.servicio_desc          -- Descripción del Servicio.

  P.puesto_id              -- Identificador del Puesto.
  P.puesto_desc            -- Descripción del Puesto.

  C.criterio_id            -- Identificador del Criterio.
  C.criterio_desc          -- Descripción del Criterio.

  O.operacion_id           -- Identificador de la Operación.
  O.operacion_desc         -- Descripción de la Operación.
  O.valor                  -- Valor de la Operación (0:Sin permiso - 1:Con permiso).

FROM acceso.usuarios U
     inner join acceso.area               A on (A.Campo_Enlace=U.Campo_Enlace)
     inner join acceso.rh_puestos_trabajo P on (P.Campo_Enlace=A.Campo_Enlace)
     inner join acceso.via_criterio       C on (C.Campo_Enlace=P.Campo_Enlace)
     inner join acceso.via_operacion      O on (O.Campo_Enlace=C.Campo_Enlace)
where (U.Usuario= : pi_usuario)

Suponiendo que existe un componente TOraSQL
Código Delphi [-]
   OraQuery.SQL.Text:='Sentencia indicada mas arriba';
   OraQuery.ParamByName('pi_usuario').Value := 322;
   OraQuery.Open;

  while not OraQuery.Eof do
  begin
         ... 
         OraQuery.Next;
  end;
  OraQuery.Close;

Espero mi comentario le ayude, Saludos cordiales
Responder Con Cita
  #3  
Antiguo 14-12-2021
jofemalo73 jofemalo73 is offline
Registrado
 
Registrado: dic 2021
Posts: 2
Poder: 0
jofemalo73 Va por buen camino
Hola Cloayza,

muchas gracias por su rápida y trabajada respuesta.

Le comento, llegué a una solución en la que no fui consciente de ella hasta que la probé.

El procedimiento del que he hablado antes basicamente lo que hace es ejecutar una consultar y alimentar la estructura que luego paso por parámetro.

Cambié el tipo del parámetro de salida (p_permiso), de tipo TPermisos por SYS_REFCURSOR, de manera que la función abría una consulta donde volcaba el contenido en dicho parámetro:

Código SQL [-]
    
OPEN p_Permiso FOR
     SELECT ...
       FROM ...
      WHERE ...
      ORDER BY ...;


Desde Delphi al llamar al procedimiento con el componente TOraStoredProc funcionó sin problemas, hice una lectura de cada una de los registros y alimente una estructura Type Record en Delphi. Fue un momento agridulce porque me di cuenta de la tontería que estaba haciendo en ese momento. Me di cuenta que para eso, la consulta que ejecutaba en el procedimiento del paquete almacenado podía ejecutarla desde Delphi y alimentar la estructura Type Record definida en Delphi.

Me parece más óptimo y más "limpio" llamar al procedimiento y que me devuelva lo que quiero, ya que no hay lógica de negocio, es obtener una foto de lo que hay en BBDD en un momento dado, y la idea es que a este paquete se acceda desde distintas aplicaciones, ya que van a limitar el acceso a los expedientes.

La solución que me ofreces es correcta y la que me imagino que al final usaré. Crearé una Unit de Delphi con las funciones que he definido en el paquete, y con la estructura Type Record creada en la misma Unit, añadiré la directiva {$WEAKPACKAGEUNIT ON} para poderla usar en todas las aplicaciones.

Investigaré un poco más a ver si consigo dar con otra solución. Si la encuentro la comentaré.

Muchas gracias por su ayuda Cloayza.
Saludos .
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Llamar función desde una DLL en Delphi freynoso Varios 2 31-10-2017 15:59:09
Como llamar a una función de BD desde delphi strelok Conexión con bases de datos 3 06-10-2017 12:46:51
Cómo llamar procedimiento almacenado desde delphi con Servidor DataSnap. novato_erick Conexión con bases de datos 2 14-11-2012 19:29:48
Como mandar llamar un procedimiento almacenado desde delphi richy08 MS SQL Server 1 03-02-2010 02:06:23
Ayuda, como llamar a un procedimiento desde otro procedimiento? Ariatna Varios 1 01-02-2005 05:05:35


La franja horaria es GMT +2. Ahora son las 01:21:13.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi