Jump to content


Photo

Consultas con 2 Bases de Datos Distintas


  • Please log in to reply
11 replies to this topic

#1 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 posts

Posted 06 June 2012 - 04:54 AM

Hola amigos, el novato aquí de nuevo perdido...  :D

Estuve mirando que para poder hacer consultas del mismo servidor Firebird (utilizo la versión 2.5.1.26351) pero con dos Bases de Datos distintas.
No puedo exportar los datos a una tabla de mi estructura inicial porque esa otra base de datos es alimentada pro un otro sistema que no es el mío y quieren tener los datos actualizados.
Estuve leyendo que a partir de la versión 2.5 utilizando EXECUTE STATEMENT se podría hacer ese tipo de consultas. Pero la verdad no tengo ni idea de como hacer ese procedure y despues pillar el resultado de esa consulta e trabajar con ella en Delphi 7.
Alguien me podría ayudar a esclarecer como unir esas partes a partir de su experiencia personal ?

Abrazos.
  • 0

#2 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 06 June 2012 - 06:56 AM

Hola.

Nunca lo he hecho, pero no se ve demasiado difícil.

Solo tienes que hacer un procedimiento almacenado que devuelva esa consulta. Ese procedimiento almacenado tendrá un bucle del tipo FOR SELECT *** para especificar cada registro a devolver. Pues bien, dentro de ese bucle FOR tienes que ejecutar el comando EXECUTE STATEMENT conectado a la segunda base de datos, para recuperar la información relacionada a ese registro.

Si eres un poco más concreto indicando en que parte no sabes continuar, intentaremos ayudarte.

Saludos.
  • 0

#3 fredycc

fredycc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 874 posts
  • LocationOaxaca, México

Posted 06 June 2012 - 07:47 AM

Yo lo usé en algunas pruebas que hice de esta características de Firebird para comprobar su efectividad y/o alcances, en resumen lo que buscaba era, tener en una base solo documentos (Fotografias,documentos digitalizados, etc) con su respectivo Id por su puesto y en otra solo los datos y demás tablas con la finalidad de reducir tiempos de respaldo pues eran blobs de tamaño considerable así que con un sp al momento de consultar los datos de un cliente, este mismo sp, me devolvía datos y fotografía(en otra base) lo que me resulto de mucha utilidad. Un ejemplo básico sería algo así:


EXECUTE BLOCK
  RETURNS (SKU INT, NOMBRE VARCHAR(50))
AS
  DECLARE DB VARCHAR(255);
BEGIN
    --Ubicación de la base datos externa
    DB = 'C:\USERS\FREDY\DOCUMENTS\DB\FB\TF.FDB';

    FOR EXECUTE STATEMENT
      'SELECT SKU, NOMBRE
      FROM PRODUCTO'
      ON EXTERNAL :DB
      AS USER CURRENT_USER PASSWORD 'masterkey' -- Nombre de Usuario y Contraseña del servidor local o remoto
      WITH COMMON TRANSACTION
      INTO :SKU, :NOMBRE
    DO SUSPEND;

END


Puedes buscar más info aquí http://dfp.firebirdt...-exctstmnt.html

Saludos
  • 0

#4 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 posts

Posted 06 June 2012 - 08:36 AM

Gracias por los aportes, voy probar sobre el código que amablemente fredycc ha proporcionado hacer lo que al final toca. Si lo logro lo meto por aquí, si no os vengo a atormentar de nuevo !!! :D
  • 0

#5 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 posts

Posted 07 June 2012 - 02:26 AM

Hola amigos,
Con lo que me habéis aportado ya soy capaz de sacar los datos que me interesan con la siguiente procedure:


