Select Query issue while fetching the fields - android

I wrote one query which select the name and designation fields based on id and then in fragment class i am calling that method which belongs to the appropriate query but unfortunately i am getting Sqlite Exception.
Database Method
public Employee getEmployeeName(int id) {
SQLiteDatabase db = this.getWritableDatabase();
Employee employee = new Employee();
String query ="SELECT " + KEY_NAME +", " +KEY_DESIG +" FROM " + TABLE_EMPLOYEES+ " WHERE " + KEY_ID + "=" + id;
Cursor cursor = db.rawQuery(query, null);
if (cursor.moveToFirst()) {
do {
employee.setName(cursor.getString(1));
employee.setDesignation(cursor.getString(2));
} while (cursor.moveToNext());
}
return employee;
}
Calling from the Fragment
db.getEmployeeName(selectedManager);
Exception
01-07 06:02:34.185: E/AndroidRuntime(2386): java.lang.IllegalStateException: Couldn't read row 0, col 2 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.

Column indexes are zero-based. getString(2) refers to the third column and your cursor has only two columns.
Change
employee.setName(cursor.getString(1));
employee.setDesignation(cursor.getString(2));
to
employee.setName(cursor.getString(0));
employee.setDesignation(cursor.getString(1));

try this
if (cursor.moveToFirst()) {
do {
employee.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME));
employee.setDesignation(cursor.getString(cursor.getColumnIndex(KEY_DESIG));
} while (cursor.moveToNext());
}
Get data from Cursor by using cursor.getColumnIndex(COLUMN NAME)

Related

How to check if there is no same row in DB?

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.

How to check if record already exists in SQLite table

This is my database
public void DBCreate() {
SQLITEDATABASE = getActivity().openOrCreateDatabase("FavoritesDB", Context.MODE_PRIVATE, null);
SQLITEDATABASE.execSQL("CREATE TABLE IF NOT EXISTS favorite(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, word VARCHAR, meaning VARCHAR);");
}
This is how I am creating new rows:
String query = "INSERT INTO favorite (word,meaning) VALUES('"+wordd+"', '"+mean+"');";
Cursor c=SQLITEDATABASE.rawQuery("SELECT * FROM favorite WHERE id=?", null);
if (c.moveToFirst())
{
Toast.makeText(getActivity(),"inserted",Toast.LENGTH_LONG).show();
SQLITEDATABASE.execSQL(query);
}
else
{
Toast.makeText(getActivity(),"exists",Toast.LENGTH_LONG).show();
}
How to check data before inserting value into table?
before inserting perform select query and check the cursor size if it is >0 than record already exist .
I am not sure why are you passing null in your query
Cursor c=SQLITEDATABASE.rawQuery("SELECT * FROM favorite WHERE id=?", null);
instead
Cursor c=SQLITEDATABASE.rawQuery("SELECT * FROM favorite WHERE id=?", new String[]{"your id1"});
or
if you want to select all record then
Cursor c=SQLITEDATABASE.rawQuery("SELECT * FROM favorite");
try this code:
Cursor c = SQLITEDATABASE.rawQuery("SELECT * FROM favorite WHERE id=?", new String[]{"your_id_name"});
Log("Cursor Count : " + c.getCount());
if(c.getCount()>0)
{
Toast.makeText(getActivity(),"exists",Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getActivity(),"inserted",Toast.LENGTH_LONG).show();
SQLITEDATABASE.execSQL(query);
}
And your select query should look like:
String sql ="SELECT PID FROM "+TableName+" WHERE PID="+pidValue;
Options:
If you do not want to repeat any of the values in a column, set the column setting in the CREATE method to "UNIQUE" or even "PRIMARY KEY" if the content should be the primary key to recognize. Thus you can probably avoid any repetitions without having to check.
Loop through the table:
Cursor c = SQLITEDATABASE.rawQuery("SELECT * FROM favorite", null);
if (c.getCount() > 0) {
String searchString = "some word"; // word you are about to insert
while (c.moveToNext()) {
c.moveToFirst();
int colIndex = c.getColumnIndex("word");
String wordInCurrentRow = c.getString(colIndex);
if (!(wordInCurrentRow.equals(searchString))) {
// insert method
} else {
// do nothing
Log.d("word already existing", "nothing to insert");
}
}
}

