Página 1 de 1

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 12:06 am
por Alfredo Sanz
Hola,
Alguien sabe si se pueden unir databases con el SqliteDatasource
http://www.sqlite.org/lang_attach.html
Y si así­ no se puede, ¿Alguna forma de hacerlo?
1 Saludico,
Fredy

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 5:34 am
por Carlos Ortiz
Sqlite no soporta el comando UNION para unir tablas?
El 05/03/2013 20:06, Alfredo Sanz escribió:
> Hola,
> Alguien sabe si se pueden unir databases con el
> SqliteDatasource
>
> http://www.sqlite.org/lang_attach.html
>
> Y si así­ no se puede, ¿Alguna forma de hacerlo?
>
> 1 Saludico,
> Fredy

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 9:50 am
por ignacio
Alfredo Sanz escribió el mié, 06 marzo 2013 00:06Hola,
Alguien sabe si se pueden unir databases con el SqliteDatasource
http://www.sqlite.org/lang_attach.html
Y si así­ no se puede, ¿Alguna forma de hacerlo?
1 Saludico,
Fredy
Mira el comando ATTACH DATABASE. La única limitación es que si utilizas encriptación ambas bases de datos han de estar encriptadas con la misma contraseña.
Saludos
Ejemplo de traspaso de tabla entre dos BD:
WITH OBJECT oDataSource
TRY
:Execute( "ATTACH DATABASE 'c:....???.db' AS Source" )
:BeginTrans()
:Execute( "DELETE FROM Tabla" )
:Execute( "INSERT INTO Tabla (campos,...) SELECT (campos, ...) FROM Source.Tabla )
:CommitTrans()
:Execute( "DETACH DATABASE Source" )
CATCH
:RollBackTrans()
Msginfo( "Error en grabación de los datos" )
END
END WITH

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 11:28 am
por Alfredo Sanz
Gracias, justo lo que buscaba.
Por cierto, sabes si hay alguna forma de conocer en sqlite si una base de datos o una tabla se encuentra bloqueada?
El problema que tengo es que si intento hacer un Execute Insert, Update, etc y hay una transacción en curso no me entero hasta que sqlite me devuelve un error 5
1 Saludico,
Fredy

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 11:29 am
por Alfredo Sanz
Hola Carlos.
Sí­ que soporta Union sobre Tablas.
Yo preguntaba más o menos lo mismo pero sobre Datablases
1 Saludico,
Fredy

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 12:04 pm
por ignacio
Hola Fredy,
Creo que SQLite bloquea la BD completamente en cada operación de escritura, por eso es tan importante usar transacciones, de esta forma se le indica a Sqlite cuando empieza y termina la transacción.
Yo personalmente pongo la propiedad lAllowProcessMessages a falso. Es posible que también te sea de ayuda.
Y por último, soy partidario de utilizar TMemDatasets cuando no voy a editar los SELECTS que haga ya que entonces los filtros y ordenaciones se resuelven sin necesisdad de usar el motor de SQLITE. Ver método TDataSource:QueryMemDataset()
Un saludo

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 1:00 pm
por Alfredo Sanz
El problema es ese, que bloquea la base de datos entera y no sólo las tablas utilizadas en la transacción.
En un entorno multiusuario, si otro usuario inicia una transacción y yo intento iniciar otra antes de que la del usuario 1 finalice, sqlite genera un error 5 (Database is locked).
El problema que me genera esto, es que cuanto más larga sea la transacción más fácil es que otro usuario tenga problemas. Imagí­nate una regeneración de almacenes que dure 3 minutos. Si no uso transacciones, en lugar de 3 minutos igual son 30. Si uso transacciones, cualquier usuario que intente grabar un dato durante los 3 minutos del proceso recibirá como respuesta un error de sqllite y posiblemente pierda los datos introducidos.
Por eso me gustarí­a conocer de antemano si la base de datos está bloqueada y esperar a que la base de datos esté desbloqueada en lugar de que genere el error.
En la prehistoria, con dbfs tení­amos el FLock(), que es algo parecido.
He probado con nTimeOut, pero creo que sqlite no lo utiliza.
Según he visto en http://www.sqlite.org/tempfiles.html
creo que puedo solucionarlo jugando con el fichero -journal de la database , pero serí­a mucho más fácil si ya existe algo para hacerlo.
1 Saludico,
Fredy

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 1:29 pm
por jfgimenez
Fredy,
> El problema es ese, que bloquea la base de datos.
>
> En un entorno multiusuario, si otro usuario inicia una
> transacción y yo intento iniciar otra antes de que la del
> usuario 1 finalice, sqlite genera un error 5 (Database is
> locked).
>
> El problema que me genera esto, es que cuanto más larga sea
> la transacción más fácil es que otro usuario tenga
> problemas. Imagí­nate una regeneración de almacenes que
> dure 3 minutos. Si no uso transacciones, en lugar de 3
> minutos igual son 30. Si uso transacciones, cualquier
> usuario que intente grabar un dato durante los 3 minutos del
> proceso recibirá como respuesta un error de sqllite y
> posiblemente pierda los datos introducidos.
Lo ideal con SQLite es que las transacciones sean muy rápidas, nunca más
de unos pocos (muy pocos) segundos. Si hay procesos que requieren
transacciones largas, y en un entorno multiusuario, entonces lo más
indicado es cambiar a otra BD.
La BD más parecida a SQLite, en cuanto a sintaxis, es MySQL. Yo tengo
aplicaciones que soportan ambos motores, y que se cambia de uno a otro
desde una opción de configuración. Todo el programa, excepto la parte de
abrir y crear las BB.DD., es común a ambos motores, es decir, que no he
tenido que cambiar ni una lí­nea de código para usar uno u otro. Y tengo
unas cuantas sentencias relativamente complejas. Tan sólo hay una
pequeña diferencia que encontré entre ambos, pero no es muy habitual
tropezarte con eso.
Ahora bien, MySQL es de pago. Pero afortunadamente, ahora tenemos una
alternativa: MariaDB ;-)
> Por eso me gustarí­a conocer de antemano si la base de datos
> está bloqueada y esperar a que la base de datos esté
> desbloqueada en lugar de que genere el error.
>
> En la prehistoria, con dbfs :) tení­amos el FLock(), que es
> algo parecido.
El eterno dilema de los "bloqueos pesimistas" frente a los "bloqueos
optimistas"...
> He probado con nTimeOut, pero creo que sqlite no lo
> utiliza.
>
> Según he visto en http://www.sqlite.org/tempfiles.html
> creo que puedo solucionarlo jugando con el fichero -journal
> de la database , pero serí­a mucho más fácil si ya existe
> algo para hacerlo.
Hasta donde yo sé, los journals son otra cosa. Los crea la propia BD
durante una transacción, y sólo sirven para hacer un rollback automático
cuando se abre la BD después de un corte de luz o algún fallo similar.
Pero dudo mucho que puedas manipularlos o usarlos directamente para
ningún otro fin.
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 1:51 pm
por Alfredo Sanz
Qué tal José,
> Lo ideal con SQLite es que las transacciones sean muy rápidas, nunca más
> de unos pocos (muy pocos) segundos. Si hay procesos que requieren
> transacciones largas, y en un entorno multiusuario, entonces lo más
> indicado es cambiar a otra BD.
Lo chulo de sqlite es que tiene cosas muy muy buenas y cosas muy muy malas, pero para ese estamos nosotros.
> La BD más parecida a SQLite, en cuanto a sintaxis, es MySQL
Lo malo es que todo lo que ganas en compatibilidad SQLite-MySQL lo pierdes en potencia de MySQL.
> Ahora bien, MySQL es de pago. Pero afortunadamente, ahora tenemos una
> alternativa: MariaDB
Sí­! Indudablemente se nos ha aparecido la Virgen ...MariaDb
> El eterno dilema de los "bloqueos pesimistas" frente a los "bloqueos
> optimistas"...
Sí­, pero es que el tí­o que inventó Sqlite es el rey de los pesimistas. Mira tú que bloquear a nivel de base de datos!!
> Hasta donde yo sé, los journals son otra cosa. Los crea la propia BD
> durante una transacción, y sólo sirven para hacer un rollback automático
> cuando se abre la BD después de un corte de luz o algún fallo similar.
> Pero dudo mucho que puedas manipularlos o usarlos directamente para
> ningún otro fin.
Realmente no lo manipulo. Sólo compruebo 2 cosas:
- Existencia:
Si no existe, está claro que nadie tiene una transacción abierta
Si existe
- Apertura en exclusivo
Si lo puedo abrir el fichero en modo exclusivo, es que el programa a petado y se ha quedado el fichero perdido
Si no lo puedo abrir es que alguien tiene una transacción en curso y me toca esperar.
1 Saludico,
Fredy

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 1:53 pm
por ignacio
Hola,
Se me ocurre que un bloque TRY..CATCH dentro de un bucle con salida cuando transcurra cierto tiempo serí­a suficiente. No?
Prueba también con BEGIN EXCLUSIVE TRANSACTION
Saludos

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 2:06 pm
por jfgimenez
Fredy,
> Lo chulo de sqlite es que tiene cosas muy muy buenas y cosas
> muy muy malas, pero para ese estamos nosotros.
Pues sí­, la verdad. Yo soy de los que me gusta muchí­simo SQLite, aunque
es cierto que hay que lidiar con algunas cosas muy suyas... pero claro,
se entiende desde el punto de vista de que es un motor empotrado y
local, ¡ahí­ es ná!
> Lo malo es que todo lo que ganas en compatibilidad
> SQLite-MySQL lo pierdes en potencia de MySQL.
Sí­, puede haber ciertas cosas que tiene MySQL y que no tiene SQLite,
pero si lo que tienes es una aplicación diseñada con SQLite, al añadir
soporte para MySQL no vas a echar nada en falta.
> Sí­, pero es que el tí­o que inventó Sqlite es el rey de
> los pesimistas. Mira tú que bloquear a nivel de base de
> datos!!
Bueno, al revés... es el rey de los optimistas. Vamos, que bloquea toda
la BD porque... "si total, no van a coincidir nunca" ;-)
> Realmente no lo manipulo. Sólo compruebo 2 cosas:
> - Existencia:
> Si no existe, está claro que nadie tiene una
> transacción abierta
> Si existe
> - Apertura en exclusivo
> Si lo puedo abrir el fichero en modo exclusivo,
> es que el programa a petado y se ha quedado el fichero
> perdido
> Si no lo puedo abrir es que alguien tiene una
> transacción en curso y me toca esperar.
No te fies. Yo no los he investigado a fondo, pero estoy convencido de
que el fichero journal lo crea con la primera transacción que hagas,
pero seguramente no lo borra, sino que solamente lo trunca, para no
tener que crearlo y borrarlo cada vez.
No obstante, para el problema que tienes, se me ocurre que podrí­as
forzarlo a iniciar una transacción antes de emprezar con la grabación de
datos, y si la transacción falla, entonces avisas al usuario. Podrí­as
hacerlo como una función del estilo de RLock(). P.ej. (y simplificando
mucho):
FUNCTION DBLock( oDB )
LOCAL lOk := .T.
TRY
oDB:BeginTrans()
oDB:Execute( "Update...." ) // Aqui pones cualquier cosa que
fuerce una grabacion para que se bloquee la DB
CATCH
lOk := .F.
END
RETURN lOk
y puedes llamar a esta función al estilo de como lo hací­as con los DBF.
Si retorna .F. es que no ha podido bloquear, y si retorna .T. es que la
BD ya la ha bloqueado e iniciado la transacción.
Un saludo,
José F. Giménez
http://www.xailer.com
http://www.xailer.info

Unir databases con SqliteDataSource

Publicado: Mié Mar 06, 2013 4:05 pm
por Carlos Ortiz
Perdón vi tablas en lugar de databases.
Serí­a indicado dormir cuando es tarde digo por la hora en que conteste
tu post inicial, saludo.