I think I have checked all the previous posts on this issue but none seem to be helping me...
Basic stuff - trying to use a cursor adaptor bound to my database but I am getting:
java.lang.IllegalArgumentException: column '_id' does not exist
My schema has that column defined (although I do have 2 tables, both with the same name - is that an issue?), like this:
public static abstract class dbMain implements BaseColumns {
public static final String TABLE_NAME = "mpgMain";
public static final String ENTRY_ID = "_id";
public static final String VEHICLE_NAME = "v_name";
}
public static abstract class dbHistory implements BaseColumns {
public static final String TABLE_NAME = "mpgHistory";
public static final String ENTRY_ID = "_id";
public static final String TRIP_DATE = "date";
}
From other posts, I have put _id in my cursor porjection:
String[] projection = {dbMain.ENTRY_ID, dbMain.VEHICLE_NAME};
Cursor mpgCur = mpgDB.query(dbMain.TABLE_NAME, projection, null, null, null, null, null);
...but then my stack trace gives the same error, on the query line. If I remove the ENTRY_ID from the projection, the same error but on the later line instantiating the adaptor:
String[] fromColumns = {dbMain.VEHICLE_NAME};
int[] toViews = {R.id.displayVehicle};
SimpleCursorAdapter vehAdapter = new SimpleCursorAdapter(this,
R.layout.activity_first_screen, mpgCur, fromColumns, toViews, 0); <--- HERE
I've also tried putting a space in the CREATE TABLE command, before the _id field:
private static final String SQL_CREATE_MAIN_TABLE =
"CREATE TABLE " + dbMain.TABLE_NAME + " ( " +
dbMain.ENTRY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
Any ideas gratefully received...
If I'm not mistaken, by implementing BaseColumns, you don't have to specify "_id" in your schema. Just use the constant _ID (so, dbMain._ID and dbHistory._ID)
Related
I've been struggling a while with querying my SQLite database using one of my table field. I successfully query using the ForeignId field, but not with the Available field of my table QuizTable. I was hoping you could point out something I missed. Here is the call I make to the function queryQuiz. Please note the whereClause (kind of cut off) which is supposed to filter the available field for a value of 1. (side note: what if you want to query for different data types?)
QuizCursorWrapper cursor = db.queryQuiz(QuizTable.Cols.AVAILABLE + "=?", new String[]{"1"});
This is my queryQuiz function in a class that extends SQLiteOpenHelper.
Here's the error I am getting from calling queryQuiz:
Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
public QuizCursorWrapper queryQuiz(String whereClause, String[] whereArgs){
Cursor cursor = db.query(
QuizTable.NAME,
null,
whereClause,
whereArgs,
null,
null,
null
);
return new QuizCursorWrapper(cursor);
}
my QuizCursorWrapper class
public class QuizCursorWrapper extends CursorWrapper {
public QuizCursorWrapper(Cursor cursor){
super(cursor);
}
public String getQuiz(){
String paragraph = getString(getColumnIndex(QuizSchema.QuizTable.Cols.PARAGRAPH));
return paragraph;
}
public String getQuizUUID(){
String uuid = getString(getColumnIndex(QuizSchema.QuizTable.Cols.UUID));
return uuid;
}
}
and finally, my QuizSchema which defines the fields in my table.
public class QuizSchema {
public static final class QuizTable{
//nested class
public static final String NAME = "quizTable";
public static final class Cols{
public static final String SCORE = "score";
public static final String PARAGRAPH = "paragraph";
public static final String FOREIGNID = "foreignId";
public static final String UUID = "uuid";
public static final String AVAILABLE = "available";
}
}
}
I am very confused because I can clearly see rows with available fields equal to 1 in my quiz table . Sorry for the broad question, it's just that I can't put a finger on a problem and the debugger isn't too helpful. Please let me know if you need more info.
I believe that your issue is how column storage class/type affinity effects comparisons.
The solution is force the type affinity and thus how the comparisons are made. Forcing the type affinity can be achieved using CAST to set the type affinity.
As such a solution could be to CAST the values to type INTEGER for the comparison. You could do this by using :-
QuizCursorWrapper cursor = db.queryQuiz("CAST(" + QuizTable.Cols.AVAILABLE + " AS INTEGER) =CAST(? AS INTEGER)", new String[]{"1"});
You may wish to have a read of :-
Datatypes In SQLite Version 3
In the DB I have implemented in my Android App, some columns are designed to contain text in different languages, for example this table:
CREATE TABLE "food" (
`_id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`ID` INTEGER NOT NULL UNIQUE,
`name` TEXT NOT NULL,
`name_it` TEXT,
`name_rus` TEXT,
`description` TEXT,
`description_it` TEXT,
`description_rus` TEXT,
`kcal` INTEGER,
`icon_food` TEXT,
`image_food` TEXT,
`category_id` INTEGER,
FOREIGN KEY(`category_id`) REFERENCES category ( _id )
)
I want to use a static String to keep the name of the column, translated according to the language of the User's device
public static final class FoodEntry implements BaseColumns {
public static final Uri CONTENT_URI =
BASE_CONTENT_URI.buildUpon().appendEncodedPath(PATH_FOOD).build();
public static final String TABLE_NAME = "food";
public static final String COLUMN_ID = "ID";
**public static final String COLUMN_NAME = Resources.getSystem().getString(R.string.food_COLUMN_NAME);**
public static final String COLUMN_DESCRIPTION = "description";
public static final String COLUMN_ICON_FOOD = "icon_food";
public static final String COLUMN_CATEGORY_ID = "category_id";
public static Uri buildFoodUri(long id) {
return ContentUris.withAppendedId(CONTENT_URI, id);
}
}
Here the string.xml
<string name="food_COLUMN_NAME">name</string>
This does not work because of the following error:
Caused by: android.content.res.Resources$NotFoundException
How could I reach the goal to translate the column without touching more code? I wish to use a string resource that seems the perfect solution for my database structure
I am working on a project that containg tables in SQL and shows them in ListViews, i get "column '_id' does not exist" crush when i try to get to the activity containing the listview, i have checked other answers here and they all say i have to have a colum named "_id", and i do, what else could cause this error?
this is my constants class
final static String DB_CLIENTS_ID = "_id";
final static String DB_CLIENTS_NAME = "name";
final static String DB_CLIENTS_BALANCE = "balance";
final static String DB_CLIENTS_IDNUM = "idNum";
final static String DB_CLIENTS_TYPE = "type";
here is the hendler function that gets the curser:
public Cursor queryClients(){
db = dbOpenHelper.getReadableDatabase();
Cursor cursor = db.query(dbConstants.TABLE_NAME_CLIENTS,
null, null, null, null, null,
dbConstants.DB_CLIENTS_NAME+ " ASC");
return cursor;
}
here is the snippet that uses the curser to make the listview:
dbhendler = new dbHendler(this);
Cursor c = dbhendler.queryClients();
startManagingCursor(c);
String[] from = new String[] {dbConstants.DB_CLIENTS_ID, dbConstants.DB_CLIENTS_NAME,dbConstants.DB_CLIENTS_BALANCE};
int[] to = new int[] {R.id.account_list_id_number, R.id.account_list_client_name, R.id.account_list_balance};
adapter = new SimpleCursorAdapter(this, R.layout.account_list_line, c, from, to);
ListView lv = (ListView) findViewById(R.id.listView1);
lv.setAdapter(adapter);
what could be the problem besides having no colum named "_id"?
edit:
here is the log cat:
01-28 10:00:31.806: E/AndroidRuntime(27937): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ziv.bank_app/com.ziv.bank_app.ClientListActivity}: java.lang.IllegalArgumentException: column '_id' does not exist
edit:
code for creating table:
public void onCreate(SQLiteDatabase db) {
String sql1 = ""
+ "CREATE TABLE "+ dbConstants.TABLE_NAME_CLIENTS+ " ("
+dbConstants.DB_CLIENTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+dbConstants.DB_CLIENTS_NAME + " TEXT,"
+dbConstants.DB_CLIENTS_IDNUM + " INTEGER,"
+dbConstants.DB_CLIENTS_TYPE + " TEXT,"
+dbConstants.DB_CLIENTS_BALANCE + " REAL"
+ ")";
db.execSQL(sql1);
when first seing the problem i saw here that the answer was to have a string named "_id", i changed it in my table creation file, however a new file was never created, it would have been created on a new device/emulator but on mine it still used the one i have created.
create a new database file by simply changing its name in the table creation code, and the problem is solved.
edit:
also raising the version number would do the trick
I had similar problem this is the way I tried it out
You can give it a try :
1) first delete your database from your device or emulator
emulator : within data/data/databases
device :use adb shell and run-as command
2) create a new database with different name(not same as previous one).
Let me know if problem persists
Hope It could help you ...
If i am not wrong then try out this in your queryClients():
Cursor cursor = db.query(dbConstants.TABLE_NAME_CLIENTS, new String[] {"_id","name","balance","idNum","type"},
null, null, null, null, "name ASC ");
or Try this:
Cursor mCursor = db.query(true, dbConstants.TABLE_NAME_CLIENTS,
new String[] {"_id","name","balance","idNum","type"},
null,null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
I am trying to put together an SQL database but don't really know how to make it work. The intention is to have multiple columns, some with integers, some with strings in their cells. For this app, I want repetitions to be an integer and exercise to be a string. Here is the relevant parts of the code:
public static final String KEY_ROWID = "_id";
public static final String KEY_DATE = "date";
public static final String KEY_EXERCISE = "exercise";
public static final String KEY_REPS = "repetitions";
private static final String DATABASE_CREATE = "create table " + DATABASE_TABLE + " ("
+ KEY_ROWID + " integer primary key autoincrement, "
+ KEY_DATE + " text not null, "
+ KEY_EXERCISE + " text not null, "
+ KEY_REPS + " int not null, "
public long createExercise(String exercise, int reps) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_DATE, date);
initialValues.put(KEY_EXERCISE, exercise);
initialValues.put(KEY_REPS, reps);
return mDb.insert(DATABASE_TABLE, null, initialValues);
}
I put data in this table using test strings. Then I try to pull the data with the following query:
public Cursor graphQuery(String exercise, String workout) {
return mDb.query(DATABASE_TABLE, new String[] {KEY_DATE, KEY_REPS}, null, null,
null, null, null);
From there I try to put the data into a number array but it gives me an error. It tells me to put KEY_REPS as a number when I declared it. But if I declare KEY_REPS as a number it doesn't let me build my databes.
Cursor cursor = mDbHelper.graphQuery(currentexercise, currentworkout);
startManagingCursor(cursor);
Number[] reps = new Number[]{workoutDbAdapter.KEY_REPS}; //error here
I feel like I am missing a key part in how to create my database. Can anyone help?
Code from book I am trying to follow (except using integers) (from comment on first answer)
private void fillData() {
Cursor remindersCursor = mDbHelper.fetchAllReminders();
startManagingCursor(remindersCursor);
// Create an array to specify the fields we want (only the TITLE)
String[] from = new String[]{RemindersDbAdapter.KEY_TITLE};
That being said, if someone knows of a good website that teaches SQLite as it applies to Android that would be awesome. The only ones I have been able to find are generic SQL sites and they aren't very helpful.
Cursor cursor = mDbHelper.graphQuery(currentexercise, currentworkout);
startManagingCursor(cursor);
Number[] reps = new Number[]{WorkoutDbAdapter.KEY_REPS}; //error here
This code here doesn't do what (I think) you want it to. You need to iterate over the cursor and get the data from there. I'm pretty sure, if you followed the Android sample code for using databases that WorkoutDbAdapter.KEY_REPS is a string constant that holds reps column name.
Try doing something like this:
List<Number> allReps = new ArrayList<Number>();
Cursor cursor = mDbHelper.graphQuery(currentexercise, currentworkout);
while (cursor.moveToNext()) {
int reps = cursor.getInt(cursor.getColumnIndexOrThrow(mDbHelper.KEY_REPS));
allReps.add(reps);
}
Number[] repsArray = allReps.toArray(new Number[]{});
// do stuff with repsArray and don't forget to close cursor
i am trying to query my database so that it returns only rows with a specific value in a certain column.but when i run it, it still returns all the rows. please take a look at the code and see if i have done it incorrectly. I am trying to query for the string in the PRIORITY column. i want to display those specific rows in a listview. Thank you.
private static final String DATABASE_NAME = "MemoData.db";
private static final int DATABASE_VERSION = 1;
public static final String DATABASE_TABLE = "Places";
public static final String KEY_ID = "_id";
public static final String NAME = "Title";
public static final String CATEGORY = "category";
public static final String PRIORITY = "priority";
private static final String TAG = "DBAdapter";
private static final String DATABASE_CREATE = "create table Places (_id integer primary key autoincrement, Title text, category text, priority text);";
public Cursor priorityData(){
String[] resultColumns = new String[] {KEY_ID,NAME,CATEGORY,PRIORITY };
String[] condition = {"High"};
Cursor cursor = db.query(DATABASE_TABLE, resultColumns, KEY_ID + "=" + "?", condition, null, null, null);
if(cursor.moveToNext()){
return cursor;
}
return cursor;
}
The values for priority columns can be "Low", "Medium" or "High". i am trying to query the database to return rows whose values are set as "High" in the PRIORITY column.
I am trying to query for the string in the PRIORITY column...
So your filter should be
PRIORITY + " = ?"
instead of
KEY_ID + "=" + "?"
Also it's not a good idea to have a text column to hold values from a limited set of possibilities that you are then filtering and your last if makes no sense.
I think he meant that you should use ENUM type to your PRIORITY variable, because it has limited set of possibilities.
So it should looks something like this:
priority ENUM('LOW','MEDIUM','HIGH') NOT NULL DEFAULT 'MEDIUM'