Android SqLite no such column _id exception - android

Don't immediately flag me for a duplicate question. My issue is different because I have a correctly formatted SQL query.
public static final String TABLE_NAME = "log";
public static final String COLUMN_ID = "_id";
public static final String LOG_TEXT = "logtext";
private static final String TABLE_CREATE = "CREATE TABLE " + TABLE_NAME + " (" +
COLUMN_ID + " integer primary key autoincrement, " +
LOG_TEXT + " TEXT not null);";
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TABLE_CREATE);
}
and I query here
String[] columns = {LOG_TEXT,COLUMN_ID};
Cursor cursor = helper.getReadableDatabase().query(TABLE_NAME, columns, null, null, null, null, COLUMN_ID + " desc");
and I catch this the exception generated containing the sql query.
catch(Exception e){
Log.D("sql Exception",e.getMessage());}
and it returns
no such column: _id: , while compiling: SELECT logtext, _id FROM log ORDER BY _id desc
I'm familar with Oracle SQL and relational databases in general. Is it my ORDER BY clause? I was certain you can ALWAYS use order by. It doesn't have the same behavior as GROUP BY.
Any ideas on why the exception?
Incase anyone wants to see i'm updating with my ArrayAdaptor statements. I'm using the cursor in a listview
String[] data = query();
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, data);
listView.setAdapter(adapter);}

Rewrite
Whenever you change the schema in TABLE_CREATE you must inform you app of these changes, they will not happen automatically when you change TABLE_CREATE. The easiest way to do this is to increment your database_version in your extended SQLiteOpenHelper class. You discovered you can also uninstall / reinstall the app, for the same results. If you are savvy with SQL you could ALTER the table. But whatever the method you must make sure that you app makes the schema changes before trying to access the new columns...
Also for SQLite:
_id integer primary key
is synonymous with:
_id integer primary key autoincrement not null
And queries use descending as the default order, so ORDER BY _id is the same as ORDER BY _id DESC.

Had the same problem, meaning it should have worked but didn't (had some typos in the create command that I fixed but that still didn't help). A colleague then told me to try clearing the data (just at AppInfo and then "Clear Data") which solved my problem, apparently the old database (that didn't work) was still there and had to be cleared out first.
I just put this answer here in case anybody else like me (android beginner) stumbles across this problem, because I went through dozens of stackoverflow threads with this problem but not one offered this possibility/solution and it bothered me for quite some time.

Did you add the definition of the _id column to your create statement later on, i.e. after the code had already been run once? Databases are persisted files, so if you modify the table structure in your code you need to make sure you clear your application's data so the database file can ge re-created with the correct table/column data.

Related

android SQLiteException: no such column on custom roms

On devices with modified android versions i get this error. For example on Xiaomi devices.
String query = "select * from dialogues where userId = ? and topChat = 0 order by updatedAtByClient desc";
Cursor dialogRes = db.rawQuery(query, new String[]{userId});
Here i get exception:
android.database.sqlite.SQLiteException: no such column: topChat (code 1):,
while compiling: select * from dialogues where userId = ? and topChat = 0
order by updatedAtByClient desc
I have written the exception message by hand, because the user has sent me it in a screenshot, so there might be typos.
How can this be fixed, and why does this happen?
UPD1:
the create table statement looks similar to this:
"CREATE TABLE IF NOT EXISTS dialogues(fieldName VARCHAR, camelCaseFieldName VARCHAR,
topChat INTEGER, createdAt DATE);";
And i have a correctly implemented update method for when im changing the DB structure, but this particular table and field name did not change for a long time.
UPD2:
i have made an apk for the user with problems, that logs that table columns, and i did see the problematic column in the log, and user says that this version works ok.
So seems that this error does not happen 100% of times. Very strange. Maybe there is a way to check the database for integrity after creating it, and recreate tables with errors?
I don't believe this would be a xiaomi issue. it rather seems be the result of an unfortunate migration, where a new column had not been added and subsequently, the user might still work with the previous version of the table. and there is no other logical explanation for an absent column), simply because either the CREATE TABLE statement works - or it doesn't.
one can still work around it with ALTER TABLE. eg. when that SQLiteException occurs, addColumnIfNotExists("dialogues", "topChat", "INTEGER DEFAULT 0"); ...in order not to cause data-loss by dropping the table, only because it lacks some column.
public void addColumnIfNotExists(String tableName, String columnName, String dataType) {
Cursor cursor = null;
try {
cursor = db.rawQuery("SELECT * FROM " + tableName, null);
if(! Arrays.asList(cursor.getColumnNames()).contains(columnName)) {
db.execSQL(String.format("ALTER TABLE %s ADD COLUMN %s %s", tableName, columnName, dataType));
}
} finally {
if(cursor != null) {
cursor.close();
}
}
}

