I have an SQLlite database with a list of cities.
My autoCompleteTextView is linked to this database but I have one problem.
There are a lot of cities in my database like this:
Sint-Truiden
Sint-Pieters-Rode
Sint-Rijkers etc...
But a lot of users will just type Sint Truiden and receive no result.
This is what I have so far:
String sql = "";
sql += "SELECT * FROM " + TABLE_CITIES;
sql += " WHERE " + KEY_NAME + " LIKE '%" + searchTerm + "%'";
How can I adjust my SQL to achieve my goal?
One solution is to normalize the search term and the database content. For example, you could add to the table a column containing the normalized name. Some normalisation examples :
Replace any kind of separator (dash, point, multiple spaces) with one space
Convert to lowercase
Remove accents
Related
I have the following table:
String sqlStatement = "CREATE TABLE " + CallsEntry.TABLE_NAME + "(";
sqlStatement += CallsEntry.FIELD_CALL_ID + " INT PRIMARY KEY DESC,";
sqlStatement += CallsEntry.FIELD_CALLER_PHONE + " TEXT,";
sqlStatement += CallsEntry.FIELD_INSERTION_DATE_MILLIS + " INT); COMMIT;";
db.execSQL(sqlStatement);
Please note that the primary key is descending.
Then I expect from my experience with SQL server that the following query will yield the records in an descending order:
SELECT * FROM tblCalls;
However, this is not the case. I'm getting the records in ascending order. I have to use this:
SELECT * FROM tblCalls ORDER BY CallId DESC;
Why is that? Can I do something differently and get the records in descending order?
There is no such thing as default key order in SQLite.
Depends on documentation:
If a SELECT statement that returns more than one row does not have an
ORDER BY clause, the order in which the rows are returned is
undefined. Or, if a SELECT statement does have an ORDER BY clause,
then the list of expressions attached to the ORDER BY determine the
order in which rows are returned to the user.
So default order is underfined without ORDER BY clause.
Does this produce the right order?
SELECT CallId FROM tblCalls
Like said in the title I am trying to sort my data from sqlite database to ascending time. Here is what I have so far:
Cursor display = db.rawQuery("SELECT * FROM "+TableName + " ORDER BY Time ASC",null );
It displays data however it doesnt sort according to my Time with formade ##.## 24hr time. Hope someone can help.
Try "SELECT * FROM " + tableName + " ORDER BY time(Time)". PS: ASC is default ;)
You can use the strftime() function:
SELECT *
FROM my_table
ORDER BY strftime('%H:%M:%S',my_column)
Here I created a fiddle as example.
The raw query should be something like:
"SELECT * FROM " + TableName + " ORDER BY strftime('%H:%M:%S'," + my_column + ")"
NOTE: strftime() function is the more general function that you can use for manipulate date. But, for this specific case you can also use time(). Indeed, as the document that I linked says:
time(...) is equivalent to strftime('%H:%M:%S', ...)
I'm writing a function for an Android app, that should get the first 8 entries (names of cities) of a database which are matching a string.
This is my query:
Cursor cursor = database.rawQuery(
"SELECT " + CITIES_NAME +
" FROM " + TABLE_CITIES +
" WHERE " + CITIES_NAME +
" LIKE " + String.format("%s%%", nameLetters) +
" LIMIT " + 8
, null);
This is the resulting error:
android.database.sqlite.SQLiteException: near "LIMIT": syntax error (code 1): , while compiling: SELECT city_name FROM CITIES WHERE city_name LIKE berl% LIMIT 8
I have already checked out other questions on the platform, but could not find any solution helping me out. The database is tested and created correctly and also the search entry is in the database.
Could anybody help?
WARNING: You should NOT use string concatenation with the + operator to insert user input in a SQL query.This leaves your app open to a SQL injection attack. I cannot emphasize this enough. Mitigating this common security flaw should be a top priority for all database developers.
Instead, you should use the ? place holder syntax:
String query = "SELECT " + CITIES_NAME +
" FROM " + TABLE_CITIES +
" WHERE " + CITIES_NAME +
" LIKE ?" +
" LIMIT 8";
String[] args = {nameLetters + "%%"};
Cursor cursor = database.rawQuery(query, args);
Even if the database is small and only used for your individual app, it is best to make this syntax a habit. Then when you work on larger, more critical databases, you won't have to worry about this issue as much.
This also has the advantage that it quotes the input for you. You completely avoid the error which you encountered that prompted the original question.
For the sake of completeness I'll turn my comment into an answer, to hopefully help anyone else who may have this issue.
Think you need quotes around the like string eg
SELECT city_name FROM CITIES WHERE city_name LIKE 'berl%' LIMIT 8
I am currently implementing a search feature in an appliction to take a user input and query the database for similar results. I have created the following database query:
String proQuery = "SELECT * FROM " + DATABASE_TABLE + " WHERE "
+ KEY_NAME + " LIKE '%" + keyword +"%'";
Obviously this query has a number of limitations due to a very generic sql statement. For example, if I start typing something in the middle of the word, it will show up first in the list if it has a lower row number in the database.
Are there libraries that help make a more intelligent search feature than this very generic sql statement? I am not sure what keywords could describe this functionality what I'm looking for, is there some field of "search algorithms" for android?
Maybe UNION is what you're looking for:
SELECT * FROM (
SELECT * FROM table_name WHERE keyname LIKE 'keyword%' ORDER BY keyname
) alias_t1
UNION ALL
SELECT * FROM (
SELECT * FROM table_name WHERE keyname LIKE '%keyword%' AND keyname NOT LIKE 'keyword%' ORDER BY keyname
) alias_t2;
I'm using SQLite on Android using SQLiteDatabase (http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html)
I am developing a bible application, which has a single table with the following columns:
book : int
chapter : int
verse : int
wordIdx : int
strongId : string
word : string
each sentence is broken down in to a series of strongId/word pairs, so wordIdx is used to order the words, strongId is simply a index in to a concordance, and word is the word in the sentence.
so I have 300,000 rows
the bottleneck appears to be my query to get a list of words for each verse:
My SQL is effectively this:
SELECT strongId, word FROM ? WHERE book=? AND chapter=? AND verse=?
Here is the code:
Cursor cursor = mBible.database().rawQuery("SELECT " + KEY_STRONGID + "," + KEY_WORD + " FROM " + tableName() + " WHERE " + KEY_BOOK + "=? AND " + KEY_CHAPTER + "=? AND " + KEY_VERSE + "=?" , new String[] { String.valueOf(mChapter.mBook.index()), String.valueOf(mChapter.index()), String.valueOf(verse) });
cursor.moveToFirst();
mWordList = new ArrayList<Word>();
do {
mWordList.add(new Word(cursor.getString(1), cursor.getString(0)));
} while (cursor.moveToNext());
Now, I've tried putting each chapter in to its own temporary view (using CREATE TEMP VIEW) which cuts down the records to about 400 in my example how ever it is still taking far to long to query
Its taking of the order of 30 seconds to generate the text for two chapters to display to the user (using a temporary view and without using a temporary view). It takes about 5 seconds if I set up a dummy list of words to avoid the database query.
How can I improve the performance of this? It seems as if a temp view is having no impact on performance as I had hoped.
A view does not change the performance of a query; it just saves the query itself, not the results of the query.
If you open your database with the sqlite3 command-line tool on your desktop machine, you can use the EXPLAIN QUERY PLAN command to check how efficient your queries are.
Without any indexes, you query always scans the entire table:
> sqlite3 bible.db
SQLite version 3.7.15.2 2013-01-09 11:53:05
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SCAN TABLE MyTable (~1000 rows)
With an index on your three lookup fields, SQLite can do a fast search in the index and needs to read only the matching records from the table:
sqlite> CREATE INDEX b_c_v ON MyTable(book, chapter, verse);
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SEARCH TABLE MyTable USING INDEX b_c_v (book=? AND chapter=? AND verse=?) (~8 rows)
If you create a covering index (with all fields used in the query, lookup fields first), SQLite does not need to read from the table at all. However, this does not give a big speedup over a normal index, and might not be worth the additional storage cost:
sqlite> CREATE INDEX cov ON MyTable(book, chapter, verse, strongId, word);
sqlite> EXPLAIN QUERY PLAN SELECT strongId, word FROM MyTable WHERE book=1 AND chapter=2 AND verse=3;
0|0|0|SEARCH TABLE MyTable USING COVERING INDEX cov (book=? AND chapter=? AND verse=?) (~8 rows)
Please note that SQLite can use at most one index per table in a query, so it does not always make sense to create multiple indexes.
Use EXPLAIN QUERY PLAN to check which indexes are actually used, and whether you can create a few indexes to optimize most of your queries.
Also see the Query Planning documentation.
I ended up creating temporary tables and performance is now acceptable