I have an SQLite db with about 400 000 entries. To query the db I am using the following method:
public double lookUpBigramFrequency(String bigram) throws SQLException {
SQLiteDatabase db = dbh.getReadableDatabase();
double frequency = 0;
bigram = bigram.toLowerCase();
String select = "SELECT frequency FROM bigrams WHERE bigram = '"
+ bigram + "'";
Cursor mCursor = db.rawQuery(select, null);
if (mCursor != null) {
if (mCursor.moveToFirst()) {
frequency = Double.parseDouble(mCursor.getString(0));
} else {
frequency = 0;
}
}
return frequency;
}
but it takes about 0.5 sec to retrieve a single entry and having few queries, it builds up and the method is executing for 10 secs. How to speeed it up?
Firstly, use an INDEX
http://www.sqlite.org/lang_createindex.html
in your case that will be something like:
CREATE INDEX idx_bigram ON bigrams (bigram)
Secondly, use '?' instead of literal query. It helps sqlite for caching requests:
String select = "SELECT frequency FROM bigrams WHERE bigram = ?";
Cursor mCursor = db.rawQuery(select, new String[]{ bigram });
Thirdly, I trust query is more efficient than rawQuery:
mCursor = dq.query("bigrams", new String[] { "frequency" }, "bigram = ?",
new String[]{ bigram }, null, null, null, null);
Fourthly, you can query several values at once (not compatible with point 2):
SELECT frequency FROM bigrams WHERE bigrams IN ('1', '2', '3')
Fifthly, you don't need to open your database every time. You should consider leaving it open.
Edit
After seeing this question IN clause and placeholders it appears you can combine 2 and 4 after all (not sure it is useful, though)
Always use transaction mechanism when you want to do lots of database operations
public static void doLotDBOperations() {
try {
// Code to Open Database
// Start transaction
sqlDb.beginTransaction();
// Code to Execute all queries
sqlDb.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
// End all transaction
sqlDb.endTransaction();
// Code to Close Database
}
}
Related
I am retrieving data according to dates but when running my app its shows nothing.
Here's my code :
SQL QUERY :
private Cursor getAllCurrentData()
{
String[] selectArg = new String[]{};
return db.query(Db_Contract.Db_Fieds.TABLE_NAME,
null ,
Db_Contract.Db_Fieds.DATE+ "= 2018-11-10",
selectArg,
null,
null,
Db_Contract.Db_Fieds.TIMESTAMP);
}
Displaying Data :
private void totalMoney()
{
Cursor cursor = getAllCurrentData();
double sum = 0.000d;
double getMoney;
while (cursor.moveToNext()) {
getMoney = cursor.getDouble(cursor.getColumnIndex(Db_Contract.Db_Fieds.MONEY));
sum += getMoney;
}
total.setText("Total money spent: " +sum);
}
I am new to Android Programming. Where I am doing wrong ?. Please correct me
First make sure you are connected to database and cursor returned by db.query() is not empty/null. Then Iterate over cursor like
private void totalMoney()
{
openDatabase();
Cursor cursor = getAllCurrentData();
cursor.moveToFirst();
double getMoney = 0;
while (!cursor.isAfterLast()) {
getMoney = cursor.getDouble(cursor.getColumnIndex(Db_Contract.Db_Fieds.MONEY));
sum += getMoney;
cursor.moveToNext();
}
total.setText("Total money spent: " + sum );
closeDatabase();
}
I have a small function for checking to see if a records already exists in my sqlite database. There is data in the database that should match the query, i have verified this by opening up the database.But i get an empty result.
Below is the function, it takes in a parameter and uses that as the search parameter. i have also verified that the parameter is correct.
public boolean checkParent(String email)
{
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = null;
try
{
res = db.rawQuery("SELECT * FROM parents WHERE email = ' " + email + " ' ",null);
res.close();
}
catch (Exception ex)
{
Log.e("Error checking parent", ex.toString());
}
if(res == null)
{
return true;
}
else
{
return false;
}
}
Right way to pass argument in rawQuery method.
db.rawQuery("SELECT * FROM parents WHERE email = ?",new String[]{email});
You are checking whether the cursor object res is null. This will never happen; rawQuery() always returns a cursor object.
You have to check whether the cursor is empty, i.e., whether the cursor actually contains any rows. To do this, call a method like moveToFirst() and check if it succeeds.
Or even better, use a helper function that does handle the cursor for you:
public boolean checkParent(String email)
{
SQLiteDatabase db = this.getReadableDatabase();
long count = DatabaseUtils.queryNumEntries(db,
"parents", "email = ?", new String[]{ email });
return count > 0;
}
I have some trouble with a SQLite database with 1 table and 2 columns, column_id and word. I extended SQLiteAssetHelper as MyDatabase and made a constructor:
public MyDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
I need to check whether some string is in the database (in column word). I tried to modify the code from answer provided by Benjamin and dipali, but I used SQLiteAssetHelper and I can't get it to work. The method that I have in mind receives the string to search for as a parameter and returns a boolean if string is in the database.
public boolean someMethod(String s)
In addition, I tried to put the check on a background thread with AsyncTask because I have 60 strings to check.
TABLE_NAME and COLUMN_WORD should be self-explanatory.
public boolean someMethod(String s) {
SQLiteDatabase db = getReadableDatabase();
String[] columns = new String[] {COLUMN_WORD};
String where = COLUMN_WORD + " = ?";
String[] whereArgs = new String[] {s};
// select column_word from table where column_word = 's' limit 1;
Cursor cursor = db.query(TABLE_NAME, columns, where, whereArgs, null, null, null, "1");
if (cursor.moveToFirst()) {
return true; // a row was found
}
return false; // no row was found
}
You can do this in the background, but I don't think for a query like this it's even necessary.
EDIT
There are some improvements that should be made to the above for the sake of correctness. For one thing, the Cursor should be closed since it is no longer being used. A try-finally block will ensure this:
Cursor cursor = db.query(...);
try {
return cursor.moveToFirst();
} finally {
cursor.close();
}
However, this method doesn't need to obtain a whole `Cursor. You can write it as follows and it should be more performant:
public boolean someMethod(String s) {
SQLiteDatabase db = getReadableDatabase();
String sql = "select count(*) from " + TABLE_NAME + " where "
+ COLUMN_WORD + " = " + DatabaseUtils.sqlEscapeString(s);
SQLiteStatement statement = db.compileStatement(sql);
try {
return statement.simpleQueryForLong() > 0;
} finally {
statement.close();
}
}
You could add a catch block and return false if you think it's possible (and valid) to encounter certain exceptions like SQLiteDoneException. Also note the use of DatabaseUtils.sqlEscapeString() because s is now concatenated directly into the query string and thus we should be wary of SQL injection. (If you can guarantee that s is not malicious by the time it gets passed in as the method argument, then you could theoretically skip this, but I wouldn't.)
because of possible data leaks best solution via cursor:
Cursor cursor = null;
try {
cursor = .... some query (raw or not your choice)
return cursor.moveToNext();
} finally {
if (cursor != null) {
cursor.close();
}
}
1) From API KITKAT u can use resources try()
try (cursor = ...some query)
2) if u query against VARCHAR TYPE use '...' eg. COLUMN_NAME='string_to_search'
3) dont use moveToFirst() is used when you need to start iterating from beggining
4) avoid getCount() is expensive - it iterates over many records to count them. It doesn't return a stored variable. There may be some caching on a second call, but the first call doesn't know the answer until it is counted.
In my application I am saving a bill number in SQLite database. Before I add a new bill number how to check if the bill number exists in the DB.
My main class code is,
String bill_no_excist_or_not = db.billno_exist_or_not(""+et_bill_number.getText().toString());
Log.v("Bill No", ""+bill_no_excist_or_not);
My DB Code,
String billno_exist_or_not(String bill_number){
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_BILL_DETAILS, new String[] { KEY_BILL_NUMBER }, KEY_BILL_NUMBER + "=?"
+ new String[] { bill_number }, null, null, null, null);
//after this i don't know how to return the values
return bill_number;
}
I don't know how to check the values which is already available or not in DB. Can any one know please help me to solve this problem.
Here is the function that helps you to find whether the value is available in database or not.
Here please replace your query with my query..
public int isUserAvailable(int userId)
{
int number = 0;
Cursor c = null;
try
{
c = db.rawQuery("select user_id from user_table where user_id = ?", new String[] {String.valueOf(userId)});
if(c.getCount() != 0)
number = c.getCount();
}
catch(Exception e) {
e.printStackTrace();
} finally {
if(c!=null) c.close();
}
return number;
}
Make your KEY_BILL_NUMBER column in your table UNIQUE and you can just insert using insertWithOnConflict with the flag SQLiteDatabase.CONFLICT_IGNORE
I saved Data in my SQL databank.
Now I want to compare this saved data, with a string
Something like this:
String example = "house";
Now I want to check, if "house" is already in the databank, with a if clause
something like this
if ( example == [SQL Data] ) {
}
else {
}
Now, how can I accomplish this ?
Do something like
String sql = "SELECT * FROM your_table WHERE your_column = '" + example + "'";
Cursor data = database.rawQuery(sql, null);
if (cursor.moveToFirst()) {
// record exists
} else {
// record not found
}
stolen from here
Writing my reply to Sharath's comment as an answer, as the code will be messed up in a comment:
Not saying your reply is wrong, but it's really inefficient to select everything from the table and iterate over it outside the database and it shouldn't be suggested as an answer to the question, because it's a bad habbit to do like that in general.
The way I usually do it, if I want to see if some record is present in the database, I do like this. Not gonna argue about using do-while over a normal while-loop, because that's about different preferences ;)
String query = "SELECT * FROM table_name WHERE column_name=" + the_example_string_to_find;
Cursor cursor = db.rawQuery(query, null);
if(cursor.getCount() > 0) {
cursor.moveToFirst();
while(!cursor.isAfterLast()) {
// Do whatever you like with the result.
cursor.moveToNext();
}
}
// Getting Specific Record by name.
// in DB handler class make this function call it by sending search criteria.
Records getRecord(String name) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_NAME, new String[]{KEY_ID, KEY_NAME, KEY_Auth_Name, KEY_B_PRICE}, KEY_ID + "=?",
new String[]{name}, null, null, null,null);
if (cursor.getCount() > 0)
cursor.moveToFirst();
Records Records = new Records(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2),cursor.getString(3));
// return book
return Records;
}
you need to first fetch all the data from the database and next check the data with what you obtained from the database.
Have a look at the link sample database example
suppose you got a cursor object from the database
cursor = db.rawQuery("SELECT yourColumnName FROM "+TABLE_NAME, null);
if(!cursor.moveToFirst()){
}
else{
do {
if(cursor.getString(0).equals(example))
//do something which you want and break
break;
} while (cursor.moveToNext());
}