I am getting this error
IllegalArgumentException: column '_id' does not exist
When using a SimpleCursorAdapter to retrieve from my database, and the table does indeed have this _id column. Noticing this a common problem, I have tried to work around it given some of the solutions online but none of them work. This is my cursor query:
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.quoterow, myCursor, new String[]{"_id", "quote"}, new int[]{R.id.quote});
although I should mention the original did not include the _id column, I added this recently to try and solve the problem. Has anyone got any ideas that might help solve the problem?
Your database doesn't have to have a column called '_id' but the SimpleCursorAdaptor does need to have one returned. You can do this with an alias.
An example is that I have a table with columns...
uid,name,number
To query this for a SimpleCursorAdapter, I do this with a database rawQuery...
SELECT uid as _id,name,number FROM MY_TABLE
This works fine and supplies the necessary '_id' column to SimpleCursorAdapter.
EDIT: As far as I understand it the _id field is used as a unique key to make sure the data the cursor handles can be handled correctly by adapters and adapterviews etc.
Look at the data model in the docs for Content Providers.
Using a unique key in 'databases' of whatever kind is pretty much universal practice, and as far as I can tell, the use of the column name '_id' (or '_ID') is simply a way of standardizing and simplifying things across databases, content providers, cursors, adapters etc etc
In short, in order for these various components to work correctly, they need a data column with unique values but they must also 'know' what the name of that column is. They wouldn't 'know', so to speak, that my column name 'uid' is the one they need as opposed to my 'name' and 'number' columns.
You either don't have a column "_id" in your table or you are not including it in your query. That is what is causing the exception. You need to fix the following as well:
Your last argument for the CursorAdapter constructor is missing the to column reference for _id.
The int[] argument is an array of view ids to populate with values from the cursor. The String[] argument is an array of column names from a row the cursor points to.
You have to have an equal number of values in the from array as you do the to array. Because the data from the Cursor is being grabbed FROM the Cursor and placed TO the views. If there are not an equal number of values in each array, the adapter throws an exception because it doesn't have the right amount of information to map the data to the views.
Also, according to the JavaDoc for SimpleCursorAdapter, that constructor is deprecated because it causes queries to be executed in the UI thread. Which is bad. Use this one instead:
http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html#SimpleCursorAdapter%28android.content.Context,%20int,%20android.database.Cursor,%20java.lang.String[],%20int[],%20int%29
A simple fix would be to add ",0" to the end of the argument list.
If you are trying to use an existing sqlite database in your Android application then you need to do some prep work to get it to work properly. This blog post describes the process in detail.
http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
Related
i'm trying to find a good way to sort the search results according to relevance after performing a search with a SearchView in Android. For me relevance means the number of matches in two SQLite text columns
I'm using a CursorLoader and there the sort order can be given to the constructor at the end
CursorLoader tLoader = new CursorLoader(
getActivity(), ContentProviderM.ARTICLE_CONTENT_URI,
tProj, tSel, tSelArgs, SORT_ORDER);
(or set using the setSortOrder (String sortOrder) method)
But i need more flexibility than this because i'm looking to sort on the number of matches rather than just on one or two columns
The only solution i can see myself is to add another column in my SQLite table, do some processing, and supply that column as the sort column to the CursorLoader
Now for my question: What is the best way to supply the sort order information to the CursorLoader using SQLite syntax, avoiding having to add a new column? (And what could this SQLite code look like?) Also, i'd like to ask more in general: Is there a different solution to this problem that i've missed?
Grateful for any help! And with kind regards,
Tord
Depending on the content provider, if it just pass to the orderBy field, you can do anything.
SQLiteDatabase query
orderBy How to order the rows, formatted as an SQL ORDER BY clause
(excluding the ORDER BY itself). Passing null will use the default
sort order, which may be unordered.
you can do whatever you want, this is just the line after ORDER BY
P.S. It is totally depending on the Content Provider, it it choose to ignore the parameter, you can do nothing.
i found a "workaround" for this problem.
After investigating different ways to write sqlite code i ended up just adding a new table column just for sorting. This column simply stores an integer and is updated every time that the user performs a search, right before the CursorLoader is created
Advantages:
We can now do all of the relevance calculations in Java code
Drawbacks:
Relevance calculation is done as the search is done so if we have a large number of items it may take some time to process everything
This is the query that I use to create a table
create table site_table(
_id integer primary key autoincrement,
name_site text,
url text,
login text,
pass text
);
I called Cursor.getColumnNames() and noticed that columns order are id, login, pass, name, url.
So, if I want a value I have to get it by the index Cursor.getString(index). Until I debugged I was messing up calling the wrong index, but now I wonder, why SQLite saves that way? Why it does not follow that way I created id, name_site, url, login and pass?
Thanks
So, if I want a value I have to get it by the index
Cursor.getString(index)
So for example for this reason you should always use
c.getString(c.getColumnIndex("ColName")); // or better getColumnIndex(CONSTANT)
This method saves all of us and ensure that you never get wrong results. Generally this method is recommended and also storing COLUMN_NAMES as CONSTANTS in separated class is very, very useful and efficient practise.
Note: Order depends on projection i.e. select name, lastname from table
That data is ordered by the order your requested it in your query, not the order you created the table with. So you probably changed the order in your query that generated said cursor.
Columns order in your cursor depends on projection. To be sure you use correct column index use c.getString(c.getColumnIndexOrThrow("COLUMN_NAME")) where c is your cursor.
I just made the experience first hand:
The indices of the columns of the cursor as a result of a
SELECT * FROM mytable WHERE ...
query have sometimes (not always) a different order that what SQLITE Database Browser shows as column order in the Database Structure tab. So referencing the columns via getColumnIndex seems to be the only safe way.
I need to check if two cursors pointing at the same rows with the same values. Is it possible?
More details:
I'm loading data from my own ContentProvider
I'm sending request to server and then updating my data inside ContentProvider with new values.
If values is changed - I need to notify user that he can update data.
As per CommonsWare's deleted answer:
Iterate over the relevant columns in the Cursor, retrieve the values, and compare each.
Although you may not know in advance the type of each column, you can find out with Cursor.getType(). You can also use Cursor.getColumnNames() to get the name of each column, and the number of columns.
This information will allow you to then use the correct accessor method to obtain each value and compare.
In SQLite, rows do not have an identity separate from their column values (but the ROWID is one of these values).
What you want requires that your data has some unique column(s) as part of the cursor, either the ROWID, or some other key value that is guaranteed to have no duplicates.
Otherwise, you can never know if what you see is just two records that happen to have the same values in those columns.
I got a SQLite database and I would like to display data in a listView, I try it with a SimpleCursorAdapter:
contactAdapter = new SimpleCursorAdapter(this, R.layout.contact_row, cursor,
new String[] { MyDb.ACCOUNT_NAME },
new int[] { R.id.contactNameTv });
On this very line I get an
IllegalArgumentException: column '_id' does not exists.
Well, thanks JVM I just don't see what the heck should I do with that, because I don't even use _id column and this statement also wrong because I exported the database and opened with sqlite database opener and I can see the column _id in the database so it does exist.
Can somebody tell me when this error should appear and what is it trying to tell me ?
E D I T:
njzk2 pointed me right, I wasn't queried the "_id" column in my cursor getting func. Thanks.
App Crashes On Startup Due To java.lang.IllegalArgumentException: column '_id' does not exist
see the above sample which has same issue like this may be it will help you
Solution
You should add "_id" field when you create your table.
//example
"CREATE TABLE TABLE_NAME (_id INTEGER PRIMARY KEY AUTOINCREMENT,field1 TEXT, field2 TEXT, etc TEXT)";
The Cursor must include a column named "_id" or this class will not work.
Additionally, using {#link android.database.MergeCursor} with this class will not work if the merged Cursors have overlapping values in their "_id"
columns.
Warning!!
SimpleCursorAdapter this constructor was deprecated in API level 11. This option is discouraged, as it results in Cursor queries being performed on the application's UI thread and thus can cause poor responsiveness or even Application Not Responding errors. As an alternative, use LoaderManager with a CursorLoader.
http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html
An alternative is to use CursorAdapter and CursorLoader.
CursorAdapter is very useful when you work with databases for example if you want to show a list of data in ListView, GridView or RecyclerView directly from a database.
CursorLoader runs an asynchronous query in the background!
http://developer.android.com/reference/android/content/CursorLoader.html
I hope it helps you!!
cheers.
Here's an interesting question that I'm shocked hasn't been asked more often on the internet. Android's CursorAdapters are extremely useful once you get a ContentProvider up and running and learn how to use it, but they are limited due to their requirement on having the _id field as part of their query (an error is thrown without it). Here's why:
My specific problem is that I have two spinners: One spinner should contain unique "category" names from the database, and the other should populate with all the database entries from the selected "category" (category being the column name, here). This seems like a pretty simple setup that many programs might use, no? Trying to implement that first spinner is where I've run into problems.
Here's the query that I would like for that first spinner:
SELECT DISTINCT category FROM table;
Making this query throws an error on CursorAdapter because the _id column is required as part of the query. Adding the _id column to the projection naturally returns every row of the table, since you're now asking for distinct id's as well, and every id is distinct (by definition). Obviously I would rather see only one entry per category name.
I've already implemented a work around, which is to simply make the query above and then copy the results into an ArrayAdapter. My reason for this post is to see if there was a more elegant solution to this odd little problem and start a discussion on what I could be doing better. Alternate implementation suggestions, such as using different kinds of controls or adapters, are very welcome.
Here's the query I ended up with:
SELECT _id, category FROM table_name GROUP BY category;
I used the rawQuery() function on an SQLiteDatabase object to carry this out. The "GROUP BY" piece was the key towards getting the right results, so thanks to user Sagar for pointing me in the right direction.
Do consider user Al Sutton's answer to this question as well, as it may be a more elegant solution to this problem.
Thanks everyone!
I'd suggest having a separate table with just _id & category in it which contains one row per unique category. Your data rows can then replace their category field with the _id from the category table.
This has the added advantage you can change the category in the categories table and it will show up in all entries in that category.
SELECT DISTINCT category,_id FROM table GROUP BY category;
I think this should give you what you are looking for. The results from this will be the category, and the first _id for that category. You can ignore the second column (_id).
You can specify an _id field alias in your select statement that is just a constant value, for example:
SELECT DISTINCT 0 _id, category FROM table;
Better yet, I solved this problem by using:
SELECT DISTINCT category AS _id FROM table
Now, you have a column with the name _id which has what you want in it