I'm trying to select a specific row from a database based on a string in a textview. The error log when I run it appears to say that it's looking for a column, but it should be looking for a row. The error log says:
--I/Database(279): sqlite returned: error code = 1, msg = no such column: Book
--D/AndroidRuntime(279): Shutting down VM
--W/dalvikvm(279): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
--E/AndroidRuntime(279): FATAL EXCEPTION: main
--E/AndroidRuntime(279): android.database.sqlite.SQLiteException: no such column: Book: , while compiling: SELECT book, background FROM bookbackgrounds WHERE book=Book
Here's the code where it gets the string from the textview, then runs a method that is supposed to return a filename in the form of a text string, then display the returned string in a second textview:
String bkString = showBooktextview.getText().toString();
bga.open();
String newBKstring = bga.getBGforBook(bkString);
bga.close();
showDBBooktextview.setText(newBKstring);
and here's the method that the error says there's no such column with the name of that book. (it's supposed to be looking for the ROW that contains that book name):
public String getBGforBook(String bkString) {
String[] thecolumns = new String[] { KEY_BOOK, KEY_BACKGROUND };
Cursor cursor = db.query(DB_TABLE, thecolumns, KEY_BOOK + "=" + bkString, null, null, null, null);
String result = "";
if (cursor != null){
cursor.moveToFirst();
result = result
+ cursor.getString(1);
}
return null;
}
so is the method written incorrectly? If so, how to write it correctly so that it looks for a row that contains the bookname string?
I think you are missing single quotes in the condition expression:
KEY_BOOK + "=" + bkString
should be
KEY_BOOK + "='" + bkString + "'"
Since the string bkString is not quoted, SQLite tries to interpret it as an identifier of a column name.
Related
I am creating a SQLite database in android. But there is some error appearing up whenever I call the method "displayDatabase()".
Please Help!!
Here is the displayDatabase() Method:
public void displayDatabase() {
DataDbHelper mDbHelper = new DataDbHelper(this);
SQLiteDatabase db = mDbHelper.getReadableDatabase();
String[] projection = {DataContract.DataEntry.COLUMN_PROJECT_NAME,
DataContract.DataEntry.COLUMN_HEAD,
DataContract.DataEntry.COLUMN_CITY,
DataContract.DataEntry.COLUMN_COST};
Cursor c = db.query(DataContract.DataEntry.TABLE_NAME,
projection,
null,
null,
null,
null,
null);
TextView textView = (TextView) findViewById(R.id.textview);
try {
//textView.setText("The database contains - " + c.getColumnCount() + "Columns containing data");
textView.setText("Hello Welcome\n");
textView.append("-" + DataContract.DataEntry._ID
+ "---" + DataContract.DataEntry.COLUMN_PROJECT_NAME
+ "---" + DataContract.DataEntry.COLUMN_HEAD
+ "---" + DataContract.DataEntry.COLUMN_CITY
+ "---" + DataContract.DataEntry.COLUMN_COST + "\n");
int currentId = c.getColumnIndex(DataContract.DataEntry._ID);
int projectNameId = c.getColumnIndex(DataContract.DataEntry.COLUMN_PROJECT_NAME);
int headId = c.getColumnIndex(DataContract.DataEntry.COLUMN_HEAD);
int cityId = c.getColumnIndex(DataContract.DataEntry.COLUMN_CITY);
int costId = c.getColumnIndex(DataContract.DataEntry.COLUMN_COST);
while (c.moveToNext()) {
int id = c.getInt(currentId);
String projectName = c.getString(projectNameId);
String head = c.getString(headId);
String city = c.getString(cityId);
String cost = c.getString(costId);
textView.append("-" + id
+ "---" + projectName
+ "---" + head
+ "---" + city
+ "---" + cost);
}
} finally {
c.close();
}
}
And here is the error appearing in the logcat :
CursorWindow: Failed to read row 0, column -1 from a CursorWindow
which has 11 rows, 4 columns. 03-15 10:00:58.359 6348-6348/?
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.student.sampledatabase, PID: 6348
java.lang.IllegalStateException: Couldn't read row 0, col -1 from
CursorWindow. Make sure the Cursor is initialized correctly before
accessing data from it.
Add this column, DataContract.DataEntry._ID, to your projection.
The Cause of the Error
The reason for the failure is that an attempt is being to get a column at offset -1, which will never exist as offsets can be from 0 to the number of columns in the cursor less 1.
The reason why -1 is being used is because that is the value returned from the
Cursor getColumnIndex method when the column name passed to the method does not exist in the cursor.
The reason why you are getting the -1 is that you have not included the column who's name is as per DataContract.DataEntry._ID resolved in the cursor so the line :-
int currentId = c.getColumnIndex(DataContract.DataEntry._ID);
results in currentId being -1
Thus the above error when the following line is executed :-
int id = c.getInt(currentId);
The Fix
One fix, would be to specify null instead of projection, this would result in all columns of the table being retrieved and is the equivalent of using SELECT * FROM .......
e.g. by using :-
Cursor c = db.query(DataContract.DataEntry.TABLE_NAME,
null,
null,
null,
null,
null,
null);
Another fix would be to change :-
String[] projection = {DataContract.DataEntry.COLUMN_PROJECT_NAME,
DataContract.DataEntry.COLUMN_HEAD,
DataContract.DataEntry.COLUMN_CITY,
DataContract.DataEntry.COLUMN_COST};
to instead be :-
String[] projection = {DataContract.DataEntry._ID,
DataContract.DataEntry.COLUMN_PROJECT_NAME,
DataContract.DataEntry.COLUMN_HEAD,
DataContract.DataEntry.COLUMN_CITY,
DataContract.DataEntry.COLUMN_COST};
Thus the column will then be included in the Cursor and the offset will be the offset of that column (0 in the case above as it is the first column in the result).
I have two method's in my SQLite Database in which i check if there is in a table certain column that is the same as a String after it i print all other columns on the same row and with the second method i check if a column from the first method equals to a data stored in a column of another table.
But i'm having issues when i check for a data that is not in the database here is an example:
TABLE CODART_BARCODE
CODART_CODART CODART_BARCODE CODART_PXC
123 1234 1
TABLE CODART_ART
DESCR_ART PVEN_ART PACQ_ART CODART_ART
PIZZ 1.50 12 123
So if in an EditText i insert 123 that equals to CODART_CODART and there is also 123 in CODART_ART from the other table i will print "PIZZ 1.50 12" but if i insert in the EditText 12356 the app crash because there is no same data in DB how can i prevent that app crash? i mean if there is no same data can i make a Toast that says "no data" or something like this but not making the app crash?
Here are the two methods from DB:
public String dbRawSearch(String id) {
StringBuilder dbString = new StringBuilder();
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_CODART + " WHERE CODART_BARCODE = " + id;
//Cursor points to a location in your results
#SuppressLint("Recycle") Cursor c = db.rawQuery(query, null);
//Move to the first row in your results
c.moveToFirst();
//Position after the last row means the end of the results
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_BARCODE")) != null) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.moveToNext();
}
db.close();
return dbString.toString();
}
// FETCH codArt from Articoli
public String dbRawArticoli(String id){
StringBuilder dbString = new StringBuilder();
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_ART + " WHERE CODART_ART = " + id;
Cursor c = db.rawQuery(query, null);
c.moveToFirst();
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_ART")) != null) {
dbString.append(c.getString(c.getColumnIndex("DESCR_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PVEN_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PACQ_ART"))).append("\n");
}
c.moveToNext();
}
db.close();
return dbString.toString();
}
Your issue is that you are not correctly enclosing the search argument and thus if the value is non numeric then SQLite will consider that you are comparing a column, hence the no column found.
Lets say assuming you use :-
String result1 = yourdbHelper.dbRawSearch("123");
Then the resultant SQL will be :-
SELECT * FROM CODART WHERE CODART_BARCODE = 123;
That is fine as the search is looking for a number.
However if you used:-
String result1 = yourdbHelper.dbRawSearch("Fred");
Then the resultant SQL will be :-
SELECT * FROM CODART WHERE CODART_BARCODE = FRED
This would fail because FRED is non-numeric, and is therefore interpreted as saying SELECT all columns from the table CODART where the column named COADRT has the same value as the column named FRED, there is no column named FRED.
The result is that you get an error along the lines of :-
06-11 11:34:12.653 1373-1373/soanswers.soanswers E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{soanswers.soanswers/soanswers.soanswers.MainActivity}: android.database.sqlite.SQLiteException: no such column: FRED (code 1): , while compiling: SELECT * FROM CODART WHERE CODART_BARCODE = FRED
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The Fix
The resolution is simple, and that is to enclose the argument being searched for in single quotes so that the SQL is then :-
SELECT * FROM CODART WHERE CODART_BARCODE = 'FRED'
Note that is just one example. However you will need to makes similar changes to both methods (dbRawSearch and dbRawArticoli), as shown :-
To do this you could change :-
String query = "SELECT * FROM " + TABLE_CODART + " WHERE CODART_BARCODE = " + id;
to :-
String query = "SELECT * FROM " + TABLE_CODART + " WHERE CODART_BARCODE = '" + id + "'";
and also change :-
String query = "SELECT * FROM " + TABLE_ART + " WHERE CODART_ART = " + id;
to :-
String query = "SELECT * FROM " + TABLE_ART + " WHERE CODART_ART = '" + id + "'";
Additional
However, there are SQLiteDatabase convenience methods that simplify building queries which also enclose/convert data accordingly.
One of these is the query method (as used in the following).
Rather than
moving to the first row and then
checking to see if you are then at the last row and then
using a moveToNext then going back to 2
in a do while loop, as all of the Cursor move??? methods return
true if the move could be made
otherwise false
you can simplify matters using :-
while(yourcursor.moveToNext) {
.... process the current row
}
As such the following methods could be considered
Note the 2 at the end of the method name is just to distinguish them from the originals
:-
public String dbRawSearch2(String id) {
StringBuilder dbString = new StringBuilder();
String whereclause = "CODART_BARCODE=?";
String[] whereargs = new String[]{id};
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.query(TABLE_CODART,null,whereclause,whereargs,null,null,null);
while (c.moveToNext()) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.close(); //<<<< Should always close cursors when finished with them
db.close();
return dbString.toString();
}
public String dbRawArticoli2(String id) {
StringBuilder dbString = new StringBuilder();
String whereclause = "CODART_ART=?";
String[] whereargs = new String[]{id};
SQLiteDatabase db = this.getWritableDatabase();
Cursor c= db.query(TABLE_ART,null,whereclause,whereargs,null,null,null);
while (c.moveToNext()) {
dbString.append(c.getString(c.getColumnIndex("DESCR_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PVEN_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PACQ_ART"))).append("\n");
}
c.close();
db.close();
return dbString.toString();
}
you should use wether your cursor is null or not and its size
if (c != null) {
if (c.getCount() > 0) {
return "your string";
}
}
return "";// In case no record found
In blank case give proper msg to the end user.
Change this part :
//Move to the first row in your results
c.moveToFirst();
//Position after the last row means the end of the results
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_BARCODE")) != null) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.moveToNext();
}
To :
//Move to the first row in your results
if(c!= null && c.moveToFirst())
{
//Position after the last row means the end of the results
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_BARCODE")) != null) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.moveToNext();
}
}
Explanation: In the case where there is no same data available you don't have the result set to get the string or column index from the result set.
im trying to get all the elements of a row in sqlite by ID using a cursor. The cursor is not null, but i can't seem to operate with the cursor, Here is my code:
public Book getBookByid (int itemId) {
String selectQuery = "SELECT * FROM " + tables[0] + " WHERE " + SQLiteHelper.ITEM_ID + " = " + itemId;
Cursor cursor = database.rawQuery(selectQuery, null);
Book bookRead = new Book();
if(cursor!=null) {
Log.i("myApp","cursor not null");
if (cursor.moveToFirst()) {
Log.i("myApp","title" + cursor.getColumnIndex(arrayFields.get(0)[1]));
bookRead.setTitle(cursor.getString(cursor.getColumnIndex(arrayFields.get(0)[1])));
bookRead.setGenre(cursor.getString(cursor.getColumnIndex(arrayFields.get(0)[2])));
bookRead.setDescription(cursor.getString(cursor.getColumnIndex(arrayFields.get(0)[3])));
bookRead.setRecommendation(cursor.getString(cursor.getColumnIndex(arrayFields.get(0)[4])));
bookRead.setPhoto(cursor.getString(cursor.getColumnIndex(arrayFields.get(0)[5])));
bookRead.setLike(cursor.getInt(cursor.getColumnIndex(arrayFields.get(0)[6])));
}
Log.i("myApp","title" + bookRead.getTitle());
}
cursor.close();
return bookRead;
}
The problem is that the code does not enter the if(cursor.moveToFirst()) so i cannot assing the values to my object, getting a null object reference.
My logs show the following:
05-13 09:37:23.720 13918-13918/com.appforbrands.meloapunto I/myApp﹕ cursor not null
05-13 09:37:23.720 13918-13918/com.appforbrands.meloapunto I/myApp﹕ titlenull
I'm also getting a blue warning or error in logcat:
05-13 10:04:14.555 3969-3969/com.appforbrands.meloapunto W/Bundle﹕ Key itemId expected Integer but value was a java.lang.Long. The default value 0 was returned.
05-13 10:04:14.559 3969-3969/com.appforbrands.meloapunto W/Bundle﹕ Attempt to cast generated internal exception:
This is steps you need to do to debug your function:
Make sure you have valid database connection.
Check and make sure your raw query are correct.
The itemID is exist in your data.
Sqlite may be confused finding your id in your Sqlite book table, so the query can't find any row. Check your table definitions or manually write the table id in your query String.
I try to get all unique values from database coulmn using SELECT DISTINCT sql command.
But i get exception when my activity is loading, i have this error code in logcat:
05-05 09:08:32.637: E/AndroidRuntime(1314): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.workoutlog/com.example.workoutlog.AddWorkOutPage}: android.database.sqlite.SQLiteException: near "SELECT": syntax error (code 1): , while compiling: SELECT * FROM exerciseTable WHERE SELECT DISTINCTexercise_typefromexerciseTable
I think that i have not wrote the command correctly, here is my code:
public String[] getAllExercies() {
String selecet = "SELECT DISTINCT" + COLUMN_EXERCISE + "from" + TABLE_NAME;
Cursor c = ourDatabase.query(TABLE_NAME, null, selecet, null, null, null, null);
int dayExercise = c.getColumnIndex(COLUMN_EXERCISE);
String[] list = new String[c.getCount()-1];
int j = 0;
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
list[j] = c.getString(dayExercise);
j++;
}
return list;
}
I think you should first checkout these answers here and here in order to see the working of .query() function.
Please note that while using ourDatabase.query() function, the parameters are as follows:
String Table Name: The name of the table to run the query against
String [ ] columns: The projection of the query, i.e., the columns to retrieve
String WHERE clause: where clause, if none then pass null
String [ ] selection args: The parameters of the WHERE clause
String Group by: A string specifying group by clause
String Having: A string specifying HAVING clause
String Order By by: A string Order By by clause
So your third variable should be a WHERE clause, something like:
String[] args = { "first string" };
Cursor c = ourDatabase.query("TABLE_NAME", null, "exercise_type=?", args, null, null, null);
Since you don't need a WHERE clause, for your purposes you might want to use rawQuery() method instead.
String selecet = "SELECT DISTINCT " + COLUMN_EXERCISE + " FROM " + TABLE_NAME;
ourDatabase.rawQuery(selecet, null);
Update
Try the answer from here. Do something like this:
Cursor c = ourDatabase.query(true, "exerciseTable", new String[] {"exercise_type"}, null, null, "exercise_type", null, null, null);
int dayExercise = c.getColumnIndex(COLUMN_EXERCISE);
//... continue with your further code
Hope this helps else please comment.
Issue:
you have not maintained the space between the words.
Explaination:
suppose, String COLUMN_EXERCISE = "exercise";
and String TABLE_NAME = "tbl_workout";
then
String selecet = "SELECT DISTINCT" + COLUMN_EXERCISE + "from" + TABLE_NAME;
simply means,SELECT DISTINCTexercisefromtbl_workout
Solution:
String selecet = "SELECT DISTINCT " + COLUMN_EXERCISE + " from " + TABLE_NAME;
Edit:
Kindly use following syntax to fire rawQuery
Cursor c = ourDatabase.rawQuery(selecet,null);
I hope it will be helpful !
You miss all the spaces in your query, you should replace with this:
String selecet = "SELECT DISTINCT " + COLUMN_EXERCISE + " FROM " + TABLE_NAME;
I am trying to run a select using sqllite. Its my first time using sqllite and I am getting this error over and over.
function ="Adding Event
CODE:
public List<Example> getExampleByFunctionList(String function)
{
List<Example> examplelist = new ArrayList<Example>();
String getQuery = "SELECT * FROM " + MySQLiteHelper.TABLE_EXAMPLE+
" where "+ MySQLiteHelper.COLUMN_EXAMPLE_FUNCTION +" = "+""+function+"";
Cursor cursor = database.rawQuery(getQuery, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Example example = cursorToExample(cursor);
examplelist.add(example);
cursor.moveToNext();
}
cursor.close();
return examplelist;
}
ERROR:
02-12 12:37:29.218: E/AndroidRuntime(3165): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tutorial/com.tutorial.ManageCalendar}: android.database.sqlite.SQLiteException: near "Events": syntax error: , while compiling: SELECT * FROM example where examplefunction = Adding Events
... +" = '"+function+"'";
^^^ ^^^
You need to quote string literals in SQL statements (regardless of whether they contain spaces or not).
Or use prepared statements and bind variables, which is much safer against SQL injection.
See: How do I use prepared statements in SQlite in Android?