I know you have many questions on here about this error, but I cannot understand why all the fields appears to be filled correctly on Logcat, but even so the failure occurs.
Here is the creation of the table:
public void onCreate(SQLiteDatabase db) {
String ddl = "CREATE TABLE Politician (id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE , idpolitician INTEGER NOT NULL, name TEXT NOT NULL, picture TEXT , position TEXT NOT NULL, country TEXT NOT NULL, state TEXT NOT NULL, city TEXT NOT NULL);";
db.execSQL(ddl);
}
Here is where I tried to save.
public void savePolitician(Politician politician) {
ContentValues values = new ContentValues();
values.put("idpolitician", politician.getId());
values.put("name", politician.getName());
values.put("picture", politician.getPictureFilename());
values.put("position", politician.getPosition());
values.put("country", politician.getCountry());
values.put("state", politician.getState());
values.put("city", politician.getCity());
mDatabase.insert("Politician", null, values);
}
And here is the LogCat:
01-08 04:03:31.149 32633-32633/? E/Database﹕ [SQLiteDatabase.java:1428:insert()] Error inserting
state=SP position=governador picture=example idpolitician=1 city=Sao Paulo country=Brasil name=Alckmin
android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1582)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1426)
at com.politify.dao.DbManegament.savePolitician(DbManegament.java:44)
As you can see all the fields are filled. Anyone can help and tell what i`m doing wrong
try remove AUTOINCREMENT UNIQUE inyour create table script
This is your mistake id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE
When you are defining any column as Primary Key then you do not need to specify it as UNIQUE. Primary Key is by default UNIQUE.
Related
I wonder what's wrong with my sql syntax.Its working on mysql but for sqlite gives me error.
CREATE TABLE IF NOT EXISTS `points` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET latin1 NOT NULL,
`longitude` double NOT NULL,
`latitude` double NOT NULL,
`radius` double NOT NULL,
`image` blob NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=4;
INSERT INTO `points` (`id`, `name`, `longitude`, `latitude`, `radius`, `image`)
VALUES (1, 'Isfahan, Iran', 51.678314, 32.65036, 0.064486,
0xffd8ffe000104a46494600010001009600960000fffe001f4c45414420546563686e6f6c6f6769657320496e632e2056312e303100ffdb008400100b0c0e0c0a100e0d0e1211101318281a181616183123251d283b343e3d3a34393841495d4f414558463839516f52586063696a693f4e737b72667a5d676964011112121815182f1a1a2f644339436464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464ffc4003000000203010000000000000000000000000001020304050101010101010100000000000000000000000102030405ffc20011
It should be AUTOINCREMENT as one word.
You dont require this statement: ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=4; which is MySQL specific. Further more, if you are setting the autoincrement value to start from 5, then you shouldn't be inserting an id of value equal to 1.
You do not seem to have a closing bracket after the insert statement.
You should instead try:
CREATE TABLE IF NOT EXISTS `points` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`name` varchar(50) CHARACTER SET latin1 NOT NULL,
`longitude` double NOT NULL,
`latitude` double NOT NULL,
`radius` double NOT NULL,
`image` blob NOT NULL
);
INSERT INTO `points` (`id`, `name`, `longitude`, `latitude`, `radius`, `image`)
VALUES (1, 'Isfahan, Iran', 51.678314, 32.65036, 0.064486,
0xffd8ffe000104a46494600010001009600960000fffe001f4c45414420546563686e6f6c6f6769657320496e632e2056312e303100ffdb008400100b0c0e0c0a100e0d0e1211101318281a181616183123251d283b343e3d3a34393841495d4f414558463839516f52586063696a693f4e737b72667a5d676964011112121815182f1a1a2f644339436464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464ffc4003000000203010000000000000000000000000001020304050101010101010100000000000000000000000102030405ffc20011);
There could be more fixes required as well. Back tick though recognized by SQLite, is a MySQL specific quoting.
I havea weird problem in my android application which is related to database relations on foreign keys. The following codes describe my simple database's structure,
i have used SQLiteOpenHelper as a super class for handle database operation
private static final String CATEGORIES_TABLE = "CREATE TABLE __CATEGORIES_TBL(_id INTEGER PRIMARY KEY AUTOINCREMENT, _name TEXT NOT NULL, _desc TEXT NULL,"
+ "_create_date INTEGER NOT NULL, _update_date INTEGER NULL"
+ ", _parent_id INTEGER NULL, FOREIGN KEY(_parent_id) REFERENCES __CATEGORIES_TBL(_id) ON DELETE RESTRICT);";
private static final String CARDS_TABLE = "CREATE TABLE __CARDS_TBL(_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "_value TEXT NOT NULL, _play_count INTEGER NULL, "
+ "_category_id INTEGER NOT NULL, FOREIGN KEY(_category_id) REFERENCES __CATEGORIES_TBL(_id) ON DELETE RESTRICT);";
#Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL("PRAGMA foreign_keys = ON;");
db.execSQL(CATEGORIES_TABLE);
db.execSQL(CARDS_TABLE);
Logger.i("DB-INIT-DONE!");
} catch (Exception ex) {
Logger.e("Database on create error", ex);
}
}
as you see everything seems to be O.K and it is; I can insert, edit , select row(s) to/from both tables but unfortunately i can delete rows which they have child rows.
as i expected. because i set the FK (foreign-key) relation between the tow tables with ON DELETE RESTRICT mode therefore i expect to get an exception when i try to delete a row from parent table (__CATEGORIES_TBL) , actually the parent record is deleting and no exception happens,
by theory sqlite must prevent deleting any row in __CATEGORIES_TBL when it has one or more child row(s) in __CARDS_TBL or any child row(s) in __CATEGORIES_TBL but in my application i can delete rows when it has a parent-child relationship rows,
consider the following code (this is the deleting code)
private SQLiteDatabase db;
public long delete(long objId) {
try {
// TABLE_NAME can be __CATEGORIES_TBL or __CARDS_TBL based on program flow
return db.delete(TABLE_NAME, COLUMN_ROWID + "=" + objId, null);
} catch (Exception e) {
Logger.d("Unable to delete category <" + objId + ">.", e);
return -123456;
}
}
every call to db.delete returns 1 (means 1 row is deleted by this command) this code is executing under android 2.3 ;
Thanks in advance.
I get the behavior I'd expect from SQLite 3.7.9.
sqlite> CREATE TABLE __CATEGORIES_TBL (
...> _id INTEGER PRIMARY KEY AUTOINCREMENT,
...> _name TEXT NOT NULL,
...> _desc TEXT NULL,
...> _create_date INTEGER NOT NULL,
...> _update_date INTEGER NULL,
...> _parent_id INTEGER NULL,
...> FOREIGN KEY(_parent_id)
...> REFERENCES __CATEGORIES_TBL(_id) ON DELETE RESTRICT
...> );
sqlite>
sqlite> CREATE TABLE __CARDS_TBL(
...> _id INTEGER PRIMARY KEY AUTOINCREMENT,
...> _value TEXT NOT NULL,
...> _play_count INTEGER NULL,
...> _category_id INTEGER NOT NULL,
...> FOREIGN KEY(_category_id)
...> REFERENCES __CATEGORIES_TBL(_id) ON DELETE RESTRICT
...> );
sqlite>
sqlite> insert into __categories_tbl values
...> (1, 'name', 'desc',current_date,current_date,1);
sqlite> insert into __cards_tbl values (1, 'value',3, 1);
sqlite> pragma foreign_keys=on;
sqlite> select * from __categories_tbl;
1|name|desc|2012-08-25|2012-08-25|1
sqlite> delete from __categories_tbl;
Error: foreign key constraint failed
If I were you, I'd try to visually inspect the SQLite database after each step to see whether what you expect to happen is actually happening. IIRC, not every failure will raise an exception.
Foreign key support was introduced in version 3.6.19. There are compile-time settings that allow SQLite to parse foreign key constraints, but don't allow it to actually enforce them. (SQLITE_OMIT_TRIGGER defined, SQLITE_OMIT_FOREIGN_KEY not defined.) You should be able to tell whether your build of SQLite can enforce foreign keys by trying to create a trigger.
If creating a trigger fails with a parse error, then SQLite will parse foreign key statements, but won't enforce them. You'll need to recompile your build of 3.6.19, or upgrade to a newer version. (And check those settings before you compile.)
A column declared NOT NULL can appear to be empty if you've inserted an empty string. By default, NULL and empty strings look identical on output. You can tell whether a column contains nulls by selecting them.
select * from table_name where column_name is null;
about this problem i have put a db.execSQL("pragma foreign_keys=on;"); before delete statement in my app code then the problem solved, but i think this is unnecessary code maybe my phone's installed sqlite configs are wrong and needs to be reconfigured , is it possible to reconfigure the sqlite on phone ?
the test device is a HTC wildfire s (running sqlite version is 3.7.2)
I want to enter name and phone number from two edit text.i use two buttons to save and show it in emulator using list view.After entering name and when i click save button how to check whether i have already entered the same name. i am new to android explanation will be really helpful.
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE "+tbname+"("+Key_id+" INTEGER PRIMARY KEY AUTOINCREMENT, "+Key_name+" TEXT,"+Key_mobile+" TEXT)");
}
public void n(String aa, String bb) {
SQLiteDatabase db=this.getWritableDatabase();
ContentValues cv=new ContentValues();
cv.put(Key_name, aa);
cv.put(Key_mobile, bb);
db.insert(tbname, Key_name, cv);
db.close();
}
public Cursor cr()
{
SQLiteDatabase db=getReadableDatabase();
String [] colms=new String[]{Key_id+" as _id",Key_name,Key_mobile};
Cursor cur=db.query(tbname, colms, null, null, null, null, null);
cur.moveToFirst();
return cur;
}
I would start with changing your table definition by adding the NOT NULL and UNIQUE constraints.
db.execSQL("CREATE TABLE "+tbname+"("+Key_id+" INTEGER PRIMARY KEY AUTOINCREMENT, "+Key_name+" TEXT NOT NULL UNIQUE,"+Key_mobile+" TEXT)");
Then you have a choice of methods to use for your insert. You can use:
insertOrThrow will return the id of your new record, or -1 on an error (and a constraint failure of not having a unique name would be an error).
insertWithOnConflict will return the id of the new record OR the primary key of the existing row if the input param 'conflictAlgorithm' = CONFLICT_IGNORE OR -1 if any error.
Personally, I would use insertWithOnConflict with the CONFLICT_IGNORE flag set. That way you can get the row id back for the duplicate record (as well as not letting the duplicate get entered).
Put UNIQUE in your table field definition an then use insertOrThrow. If you insert the same, insertOrThrow will cause an exception, you can intercept it.
I'm trying to build a database using 21 tables each bind with constraints. I have implemented the database in PHPmyAdmin and then download the structure script to import in my Android SQLite database.
But I would like to know what are the good practices in building relational databases with many tables in Android, and how to create them.
currently I have a class implementing SQLiteOpenHelper:
public class SqlSig extends SQLiteOpenHelper {
#Override
public void onCreate(SQLiteDatabase db) {
for(int i = 0; i != ConfigBDD.requetes.length; i++){
db.execSQL(ConfigBDD.requetes[i]);
}
}
}
ConfigBDD.requetes[i] fetch a string array containing tables creation requests and constraints requests. This code doesn't work at all, and logCat show an error with the PRIMARY KEY instruction:
05-29 15:13:51.992: E/Database(8187): Failure 1 (near "KEY": syntax error) on 0x15c4b8
when preparing 'CREATE TABLE IF NOT EXISTS `arret` ( `id` int(11) NOT NULL , `id_externe`
varchar(10) DEFAULT NULL, `id_pid` int(11) NOT NULL, `nom` varchar(50) NOT NULL,
`description` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), KEY `id_pid` (`id_pid`) )
DEFAULT CHARSET=utf8 =1 ;'.
I am pretty sure there are other ways to create this database but did not found any explanations about multi tables Android SQLite database creation...
Your:
CREATE TABLE IF NOT EXISTS `arret` (
`id` int(11) NOT NULL ,
`id_externe` varchar(10) DEFAULT NULL,
`id_pid` int(11) NOT NULL,
`nom` varchar(50) NOT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_pid` (`id_pid`))
DEFAULT CHARSET=utf8 =1 ;
should probably look something like this if you want it to work in SQLite.
CREATE TABLE IF NOT EXISTS arret (
id INTEGER PRIMARY KEY NOT NULL ,
id_externe TEXT DEFAULT NULL,
id_pid INTEGER NOT NULL,
nom TEXT NOT NULL,
description TEXT
);
followed by a CREATE INDEX for your id_pid which is what KEY implies in MySQL.
I'm creating a dataBase to insert a *unique patient *(no more than one), so I just created a database that doesn't autoincrement its id like this:
CREATE TABLE IF NOT EXISTS PACIENTE(idPaciente INTEGER PRIMARY KEY, nombre VARCHAR(100) NOT NULL, apellidos VARCHAR(100), email VARCHAR(100), genero CHAR, edad INTEGER NOT NULL, peso INTEGER, kMedico INTEGER, pkHistorial INTEGER, pkConfProg INTEGER, altura INTEGER, FOREIGN KEY (pkMedico) REFERENCES MEDICO(idMedico), FOREIGN KEY (pkHistorial) REFERENCES HISTORIAL(idHistorial), FOREIGn KEY (pkConfProg) REFERENCES CONFPROGRAMA(idConf));
As you can see, the way to add a patient here is tell the database the idPaciente explicitly.
So I used this code to insert a patient:
public long addPaciente(BDPaciente pac)
{
ContentValues cv = new ContentValues();
cv.put("idPaciente", 1);
cv.put("nombre", pac.getNombre());
cv.put("edad", 26);
try
{
db.insert("PACIENTE", null, cv);
return -1;
}
catch (SQLiteConstraintException e)
{
return -100;
}
}
As you can see, what I'm trying to do is insert a patient, and then, if it is inserted before, catch the Exception and throw it to my parent Window. The thing is that, the exception is thrown, but not catched. And the program says:
Error inserting nombre=blabla edad=25 idPaciente=1
android.database.SQLiteConstraintException: error code 19: constraint failed
I know that it's something about the duplication on the primary key, but I wanna do so!
Flo, thanky you for your answer, but yes, I created the table, but what I didn't post, is that I have a method for erasing all databases and then creating them again whenever I press a button like this:
db.execSQL(DROP_TABLE_HISTORIAL);
db.execSQL(DROP_TABLE_MEDICO);
db.execSQL(DROP_TABLE_CONF);
db.execSQL(DROP_TABLE_PACIENTE);
So yes, I'm sure. But what Sarmand answered works for me, so thank you for your help :-)
Sorry, but I can't vote... Don't have enough points >_<
If you want to duplicate primary key then dont declare it as primary key. Do it like this
CREATE TABLE IF NOT EXISTS PACIENTE(idPaciente INTEGER , ....);