I am trying to Query in the database.The database is not created in the app, I have created outside, and I am using as this tutorial explain. But I have an error related with column _id.
In the Class DatabaseHelper, I have the following code:
public Cursor Search(Context context,String search){
SQLiteDatabase db= getReadableDatabase();
String cursorFactory = "SELECT * FROM words WHERE eng || ' ' || rus LIKE ?";
Cursor cursor = db.rawQuery(cursorFactory, new String[]{"%" + search + "%"});
return cursor;
}
In the Activity, the code I wrote is:
public void search(View v){
text2search= searchText.getText().toString();
cursor= myDbHelper.Search(mContext, text2search);
adapter =new SimpleCursorAdapter(getBaseContext(),R.layout.list_item,
cursor,
new String[]{"rusword","engword","kind"},
new int[]{R.id.rusWord,R.id.engWord,R.id.knd});
wordsList.setAdapter(adapter);
}
And I get the error related with the _id:(in the LogCat)
09-03 14:12:38.018: E/AndroidRuntime(16581): Caused by:
java.lang.IllegalArgumentException: column '_id' does not exist
But the data base, that I create, it has the "_id" column:( I cant upload image, so here is the link https://www.dropbox.com/s/9a2ol1acrnxmzob/sql-db-rusWjpg.png )
Thank you!
So problem isn't too tricky. Some adapters, in you case SimpleCursorAdapter this adapter needs when are try to select something you need to select column _id.
So try this:
new String[] {"_id", "rusword", "engword", "kind"}
String cursorFactory = "SELECT _id, [next columns] FROM ...;
now it should works.
Similar question is here:
App Crashes On Startup Due To java.lang.IllegalArgumentException:
column '_id' does not
exist
Note: In the case you don't want to have _id column you can use this simple trick:
SELECT keyID AS _id FROM TableName
Related
I was trying to solve the question on why I was getting this error yesterday with some code:
java.lang.IllegalArgumentException: column '_id' does not exist
I had a lot more code, especially that I did not need, so I stripped a lot of it out to make it easier to understand where I am going wrong. But essentially this is my schema:
database.execSQL("CREATE TABLE events (" +
"_id INTEGER PRIMARY KEY, event_name TEXT" +
")");
As one can tell, looks fine right.
Unless I forgot to read, it's most obviously there. But then I figured out where my error was coming from, or at least I am sure this is why. This code that retrieves a cursor:
public Cursor getEventsName() {
return database.rawQuery( "SELECT event_name FROM events", null);
}
According to android, this is the error. When I change it to this:
public Cursor getEventsName() {
return database.rawQuery( "SELECT * FROM events", null);
}
Everything is peachy. When the former, it crashes. Any reason as to why this is. I thought that in rawQuery() I could do that. So long as I am not including where clauses, which I am not. Any help much appreciated.
Let's call these, event cursor:
public Cursor getEventsName() {
return database.rawQuery( "SELECT event_name FROM events", null);
}
... and * cursor:
public Cursor getEventsName() {
return database.rawQuery( "SELECT * FROM events", null);
}
Most of the answers that you have received (even the ones here: In Android, does _id have to be present in any table created?) are guessing at the likely cause for your error. I figured I would answer your question as well:
Any reason as to why (the former crashes and the later is peachy?)
The difference between the * and event cursors is that * is selecting every column implicitly and event is only selecting event_name. In your events table, the * cursor is the equivalent of:
SELECT _id, event_name FROM events;
which is why the this cursor works just peachily. In other words you are not receiving this error:
java.lang.IllegalArgumentException: column '_id' does not exist
because you are implicitly selecting the _id column with *.
Of course the most probable reason for getting this error is when you bind your data with a ListView, Spinner, etc; they all tend to use a CursorAdapter of some form. This is from the CursorAdapter documentation:
Adapter that exposes data from a Cursor to a ListView widget. The Cursor must include a column named "_id" or this class will not work.
So the Solution is simple: you must select the _id column in your query as well as the other columns that you want. (The compiler isn't lying to you.)
That being said, if this still doesn't seem valid to your app or doesn't make sense please post the code where you use the Cursor and the error is thrown.
I suspect that whatever was handling the cursor was trying to get the _ID column but it wasn't specified in your select statement. Doing something like,
public Cursor getEventsName() {
return database.rawQuery( "SELECT _id, event_name FROM events", null);
}
Some Android components, such as the SimpleCursorAdapter require the _ID be available in the select statement since it uses internally when getItemId() is called.
java.lang.IllegalArgumentException: column '_id' does not exist
I had same problem, this exception is thrown because SimpleCursorAdapter need for SELECT column named _id so you can resolve it when for example if you created some table with column KEY_ID as PK so you can try it like this:
SELECT KEY_ID AS _id, column1, column2 FROM SomeTable.
public Cursor getEventsName() {
return database.rawQuery( "SELECT * FROM events", null);
Change it to
public Cursor getEventsName(){
final String[] columns = new String[]{"_id", "event_name "};
return database.query(events, columns, "" , null, null, null, null);
}
I've written the following DB query.
However, the app crashes when I access the list activity that displays the results.
I've traced the error to the method below (other simpler query methods work just fine):
public Cursor fetchInterface_HSE_Entries(String string) throws SQLException{
String[] columns = new String[] {KEY_ROW_ID_INTERFACE, KEY_TEXTVIEW_VALUE, KEY_CATEGORY_OPTIONS, KEY_WORKSCREEN};
String whereClause = KEY_WORKSCREEN+"=" + string;
Cursor cursor = db.query(TEXTVIEWS_TABLE, columns, whereClause, null, null, null, null);
if(cursor != null){
cursor.moveToFirst();
}
return cursor;
}
And this is part of my error log:
12-31 16:13:38.851: E/AndroidRuntime(480): Caused by: android.database.sqlite.SQLiteException: no such column: testInterface1: , while compiling: SELECT _id, textviewvalue, categoryoptions, workscreen FROM interfacetable WHERE workscreen=testInterface1
Try with:
String whereClause = KEY_WORKSCREEN+"='" + string + "'";
You need to quote text values in your queries, otherwise they will be interpreted as column names (or functions, or whatever).
Note that this is not safe against SQL Injection attacks, you should be using bind variables.
String whereClause = KEY_WORKSCREEN+" = ?";
Cursor cursor = db.query(TEXTVIEWS_TABLE, columns, whereClause,
new String[]{string}, null, null, null);
Because you do not put quotes around your whereClause.
Try:
String whereClause = KEY_WORKSCREEN+"='" + string + "'";
You can clearly see it in your error log:
SELECT _id, textviewvalue, categoryoptions, workscreen FROM interfacetable WHERE workscreen=testInterface1
should be:
SELECT _id, textviewvalue, categoryoptions, workscreen FROM interfacetable WHERE workscreen='testInterface1'
SELECT _id, textviewvalue, categoryoptions, workscreen FROM interfacetable WHERE workscreen=testInterface1
As error says you don't have testInterface1 collumn in interfacetable table, i think you should have value instead of testInterface1 in your sql statement. Run your query in db, and you will see the same error.
You need to put your string value in the where clause into quotes.
Workscren is string edit your query and add single quotes. Key-workscreen+"="'+ string +'" like that
I’m trying to query a single table database that I’ve created in my code. To the best of my knowledge the database is being created correctly. The query is supposed to be used to populate a ListView but when I try to use the resulting cursor from my query to create SimpleCursorAdapter, it crashes with: java.lang.IllegalArgumentException: column '_id' does not exist. I am assuming this can be traced to the cursor, and also the cursor seems to be empty.
The database is created in the following way within the onCreate() of my implementation of a SQLiteOpenHelper:
db.execSQL("CREATE TABLE " + TABLE_NAME + " (_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, title TEXT NOT NULL, path TEXT NOT NULL);");
And then the actual query is set up and executed in my DataHelper Class which is used to interact with the database:
public Cursor selectEntryStartsWith(String partialName , String title)
{
String where = "name LIKE '" + partialName + "%' AND title LIKE '" + title + "'";
if (title== null || title.equals("")){
where = "name LIKE '" + partialName + "%'";
}
Cursor cur = mDatabase.query(TABLE_NAME, new String[] {"_id", "name", "title"}, where, null, null, null, "name");
return cur;
}
The code that uses the cursor is as follows:
Cursor cursor = mDataHelper.selectEntryStartsWith("ex", null); //get all entries that start with "ex"
String [] from = new String [] { "name", "title" };
int [] to = new int [] { R.id.name, R.id.title };
SimpleCursorAdapter adapter = new SimpleCursorAdapter(mContext, R.layout.listview_entry, cursor, from, to);
songList.setAdapter(adapter);
I'm using tabs to this last piece of code is from within the onActivityCreated() of a Fragment; I not that it might be better to extend a ListFragment, but I don't think this is the problem here in particularity.
Sorry in advance if I have missed an information that you may require, I've been banging my head on this problem for some time now.
Do you know the data is actually in the database? Run 'adb shell', cd to your data directory '/data/data/[app package name]/databases'. Then run sqlite3 [db file name]. Run some direct sql queries and make sure data exists.
If there is data there, rather than going right to the SimpleCursorAdapter, run some text queries in code, and see if you can access the results.
Once all of that works out, add the ListView stuff as a last step.
Some things to mention. If the user is typing in query values, you need to escape those statement values. Either use selectionArgs in the query statement:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String)
or use my stripped-down apache commons-lang, and the StringEscapeUtils class.
http://www.touchlab.co/blog/android-mini-commons/
Another thing to consider, although if you're not having trouble, its probably not an issue. 'name' and 'title' might be tricky keywords in sql statements.
The problem was indeed the database was not set up properly, I tried another method of inserting the data i.e. using ContentValues and inserting directly into the database, as opposed to using the precompiled insert statement I was using before.
The insert method now looks like this:
public long insert(String name, String title)
{
ContentValues cv = new ContentValues();
cv.put("name", name);
cv.put("title", title);
return mDatabase.insert(TABLE_NAME, null, cv);
/* The old code was using this precompiled statement
mInsertStatement.bindString(1, name);
mInsertStatement.bindString(2, title);
return mInsertStatement.executeInsert();
*/
}
I am stuck with SimpleCursorAdapter, I am calling my local SQLite DB and putting it into a cursor which then is passed to the SimpleCursorAdapter.
For same reason the Log Cat keeps showing this error below. I have no idea what is going on and I have been working on this for 6 hours, I didn't think SimpleCursorAdapter would be so difficult to understand.
05-28 19:47:27.524: ERROR/AndroidRuntime(9353): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nyneaxis.android.mpg/com.nyneaxis.android.mpg.userInfo}: java.lang.IllegalArgumentException: column '_id' does not exist
setArray();
rec.open();
Cursor c = rec.getAllVeh();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.userinfo, c, new String[]{c.getString(1)}, new int[]{R.id.nameTxtL});
this.setListAdapter(adapter);
rec.close();
//data adapter
public Cursor getAllVeh() {
try{
return db.query(database_table, new String[] { key_rowid, vehicle_name,
year, make, model, style, vin, plate, notes }, null, null,
null, null, null);
}finally{
}
}
Okay I have modified my code to a rawQuery and I get this error again:
05-28 22:41:48.876: ERROR/AndroidRuntime(1359): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nyneaxis.android.mpg/com.nyneaxis.android.mpg.userInfo}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 0
private static final String db_sel = "SELECT id as _id, vehicle_name FROM vehicle";
public Cursor getAllVeh() {
try{
return db.rawQuery(db_sel, null);
/*return db.query(database_table, new String[] { key_rowid, vehicle_name,
year, make, model, style, vin, plate, notes }, null, null,
null, null, null);*/
}finally{
}
}
See my answer to this question Android: column '_id' does not exist problem. It explains about the need for the _id column and how to alias it if your DB tables don't have a column with that name.
****EDIT:**** To alias the column in the DB which contains 'unique identifiers' you need to use db.rawQuery(...) instead of db.query(...). The db.rawQuery(...) method takes a SQL string which will allow you to alias the column name to '_id' which is required by the adapter. Example...
Cursor c = db.rawQuery("SELECT <my_unique_column_name> as _id, vehicle_name, ... FROM vehicles");
In the above, replace <my_unique_column_name> with the actual name of the column in the vehicles table which contains unique identifiers. Also, use the actual column names for any other columns that you're requesting the data for.
Well, as the error says your database table definition is missing the default _id column that SimpleCursorAdapter expects to use as the ID column. What is your database table defined as? Add the CREATE TABLE statement you are using to your question.
SimpleCursorAdapter relies on the presence of an _id column: if you don't have it then you'll get that error.
Thanks guys for all you help. I managed to do it a different way and it seems to work like a charm. If anyone has any question or suggestions let me know.
Cursor c = rec.getAllVeh();
while (c.moveToNext()) {
String vehName = c.getString(1);
vehInfo.add(vehName);
}
//put information into the addapter for listview
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_single_choice, vehInfo);
//applies adapter to listview
list.setAdapter(adapter);
So I have a SQliteDatabase mDb. It only has one column, and its data are Strings for previously saved inputs. I'm trying to populate all the data from mDb into a String[] for AutoCompleteTextView (so that the autocomplete is based on previous inputs), and here's my code to get all of the String.
public String[] fetchAllSearch() {
ArrayList<String> allSearch = new ArrayList<String>();
Cursor c = mDb.rawQuery("select * from " + DATABASE_TABLE, null);
c.moveToFirst();
if (c.getCount() > 0) {
do {
allSearch.add(c.getString(c.getColumnIndex("KEY")));
} while (c.moveToNext());
}
String[] foo = (String[]) allSearch.toArray();
if (foo == null) {
foo = new String[] {""};
}
return foo;
}
my CREATE_TABLE command is
private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE;
..
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
But for some reason the line mDb.rawQuery(...) is giving me "no such table found" exception, and for the life of me I can't figure out why. Any pointers?
What is the value of DATABASE_TABLE?
If it is just a table name, then the create statement is incomplete because it doesn't specify the columns.
If it is a name plus column definitions, then the select will not work.
So, you need to use different text in the two places you used DATABASE_TABLE
Try using the SQLite3 command line program to try out your SQL. E.g.,
sqlite> create table foo;
Error: near ";": syntax error
sqlite> create table foo(col);
sqlite> select * from foo(col);
Error: near "(": syntax error
sqlite>
Use SELECT column_name FROM table_name.
Avoid using * in the query as it might cause the problem related to primary key.