delphi
  1. EXECUTE BLOCK RETURNS (CLI_ID INT, CLI_NIF VARCHAR(20), CLI_NOMBRE VARCHAR(50),
  2. CLI_EMAIL VARCHAR(50), CLI_CODIGOBANCO VARCHAR(10), CLI_CODIGOSUCURSAL VARCHAR(10),
  3. CLI_NUMEROCUENTA VARCHAR(15), CLI_DIGITOCONTROL VARCHAR(2), CLI_CONTACTO VARCHAR(50),
  4. DIR_DIRECCION VARCHAR(50), DIR_CP VARCHAR(10), DIR_POBLACION VARCHAR(40),
  5. DIR_TELEFONO1 VARCHAR(15), DIR_TELEFONO2 VARCHAR(15), PRV_NOMBRE VARCHAR(50))
  6. AS
  7.   DECLARE DB VARCHAR(255);
  8. BEGIN
  9.     DB = 'localhost:D:\bases_datos\Datos_Clientes.BD';
  10.  
  11.     FOR EXECUTE STATEMENT
  12.         'select CLI_ID, CLI_NIF, CLI_NOMBRE, CLI_EMAIL, CLI_CODIGOBANCO, CLI_CODIGOSUCURSAL,
  13.         CLI_NUMEROCUENTA, CLI_DIGITOCONTROL, CLI_CONTACTO, DIR_DIRECCION,
  14.         DIR_CP, DIR_POBLACION, DIR_TELEFONO1, DIR_TELEFONO2, PRV_NOMBRE
  15.         from CLIENTE
  16.         left join DIRECCION on CLI_ID=DIR_IDPROPIETARIO
  17.         left join PROVINCIA on PRV_ID=DIR_IDPROVINCIA
  18.         order by CLI_ID'
  19.         ON EXTERNAL DATA SOURCE:DB
  20.         AS USER 'sysdba' PASSWORD 'masterkey'
  21.         WITH COMMON TRANSACTION
  22.         INTO :CLI_ID, :CLI_NIF, :CLI_NOMBRE, :CLI_EMAIL, :CLI_CODIGOBANCO, :CLI_CODIGOSUCURSAL,
  23.             :CLI_NUMEROCUENTA, :CLI_DIGITOCONTROL, :CLI_CONTACTO, :DIR_DIRECCION,
  24.             :DIR_CP, DIR_POBLACION, :DIR_TELEFONO1, :DIR_TELEFONO2, :PRV_NOMBRE
  25.         DO SUSPEND;
  26. END



Los datos de las tablas de ese código están en la base de datos Datos_Clientes.
Ejecuto ese código por el IBExpert por el SQLEditor estando conectado en mi base de datos Cursos.
Ya los miro, pero como hago un Join por ejemplo ?
Es que los datos de Cliente de esa base de datos van ser claves foraneas de algunas tablas de Cursos, como Empleados por ejemplo.
como hago esas asociaciones ?
  • 0

#6 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 07 June 2012 - 05:47 AM

Ya los miro, pero como hago un Join por ejemplo ?


No puedes hacer un JOIN en tablas en distintas bases de datos.

Tienes que recorrer la tabla en la primera base de datos mediante un bucle FOR SELECT, y dentro de ese bucle, para cada uno de sus registros tienes que lanzar un EXECUTE STATEMENT a la otra base de datos, recuperando los datos relacionados al registro.

Una vez pongas esos valores en los parámetros de salida del procedimiento almacenado, el resultado va a ser el mismo a que hubieses hecho un JOIN de las dos tablas.

Saludos.
  • 0

#7 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 07 June 2012 - 05:51 AM

Es decir, declara más parámetros de salida en el procedimiento almacenado, para los campos que deseas cruzar.

En el procedimiento almacenado, donde tienes DO SUSPEND; cambiálo por algo del tipo :


DO BEGIN
  SELECT COUNT(*) FROM CURSOS WHERE CURSOS.CLI_ID = :CLI_ID
  INTO :NUM_CURSOS;

  SUSPEND;
END


Previamente tengo que haber añadido NUM_CURSOS a los parámetros de salida del procedimiento almacenado.

Saludos.
  • 0

#8 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 posts

Posted 08 June 2012 - 02:14 AM

Hola Marc, gracias por la ayuda.

Hice los cambios como comentaste y bien, pero si intento hacer así:


delphi
  1. FOR EXECUTE STATEMENT
  2.         'select CLI_ID, CLI_NIF, CLI_NOMBRE, CLI_EMAIL, CLI_CODIGOBANCO, CLI_CODIGOSUCURSAL,
  3.         CLI_NUMEROCUENTA, CLI_DIGITOCONTROL, CLI_CONTACTO, DIR_DIRECCION,
  4.         DIR_CP, DIR_POBLACION, DIR_TELEFONO1, DIR_TELEFONO2, PRV_NOMBRE
  5.         from CLIENTE
  6.         left join DIRECCION on CLI_ID=DIR_IDPROPIETARIO
  7.         left join PROVINCIA on PRV_ID=DIR_IDPROVINCIA
  8.         order by CLI_ID'
  9.         ON EXTERNAL DATA SOURCE:DB
  10.         AS USER 'sysdba' PASSWORD 'masterkey'
  11.         WITH COMMON TRANSACTION
  12.         INTO :CLI_ID, :CLI_NIF, :CLI_NOMBRE, :CLI_EMAIL, :CLI_CODIGOBANCO, :CLI_CODIGOSUCURSAL,
  13.             :CLI_NUMEROCUENTA, :CLI_DIGITOCONTROL, :CLI_CONTACTO, :DIR_DIRECCION,
  14.             :DIR_CP, DIR_POBLACION, :DIR_TELEFONO1, :DIR_TELEFONO2, :PRV_NOMBRE
  15.         DO BEGIN
  16.             select GRU_IDCUR , GRU_IDCLI
  17.             from GRUPO
  18.             where GRU_IDCLI= :CLI_ID AND GRU_IDCUR= :cur_id
  19.             INTO :GRU_IDCUR, :GRU_IDCLI;
  20.             SUSPEND;
  21.         END



