Mantengo una aplicación que periódicamente necesita actualizar una base de datos sqlite y migrar bases de datos antiguas al nuevo esquema y esto es lo que hago:
Para rastrear la versión de la base de datos, utilizo la variable de versión de usuario incorporada que proporciona sqlite (sqlite no hace nada con esta variable, usted es libre de usarla como quiera). Comienza en 0 y puede obtener / establecer esta variable con las siguientes declaraciones sqlite:
> PRAGMA user_version;
> PRAGMA user_version = 1;
Cuando se inicia la aplicación, verifico la versión de usuario actual, aplico los cambios necesarios para actualizar el esquema y luego actualizo la versión de usuario. Envuelvo las actualizaciones en una transacción para que, si algo sale mal, los cambios no se confirmen.
Para realizar cambios de esquema, sqlite admite la sintaxis "ALTER TABLE" para ciertas operaciones (cambiar el nombre de la tabla o agregar una columna). Esta es una forma sencilla de actualizar las tablas existentes en el lugar. Consulte la documentación aquí: http://www.sqlite.org/lang_altertable.html . Para eliminar columnas u otros cambios que no son compatibles con la sintaxis "ALTER TABLE", creo una nueva tabla, migro la fecha en ella, elimino la tabla anterior y cambio el nombre de la nueva tabla al nombre original.
application_id
es un bit extra para identificar el formato de archivo porfile
utilidad, por ejemplo, no para las versiones de la base de datos.La respuesta de Just Curious es acertada (¡entendiste mi punto!), Y es lo que usamos para rastrear la versión del esquema de base de datos que se encuentra actualmente en la aplicación.
Para ejecutar las migraciones que deben ocurrir para que user_version coincida con la versión de esquema esperada de la aplicación, usamos una declaración de cambio. Aquí hay un ejemplo cortado de cómo se ve esto en nuestra aplicación Strip :
fuente
toVersion
en tu código. ¿Cómo se maneja cuando está en la versión 0 y hay dos versiones más después de eso? Esto significa que debe migrar de 0 a 1 y de 1 a 2. ¿Cómo maneja esto?break
declaraciones en elswitch
, por lo que todas las migraciones posteriores también ocurrirán.Permítanme compartir un código de migración con FMDB y MBProgressHUD.
Así es como lee y escribe el número de versión del esquema (esto es presumiblemente parte de una clase modelo, en mi caso es una clase singleton llamada Base de datos):
Aquí está el
[self database]
método que abre perezosamente la base de datos:Y aquí están los métodos de migración llamados desde el controlador de vista:
Y aquí está el código del controlador de vista raíz que invoca la migración, usando MBProgressHUD para mostrar un bisel de progreso:
fuente
schema_version
pragma tampoco es algo con lo que la gente se enfrente normalmente.En mi opinión, la mejor solución es crear un marco de actualización de SQLite. Tuve el mismo problema (en el mundo C #) y construí mi propio marco de trabajo. Puedes leer sobre esto aquí . Funciona perfectamente y hace que mis actualizaciones (que antes eran de pesadilla) funcionen con un mínimo esfuerzo de mi parte.
Aunque la biblioteca está implementada en C #, las ideas presentadas allí también deberían funcionar bien en su caso.
fuente
1
. Cree una/migrations
carpeta con la lista de migraciones basadas en SQL, donde cada migración se parece a esto:/migrations/001-categories.sql
/migrations/002-posts.sql
2
. Cree una tabla de base de datos que contenga la lista de migraciones aplicadas, por ejemplo:3
. Actualice la lógica de arranque de la aplicación para que, antes de que comience, tome la lista de migraciones de la/migrations
carpeta y ejecute las migraciones que aún no se han aplicado.A continuación se muestra un ejemplo implementado con JavaScript: SQLite Client para aplicaciones Node.js
fuente
Algunos consejos...
1) Recomiendo poner todo el código para migrar su base de datos a una NSOperation y ejecutarlo en segundo plano. Puede mostrar un UIAlertView personalizado con un control giratorio mientras se migra la base de datos.
2) Asegúrese de que está copiando su base de datos del paquete en los documentos de la aplicación y usándola desde esa ubicación; de lo contrario, simplemente sobrescribirá la base de datos completa con cada actualización de la aplicación y luego migrará la nueva base de datos vacía.
3) FMDB es genial, pero su método executeQuery no puede realizar consultas PRAGMA por alguna razón. Deberá escribir su propio método que use sqlite3 directamente si desea verificar la versión del esquema usando PRAGMA user_version.
4) Esta estructura de código asegurará que sus actualizaciones se ejecuten en orden y que todas las actualizaciones se ejecuten, sin importar cuánto tiempo pase el usuario entre actualizaciones de la aplicación. Podría refactorizarse aún más, pero esta es una forma muy simple de verlo. Este método se puede ejecutar de forma segura cada vez que se crea una instancia de su singleton de datos, y solo cuesta una pequeña consulta de db que solo ocurre una vez por sesión si configura su singleton de datos correctamente.
fuente
Si cambia el esquema de la base de datos y todo el código que lo usa al mismo tiempo, como es probable que sea el caso en las aplicaciones integradas y ubicadas en el teléfono, el problema está realmente bien bajo control (nada comparable a la pesadilla que es la migración de esquemas en una base de datos empresarial que puede estar sirviendo a cientos de aplicaciones, no todas bajo el control del DBA ;-).
fuente
Para .net puede usar lib:
EntityFrameworkCore.Sqlite.Migrations
Es simple, por lo que para cualquier otra plataforma puede implementar fácilmente el mismo comportamiento que en lib.
fuente