Android Database Writing error

I got an app that as an internal database, and the app crashes with this error :
04-30 20:46:30.836 1647-1647/prosis.guiatour E/SQLiteLog﹕ (1) no such column: Basílica_Santa_Luzia
and the code that this is refering to is :
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_QUERY);
Log.e("Database Operations"," Table Created....");
db.execSQL(addingInfo("Basílica_Santa_Luzia", "Stuff", "10.43597", "-10.5747"));
Log.e("Database Operations"," Data Inserted");
}
public String addingInfo(String nome, String cat, String lat, String longi){
String Query = "INSERT INTO "+ Table_name+" VALUES("+nome+","+cat+","+lat+","+longi+");";
return Query;
}
And this is my contructer query :
private static final String CREATE_QUERY = "CREATE TABLE "+ Contract.NewLocalInfo.Table_name+" ("+ Contract.NewLocalInfo.Nome+" TEXT,"+ Contract.NewLocalInfo.Categoria+" TEXT,"+ Contract.NewLocalInfo.Latitude+" TEXT,"+ Contract.NewLocalInfo.Longitude+" TEXT);";
I think the SQL is well Writen so what do you think is the problem here?
Your SQL would not be valid. Based on your function, you would get:
INSERT INTO table_name VALUES(Basilica_Santa_Luzia,Stuff,10.43,10.57)
which is not valid. You have to single-quote strings like:
INSERT INTO table_name VALUES('Basilica_Santa_Luzia','Stuff','10.43','10.57')
But, you should not be writing any SQL unless you have complex requirements. You should use what's built into Android or get a third-party option.
Writing an SQL Query string creates security risks and causes errors like this one.
To insert, instead do:
ContentValues cv = new ContentValues();
cv.put("key","value");
cv.put("key2","value2");
db.insert("table_name",cv);
This approach will automatically escape any paramaters and guarantee that your query is not erroneous.
Also, the latitude and longitude probably should not be Strings. I don't remember for sure, but what I think you need is double for the Java/Android side and in normal SQL, you would need a decimal datatype on the column, but its SQLite and I'm not sure what you're supposed to do for a decimal column in sqlite, so maybe Duck it.
Also, I made a database manager class which wraps the SQLiteOpenHelper class to ensure synchronization and thread safety, which can simplify your life a ton and prevent tons of errors.
Add single quote around all values then this insert will work. Final query should be like below
INSERT INTO TABLE_NAME VALUES('Basílica_Santa_Luzia','Stuff','10.43597','-10.5747');

Inserting or Updating into SQLite but only updating if one of the values meets a condition [duplicate]

