Android SQLite ordering table columns differently - java

I'm setting up an SQLite Database and I've got most things set up how I think they're supposed to be. The main error has to with a column not being where it should be. I initialized the database column names in strings like so:
public static final String KEY_ROWID = "_id";
public static final String KEY_SPORT = "given_sport";
public static final String KEY_NAME = "given_name";
public static final String KEY_DATE = "given_date";
public static final String KEY_TIME = "given_time";
public static final String KEY_PERIOD = "given_period";
public static final String KEY_LOCATION = "given_location";
When it was time to create a table with the column names:
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_SPORT + " TEXT NOT NULL, " +
KEY_NAME + " TEXT NOT NULL, " +
KEY_DATE + " TEXT NOT NULL, " +
KEY_TIME + " TEXT NOT NULL, " +
KEY_PERIOD + " TEXT NOT NULL, " +
KEY_LOCATION + "TEXT NOT NULL);"
);
The problem now is that I'm getting the following error:
05-27 04:13:01.448: E/Database(273): android.database.sqlite.SQLiteException: table groupTable has no column named given_location: , while compiling: INSERT INTO groupTable(given_location, given_time, given_date, given_period, given_sport, given_name) VALUES(?, ?, ?, ?, ?, ?);
It seems like the table names are being reordered and that's what is causing the error in insertion. I'm clueless though and I'd really appreciate some help with this.
EDIT: here's the INSERT command
ContentValues cv = new ContentValues();
cv.put(KEY_SPORT, sportInput);
cv.put(KEY_NAME, nameInput);
cv.put(KEY_DATE, dateInput);
cv.put(KEY_TIME, timeInput);
cv.put(KEY_PERIOD, periodInput);
cv.put(KEY_LOCATION, locationInput);
return dbSQL.insert(DATABASE_TABLE, null, cv);

The problem is probably that you've changed the database structure but not the database version. It's a weird issue that I had to spend a lot of time figuring out the first time.
In your DatabaseHelper class there should be a version number, just increment it by one anytime you change any table schema etc.
EDIT
You're missing a space before the "TEXT" in your SQL table creation.
It should be:
...
+ KEY_LOCATION+ " TEXT" ...
once you fix that, increment the version number again.

The order of the table columns will not create "no column" error. If you have added the column to your table after running your app at least once but haven't incremented the database version, this is one way to cause this error.
The order of these columns:
INSERT INTO groupTable(given_location, given_time, given_date, given_period, given_sport, given_name) ...
depends on the order of the columns when you write your INSERT statement, it is not a fixed order based off of the CREATE command.

Related

SQLite database "No such column" error on verified existing column [duplicate]