Sigue me sacando todos los datos, cuando lo que yo quiero es hacer el join de los valores que coincidan con la clausula where.
La verdad que estoy bastante perdido y no termino de pillarle el truquillo.
Agradezco cualquier ayuda.

  • 0

#9 Marc

Marc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1484 posts
  • LocationMallorca

Posted 08 June 2012 - 09:27 AM

Hola.

Sigue me sacando todos los datos, cuando lo que yo quiero es hacer el join de los valores que coincidan con la clausula where.
La verdad que estoy bastante perdido y no termino de pillarle el truquillo.
Agradezco cualquier ayuda.


Llama al comando SUSPEND (devolver registro) dentro de una IF para que se devuelva ese registro solo cuando cumpla las condiciones que te interesen.

Saludos.
  • 0

#10 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 posts

Posted 11 June 2012 - 12:54 AM

Hola.


Sigue me sacando todos los datos, cuando lo que yo quiero es hacer el join de los valores que coincidan con la clausula where.
La verdad que estoy bastante perdido y no termino de pillarle el truquillo.
Agradezco cualquier ayuda.


Llama al comando SUSPEND (devolver registro) dentro de una IF para que se devuelva ese registro solo cuando cumpla las condiciones que te interesen.

Saludos.


Pero como lo hago si una condición es de la base de Clientes y la otra condición es de la base de Cursos.
En ese ejemplo quiero cruzar los datos de ClientesxCurso. Estoy acostumbrado a hacerlo en la claúsula where y la verdad ni idea de como acerlo con ese concepto de EXECUTE STATEMENT.

Gracias
  • 0

#11 fredycc

fredycc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 874 posts
  • LocationOaxaca, México

Posted 11 June 2012 - 10:23 AM

espero esto te pueda ayudar, verifica el siguiente código expuesto en: http://www.firebirds...l-execstat.html en el apartado de Parameterized statements



delphi
  1. ...
  2. declare license_num varchar(15);
  3. declare connect_string varchar(100);
  4. declare stmt varchar(100) =
  5.   'select license from cars where driver = :driver and location = :loc';
  6. begin
  7.   ...
  8.   select connstr from databases where cust_id = :id into connect_string;
  9.   ...
  10.   for select id from drivers into current_driver do
  11.   begin 
  12.     for select location from driver_locations
  13.       where driver_id = :current_driver
  14.       into current_location do
  15.     begin
  16.       ...
  17.       execute statement (stmt) (driver := current_driver,
  18.                                   loc := current_location)
  19.         on external connect_string
  20.         into license_num;
  21.       ...



Serían 2 FOR SELECT que posteriormente se devolvería en license_num, esta forma de parametrizar te ahorraría un poco de trabajo, no lo he probado, pero suena lógico. No olvides comentar!. Al perecer es laborioso pero le veo varias ventajas aprovechando que es una iteración  :)

Saludos
  • 0

#12 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 posts

Posted 12 June 2012 - 01:23 AM

espero esto te pueda ayudar, verifica el siguiente código expuesto en: http://www.firebirds...l-execstat.html en el apartado de Parameterized statements



delphi
  1. ...
  2. declare license_num varchar(15);
  3. declare connect_string varchar(100);
  4. declare stmt varchar(100) =
  5.   'select license from cars where driver = :driver and location = :loc';
  6. begin
  7.   ...
  8.   select connstr from databases where cust_id = :id into connect_string;
  9.   ...
  10.   for select id from drivers into current_driver do
  11.   begin 
  12.     for select location from driver_locations
  13.       where driver_id = :current_driver
  14.       into current_location do
  15.     begin
  16.       ...
  17.       execute statement (stmt) (driver := current_driver,
  18.                                   loc := current_location)
  19.         on external connect_string
  20.         into license_num;
  21.       ...



Serían 2 FOR SELECT que posteriormente se devolvería en license_num, esta forma de parametrizar te ahorraría un poco de trabajo, no lo he probado, pero suena lógico. No olvides comentar!. Al perecer es laborioso pero le veo varias ventajas aprovechando que es una iteración  :)

Saludos


Gracias amigo, si lo probaré y cuando tenga algo o sencillamente no me salga nada (soy novato y realista jejejejeje) pues voy postear por aquí.
  • 0




IP.Board spam blocked by CleanTalk.