This question already has answers here:
INSERT IF NOT EXISTS ELSE UPDATE?
(9 answers)
Closed 9 years ago.
I want to insert a record, unless it exists, then I want to update that record if its COLUMN_GENERATION value is less than that of the existing record. I'm not sure how to structure the query, or what command to use, even.
I setup my database like this:
public static final String TABLE_SEARCH = "SearchTable";
public static final String COLUMN_OWNER = "Owner";
public static final String COLUMN_SPOUSE = "Spouse";
public static final String COLUMN_CHILD = "Child";
public static final String COLUMN_GENERATION = "Generations";
private static final String DATABASE_NAME = "searches.db";
private static final int DATABASE_VERSION = 1;
// Database creation sql statement
private static final String DATABASE_CREATE = "CREATE TABLE "
+ TABLE_SEARCH + "("
+ COLUMN_OWNER + " INTEGER PRIMARY KEY, "
+ COLUMN_SPOUSE + " INTEGER DEFAULT 0, "
+ COLUMN_CHILD + " INTEGER DEFAULT 0, "
+ COLUMN_GENERATION
+ " INTEGER DEFAULT 0);";
And this is the query I"m using now, which just ignores conflicting entries:
values.put(SearchDatabaseHelper.COLUMN_OWNER, personID);
values.put(SearchDatabaseHelper.COLUMN_SPOUSE, spouseID);
values.put(SearchDatabaseHelper.COLUMN_CHILD, childID);
values.put(SearchDatabaseHelper.COLUMN_GENERATION, gens);
long insertID = database.insertWithOnConflict(SearchDatabaseHelper.TABLE_SEARCH, null, values, SQLiteDatabase.CONFLICT_IGNORE);
I tried putting a query to just search the database first, and insert or update as needed, but that was really slow and didn't actually work. I'd sure appreciate some help on this.
Wow-- closed down as a duplicate question. No real answers. I'm concerned that I didn't properly word the title to my question and so people just skimmed that and didn't read what I was asking.
Nobody seemed to notice the key phrase in the first paragraph of:
"I want to update that record if its COLUMN_GENERATION value is less than that of the existing record."
I can insert/update databases. The underlying question is, "Is it possible to make a single query that looks to see if a row exists in the database with my primary key, and if it doesn't, inserts, and if it does, then updates only if the stored value of one of the columns is higher than the inputted data?"
I really want to be able to do this all within a single SQLite call, as SQLite is so much faster than comparing and decision making outside of SQLite.
Read the generation of the existing record from the DB.
If it exists and has a lower generation, delete it.
If it did not exist or had a lower generation, insert the new one.
The various INSERT OR XXX commands only work for specific common cases; for your algorithm, you have to write it out.
Just write the commands correctly and wrap a transaction around them, and it will work, fast.

onCreate not being called after getWritableDatabase/getReadableDatabase

My app's got a database with three tables in it: one to store the names of the people it tracks, one to track an ongoing event, and one - for lack of a better term - for settings.
I load the first table when the app starts. I ask for a readable database to load in members to display, and later I write to the database when the list changes. I've had no problems here.
The other two tables, however, I can't get to work. The code in the helper classes is identical with the exception of class names and column names, and (at least until the point where I try to access the table) the code to use the table is nearly identical as well.
Here's the code for my helper class (I've got a separate helper for each table, and as I said, it's identical except for class names and columns):
public class db_MembersOpenHelper extends SQLiteOpenHelper
{
public static final String TABLE_NAME = "members_table";
public static final String[] COLUMN_NAMES = new String[] {
Constants.KEY_ID,
"name",
"score"
};
private static final String TABLE_CREATE = "CREATE TABLE " + TABLE_NAME + " ("
+ COLUMN_NAMES[0] + " INTEGER PRIMARY KEY autoincrement, "
+ COLUMN_NAMES[1] + " TEXT, "
+ COLUMN_NAMES[2] + " INTEGER);";
public db_MembersOpenHelper(Context context)
{
super(context, Constants.DATABASE_NAME, null, Constants.DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE); }
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
Log.w("TaskDBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + ".");
// Do nothing. We do not have any updated DB version
}
}
Here's how I use it successfully:
db_MembersOpenHelper membersDbHelper = new db_MembersOpenHelper(this);
SQLiteDatabase membersDb = membersDbHelper.getReadableDatabase();
Cursor membersResult = membersDb.query(TABLE_NAME, null, null, null, null, null, null);
members = new HashMap<String, Integer>();
membersResult.moveToFirst();
for(int r = 0; r < membersResult.getCount(); r++)
{
members.put(membersResult.getString(1), membersResult.getInt(2));
membersResult.moveToNext();
}
membersDb.close();
And here's where it fails:
db_PlayersOpenHelper playersDbHelper = new db_PlayersOpenHelper(this);
final SQLiteDatabase playersDb = playersDbHelper.getWritableDatabase();
if(newGame)
{
for(String name : players)
{
ContentValues row = new ContentValues();
row.put(COLUMN_NAMES[1], name);
row.put(COLUMN_NAMES[2], (Integer)null);
playersDb.insert(TABLE_NAME, null, row);
}
}
The first one works like a charm. The second results in ERROR/Database(6739): Error inserting achievement_id=null name=c
android.database.sqlite.SQLiteException: no such table: players_table: , while compiling: INSERT INTO players_table(achievement_id, name) VALUES(?, ?);
...
I did do some testing, and the onCreate method is not being called at all for the tables that aren't working. Which would explain why my phone thinks the table doesn't exist, but I don't know why the method isn't getting called.
I can't figure this out; what am I doing so wrong with the one table that I accidentally did right with the other?
I think the problem is that you are managing three tables with with three helpers, but only using one database. SQLiteOpenHelper manages on database, not one table. For example, it checks to see whether the database, not table, exists when it starts. It already does, so onCreate() does not fire.
I would manage all tables with one helper.
Let me see if I get this right. You are trying to create one database with three tables. But when you create the database, you create just one table; you are somehow instantiating the same database at a different place and wonder why its onCreate method doesn't get called. Is this a correct interpretation?
My strategy would be to try and create all three tables in the single onCreate() method.
If you are working with multiple tables, then you have to create all of the tables at once. If you have run your application first and later you update your database, then it will not upgrade your DB.
Now delete your application, then run it again.
There is one more solution but it is not proper. You can declare onOpen method in which you can call onCreate. And add IF NOT EXISTS before table name in your create table string. – Sourabh just now edit

