I'm creating my first android app and I'm having difficulties using sqlite. I'm using the following code to create my table. It works fine for the 3 first columns (_ID, COL_TITLE and COL_MAX) but I can't seem to create the last column.
String createTable = "CREATE TABLE " + TaskContract.Entry.TABLE + " (" +
TaskContract.Entry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
TaskContract.Entry.COL_TITLE + " TEXT NOT NULL, " +
TaskContract.Entry.COL_MAX + " REAL, " +
TaskContract.Entry.COL_INCREMENT + " REAL " +
");";
I tried getting the column index like this:
Cursor cursor = db.query(TaskContract.Entry.TABLE,
new String[]{TaskContract.Entry._ID,
TaskContract.Entry.COL_TITLE,
TaskContract.Entry.COL_MAX},
TaskContract.Entry._ID + " = ?",
new String[]{String.valueOf(id)},
null, null, null);
int idx_id = cursor.getColumnIndex(TaskContract.Entry._ID); //returns 0
int idx_title = cursor.getColumnIndex(TaskContract.Entry.COL_TITLE); //returns 1
int idx_max = cursor.getColumnIndex(TaskContract.Entry.COL_MAX); //returns 2
int idx_inc = cursor.getColumnIndex(TaskContract.Entry.COL_INCREMENT); //returns -1
As you can see getColumnIndex returns -1 for COL_INCREMENT
I also tried reading the data like this:
cursor.getString(3)
Looks as if the table only contains 3 column and I don't know where I went wrong. I've tried updating database version and uninstalling the app.
You need to pass TaskContract.Entry.COL_INCREMENT in your query too. Its missing out currently in your query.
Cursor cursor = db.query(TaskContract.Entry.TABLE,
new String[]{TaskContract.Entry._ID,
TaskContract.Entry.COL_TITLE,
TaskContract.Entry.COL_MAX,
TaskContract.Entry.COL_INCREMENT},
TaskContract.Entry._ID + " = ?",
new String[]{String.valueOf(id)},
null, null, null);
Related
I'm trying to remove a row from an SQL table using this code below. However, whenever I call this method I get this following error:
android.database.sqlite.SQLiteException: no such column: Plumber (code 1): , while compiling: DELETE FROM service WHERE name = Plumber
public boolean deleteService(String name){
SQLiteDatabase db = this.getWritableDatabase();
boolean result = false;
String query = "SELECT * FROM "
+ TABLE_SERVICE
+ " WHERE "
+ COLUMN_NAME
+ " = \""
+ name
+ "\""
;
Cursor cursor = db.rawQuery(query, null);
if(cursor.moveToFirst()){
String nameStr = cursor.getString(0);
db.delete(TABLE_SERVICE, COLUMN_NAME + " = " + nameStr, null);
cursor.close();
result = true;
}
db.close();
return result;
}
This is my table
public void onCreate(SQLiteDatabase db){
String CREATE_USERS_TABLE = "CREATE TABLE " +
TABLE_SERVICE + "("
+
COLUMN_NAME + " TEXT," +
COLUMN_RATE + " TEXT," +
COLUMN_CATEGORY + " TEXT," + COLUMN_SUBCATEGORY + " TEXT)";
db.execSQL(CREATE_USERS_TABLE);
}
First you're fetching all the rows that in COLUMN_NAME have the value name.
Next you want to delete the 1st of these rows (maybe it's the only one?) because nameStr gets the value of the 1st column which is COLUMN_NAME.
Why are you doing this?
Just execute this statement:
int number = db.delete(TABLE_SERVICE, COLUMN_NAME + " = '" + name + "'", null);
if number gets the value 0 then no rows were deleted, else it gets the number of deleted rows.
delete deletes rows not columns.
If you want to get rid of a column, you need to drop it. The SQL syntax is:
alter table table_service drop column <column_name>;
I don't know how to express this in java with the methods that you are using.
Ensure that your SQL syntax is correct, and that "Plumber" is a string with double quotes. By my experience, these errors are usually caused by an incorrect column or name.
Use this format:
DELETE FROM table_name WHERE condition(s)
SQLite browser can also help you visualize your database.
I have a database for my leaderboard. Currently, I insert all scores into my leaderboard, and select the 5 highest scores to show on my app. I think it would take up too much room to never delete the other scores, so I would like to delete them. How can I do this?
Here's how I select the top 5 scores, ranked first by score and second by time if score is equal:
public Cursor gethmLeaderboard(SQLiteDatabase db){
String[] columns = {TableInfo.LB_RANK, TableInfo.LB_SCORE, TableInfo.LB_TIME};
Cursor c = db.query(TableInfo.TABLE_HM, null, null, null, null, null, TableInfo.LB_SCORE + " DESC, " + TableInfo.LB_TIME + " ASC", "5");
return c;
}
Here's how I create my table:
public String CREATE_HMQUERY = "CREATE TABLE " + TableInfo.TABLE_HM + "("
+ TableInfo.LB_RANK + " INTEGER PRIMARY KEY AUTOINCREMENT DEFAULT 1 ," + TableInfo.LB_SCORE +
" INT,"+ TableInfo.LB_TIME + " VARCHAR );";
I want to delete all rows NOT IN that query. How can I do that?
Edit:
I tried this query:
public String DEL_ALLBUTES = "DELETE FROM " +
TableInfo.TABLE_HM + " WHERE " +
TableInfo.LB_RANK + " NOT IN (SELECT " +
TableInfo.LB_RANK + " FROM " +
TableInfo.TABLE_HM + " ORDER BY " +
TableInfo.LB_SCORE + " DESC, " +
TableInfo.LB_TIME + " ASC LIMIT 5);";
In this format:
db.rawQuery(DEL_ALLBUTES, null);
But when I check the database there are still tons of rows so it doesn't work.
Your table needs to have some unique ID. Use that to identify the rows you want to keep:
DELETE FROM ES
WHERE ID NOT IN (SELECT ID
FROM ES
ORDER BY Score DESC, Time ASC
LIMIT 5);
You can create temp table insert top 5 score into temp table and delete all table then insert temp table into main table.
CREATE TEMP TABLE TempES AS SELECT
ID
FROM
ES
ORDER BY
Score DESC,
Time ASC
LIMIT 5;
DELETE
FROM
ES;
INSERT INTO ES SELECT
*
FROM
TempES;
DROP TABLE TempES;
I'm having an issue inputting information into a Sqlite database on the app I'm creating. I was using the help of the Cursor before. I am used to MySQL although clearly not 'used to' that well.
I am trying to add to the database from a file. I had this working before but it would be added with the Cursor. I was then told that in order to make it so I could add new information to the file and have the app ONLY add the new information into the database I should use INSERT OR IGNORE.
Is this the correct syntax? I currently am not having any information inserted for whatever reason...
ourDatabase.rawQuery("INSERT OR IGNORE INTO " + DATABASE_TABLE + " ("+KEY_CLASS+",
" + KEY_QUESTION+ ") VALUES ('" + qclass + "', '" + question + "');", null);
This is my database:
"CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_CLASS + " TEXT NOT NULL, " +
KEY_QUESTION + " TEXT NOT NULL UNIQUE);
Thanks for the help in advance!
Your query seems right but try the one below anyway
ContentValues insertValues = new ContentValues();
insertValues.put(KEY_CLASS, qclass);
insertValues.put(KEY_QUESTION, question);
yourDbName.insertWithOnConflict(DATABASE_TABLE, null, insertValues, SQLiteDatabase.CONFLICT_IGNORE);
KEY_QUESTION + " TEXT NOT NULL UNIQUE);";
I am attempting to enter values such as "0.20" within a table but when I display it within an activity it shows "0.2". I am uncertain as to why the '0' is being removed i.e. incorrect structure of the table, insertion, or being returned.
My table is created as followed:
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" + KEY_ROWID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_NAME
+ " TEXT NOT NULL, " + KEY_SWIMMERLAPS + " INT NOT NULL, "
+ KEY_SPONSOR + " DEC(4,2) NOT NULL );");
I then insert the data:
public long addSwimmer(String name, String laps, String sponsor) {
int i = Integer.parseInt(laps);
ContentValues cv = new ContentValues();
cv.put(KEY_NAME, name);
cv.put(KEY_SWIMMERLAPS, i);
cv.put(KEY_SPONSOR, (new DecimalFormat("0.00##")).format(0.20));
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}
and then return the sponsorship data:
public String getSwimmerSponsors() {
String[] columns = new String[] { KEY_SPONSOR };
Cursor c = ourDatabase.query(DATABASE_TABLE, columns, null, null, null,
null, KEY_SWIMMERLAPS + " DESC");
String result = "";
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
result = result + c.getString(0) + "\n";
}
return result;
}
Edit - I display the returned result in my layout as follows:
String sponsors = swimmerDb.getSwimmerSponsors();
tvSponsor.setText(sponsors);
Thanks.
Because you're displaying an unformatted Java variable, and leading/trailing 0s are suppressed.
If you want to format it with a specific layout, use one of the printf/format variants:
printf("%.2f", num); // Etc.
When talking numbers 0.20 and 0.2 are exactly the same. If you want to keep the formatting than I suggest you insert the value as a formatted string.
cv.put(KEY_SPONSOR,0.20);
turns into
cv.put(KEY_SPONSOR, (new DecimalFormat("0.00##")).format(0.20));
EDIT: If you go this way, don't forget to change the KEY_SPONSOR column type from DEC to TEXT
SQLite does not offer DECIMAL or any similar type where you can specify the precision. The only data type with decimal places is REAL and that is how your number is being handled.
If you need specified precision you can multiply (by 100, in this case) and store as INTEGER, or use a TEXT column.
I have an SQL table which is created by the following code:
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (" + _ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, " + SUBJECT
+ " TEXT NOT NULL," + TOPIC + " TEXT NOT NULL, "
+ LECTURENUMBER + " TEXT NOT NULL, " + PAGENUMBER
+ " TEXT NOT NULL, " + DATE + " TEXT NOT NULL, " + _DATA
+ " TEXT NOT NULL);");
}
I query the table as follows:
String sql = "SELECT " + _ID + "," + SUBJECT + " FROM " + TABLE_NAME
+ " GROUP BY " + SUBJECT + ";";
Cursor cursor = subjects.getReadableDatabase().rawQuery(sql, null);
The problem is I have to start an Activity A if the cursor is empty(i.e. the table is storing no values) and Activity B if the cursor is not empty(i.e. table is filled).
I am unable to find a method which can tell me if the table is empty or not.
I Have tried to used Log as follows:
private void showSubjectsOnList() {
String sql = "SELECT " + _ID + "," + SUBJECT + " FROM " + TABLE_NAME
+ " GROUP BY " + SUBJECT + ";";
Cursor cursor = subjects.getReadableDatabase().rawQuery(sql, null);
Log.d("Events",Integer.toString(cursor.getCount()));
if(cursor.isNull(0)!=false){
cursor.close();
subjects.close();
startActivity(new Intent(this,OpenScreen.class));
}
}
But the LOG shows 1, if the table is empty...and again 1, if table has 1 entry....it shows 2, if table has two entries and so on.
Can you suggest some method of solving my problem of starting different activities based on if cursor is empty or not.
What about testing the cursor like this, and then doing what you've said:
if(cursor!=null && cursor.getCount()>0)
getCount ()
Returns the numbers of rows in the cursor
http://developer.android.com/reference/android/database/Cursor.html#getCount()
The easiest and cleanest way to test for an empty cursor is the following code:
if ( cursor.moveToFirst() ) {
// start activity a
} else {
// start activity b
}
Per the docs, the method returns false if the cursor is empty:
http://developer.android.com/reference/android/database/Cursor.html#moveToFirst%28%29
public abstract boolean moveToFirst ()
Added in API level 1 Move the cursor to the first row.
This method will return false if the cursor is empty.
Returns whether the move succeeded.
You just need to use getCount().
If your sql is correct but doesn't return any row you will have a NOT null cursor object but without a rows and getCount() will return 0.
Deleted records remain in SQLite as null records, but getCount() counts only not null records. If your table has some records that are null, some of not null records will have _Id numbers bigger than result of getCount(). To reach them, you can iterate cursor ( using for() loop ) double the number of times than result of getCount() and use the cursor to fill record_Id numbers into an array. Lets say resulting array is { 1, 2, 5, 6, 7, 8, 9, 11, 12, 14 }.
That means records 3, 4, 10, 13, are null records and your table has 14 record all together, not 10 that you got from getCount().
Remember:
getCount() returns number of not null records ,
cursor returns _Id numbers of not null records,
_Id numbers "missed" by cursor are _Id numbers of null records,
must reach sufficiently further than getCount() to get them all.
My suggestion would be using a ListActivity.
Those are Activity's which are meant to display items in a ListView. You can simply use a SimpleCursorAdapter to populate them (also illustrated in the ListActivitys JavaDoc page).
They also offer a setEmptyView()-method, which can be used to display a View (might be a TextView) which informs the user that there are no records yet and how he can create one.
An example on how to do that can be found here.
I believe your problem is you're not creating a proper query.
You should use the SQLiteDatabase query.
Cursor c = db.query(TABLE_NAME, null,
null, null, null, null, null);
You then can use c.getCount() to determine if the table has anything.