Error inserting in SQLite database
I'm trying to create the following database:
public static final String KEY_NAME = "nombre";
public static final String KEY_ROWID = "_id";
public static final String KEY_ID = "id";
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
private static final String DATABASE_CREATE =
"create table capas (_id integer primary key autoincrement, "
+ "id text not null, "
+ "nombre text not null);"
+ "create table poi (_id integer primary key autoincrement, "
+ "id text not null, "
+ "nombre text not null, "
+ "lon real not null, "
+ "lat real not null, "
+ "info text, "
+ "email text, "
+ "telefono text, "
+ "web text, "
+ "usuario text, "
+ "capas_id text not null);"
+ "create table mensajes (_id integer primary key autoincrement, "
+ "id text not null, "
+ "mensaje text not null, "
+ "fecha text not null, "
+ "poi_id text not null, "
+ "usuario text not null);";
private static final String DATABASE_NAME = "upv_db";
private static final String DATABASE_TABLE_CAPAS = "capas";
private static final String DATABASE_TABLE_POIS = "poi";
private static final String DATABASE_TABLE_MENSAJES = "mensajes";
private static final int DATABASE_VERSION = 2;
There're three tables in it. These are the methods to initialize, create and retrieve rows from the first table (I haven't written the methods for the other 2 tables yet):
public long createCapa(String id, String nombre) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_ID, id);
initialValues.put(KEY_NAME, nombre);
return mDb.insert(DATABASE_TABLE_CAPAS, null, initialValues);
}
/**
* Return a Cursor over the list of all notes in开发者_JS百科 the database
*
* @return Cursor over all notes
*/
public Cursor leerCapas() {
return mDb.query(DATABASE_TABLE_CAPAS, new String[] {KEY_ROWID, KEY_ID, KEY_NAME}, null, null, null, null, null);
}
//Inicializa la tabla de capas por defecto
public void inicializaCapas(){
createCapa("cap001", "Escuelas");
createCapa("cap002", "Departamentos");
createCapa("cap003", "Edificios");
}
The app is not working because it gets an error when inserting in the DB. This is the error in the log:
07-23 20:39:14.354: ERROR/Database(743): Error inserting nombre=Escuelas id=cap001
07-23 20:39:14.354: ERROR/Database(743): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
07-23 20:39:14.354: ERROR/Database(743): at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
07-23 20:39:14.354: ERROR/Database(743): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:55)
07-23 20:39:14.354: ERROR/Database(743): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1549)
07-23 20:39:14.354: ERROR/Database(743): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1410)
07-23 20:39:14.354: ERROR/Database(743): at com.android.upvar.DatosDB.createCapa(DatosDB.java:131)
07-23 20:39:14.354: ERROR/Database(743): at com.android.upvar.DatosDB.inicializaCapas(DatosDB.java:180)
07-23 20:39:14.354: ERROR/Database(743): at com.android.upvar.menu.listaCapas(menu.java:52)
07-23 20:39:14.354: ERROR/Database(743): at com.android.upvar.menu.onCreate(menu.java:46)
07-23 20:39:14.354: ERROR/Database(743): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
07-23 20:39:14.354: ERROR/Database(743): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
07-23 20:39:14.354: ERROR/Database(743): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
07-23 20:39:14.354: ERROR/Database(743): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
07-23 20:39:14.354: ERROR/Database(743): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
07-23 20:39:14.354: ERROR/Database(743): at android.os.Handler.dispatchMessage(Handler.java:99)
07-23 20:39:14.354: ERROR/Database(743): at android.os.Looper.loop(Looper.java:123)
07-23 20:39:14.354: ERROR/Database(743): at android.app.ActivityThread.main(ActivityThread.java:4627)
07-23 20:39:14.354: ERROR/Database(743): at java.lang.reflect.Method.invokeNative(Native Method)
07-23 20:39:14.354: ERROR/Database(743): at java.lang.reflect.Method.invoke(Method.java:521)
07-23 20:39:14.354: ERROR/Database(743): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
07-23 20:39:14.354: ERROR/Database(743): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
07-23 20:39:14.354: ERROR/Database(743): at dalvik.system.NativeStart.main(Native Method)
07-23 20:39:14.394: ERROR/Database(743): Error inserting nombre=Departamentos id=cap002
.
.
.
So it complains about some constraint violation, but I don't see any of those. The only constraints are the primary keys and they are set to be autoincrement, so I don't understand what it is complaining about.
The first thing I think of with "constraint failed" is that something is either being inserted a NULL or you're missing a column. Nothing is being inserted as NULL in that example, and the only missing column is an autoincrement primary key.
However, unless you indicate it in some way, the database and tables are not recreated on each test. Could you be testing on a device that has an older version of those tables in it, one where the "_id" column was not autoincrement? If so, it's expecting ContentValues to also contain a value for that column.
Hm...try this idea:
Have you tried to allow writing to the database before you do the writing? SQLiteDatabase.OPEN_READWRITE
?
Like
mDb=SQLiteDatabase.openDatabase(PATH, null, SQLiteDatabase.OPEN_READWRITE);
?
I haven't worked with Android, so this could be off, but it appears you're sending the ID with the insert into CAPAS table, but it's unnececessary because you have it defined as AUTOINCREMENT.
You have:
public long createCapa(String id, String nombre) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_ID, id);
initialValues.put(KEY_NAME, nombre);
return mDb.insert(DATABASE_TABLE_CAPAS, null, initialValues);
}
What happens if you do this?
public long createCapa( String nombre) {
ContentValues initialValues = new ContentValues();
//initialValues.put(KEY_ID, id);
initialValues.put(KEY_NAME, nombre);
return mDb.insert(DATABASE_TABLE_CAPAS, null, initialValues);
}
and this:
createCapa("Escuelas");
Is it really common practice to define both _id and id in Android? When you define the pk as integer primary key in SQLite it becomes an alias for the rowid automatically. Here's how I would do it normally:
create table capas (id integer primary key autoincrement, nombre text not null);
YOU can try this it worked for me when i was getting same error for no reason
return mDb.insertWithOnConflict(DATABASE_TABLE_CAPAS, null,
initialValues,SQLiteDatabase.CONFLICT_REPLACE);
I tried all your suggestions during these 2 days and I appreciate them. But you know what? When I started Eclipse today, I run the app and I just worked out. I have no idea how, because yesterday when I finished trying it didn't work. But surprisingly it's fixed.
I'm quite happy about that, but also concerned, because that makes me feel the app is not reliable. Does these things happen usually in Android or in SQLite? Has it happened to you before? If you have some advice, please share it, because maybe it will stop working suddenly some other day, who knows?
精彩评论