Eu mantenho um aplicativo que precisa atualizar periodicamente um banco de dados sqlite e migrar bancos de dados antigos para o novo esquema e aqui está o que eu faço:
Para rastrear a versão do banco de dados, eu uso a variável integrada de versão do usuário que o sqlite fornece (o sqlite não faz nada com essa variável, você pode usá-la como quiser). Ele começa em 0 e você pode obter / definir essa variável com as seguintes instruções sqlite:
> PRAGMA user_version;
> PRAGMA user_version = 1;
Quando o aplicativo é iniciado, verifico a versão do usuário atual, aplico as alterações necessárias para atualizar o esquema e, em seguida, atualizo a versão do usuário. Eu envolvo as atualizações em uma transação para que, se algo der errado, as alterações não sejam confirmadas.
Para fazer alterações no esquema, o sqlite suporta a sintaxe "ALTER TABLE" para certas operações (renomear a tabela ou adicionar uma coluna). Esta é uma maneira fácil de atualizar as tabelas existentes no local. Consulte a documentação aqui: http://www.sqlite.org/lang_altertable.html . Para excluir colunas ou outras alterações que não são suportadas pela sintaxe "ALTER TABLE", eu crio uma nova tabela, migro a data para ela, elimino a tabela antiga e renomeio a nova tabela com o nome original.
application_id
é um bit extra para identificar o formato do arquivo porfile
utilitário por exemplo, não para versões de banco de dados.A resposta de Just Curious é perfeita (você entendeu!) E é o que usamos para rastrear a versão do esquema de banco de dados que está atualmente no aplicativo.
Para executar as migrações que precisam ocorrer para obter user_version correspondente à versão de esquema esperada do aplicativo, usamos uma instrução switch. Aqui está um exemplo recortado de como isso se parece em nosso aplicativo Strip :
fonte
toVersion
em seu código? Como isso é tratado quando você está na versão 0 e há mais duas versões depois disso. Isso significa que você deve migrar de 0 para 1 e de 1 para 2. Como você lida com isso?break
instruções noswitch
, então todas as migrações subsequentes também acontecerão.Deixe-me compartilhar alguns códigos de migração com FMDB e MBProgressHUD.
Veja como você lê e escreve o número da versão do esquema (presumivelmente, faz parte de uma classe de modelo, no meu caso é uma classe singleton chamada Database):
Este é o
[self database]
método que abre lentamente o banco de dados:E aqui estão os métodos de migração chamados a partir do controlador de visualização:
E aqui está o código do controlador de visualização raiz que invoca a migração, usando MBProgressHUD para exibir um painel de progresso:
fonte
schema_version
pragma normalmente não é algo com que as pessoas lidam.A melhor solução da IMO é construir uma estrutura de atualização do SQLite. Eu tive o mesmo problema (no mundo C #) e construí meu próprio framework. Você pode ler sobre isso aqui . Ele funciona perfeitamente e faz com que minhas atualizações (antes terríveis) funcionem com o mínimo de esforço da minha parte.
Embora a biblioteca seja implementada em C #, as idéias apresentadas devem funcionar bem no seu caso também.
fonte
1
. Crie uma/migrations
pasta com a lista de migrações baseadas em SQL, onde cada migração se parece com isto:/migrations/001-categories.sql
/migrations/002-posts.sql
2
. Crie uma tabela de banco de dados contendo a lista de migrações aplicadas, por exemplo:3
. Atualize a lógica de bootstrap do aplicativo para que antes de iniciar, pegue a lista de migrações da/migrations
pasta e execute as migrações que ainda não foram aplicadas.Aqui está um exemplo implementado com JavaScript: Cliente SQLite para aplicativos Node.js
fonte
Algumas dicas...
1) Eu recomendo colocar todo o código para migrar seu banco de dados em um NSOperation e executá-lo em segundo plano. Você pode mostrar um UIAlertView personalizado com um botão giratório enquanto o banco de dados está sendo migrado.
2) Certifique-se de copiar seu banco de dados do pacote para os documentos do aplicativo e usá-lo desse local, caso contrário, você apenas substituirá todo o banco de dados a cada atualização do aplicativo e, em seguida, migrará o novo banco de dados vazio.
3) FMDB é ótimo, mas seu método executeQuery não pode fazer consultas PRAGMA por algum motivo. Você precisará escrever seu próprio método que usa sqlite3 diretamente se quiser verificar a versão do esquema usando PRAGMA user_version.
4) Esta estrutura de código irá garantir que suas atualizações sejam executadas em ordem, e que todas as atualizações sejam executadas, não importa quanto tempo o usuário fica entre as atualizações do aplicativo. Ele poderia ser refatorado posteriormente, mas esta é uma maneira muito simples de olhar para ele. Esse método pode ser executado com segurança toda vez que seu singleton de dados é instanciado e custa apenas uma pequena consulta db que só acontece uma vez por sessão se você configurar seu singleton de dados corretamente.
fonte
Se você alterar o esquema do banco de dados e todo o código que o está usando em um lockstep, como é provável que seja o caso em aplicativos integrados e localizados por telefone, o problema está realmente bem sob controle (nada comparável ao pesadelo que é a migração do esquema em um banco de dados corporativo que pode servir centenas de aplicativos - nem todos sob o controle do DBA ;-).
fonte
Para .net, você pode usar lib:
EntityFrameworkCore.Sqlite.Migrations
É simples, portanto, para qualquer outra plataforma, você pode implementar facilmente o mesmo comportamento do lib.
fonte