¿Cuándo se ejecuta SQLiteOpenHelper onCreate()/onUpgrade()?
He creado mis tablas en mi SQLiteOpenHelper
onCreate()
pero recibo
SQLiteException: no such table
o
SQLiteException: no such column
errores. ¿Por qué?
NOTA:
(Este es el resumen combinado de decenas de preguntas similares cada semana. Intentamos proporcionar una pregunta/respuesta wiki de la comunidad "canónica" aquí para que todas esas preguntas puedan dirigirse a una buena referencia).
SQLiteOpenHelper
onCreate()
y onUpgrade()
las devoluciones de llamada se invocan cuando la base de datos se abre realmente, por ejemplo mediante una llamada a getWritableDatabase()
. La base de datos no se abre cuando se crea el objeto auxiliar de la base de datos.
SQLiteOpenHelper
versiona los archivos de la base de datos. El número de versión es el int
argumento pasado al constructor . En el archivo de base de datos, el número de versión se almacena en formato PRAGMA user_version
.
onCreate()
solo se ejecuta cuando el archivo de base de datos no existía y recién se creó. Si onCreate()
regresa exitosamente (no arroja una excepción), se supone que la base de datos se creó con el número de versión solicitado. Como implicación, no deberías atrapar SQLException
s en onCreate()
ti mismo.
onUpgrade()
solo se llama cuando el archivo de base de datos existe pero el número de versión almacenada es inferior al solicitado en el constructor. Deben onUpgrade()
actualizar el esquema de la tabla a la versión solicitada.
Al cambiar el esquema de la tabla en el código ( onCreate()
), debe asegurarse de que la base de datos esté actualizada. Dos enfoques principales:
Elimine el archivo de base de datos antiguo para que
onCreate()
se ejecute nuevamente. Esto suele ser preferible en el momento del desarrollo, donde se tiene control sobre las versiones instaladas y la pérdida de datos no es un problema. Algunas formas de eliminar el archivo de base de datos:Desinstale la aplicación. Utilice el administrador de aplicaciones o
adb uninstall your.package.name
desde el shell.Borrar datos de la aplicación. Utilice el administrador de aplicaciones.
Incrementar la versión de la base de datos para que
onUpgrade()
se invoque. Esto es un poco más complicado ya que se necesita más código.Para actualizaciones del esquema de tiempo de desarrollo donde la pérdida de datos no es un problema, puede usar
execSQL("DROP TABLE IF EXISTS <tablename>")
in para eliminar las tablas existentes y llamaronCreate()
para recrear la base de datos.Para las versiones publicadas, debe implementar la migración de datos
onUpgrade()
para que sus usuarios no pierdan sus datos.
Para agregar más puntos faltantes aquí, según la solicitud de Jaskey
La versión de la base de datos se almacena dentro del SQLite
archivo de la base de datos.
captura es el constructor
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
Entonces, cuando se llama al constructor auxiliar de la base de datos con un name
(segundo parámetro), la plataforma verifica si la base de datos existe o no y, si la base de datos existe, obtiene la información de la versión del encabezado del archivo de la base de datos y activa la devolución de llamada correcta.
Como ya se explicó en la respuesta anterior, si la base de datos con el nombre no existe, se activa onCreate
.
La siguiente explicación explica onUpgrade
el caso con un ejemplo.
Digamos que su primera versión de la aplicación tenía DatabaseHelper
(extendido SQLiteOpenHelper
) con el constructor pasando la versión como 1
y luego proporcionó una aplicación actualizada con el nuevo código fuente con la versión pasada como 2
, luego, automáticamente, cuando se DatabaseHelper
construye, la plataforma se activa onUpgrade
al ver que el archivo ya existe. pero la versión es inferior a la versión actual que aprobó.
Ahora digamos que está planeando ofrecer una tercera versión de la aplicación con la versión db como 3
(la versión db aumenta solo cuando se va a modificar el esquema de la base de datos). En dichas actualizaciones incrementales, debe escribir la lógica de actualización de cada versión de forma incremental para obtener un código mejor mantenible.
Pseudocódigo de ejemplo a continuación:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch(oldVersion) {
case 1:
//upgrade logic from version 1 to 2
case 2:
//upgrade logic from version 2 to 3
case 3:
//upgrade logic from version 3 to 4
break;
default:
throw new IllegalStateException(
"onUpgrade() with unknown oldVersion " + oldVersion);
}
}
Observe la break
declaración que falta en caso 1
y 2
. Esto es lo que quiero decir con actualización incremental.
Digamos que si la versión anterior es 2
y la nueva es 4
, entonces la lógica actualizará la base de datos de 2
a 3
y luego a4
Si la versión anterior es 3
y la nueva es 4
, simplemente ejecutará la lógica de actualización 3
para4
onCreate()
Cuando creamos una base de datos por primera vez (es decir, la base de datos no existe),
onCreate()
creamos una base de datos con la versión que se pasa.SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
onCreate()
El método es crear las tablas que has definido y ejecutar cualquier otro código que hayas escrito. Sin embargo, este método solo se llamará si falta el archivo SQLite en el directorio de datos de su aplicación (/data/data/your.apps.classpath/databases
).No se llamará a este método si cambiaste tu código y lo reiniciaste en el emulador. Si desea
onCreate()
ejecutar, debe usar adb para eliminar el archivo de base de datos SQLite.
onUpgrade()
SQLiteOpenHelper
debería llamar al superconstructor.- El
onUpgrade()
método solo se llamará cuando el número entero de la versión sea mayor que la versión actual que se ejecuta en la aplicación. - Si desea
onUpgrade()
que se llame al método, debe incrementar el número de versión en su código.
Quizás sea demasiado tarde, pero me gustaría compartir mi breve y concisa respuesta. Por favor marque Respuesta para el mismo problema. Definitivamente te ayudará. No más especificaciones profundas.
Si tiene confianza en la sintaxis para crear una tabla, esto puede suceder cuando agrega una nueva columna en la misma tabla, por eso...
1) Desinstale de su dispositivo y ejecútelo nuevamente.
O
2) Configuración -> aplicación -> ClearData
O
3) Cambie DATABASE_VERSION
su clase "DatabaseHandler" (si ha agregado una nueva columna, se actualizará automáticamente)
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
O
4) Cambie DATABASE_NAME
su clase "DatabaseHandler" (me enfrenté al mismo problema, pero lo logré al cambiar DATABASE_NAME
).