A veces necesitamos realizar consultas que involucren a dos (o más) tablas que se encuentran en dos (o más) bases de datos diferentes.
Ejemplo:
En la «Casa Central» tenemos una Base de Datos que tiene una tabla de CLIENTES y en la «Sucursal 1» tenemos otra Base de Datos que tiene otra tabla de CLIENTES. No podemos tener una Base de Datos única porque la conexión con Internet no es constante, sufre de frecuentes cortes, por lo tanto optamos por tener dos bases de datos, independientes, cada una con sus propios datos.
Pero a veces es necesario reunir en una sola consulta los nombres de los clientes que se encuentran en la «Casa Central» y en la «Sucursal 1».
En este momento, estos son algunos de los clientes que tenemos en la «Casa Central»
Captura 1. Si haces clic en la imagen la verás más grande
Y estos son algunos de los clientes que tenemos en la «Sucursal 1»:
Captura 2. Si haces clic en la imagen la verás más grande
Que como puedes ver los nombre son distintos, aunque algunos identificadores se repiten.
Para tener en una sola consulta los nombres de los clientes de la «Casa Central» y de la «Sucursal 1» escribimos este stored procedure:
CREATE PROCEDURE CONSULTAR_2_BASES RETURNS( ftnCodSuc TYPE OF COLUMN CLIENTES.CLI_CODSUC, ftnIdenti TYPE OF COLUMN CLIENTES.CLI_IDENTI, ftcNombre TYPE OF COLUMN CLIENTES.CLI_NOMBRE) AS DECLARE VARIABLE lcComando VARCHAR(200); BEGIN lcComando = 'SELECT CLI_CODSUC, CLI_IDENTI, CLI_NOMBRE FROM CLIENTES'; FOR EXECUTE STATEMENT lcComando ON EXTERNAL 'E:\SQL\SQL_CONTA\DATABASES\ERP2000.FDB' AS USER 'SYSDBA' PASSWORD 'masterkey' INTO :ftnCodSuc, :ftnIdenti, :ftcNombre DO SUSPEND; FOR SELECT CLI_CODSUC, CLI_IDENTI, CLI_NOMBRE FROM CLIENTES INTO :ftnCodSuc, :ftnIdenti, :ftcNombre DO SUSPEND; END;
Y esto es lo que observamos (luego de hacer clic sobre la columna ftnIdenti) para que las filas queden ordenadas:
Captura 3. Si haces clic en la imagen la verás más grande
Como puedes ver algunos identificadores están repetidos pero eso no es problema porque podemos diferenciarlos mediante la columna CLI_CODSUC (código de la Sucursal). Un valor de 0 en esa columna significa «Casa Central» y un valor de 1 significa «Sucursal 1».
Pero ¿y si esta consulta se repetirá varias veces durante el día? ¿o si queremos verla ordenada por Identificador o por Nombre del Cliente?
Estar ejecutando el stored procedure CONSULTAR_2_BASES cada vez que se requiere ver los datos de todos los clientes es impráctico porque las consultas a las bases de datos externas son más lentas. Entonces ¿cuál es la solución?
Crear una tabla temporal (una tabla GTT) y guardar en ella cada fila que nos devuelve el stored procedure CONSULTAR_2_BASES, de esa manera tendremos una gran velocidad. O sea, la primera consulta será lenta (porque deberá traer los datos de una Base de Datos externa e insertar esas filas, más las filas de la tabla local, en una tabla GTT) pero las demás consultas serán rapidísimas.
Conclusión:
Es perfectamente posible con Firebird consultar tablas que se encuentran en bases de datos externas. Y si esas consultas se repetirán varias veces durante el día o si necesitamos tener a las filas ordenadas por algún criterio lo más aconsejable es realizarlas una sola vez y guardar el resultado en una tabla GTT, al ser la tabla GTT una tabla local las consultas a ella son rapidísimas y como toda tabla podemos ordenarla según cualquier criterio que nos parezca.
Por supuesto que las consultas a las bases de datos externas pueden involucrar a muchas tablas y a muchas bases de datos, no tienen por que ser solamente 2, como se mostró en este ejemplo.
Artículos relacionados:
Francisco
Dic 11, 2013 @ 16:18:46
Walter buen tema, ahora si no es mucha molestia, en 2 sucursales como comentas, que tendriamos que hacer para que se puedan accesar via internet? que debemos de configurar en cada sucursal, suponiendo que en oficinas centrales , quieren estar consultando de las dos sucursales?
de antemano, gracias por el aporte.
wrov
Dic 11, 2013 @ 18:24:03
Pues simplemente una IP pública en la computadora donde se encuentra el Servidor de Firebird, nada más que eso.
Una IP pública aquí cuesta 5 dólares mensuales.
Pero eso es para que se puedan conectar a la Base de Datos, otro tema es el de la seguridad. Enviar y recibir datos por una IP pública es muy vulnerable a hackers entonces lo conveniente es contratar una VPN (que cuesta bastante más que 5 dólares) y usar Zebedee o similar para que los datos viajen comprimidos y encriptados dificultándoles así en gran medida la tarea a los hackers:
Adicionalmente, otra importantísima medida que debes obligarles a tus clientes a adoptar (si no quieren hacerla les debes decir que no les ofreces la mínima garantía) es la siguiente: la conexión a Internet debe utilizarse EXCLUSIVAMENTE para la comunicación con las bases de datos. No debe ser usada para navegar, para el Facebook, para los e-mails, y muchísimo menos para descargar música, vídeos o ver películas on-line porque el ancho de bando siempre es limitado y si lo usan para esas tonterías entonces no habrá ancho de banda que aguante.
Saludos.
Walter.
Francisco
Dic 11, 2013 @ 21:15:57
Perfecto Walter, como siempre, muy bien explicado, te agradezco.
Benjamín Alvarez
Mar 13, 2015 @ 17:18:13
Hola buenas tardes, uso firebird 2.5 y cuanto intento usar «FOR EXECUTE STATEMENT» me da error de precompilación.
Me puedes orientar un poco para usar este recurso
wrov
Mar 13, 2015 @ 20:25:34
Con solamente esa información es muy poco lo que puedo decirte.
Tendrías que enviarme tu stored procedure para tratar de encontrar el problema.
Saludos.
Walter.
Fernando Arbach
Abr 26, 2016 @ 18:02:08
Hola como va? Felicitaciones por el blog! Es realmente muy util.
Te comento un problema relacionado con esto para que si podes me des tu opinion.
Tengo que hacer un JOIN de un detalle de facturas, pero ocurra que el sistema usa 2 bases de datos, en la segunda base de datos no esta la tabla articulos.
Lei que en Firebird 2.5 si se puede, es cierto?
Para poder hacer el join, debo si o si acudir a esto que comentar en la entrada?
Gracias!
wrov
Abr 28, 2016 @ 15:00:48
En Firebird hasta la versión 2.5.5, que es la última que yo utilizo, no se pueden relacionar tablas que se encuentran en bases de datos diferentes.
Sí se pueden insertar, actualizar, borrar, y consultar, tablas que se encuentran en otra Base de Datos pero no se puede hacer un JOIN entre dos tablas de dos bases de datos, ni tener una Foreign Key, etc.
Algo así podría realmente ser muy útil porque nos permitiría organizarnos mejor, por ejemplo tener una tabla CLIENTES en una Base de Datos y que desde las demás bases de datos podríamos relacionarnos a esa tabla. De esta manera podríamos tener muchas bases de datos pero una sola tabla de CLIENTES. Lastimosamente por el momento tal cosa no es posible de realizar en Firebird.
Saludos.
Walter.
Maby
Nov 06, 2020 @ 12:49:59
Buenas! como será la sintaxis para hacer un update de una tabla con datos de otra tabla de otra Base de datos?
Maby
Nov 06, 2020 @ 12:52:15
create or alter procedure UPDATECAS (
VNEWSTOCK double precision,
as
declare variable LCCOMANDO2 varchar(256);
begin
LCCOMANDO2 = ‘update CAS
set STOCK = STOCK-‘ || :VNEWSTOCK || »;
for execute statement LCCOMANDO2 on external ‘C:\DB\DB.GDB’ as
user ‘SYSDBA’ password ‘masterkey’
suspend;
end
Este me da el siguiente error
can’t format message 13:896 — message file C:\WINDOWS\firebird.msg not found. Dynamic SQL Error. SQL error code = -104. Token unknown. suspend
Que es lo que estoy haciendo mal? es posible realizarlo?
wrov
Nov 07, 2020 @ 16:43:22
Cuando en el mensaje que te envía el Firebird aparece: «firebird.msg not found» eso significa que no encontró al archivo FIREBIRD.MSG en la carpeta superior del archivo FBCLIENT.DLL
La solución es muy simple: copiar el archivo FIREBIRD.MSG en la carpeta superior a FBCLIENT.DLL
y la palabra «for» y la palabra «suspend» están de más.
Saludos.
Walter.
Cesar Ramirez
May 18, 2022 @ 14:38:17
hola buenas tardes, estoy haciendo una consulta a 2 bases donde solo quiero que me regrese los datos mencionados en la consulta, en la Primera base si me respeta el where, pero en la segunda base no me respeta el where, me arroja todos los datos de la tabla
create or alter procedure CONSULTAR_2_BASES
returns (
CLAVE_ART varchar(20),
VITRO SI_NO_N)
as
declare variable LCCOMANDO varchar(500);
BEGIN
lcComando = ‘select claves_articulos.clave_articulo, libres_articulos.vitros from claves_articulos
left join libres_articulos on (libres_articulos.articulo_id = claves_articulos.articulo_id)
where libres_articulos.vitros = »S»’;
FOR EXECUTE STATEMENT
lcComando
ON EXTERNAL
‘192.168.100.25:C:\Microsip datos\CAPACITACION.FDB’
AS
USER ‘SYSDBA’
PASSWORD ‘masterkey’
INTO
:CLAVE_ART,
:VITRO
DO
SUSPEND;
FOR SELECT
CLAVE_ARTICULO,
VITROS
FROM CLAVES_ARTICULOS, LIBRES_ARTICULOS WHERE LIBRES_ARTICULOS.vitros = ‘S’
INTO
:CLAVE_ART,
:VITRO
DO BEGIN
SUSPEND;
END
END^
y el resultado es algo así (en el siguiente LINK)
https://ibb.co/BCVddLg
me podrían ayudar por favor por favor