SQLite no such column error

Hi can anyone please help me with below error in android sqlite ? really appreciate!
Caused by: android.database.sqlite.SQLiteException: no such column: House (code 1): , while compiling: select * from category where category =House
below is part of my code in which I have inserted "House" in the table
public void onCreate(SQLiteDatabase db) {
String CREATE_CATEGORY_TABLE = "CREATE TABLE category( " +
"_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"category TEXT UNIQUE)";
db.execSQL(CREATE_CATEGORY_TABLE);
}
public void addCategory(String name){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("category", name);
db.insert(CATEGORY_TABLE, // table
null, //nullColumnHack
cv); // key/value -> keys = column names/ values = column values
db.close();}
public List getCategory(){
List<String> list=new LinkedList();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor =
db.rawQuery("select * from category where category =house" , null);
// 3. if we got results get the first one
if (cursor != null)
cursor.moveToFirst();
do {
String s = (cursor.getString(1));
list.add(s);
}while (cursor.moveToNext());
return list;
}
You need to wrap house with single quotes
db.rawQuery("select * from category where category = 'house'" , null);
In my case error was in trigger I wrote on table insert and update

how to check if a value already exist in db, and if so how to get the id of that row? android sql

i have created the next db file -
String sql = ""
+ "CREATE TABLE "+ Constants.TABLE_NAME + " ("
+ Constants.NAME_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ Constants.NAME_PERSON + " TEXT"
+ ")";
db.execSQL(sql);
Now what I would like to know is, how to be able to run on the db and to know if a name already exist sin the db, and if so i would like to get the id of that row.
all i can understand is that i should use the
Cursor c= db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy)
but I don't have a clue what I should do next -
so thanks for any kind of help
you can add this in your DB and call the function passing "to be searched key" as an argument
public boolean checkIfExist(String name) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_INFO, new String[] { KEY_TITLE}, KEY_TITLE + "=?",
new String[] { name }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
if (cursor.moveToFirst()) {
return true;
}else{
return false;
}
}
Where KEY_TITLE is the column name in your table.
Take more example on this:
AndroidSQLite
AndroidSQLite with multi tables
Make a SELECT request. Then check with if(cursor.moveToFirst()) if your name is already existing. (moveToFirst() return true if there is at least 1 value).
So if your value is existing, juste get its id with cursor.getString(cursor.getColumnIndex("_id"));

Getting the next AUTO_INCREMENT value of a SQLite database

