I have a DB helper that does this function:
public Cursor getCourseNames() throws SQLException {
mDb = mDbHelper.getReadableDatabase();
return mDb.query("Course",null, COURSE_ROWID, null, null, null, null, null);
}
The table it is pulling from looks like this:
private static final String COURSE_ID = "CourseID";
private static final String COURSE_NAME = "Name";
private static final String COURSE_CODE = "CourseCode";
private static final String COURSE_ROWID = "_id";
private static final String COURSE_CREATE =
"create table " +
"Course" + " ( " +
COURSE_ROWID + " integer primary key autoincrement, " +
COURSE_ID + "integer not null," +
COURSE_NAME + "text not null, " +
COURSE_CODE + "text not null" + ");";
In my main activity I try this and get a null pointer...
public void buildCoursetoChapterList(){
Cursor cursor = dbHelper.getCourseNames();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(MainActivity.this, android.R.layout.simple_list_item_1, cursor, null, null);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
}
Anyone have an idea what my problem is?
I put data into the db earlier on:
if(dbHelper.checkCourseForData() !=null)
{
setContentView(R.layout.classlist);
}
else
{
dbHelper.addFirstClassToDb(course_code, name, course_id);
Log.d+i("Course added to DB", course_code + " " + name + " " + course_id);
}
tried this and still nothing, I want to select all the Name values within Course.
No clue... losing hope.
public Cursor checkCourseForData() throws SQLException {
String[] values = {COURSE_NAME};
Cursor mCursor = mDb.query("Course",values,COURSE_ROWID + "=" + "Name", null, null, null, null, null);
if (mCursor != null) { mCursor.moveToFirst(); }
return mCursor;
}
It should be this
public Cursor getCourseNames() throws SQLException {
String[] values = {COURSE_NAME};
mDb = mDbHelper.getReadableDatabase();
return mDb.query("Course",values,COURSE_ROWID, null, null, null, null, null);
}
Explanation :
the medthod in the api has been defined as
public Cursor query (String table, String[] columns, String selection,
String[] selectionArgs, String groupBy, String having, String orderBy)
So you need to pass the strings accordingly.
User my example as a reference it works for me
private String name;
private String Events_Table = "events";
private String[] Columns = {"_id", "Name", "Date", "Time_Slot", "Venue", "Details", "EHName", "EHNumber"} ;
private String WhereClause = Columns[1]+"=?" ;
Cursor cursor = db.query(Events_Table, Columns, WhereClause, new String[] {name}, null, null, null);
Consider Reading this
Parameters
table The table name to compile the query against.
columns A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
selection A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
groupBy A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.
having A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.
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.
Related
I am trying to return the names of distinct values in the 'category' column of an SQLite database. The cursor does not appear to be returning any results.
I'm building an Android app using a pre-existing database of bird species. The aim is to allow the user to explore the database through the app. The problem I'm having is in trying to return the distinct categories of bird species that exist in the database. The database appears to be opening successfully - no SQLite exception is being thrown, - but after using the query, the '.moveToNext' method does not appear to be returning any data.
public ArrayList<String> getCategory(String[] name){
String TABLE_BIRDS = "main";
String[] COLUMN = name;
ArrayList<String>categories = new ArrayList<>();
if (name[0]!=null)
{
Log.d(LOG_TAG, name[0]);
} else {
Log.d(LOG_TAG, "name[0] has not been passed");
}
x = db.query(true, TABLE_BIRDS, new String[] { COLUMN[0] } , null, null, COLUMN[0], null, null, null );
if (x.moveToNext()) {
Log.i(LOG_TAG, x.getString(x.getColumnIndex("category")));
}
else {
Log.i(LOG_TAG, "The cursor is not returning any data");
}
//Simple cursor loop
if (x.moveToNext()){
String category = new String();
category = x.getString(x.getColumnIndex(category));
categories.add(category);
Log.i("cursor loop", category);
}
return categories;
In the above code, the log messages are showing that: getCategory is receiving the expected string "category" before the query, but right after the query, the if/else loop is reporting that "The cursor is not returning any data".
What I expected is that the query would return six Strings, the cursor loop would add them to the ArrayList 'categories', and this ArrayList would be returned.
Please any help would be appreciated.
Here is a simpler version of your method:
public ArrayList<String> getCategory(String[] name) {
String TABLE_BIRDS = "main";
ArrayList<String> categories = new ArrayList<>();
if (name[0] != null) {
Log.d(LOG_TAG, name[0]);
} else {
Log.d(LOG_TAG, "name[0] has not been passed");
}
Cursor x = db.query(true, TABLE_BIRDS, new String[]{name[0]}, null, null, null, null, null, null);
while (x.moveToNext()) {
String category = x.getString(0);
categories.add(category);
Log.i("cursor loop", category);
}
if (x.getCount() == 0) {
Log.i(LOG_TAG, "The cursor is not returning any data");
}
x.close();
return categories;
}
I guess name[0] contains the string 'category' which is the column that you want to query.
Since you pass true as the 1st argument in the method query() this means that you will get distinct values, so no need for the group by argument.
You don't need the variable COLUMN since you have what you need in the variable name.Also you don't need getColumnIndex() since the cursor returns only 1 column.
Edit
Instead of:
Cursor x = db.query(true, TABLE_BIRDS, new String[]{name[0]}, null, null, null, null, null, null);
try rawQuery():
Cursor x = db.rawQuery("SELECT DISTINCT " + name[0] + " FROM " + TABLE_BIRDS, null);
Assuming the cursor is not null, you should
iterate over the results with a while/for loop.
e.g :while(x.moveToNext()) {
//your logic
}
It is always useful when debugging this kind of issues to install an SQLite DB browser then check the cursor's query against your DB to see if you have any data.
Instead of using direct query to db im using contentResolver but it returns null. And i dont know do i need to add some code or there is a mistake in mine.
private void displayDatabaseInfo() {
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
PetEntry._ID,
PetEntry.COLUMN_PET_NAME,
PetEntry.COLUMN_PET_BREED,
PetEntry.COLUMN_PET_GENDER,
PetEntry.COLUMN_PET_WEIGHT };
// Perform a query on the provider using the ContentResolver.
// Use the {#link PetEntry#CONTENT_URI} to access the pet data.
Cursor cursor = getContentResolver().query(
PetEntry.CONTENT_URI, // The content URI of the words table
projection, // The columns to return for each row
null, // Selection criteria
null, // Selection criteria
null); // The sort order for the returned rows
Log.v(LOG_TAG, "Проверка курсора " + cursor);
TextView displayView = (TextView) findViewById(R.id.text_view_pet);
if (cursor != null){
try {
// Create a header in the Text View that looks like this:
//
// The pets table contains <number of rows in Cursor> pets.
// _id - name - breed - gender - weight
//
// In the while loop below, iterate through the rows of the cursor and display
// the information from each column in this order.
displayView.setText("The pets table contains " + cursor.getCount() + " pets.\n\n");
displayView.append(PetEntry._ID + " - " +
PetEntry.COLUMN_PET_NAME + " - " +
PetEntry.COLUMN_PET_BREED + " - " +
PetEntry.COLUMN_PET_GENDER + " - " +
PetEntry.COLUMN_PET_WEIGHT + "\n");
// Figure out the index of each column
int idColumnIndex = cursor.getColumnIndex(PetEntry._ID);
int nameColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_NAME);
int breedColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_BREED);
int genderColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_GENDER);
int weightColumnIndex = cursor.getColumnIndex(PetEntry.COLUMN_PET_WEIGHT);
// Iterate through all the returned rows in the cursor
while (cursor.moveToNext()) {
// Use that index to extract the String or Int value of the word
// at the current row the cursor is on.
int currentID = cursor.getInt(idColumnIndex);
String currentName = cursor.getString(nameColumnIndex);
String currentBreed = cursor.getString(breedColumnIndex);
int currentGender = cursor.getInt(genderColumnIndex);
int currentWeight = cursor.getInt(weightColumnIndex);
// Display the values from each column of the current row in the cursor in the TextView
displayView.append(("\n" + currentID + " - " +
currentName + " - " +
currentBreed + " - " +
currentGender + " - " +
currentWeight));
}
} finally {
// Always close the cursor when you're done reading from it. This releases all its
// resources and makes it invalid.
cursor.close();
}
}
}
Before that i got an error null exception. After added if/else statement exceptions dissapeared but anyway it doesnt work and returns null
Problem was in ContentProvider. I have changed code and now it works.
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// Get readable database
SQLiteDatabase database = mDbHelper.getReadableDatabase();
// This cursor will hold the result of the query
Cursor cursor;
// Figure out if the URI matcher can match the URI to a specific code
int match = sUriMatcher.match(uri);
switch (match) {
case PETS:
// For the PETS code, query the pets table directly with the given
// projection, selection, selection arguments, and sort order. The cursor
// could contain multiple rows of the pets table.
cursor = database.query(PetEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
case PET_ID:
// For the PET_ID code, extract out the ID from the URI.
// For an example URI such as "content://com.example.android.pets/pets/3",
// the selection will be "_id=?" and the selection argument will be a
// String array containing the actual ID of 3 in this case.
//
// For every "?" in the selection, we need to have an element in the selection
// arguments that will fill in the "?". Since we have 1 question mark in the
// selection, we have 1 String in the selection arguments' String array.
selection = PetEntry._ID + "=?";
selectionArgs = new String[] { String.valueOf(ContentUris.parseId(uri)) };
// This will perform a query on the pets table where the _id equals 3 to return a
// Cursor containing that row of the table.
cursor = database.query(PetEntry.TABLE_NAME, projection, selection, selectionArgs,
null, null, sortOrder);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI " + uri);
}
return cursor;
}
I have a database with product name,product price and product counter.
Product name is unique,product price gets replaced everytime a new value is entered and the problem is the product counter.
Its default value is 1,when a new product is entered his value is set to 1.I need it to increment whenever there is a conflict for the product name.So if Cheese is entered twice,the counter will say 2 and so on.
What i need it to do is when there is a conflict,add 1 to its value. I want to do it this way because i'll need this later.I'll need to add the inputed value to the table value on some other thing i plan to implement in my app.
How can i achieve this ? I'd like to keep doing it the way i'm doing it now,with the contentvalues method of inserting and not with the sqlite syntax(INSERT,SELECT,etc).Is that even possible ? Cuz i'm an absolute 0 at sqlite syntax.And also,i need it to have a method that i can call in other activities to insert into the database (like insertCountry(Japan,10))
public class SQLiteCountryAssistant extends SQLiteOpenHelper {
private static final String DB_NAME = "usingsqlite.db";
private static final int DB_VERSION_NUMBER = 1;
private static final String DB_TABLE_NAME = "countries";
private static final String DB_COLUMN_1_NAME = "country_name";
private static final String DB_COLUMN_2_NAME = "country_price";
private static final String DB_COLUMN_3_NAME = "country_counter";
private static final String DB_CREATE_SCRIPT = "create table "
+ DB_TABLE_NAME
+ " (_id integer primary key autoincrement, country_name text UNIQUE ON CONFLICT REPLACE,country_price text,country_counter integer default '1' );)";
And this is how i insert :
public void insertCountry(String countryName, String countryPrice) {
sqliteDBInstance.execSQL("INSERT INTO " + DB_TABLE_NAME
+ "(country_name, country_price) VALUES('" + countryName
+ "', '" + countryPrice + "')");
}
Incrementing a value to a specific cell is not available in sqlite. You have to read the current value of cell and add your needed value to it and replace it with the old one. You can use update method.
public void update(String countryName, String price, long id) {
ContentValues cv = new ContentValues();
cv.put(dbHelper.COLUMN_1, countryName); // These Fields should be your
// String values of actual column
// names
cv.put(dbHelper.COLUMN_2, price);
database.update(dbHelper.TABLE_NAME, cv, "_id " + "=" + id, null);
}
every time you're going to add a row to your table you have to read all it and check if the row exists.here is a method to retrieve all rows:
public List<TableRow> getAllRows() {
List<TableRow> rows= new ArrayList<TableRow>();
Cursor cursor = database.query(Helper.TABLE_SITUPS, allColumns,
null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
TableRow row = cursorToRow(cursor);
comments.add(row);
cursor.moveToNext();
}
// Make sure to close the cursor
cursor.close();
return rows;
}
TableRow is a class for database table rows and contains fields stands for actual table columns.
with iterating this list and get "country" value of each one you can understand if that row exists or not.
These are basic concepts of sqlite databases programming. I recommend you to research a bit in this matter.
I don't know your database class, but check this method:
return this.sqliteDBInstance.insertWithOnConflict(DB_TABLE_NAME, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE);
If you are creating your column correctly, if there is a conflict, the new entry will replace the old one.
EDIT: after your last comment, all you need is an update: first query your database with the name of your item (check carefully if parameters are ok):
return this.sqliteDBInstance.query(DB_TABLE_NAME, null, DB_COLUMN_1_NAME + "=?", new String[] {productName}, null, null, null);
This will return a Cursor with 0 or 1 row. If there aren't row, you can proceed inserting data normally (don't forget to add your counter: is 1 on first insert):
public void insertCountry(String countryName, String countryPrice) {
sqliteDBInstance.execSQL("INSERT INTO " + DB_TABLE_NAME
+ "(country_name, country_price) VALUES('" + countryName
+ "', '" + countryPrice + "', '" + countryCounter + "')");
}
if there is 1 row, your product is already on your database, so just iterate the Cursor, take the value on counter, add +1 on it and update your database with this method:
public int update (String table, ContentValues values, String whereClause, String[] whereArgs)
I want to return the rows in my database that have the attribute in one of the fields equal to the parameter to the method. My code is:
public Cursor fetchStatus(String status){
Cursor mCursor =
mDb.query(DATABASE_TABLE, new String[] {KEY_COMPANY, KEY_POSITION, KEY_NOTES, KEY_WAGE, KEY_STATUS},
KEY_STATUS+ "= "+status, null, null, null, null)
;
if(mCursor!=null) mCursor.moveToFirst();
return mCursor;
}
I want to return the KEY_COMPANY, KEY_POSITION, KEY_NOTES, KEY_WAGE and KEY_STATUS columns where the KEY_STATUS is equal to the parameter 'status'
Perhaps you may try something like this:
public object GetValues (string status)
{
string query = "SELECT KEY_COMPANY, KEY_POSITION, KEY_NOTES, KEY_WAGE,KEY_STATUS
FROM DATABASE_TABLE
WHERE KEY_STATUS = "'" +status+ "'" " ;
dbcomands part...
List<object> = execute db comand....
}
The error you specified in your comment might be caused by the lack of ' ' in you query. Just a thought.
Use PreparedStatement.
You can simply specify your query and set parameters in search query.
Ok, so here is my database create statement:
create table entry (
_id integer primary key autoincrement,
date integer not null,
checknum integer,
payee text not null,
amount integer not null,
category text,
memo text,
tag text
);
After the datbase is created, and I make a call like:
mChecknum = cursor.getColumnIndex("checknum");
mChecknum is -1. I have pulled the database from the device and used SQLite Browser on it, and the checknum field is there.
Block around statement in question:
mDbHelper.open();
Cursor cursor = mDbHelper.fetchAll();
startManagingCursor(cursor);
COL_DATE = cursor.getColumnIndex("date");
Log.v("Main:123", "COL_DATE: " + String.valueOf(COL_DATE) );
COL_CHECKNUM = cursor.getColumnIndex("checknum");
Log.v("Main:125", "COL_CHECKNUM: " + String.valueOf(COL_CHECKNUM) );
COL_PAYEE = cursor.getColumnIndex("payee");
COL_DATE returns 1 and COL_PAYEE returns 2. Why is COL_CHECKNUM being ignored/passed over?
In my situation getColumnIndex was returning error on the column which had name which contained the "." symbol i.e.:
int colIndex = cursor.getColumnIndex("Item No.");
and despite the column "Item No." was inside the cursor (the debugger Watch showed it) trying to get the column index failed.
In my fetch/fetchAll database functions, I forgot to update the query with the new column.
For example, before i added the new column, my fetchAll code looked like:
public Cursor fetchAll() {
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_DATE,
KEY_PAYEE, KEY_AMOUNT, KEY_CATEGORY, KEY_MEMO, KEY_TAG},
null, null, null, null, KEY_DATE + " desc");
}
After adding the new column to the database, my fetchAll function looks like:
public Cursor fetchAll() {
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_DATE,
KEY_CHECKNUM, KEY_PAYEE, KEY_AMOUNT, KEY_CATEGORY, KEY_MEMO, KEY_TAG},
null, null, null, null, KEY_DATE + " desc");
}