I want to order my data objects from an ORMLite DAO case insensitively.
Currently I am using the following sqlite code to order my owner items case sensitively:
ownerDao.queryBuilder().orderBy("Name", true).query();
I see here that sqlite supports case insensitive "order by" with the following raw SQL:
SELECT * FROM owner ORDER BY Name COLLATE NOCASE
Any easy way (easier than calling queryRaw()) of adding the desired suffix?
Could an alternative solution be to set the columnDefinition property on the DatabaseField annotation to TEXT COLLATE NOCASE?
I think what you want is to use the QueryBuilder.orderByRaw(String) method. It would look something like:
ownerDao.queryBuilder().orderByRaw("Name COLLATE NOCASE").query();
Notice the raw string does not contain the ORDER BY part of the string. To quote the javadocs:
Add raw SQL "ORDER BY" clause to the SQL query statement. This should not include the "ORDER BY".
The TEXT COLLATE NOCASE columnDefinition might work although I don't have any experience with using that at all.
Also, I would not use the orderBy("Name COLLATE NOCASE", true) answer since typically ORMLite tries to escape the column names and the quotes would be in the wrong place.
Related
I am making an Android app in Kotlin with SQLite, and I use the code below to delete a record with 'subject' column.
val rows = db.delete(TABLE_NAME, "subject=?", arrayOf(subject))
It works as intended, e.g. if I provide the subject string "Math", it deletes the record whose subject is "Math".
My question is, how can I delete a record of subject of "math" case-insenstively. I mean, either Math or math should delete the record.
I read somewhere that I can use "COLLATE NOCASE" in SQL statement as
DELETE FROM TABLE_NAME WHERE subject = "math" COLLATE NOCASE;
But as I am using the delete() method of SQLiteDatabase class in Android, I wonder how I can implement the same case-insensitive comparison.
For normal case insensitivity you can use LIKE rather than = e.g.
val rows = db.delete(TABLE_NAME, "subject LIKE ?", arrayOf(subject))
see https://www.sqlite.org/lang_expr.html#the_like_glob_regexp_match_and_extract_operators for a more in-depth explanation and caveats etc.
The following demonstrates using native SQLite using an SQLite tool (Navicat in this case, other tools exist):-
DROP TABLE IF EXISTS example; /* just in case */
CREATE TABLE IF NOT EXISTS example (subject TEXT); /* create the table */
/* Add some testing data */
INSERT INTO example VALUES ('Math'),('MAth'),('math'),('mATH'),('something else');
SELECT * FROM example; /* output the original data (Result 1)*/
DELETE FROM example WHERE subject = 'math'; /* case sensitive delete*/
SELECT * FROM example; /* output the data after deletion (Result 2)*/
DELETE FROM example WHERE subject LIKE 'math'; /* case insensitive deletion */
SELECT * FROM example; /* output the data after deletion (Result 3)*/
/* Cleanup Environment */
DROP TABLE IF EXISTS example;
Resulting in:-
original data
after case sensitive deletion (i.e. just math is deleted)
after the case insensitive deletion (i.e. all rows bar something deleted)
would delete the math row if it hadn't been deleted previously
I read somewhere that I can use "COLLATE NOCASE" in SQL statement as DELETE FROM TABLE_NAME WHERE subject = "math" COLLATE NOCASE;
Then you could use:-
val rows = db.delete(TABLE_NAME, "subject=? COLLATE NOCASE", arrayOf(subject))
Note that the documentation for the 2nd parameter of the delete method says:-
whereClause String: the optional WHERE clause to apply when deleting. Passing null will delete all rows.
without the WHERE keyword itself
WHERE is added by the method, like FROM is added to the tablename (first parameter) and DELETE is added; when building the SQL that is executed).
i.e. the entire clause (as shown above). The WHERE clause expects and expression which can be quite complex see link above and scroll to the top for what an expression can consist of.
I want to make a contacts query where the selection is in the form Phone.DISPLAY_NAME_PRIMARY + " LIKE ?, but I want the search to be accent insensitive.
If I use COLLATE LOCALIZED, it works with the = operator, not with the like.
Android's default contact app somehow manages to do that.
Instead of making a query to ContactsContract.Data.CONTENT_URI and using a "selection", make a query to ContactsContract.Contacts.CONTENT_FILTER_URI where the query is added as an additional path segment.
For example, if i have these records
word
AAA
AAB
AAC
BAA AA
With a normal table i would use sql like
select * from table where word like 'AA%'order by H collate nocase asc
How do i select with FTS3 table instead?
Also i would like to know if FTS3 will still have better performance than normal table with this kind of query?
How do i select with FTS3 table instead?
Quoting the documentation:
An FTS table may be queried for all documents that contain a specified term (the simple case described above), or for all documents that contain a term with a specified prefix. As we have seen, the query expression for a specific term is simply the term itself. The query expression used to search for a term prefix is the prefix itself with a '*' character appended to it.
The documentation also gives a sample:
-- Query for all documents containing a term with the prefix "lin". This will match
-- all documents that contain "linux", but also those that contain terms "linear",
--"linker", "linguistic" and so on.
SELECT * FROM docs WHERE docs MATCH 'lin*';
I am making a dictionary of over 20,000 words in it. So, to make it work faster when search data, i am using fts3 table to do it.
my select query:
Cursor c=db.rawQuery("Select * from data where Word MATCH '"+word+"*'", null);
Using this query, it will show all the word that contain 'word' , but what i want is to get only the word that contain the beginning of the searching word.
Mean that i want it work like this query:
Cursor c=db.rawQuery("Select * from data where Word like '"+word+"%'", null);
Ex: I have : apple, app, and, book, bad, cat, car.
when I type 'a': i want it to show only: apple, app, and
What can i solve with this?
table(_id primary key not null autoincrement, word text)
FTS table does not use the above attributes. It ignores data type. It does not auto increment columns other than the hidden rowid column. "_id" will not act as a primary key here. Please verify that you are implementing an FTS table
https://www.sqlite.org/fts3.html
a datatype name may be optionally specified for each column. This is
pure syntactic sugar, the supplied typenames are not used by FTS or
the SQLite core for any purpose. The same applies to any constraints
specified along with an FTS column name - they are parsed but not used
or recorded by the system in any way.
As for your original question, match "abc*" already searches from the beginning of the word. For instance match "man*" will not match "woman".
FTS supports searching for the beginning of a string with ^:
SELECT * FROM FtsTable WHERE Word MATCH '^word*'
However, the full-text search index is designed to find words inside larger texts.
If your Word column contains only a single word, your query is more efficient if you use LIKE 'a%' and rely on a normal index.
To allow an index to be used with LIKE, the table column must have TEXT affinity, and the index must be declared as COLLATE NOCASE (because LIKE is not case sensitive):
CREATE TABLE data (
...
Word TEXT,
...
);
CREATE INDEX data_Word_index ON data(Word COLLATE NOCASE);
If you were to use GLOB instead, the index would have to be case sensitive (the default).
You can use EXPLAIN QUERY PLAN to check whether the query uses the index:
sqlite> EXPLAIN QUERY PLAN SELECT * FROM data WHERE Word LIKE 'a%';
0|0|0|SEARCH TABLE data USING INDEX data_Word_index (Word>? AND Word<?)
just wondering if theres a way of sorting the results of a query ignoring case. Cause at the moment fields starting with an upper case letter are sorted and put on top of the list and fields starting with lower case letter are also sorted but are put after the upper case fields.
Thanks --
Mike
ORDER BY column COLLATE NOCASE;
See http://www.sqlite.org/datatype3.html#collation
On the Android you are given a collation function called LOCALIZED.
When you specify your column, do the following:
CREATE TABLE song(..., title TEXT COLLATE LOCALIZED ASC, ...)
It works great. If you have the Android source code, just do a search for "COLLATE" to see all sorts of examples.
Convert all entries to lower case for example: select name from table order by LCASE(name)
LCASE or LOWER (Check documentation)