I am trying to get the max id of a table in SQLite in Android. This is how I get it in the database helper:
public int getMaxIncrementation() {
SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
String result = "0";
try{
Cursor cursor = sqLiteDatabase.rawQuery("SELECT MAX(id) FROM " +TABLE_INCREMENTATION, new String[]{});
cursor.moveToFirst();
result = cursor.getString(cursor.getColumnIndex(INCREMENTATION_ID));
}catch (Exception ex) {
Log.e("ex", ex.getMessage());
}
return Integer.parseInt(result);
};
This is how I created the table:
private static final String CREATE_TABLE_INCREMENTATION = "CREATE TABLE IF NOT EXISTS " + TABLE_INCREMENTATION
+ "("
+ INCREMENTATION_DATEADDED + " TEXT,"
+ INCREMENTATION_DIRECTION + " INTEGER,"
+ INCREMENTATION_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ INCREMENTATION_USER + " TEXT"
+ ")";
This is the snapshot of my table with data in it:
On debugging, I always get this error:
Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor
is initialized correctly before accessing data from it.
First, since you don't have in the query any ? placeholders then you don't need to pass any parameters to the sql statement, so the 2nd argument of rawQuery() should be null.
Also you must give an alias to the column that your query returns and use it to get the returned value (you can't use INCREMENTATION_ID because it is not the name of the column returned):
Cursor cursor = sqLiteDatabase.rawQuery("SELECT MAX(id) AS maxid FROM " +TABLE_INCREMENTATION, null);
if (cursor.moveToFirst())
result = cursor.getString(cursor.getColumnIndex("maxid"));
Or if you don't use an alias then use 0 as there is only 1 column returned:
Cursor cursor = sqLiteDatabase.rawQuery("SELECT MAX(id) FROM " +TABLE_INCREMENTATION, null);
if (cursor.moveToFirst())
result = cursor.getString(0);
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.
So I have a method that allows me to get the id of a certain item by using a name i already have in an SQL Database. How would I go about getting the entire row of information and storing each item in its own variable.
Method that only works with ID
public Cursor getID(String name){
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
String query = " SELECT " + COL1 + " FROM " + TABLE_NAME + " WHERE " + COL2 + " = '" + name + "'";
Cursor data = sqLiteDatabase.rawQuery(query, null);
return data;
}
And the method that gets the query and stores the result
Cursor data = mydb2.getID(name);
int itemId= -1;
while(data.moveToNext()){
itemId = data.getInt(0);
}
Using this method below how would i store all of the data in its own variable using this (or any other way to get data of entire row).
public Cursor rowData(String name){
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
String query = " SELECT * FROM " + TABLE_NAME + " WHERE " + COL2 + " = '" + name + "'";
Cursor data = sqLiteDatabase.rawQuery(query, null);
return data;
}
I know this might be a dumb question, and I have tried looking at other questions, I have gotten this far I just don't know what to do next (I'm very new to Sq Lite databases and Android development)
You'd use something like :-
Cursor csr = instance_of_yourdbhelper.rowData();
while(csr.moveToNext()) {
long thisItemId = csr.getLong(csr.getColumnIndex(yourdbhelper.COL_1));
String thisName = csr.getString(csr.getColumnIndex(yourdbhelper.COL_2));
// etc for other columns
}
Notes
yourdbhelper is the class for your DatabaseHelper which is the class that extends SQLiteOpenHelper (the assumption is that the above methods are from such a class, as this is a common usage of SQLite)
instance_of_yourdbhelper is the instance of the DatabaseHelper class i.e. you may have yourdbhelper dbhlpr = new yourdbhelper(parameters);, in which case dbhlpr is the instance.
This just overwrites the same variables (thisItemId and thisName) for each row in the cursor, although there is perhaps the likliehood that the rowData method only returns one row.
You will likely encounter fewer errors using the getColumnIndex method as it returns the offset according to the column name. Miscalculated offsets is a frequent cause of problems.
You may wish to handle a no rows returned situation in which case you can use cursor.getCount(), which will return the number of rows in the cursor.
I keep getting this error message: "Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0" in my code.
I have already referenced the following links, but none of them have worked:
Android cursor out of bounds exception
Cursor index out of bounds
Cursor Index Out Of Bounds Error Android?
cursor index out of bounds exception
public Product getProduct(int id) {
db = this.getReadableDatabase();
Cursor cursor = db.query(
TABLE_NAME,
null,
COLUMN_ID + " = ?",
new String[] { Integer.toString(id)},
null, null, null, null);
Product product = new Product();
cursor.moveToFirst();
if (cursor != null) {
product.setID(cursor.getInt(0));
product.setName(cursor.getString(1));
product.setSize(cursor.getDouble(2));
product.setHp(cursor.getDouble(3));
product.setCategory(cursor.getString(4));
product.setPowerType(cursor.getString(5));
product.setExplosionProof(cursor.getInt(6));
product.setRPM(cursor.getInt(7));
product.setBypassPSI(cursor.getInt(8));
product.setGPM(cursor.getInt(9));
product.setPrice(cursor.getDouble(10));
cursor.close();
}
db.close();
return product;
}
And here are my constants:
private static final String TABLE_NAME = "Products";
private static final String COLUMN_ID = "'_id'";
I would greatly appreciate any help.
Now, it won't go into the if-loop. I got that query model straight from another stack overflow question.
It is very likely that the cursor is empty, as such you need to ascertain why. It could be that there is no underlying data or it could be that the cursor where clause is excluding all data. From what you have provided it is impossible to determine why.
I would suggest removing the where clause to see if this changes matters.
i.e. instead of
Cursor cursor = db.query(
TABLE_NAME,
null,
COLUMN_ID + " = ?",
new String[] { Integer.toString(id)},
null, null, null, null);
use :-
Cursor cursor = db.query(
TABLE_NAME,
null,
null,
null,
null, null, null, null);
This would return all rows from the cursor, if this works then the issue is with the where clause (3rd and 4th parameters passed to db.query). If it doesn't resolve the issue then it is likely that the table itself has no rows.
You could circumvent the CursorIndexOutOfBoundsException by using :-
if (cursor.getCount() > 0) {
cursor.moveToFirst();
product.setID(cursor.getInt(0));
product.setName(cursor.getString(1));
product.setSize(cursor.getDouble(2));
product.setHp(cursor.getDouble(3));
product.setCategory(cursor.getString(4));
product.setPowerType(cursor.getString(5));
product.setExplosionProof(cursor.getInt(6));
product.setRPM(cursor.getInt(7));
product.setBypassPSI(cursor.getInt(8));
product.setGPM(cursor.getInt(9));
product.setPrice(cursor.getDouble(10));
} else {
// setup to return a product not found
}
cursor.close();
However, this won't fix the underlying issue that the cursor is not returning any rows.
You could use something like the following to get more information regarding the cursor (running with the cursor selecting all rows as per change above). This should work for any cursor :-
int rowcount = cursor.getCount();
String colnames = "";
for (String columns : cursor.getColumnNames()) {
colnames = colnames +
"Column Index=" +
Integer.toString(cursor.getColumnIndex(columns)) +
" Name=>" +
columns +
"< ";
}
Log.d("DBCHK","Table has " + Integer.toString(rowcount) + " rows. With columns:- " + colnames);
String values;
while (cursor.moveToNext()) {
values = "";
for (int i = 0; i < cursor.getColumnCount(); i++) {
values = values +
"Column = " +
cursor.getColumnName(i) +
" Index=" +
Integer.toString(i) +
" Value=" + cursor.getString(i) + ": ";
}
Log.d("DBCHK",values);
}
This would write data to the log along the lines of :-
D/DBCHK: Table has 2 rows. With columns:- Column Index=0 Name=>_id< Column Index=1 Name=>myfloat<
D/DBCHK: Column = _id Index=0 Value=null: Column = myfloat Index=1 Value=56.7897:
D/DBCHK: Column = _id Index=0 Value=null: Column = myfloat Index=1 Value=87.7655:
There will be a line per row, these preceded with a line listing the number of rows and what the columns are.
I couldn't give a good title to the problem I'm having, but basically I have two columns Name and MaxNum string and int respectively!
I need int method that makes a query which retrieves the MaxNum for specific Name that I give in parameter!
.. so if I have this data
ID | Name | MaxNum
0 | Mike | 50
1 | John | 40
2 | Jess | 30
..when I put Jess in as parameter it will return 30 !
My method so far.. but I can't use it since it doesn't return int value !
public void maxFromName(String name){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT " + COLUMN_MAX + " FROM "+ TABLE_AZKAR+" WHERE " +COLUMN_NAME+ "=" + name ;
db.execSQL(query);
}
You have to get the result using
Cursor
String query = "SELECT " + COLUMN_MAX + " FROM "+ TABLE_AZKAR+" WHERE " +COLUMN_NAME+ "=" + name ;
Cursor c = db.rawQuery(query, null);
c.moveToFirst();
return c.getInt(c.getColumnIndex("MaxNum"));
Update
Since you are facing the problem, I suggest you use the below query:
String query = Select MaxNum from azkar WHERE Name ='Jess';
after this use my code from Cursor c line, this will work.
Use rawQuery for getting data from SQLite. And from the cursor get integer value using getInt function.
Change your maxFromName function with the following.
public int maxFromName(String name){
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT " + COLUMN_MAX + " FROM "+ TABLE_AZKAR+" WHERE " +COLUMN_NAME+ "= '" + name +"'" ;
Cursor c = db.rawQuery(query, null);
if(c.getCount()!=0){
c.moveToFirst();
return c.getInt(c.getColumnIndex("MaxNum"))
}
return 0;
}
In the API it says the following in the description of execSQL():
Execute a single SQL statement that is NOT a SELECT or any other SQL
statement that returns data.
Use a query method that returns a Cursor type in order to retrieve results
The easiest way to get a single value from a database is with the stringForQuery() or longForQuery() helper functions:
public long maxFromName(String name) {
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT "+COLUMN_MAX+" FROM "+TABLE_AZKAR+" WHERE "+COLUMN_NAME+" = ?";
return DatabaseUtils.longForQuery(db, query, new String[]{ name });
}
(To prevent string formatting problems and SQL injection attacks, always use parameters instead of inserting string values directly into the query.)
You can use rawQuery
public ArrayList<String> maxFromName(String name){
ArrayList<String> maxNums = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT " + COLUMN_MAX + " FROM "+ TABLE_AZKAR+" WHERE "
+COLUMN_NAME+ "=" + name ;
Cursor c = db.rawQuery(query, null);
c.moveToFirst();
do { // if that kind of rows are more then one, this metod get all of them
maxNums.add(c.getInt(c.getColumnIndex("MaxNum")));
}
return maxNums;
}
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.