This question already has an answer here:
android.database.sqlite.SQLiteException: no such column or name
(1 answer)
Closed 3 months ago.
I am stuck on an "SQLiteException: no such column:" error. I am trying to make some code to check if an item exists in the database before storing it, I don't know if it's the best way or not but it does the job. Or not really, when I use all numbers for the data in the particular column that I'm searching it works fine. But if there is any letter in the column data it crashes.
The MainActivity
private ConversationsDatabaseHelper db;
//onCreate stuff here
db = new ConversationsDatabaseHelper(this);
String threadId = "886";
Log.d(TAG, "dbTest: EXISTS; " + db.conversationExists(threadId));
and in the databaseHelper class is the converstionExists function
public boolean conversationExists(String threadId) {
// Select All Query
String selectQuery = "SELECT * FROM " + Conversations.TABLE_NAME + " WHERE " +
Conversations.COLUMN_THREAD_ID + " LIKE " + threadId;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
boolean returnValue = false;
// Check if this message exists
if (cursor.moveToFirst()) {
returnValue = true;
}
// close db connection
db.close();
return returnValue;
}
So if I use for example "886" as the threadId value then all is fine. If I create a row with matching threadId then it returns true. In this case I did not so hence false.
stack trace...
dbTest: EXISTS; false
but using a886 results in
Caused by: android.database.sqlite.SQLiteException: no such column: a886 (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM conversations WHERE thread_id LIKE a886
and 88a6 results in this
Caused by: android.database.sqlite.SQLiteException: unrecognized token: "88a6" (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM conversations WHERE thread_id LIKE 88a6
It almost looks like mixing letters and numbers might be part of the reason here but should not be as the column was created to hold TEXT datatype. here is the database create table query string.
public static final String TABLE_NAME = "conversations";
public static final String COLUMN_ID = "id";
public static final String COLUMN__ID = "_id";
public static final String COLUMN_GROUP_ID = "group_id";
public static final String COLUMN_LAST_MESSAGE_ID = "last_message_id";
public static final String COLUMN_THREAD_ID = "thread_id";
public static final String COLUMN_ADDRESS = "address";
public static final String COLUMN_CONTACT = "contact";
public static final String COLUMN_BODY = "body";
public static final String COLUMN_DATE = "date";
public static final String COLUMN_TYPE = "type";
public static final String COLUMN_STATE = "state";
public static final String COLUMN_READ = "read";
public static final String COLUMN_STATUS = "status";
public static final String COLUMN_CT = "ct";
// Create table SQL query
public static final String CREATE_TABLE =
"CREATE TABLE " + TABLE_NAME + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY ,"
+ COLUMN_LAST_MESSAGE_ID + " TEXT,"
+ COLUMN__ID + " TEXT,"
+ COLUMN_GROUP_ID + " TEXT,"
+ COLUMN_THREAD_ID + " TEXT,"
+ COLUMN_ADDRESS + " TEXT,"
+ COLUMN_CONTACT + " TEXT,"
+ COLUMN_BODY + " TEXT,"
+ COLUMN_DATE + " TEXT,"
+ COLUMN_TYPE + " TEXT,"
+ COLUMN_STATE + " TEXT,"
+ COLUMN_READ + " TEXT,"
+ COLUMN_STATUS + " TEXT,"
+ COLUMN_CT + " TEXT"
+ ")";
I am "up a creek" with this and any help would be greatly appreciated.
The value a886 should be a text/string literal not a numeric literal. Therefore it should be enclosed in single quotes. The errors are because:-
a886 fails with no column found as it's taken to be a column name as it's not a literal.
whilst 88a6 is first not a valid literal (due to the a) and therefore a column name but then an invalid column (cannot start with a numeric unless enclosed) name and thus not a known token.
See Literal Values (Constants)
You could fix this using (enclosing the threadId in single quotes ) :-
String selectQuery = "SELECT * FROM " + Conversations.TABLE_NAME + " WHERE " +
Conversations.COLUMN_THREAD_ID + " LIKE '" + threadId + "'";
However, it is recommended to use bound parameters to protect against SQL Injection.
Thus it would be recommended to use :-
String selectQuery = "SELECT * FROM " + Conversations.TABLE_NAME + " WHERE " +
Conversations.COLUMN_THREAD_ID + " LIKE ?";
along with :-
Cursor cursor = db.rawQuery(selectQuery, new String[]{threadId});
i.e. the ? is replaced by the threadId value properly enclosed.
You may wish to consider using the convenience query method rather than rawQuery, this would be :-
Cursor cursor = db.query(Conversations.TABLE_NAME,null,Conversations.COLUMN_THREAD_ID + " LIKE ?", new String[]{theadId},null,null, null);
The SQL is built for you.
It almost looks like mixing letters and numbers might be part of the reason here but should not be as the column was created to hold TEXT datatype.
SQlite has no issue storing any value in any type. The type, which itself can be virtually anything (rules are used to determine the resultant type), is only an indication of the value that will be stored. The only exception is that a rowid or an alias of the rowid MUST be an integer value (your id column is an alias of the rowid column).

SQLite 1:M relationship

As part of project i am making android app that tracks users workouts in the gym. With the workouts and exercises with various set, weight and reps. This will a 1:M relationship with the workout id being the foreign key. I am still new to android and sqlite so i just wanted to check that code below is correct before going ahead.
Any advice would be greatly appreciated
DBHelper
public class DBHelper extends SQLiteOpenHelper {
public static String DATABASE_NAME = "gym_db";
private static final int DATABASE_VERSION = 1;
public static final String TABLE_WORKOUT = "workout_table";
public static final String WORKOUT_ID = "_id";
public static final String WORKOUT_NAME = "workout_name";
public static final String TABLE_EXERCISE = "exercise_table";
public static final String EXERCISE_ID = "exercise_id";
public static final String EXERCISE_NAME = "exercise_name";
public static final String EXERCISE_SET = "exercise_set";
public static final String EXERCISE_WEIGHT = "exercise_weight";
public static final String EXERCISE_REP = "exercise_rep";
public static final String createWorkoutTable = "CREATE TABLE" + TABLE_WORKOUT + "("
+WORKOUT_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ WORKOUT_NAME + " TEXT NOT NULL,"+
");";
public static final String createExerciseTable = " CREATE TABLE " + TABLE_EXERCISE + "("
+EXERCISE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ EXERCISE_NAME + " TEXT NOT NULL, "
+ EXERCISE_SET + " INTEGER NOT NULL, "
+ EXERCISE_WEIGHT + " INTEGER NOT NULL, "
+ EXERCISE_REP + " INTEGER NOT NULL, "
+ WORKOUT_ID + "FOREIGN KEY"+
"(;";
I have also turned on the foreign key in the onUpgrade method
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
super.onOpen(db);
if (!db.isReadOnly()){
db.execSQL("PRAGMA foreign_keys=ON;");
}
Coding WORKOUT_ID + "FOREIGN KEY" will not have the desired (assuming this is to be a foreign key constraint) result.
In theory (see later) the above would create a column named _id with a column type of FOREIGN KEY (which would be translated/converted to a column type of NUMERIC). However, as FOREIGN is a keyword the attempt to set the column type would fail with a syntax error. You need to specify a column type which would likely be INTEGER. So you would have WORKOUT_ID + " INTEGER ....".
However FOREIGN KEY on it's own is insufficient and also in the wrong place.
There are two ways of defining a FOREIGN KEY, as part of the column definition or as part of the table definition.
The former, (column definition) does not use the FOREIGN KEY keyword but the missing 2nd part the REFERENCES (i.e. saying what the primary table is along with the referenced column) using this method you would use :-
WORKOUT_ID + " INTEGER REFERENCES " + TABLE_WORKOUT +"(" + WORKOUT_ID +")"
The latter (table definition) does use the FOREIGN KEY keyword. You would code this along the lines of :-
WORKOUT_ID + " INTEGER, FOREIGN KEY (" + WORKOUT_ ID + ") REFERENCES " + TABLE_WORKOUT + "(" + WORKOUT_ID + ")"
You may wish to have a look at SQLite Foreign Key Support
The following line "(;" will result in a syntax error it should be ");".
I'd also suggest that using _id as the name of the column that references the _id column may cause confusion and difficulties (e.g. when you do a select with a join you'd have two _id columns in the resultant Cursor).
I'd suggest using a different column name e.g workout_id_reference.
This goes into some detail of this scenario How do I access individual _id columns when there are multiple _id columns from a join?

Autoincrement not working on ID

I'm having some trouble getting my autoincrement to work in SQL in my android app.
public static final String TABLE_NAME = "collections";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_TITLE = "title";
public static final String CREATE_STATEMENT = "CREATE TABLE " + TABLE_NAME +
"(" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
COLUMN_TITLE + " TEXT NOT NULL" + ")";
Are there any major problems with the create statement that could cause this?
There is no need to add AUTOINCREMENT NOT NULL to the primary key, As primary key(column) is supposed to be auto-increment and it can't be null.
following is an example of a SQL query which you may edit to create your own table.
public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + "Your_Table_Name" +
" (" + BaseColumns._ID + " INTEGER PRIMARY KEY," +
"first_column_name" + " TEXT" + "," +
"second_column_name" + " TEXT" + ")";
and BaseColumns is in interface provided by android in package android.provider which you may use to create a primary column with name "_id"
When you insert a new value do not define id (it will be automatically generated) just use COLUMN_TITLE.
Even in scheme you can skip id definition, because sqlite use RAWID internally and latter aliases your ID to RAWID.

Inserting in the sqlite with exesql

i need a tip here , here i have a code to insert into sqlite database:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
String sqlCreate = "CREATE TABLE IF NOT EXISTS " + name
+ " (ID INTEGER PRIMARY KEY AUTOINCREMENT,"
+ " Type TEXT,"
+ " Text TEXT,"
+ " OtherFormats TEXT,"
+ " Date TEXT,"
+ " Image TEXT,"
+ " RealName TEXT)";
db.execSQL(sqlCreate);
//(String Type, String Text ,String name,String OtherFormats,String Itime,String
RealName)
String sqlInsert= "INSERT INTO " + "'"+name+"'" +
" VALUES
("+"'"+ID+"'"+","+"'"+Type+"'"+","+"'"+Text+"'"+","+
"'"+OtherFormats+"'"+","+"'"+Date+"'"+"
,"+"'"+Image+"'"+","+"'"+RealName+"')";
db.execSQL(sqlInsert);
}
});
t.start();
the question is as you u see my ID is auto increment, but for executing it well, i need to put a value there,what value should i put so it database does the increament itself?
thanks
05-26 03:56:33.018: E/AndroidRuntime(23809):
android.database.sqlite.SQLiteException: near "VALUES": syntax error (code 1): ,
while compiling: INSERT INTO 'new' (Type,Text,OtherFormats ,Date,Image,RealName VALUES('m','hey','n','03:56','j','s')
You can do this. Enter the name of columns you need to insert
String sqlInsert= "INSERT INTO " + "'"+name+"' (Type,Text,OtherFormats ,Date,Image,RealName )VALUES
("+"'"+ID+"'"+","+"'"+Type+"'"+","+"'"+Text+"'"+","+
"'"+OtherFormats+"'"+","+"'"+Date+"'"+"
,"+"'"+Image+"'"+","+"'"+RealName+"')";
db.execSQL(sqlInsert);
the question is as you u see my ID is auto increment, but for executing it well, i need to put a value there,what value should i put so it database does the increament itself?
Put in a NULL or just leave it unspecified.
From the documentation:
If no ROWID is specified on the insert, or if the specified ROWID has a value of NULL, then an appropriate ROWID is created automatically.

android.database.sqlite.SQLiteException: table has no such column

So I guess it is a very common issue, searching the web I found that I am not the only one who faced a such issue and yes I know that there is a question with almost the same title, however that did not help to solve the issue I am facing ... so let's start from the beginning
I am simply trying to insert into a table that I created.
This table has three columns: "id", "name", "value", and was created as following
public static final String TABLE_NAME = "cookie";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_VALUE = "val";
private static final String DATABASE_NAME = "commments.db";
private static final int DATABASE_VERSION = 2;
// Database creation sql statement
private static final String DATABASE_CREATE = "create table "
+ TABLE_NAME + "("
+ COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_VALUE + "text not null, "
+ COLUMN_NAME + " text not null"
+ ");";
public MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE);
}
Now I am trying to insert into this table as following
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_NAME, "username");
values.put(MySQLiteHelper.COLUMN_VALUE, username);
long insertId = database.insert(MySQLiteHelper.TABLE_NAME, null, values);
Cursor cursor = database.query(MySQLiteHelper.TABLE_NAME, allColumns, MySQLiteHelper.COLUMN_ID + " = " + insertId, null, null, null, null);
cursor.moveToFirst();
nameValuePair newComment = cursorToNameValuePair(cursor);
cursor.close();
However I am getting this error
table cookie has no column named val
I searched for similar issues online, most of the solution where talking about a change happened to the database so I need to either
1- Un-install the application before trying to run in debugging mode again
2- update the database version from 1 to 3
However that did not help .. So looking forward for your solutions :)
Problem is here
+ COLUMN_VALUE + "text not null, "
into DATABASE_CREATE String. You missed space between column name and column type.
It should be
+ COLUMN_VALUE + " text not null, "

Categories