Using the typical SQLiteDatabase object in Android's API, what can I do to get the next AUTO_INCREMENT value of a particular column (ie. id) without affecting the value itself. Is there a method for that? Or what query should I execute to get that result. Keep in mind that SQLiteDatabase.query() returns a Cursor object, so I'm not too sure how to deal with that directly if I just want to get a value out of it.
You're right. The first answer (still below) only works without an AUTOINCREMENT for id. With AUTOINCREMENT, the values are stored in a separate table and used for the increment. Here's an example of finding the value:
public void printAutoIncrements(){
String query = "SELECT * FROM SQLITE_SEQUENCE";
Cursor cursor = mDb.rawQuery(query, null);
if (cursor.moveToFirst()){
do{
System.out.println("tableName: " +cursor.getString(cursor.getColumnIndex("name")));
System.out.println("autoInc: " + cursor.getString(cursor.getColumnIndex("seq")));
}while (cursor.moveToNext());
}
cursor.close();
}
See: http://www.sqlite.org/autoinc.html
First Answer:
You can query for the max of the _id column, such as:
String query = "SELECT MAX(id) AS max_id FROM mytable";
Cursor cursor = db.rawQuery(query, null);
int id = 0;
if (cursor.moveToFirst())
{
do
{
id = cursor.getInt(0);
} while(cursor.moveToNext());
}
return id;
This works for row ids that haven't been specified as "INTEGER PRIMARY KEY AUTOINCREMENT" (all tables have a row id column).
This is the best way to get the last ID on auto increment PRIMARY KEY with SQLITE
String query = "select seq from sqlite_sequence WHERE name = 'Table_Name'"
An important remark about the SQLITE_SEQUENCE table.
The documentation says
The SQLITE_SEQUENCE table is created and initialized automatically whenever a normal table that contains an AUTOINCREMENT column is created.
So the SQLITE_SEQUENCE table is created, but NOT the row associated with the table that contains the AUTOINCREMENT column. That row is created with the first insert query (with "seq" value of 1).
That means that you must doing at least one insert operation before looking for the next autoincrement value of a specific table. It could be done for example just after the creation of the table, performing an insert and a delete of a dummy row.
Here is what I use to get the next AUTOINCREMENT value for a specific table:
/**
* Query sqlite_sequence table and search for the AUTOINCREMENT value for <code>tableName</code>
* #param tableName The table name with which the AUTOINCREMENT value is associated.
*
* #return The next AUTOINCREMENT value for <code>tableName</code>
* If an INSERT call was not previously executed on <code>tableName</code>, the value 1 will
* be returned. Otherwise, the returned value will be the next AUTOINCREMENT.
*/
private long getNextAutoIncrement(String tableName) {
/*
* From the docs:
* SQLite keeps track of the largest ROWID using an internal table named "sqlite_sequence".
* The sqlite_sequence table is created and initialized automatically
* whenever a normal table that contains an AUTOINCREMENT column is created.
*/
String sqliteSequenceTableName = "sqlite_sequence";
/*
* Relevant columns to retrieve from <code>sqliteSequenceTableName</code>
*/
String[] columns = {"seq"};
String selection = "name=?";
String[] selectionArgs = { tableName };
Cursor cursor = mWritableDB.query(sqliteSequenceTableName,
columns, selection, selectionArgs, null, null, null);
long autoIncrement = 0;
if (cursor.moveToFirst()) {
int indexSeq = cursor.getColumnIndex(columns[0]);
autoIncrement = cursor.getLong(indexSeq);
}
cursor.close();
return autoIncrement + 1;
}
Inside the SQLiteOpenHelper you use, start a transaction. Insert some data and then rollback.
Such a way, you 'll be able to get the next row id, like this:
public long nextId() {
long rowId = -1;
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
// fill values ...
// insert a valid row into your table
rowId = db.insert(TABLE_NAME, null, values);
// NOTE: we don't call db.setTransactionSuccessful()
// so as to rollback and cancel the last changes
} finally {
db.endTransaction();
}
return rowId;
}
It's work.
public static long getNextId(SQLiteDatabase db, String tableName) {
Cursor c = null;
long seq = 0;
try {
String sql = "select seq from sqlite_sequence where name=?";
c = db.rawQuery(sql, new String[] {tableName});
if (c.moveToFirst()) {
seq = c.getLong(0);
}
} finally {
if (c != null) {
c.close();
}
}
return seq + 1;
}
You can use cursor.getInt(i); method
i here is index of the id column
Cursor c = db.rawQuery("Select * From mSignUp", null);
String mail = null;
try {
while (c.moveToNext()) {
mail = c.getString(0);
String pas = c.getString(1);
Toast.makeText(getApplicationContext(), "Name = " + mail + " Pass = " + pas, Toast.LENGTH_SHORT).show();
}
}catch (CursorIndexOutOfBoundsException e){
Log.e("OutOfBound", Log.getStackTraceString(e));
}
finally {
c.close();
}

Categories

Resources