why does db.insert() giving the sqliteconstraintexception error 19 constraint failed

I have read most of the questions related to this exception but none of them are clear or indicative of why db.insert would throw this error. It was working fine without errors until I manually deleted the db from DDMS. Following is my SQLiteOpenHelper code:
public class LoginSQLiteOpenHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "logincredentials.sqlite";
public static final int DB_VERSION_NUMBER = 1;
public static final String DB_TABLE_NAME = "credentials";
public static final String USERNAME = "user_name";
public static final String PASSWORD = "password";
private static final String DB_CREATE_SCRIPT = "create table " + DB_TABLE_NAME +
"( _id integer primary key autoincrement," +
USERNAME + " text not null, " +
PASSWORD + " text not null );" ;
public LoginSQLiteOpenHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION_NUMBER);
}
#Override
public void onCreate(SQLiteDatabase aSqliteDB) {
Logger.d("Create", "Creating the database...");
aSqliteDB.execSQL(DB_CREATE_SCRIPT);
}
}
My code for inserting the values is:
ContentValues contentValues = new ContentValues();
contentValues.put(LoginSQLiteOpenHelper.USERNAME, loginId);
contentValues.put(LoginSQLiteOpenHelper.PASSWORD, password);
database.insert(LoginSQLiteOpenHelper.DB_TABLE_NAME, null, contentValues);
This is why it occurred to me. If you declare one of your column name type as UNIQUE in your Create Table query in Database and try to insert a non unique variable, it invokes SQLiteConstraintException error.
A UNIQUE constraint is similar to a PRIMARY KEY constraint, except that a single table may have any number of UNIQUE constraints. For each UNIQUE constraint on the table, each row must feature a unique combination of values in the columns identified by the UNIQUE constraint. As with PRIMARY KEY constraints, for the purposes of UNIQUE constraints NULL values are considered distinct from all other values (including other NULLs). If an INSERT or UPDATE statement attempts to modify the table content so that two or more rows feature identical values in a set of columns that are subject to a UNIQUE constraint, it is a constraint violation. Source - http://www.sqlite.org/lang_createtable.html
I have read pretty much all forums looking for an exact reason for the occurrence of this exception. However, nowhere it clearly states so. However, by means of this code of mine, I can explain why it ocurred for me.
The code snippet I provided, is actually flawless. I am doing exactly what is required to do a db.insert().
However, i figured out the exception in 2 steps.
1. first time when i inserted values, I did not insert a value for the column Password.
2. second time, I added a value for column for Password, but due to incorrect passing of values it was null.
hence, I deduced from this exercise, that no column are allowed null values. You must initialize them with some value.
Please feel free to comment/add or correct me if I am wrong. I would like anyone else running into this issue to be clear on it as there are no good documentation on this exception.

Categories

Resources