Ignore accents SQLite3 - android

How do I make a SELECT with a LIKE clause ignoring accents on SQLite3?
PS: It's for Android build-in SQLite support.

There is a solution, it is not elegant, but it works on Android.
The function REPLACE can replace the accented character by the normal character. Example:
SELECT YOUR_COLUMN FROM YOUR_TABLE WHERE replace(replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace( lower(YOUR_COLUMN), 'á','a'), 'ã','a'), 'â','a'), 'é','e'), 'ê','e'), 'í','i'),
'ó','o') ,'õ','o') ,'ô','o'),'ú','u'), 'ç','c') LIKE 'SEARCH_KEY%'
Or use unicode:
SELECT YOUR_COLUMN FROM YOUR_TABLE WHERE replace(replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace( lower(YOUR_COLUMN), '\u00E1','a'), '\u00E3','a'), '\u00E2','a'), '\u00E9','e'), '\u00EA','e'), '\u00ED','i'),
'\u00F3','o') ,'\u00F5','o') ,'\u00F4' ,'o'),'\u00FA','u'), '\u00E7' ,'c') LIKE 'SEARCH_KEY%'
Where SEARCH_KEY is the key word that you wanna find on the column.

There has been a similar question here.
They said it is not really possible on Android, but there is a workaround with an additional normalized column.

You can a create a mask column and update after insert values in to table with a trigger.
-- Table
CREATE TABLE IF NOT EXISTS mytable (
id TEXT PRIMARY KEY,
description TEXT default '',
description_mask TEXT default ''
);
-- Trigger
CREATE TRIGGER IF NOT EXISTS mytable_in AFTER INSERT ON mytable
BEGIN
UPDATE mytable
SET description_mask =
lower(
replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(
NEW.description,
'á','a'), 'ã','a'), 'â','a'), 'é','e'), 'ê','e'), 'í','i'), 'ó','o') ,'õ','o') ,'ô','o'),'ú','u'),'ç','c'),'ñ','n'),
'Á','a'), 'Ã','a'), 'Â','a'), 'É','e'), 'Ê','e'), 'Í','e'), 'Ó','o') ,'Õ','o') ,'Ô','o'),'Ú','u'),'Ç','c'),'Ñ','n')
)
WHERE id = NEW.id;
END;
-- Select example
SELECT * FROM mytable WHERE (description LIKE '%acido%' OR description_mask LIKE '%ácido%');

Related

Sqlite query to get list of next available characters after the matching search keyword

How to query sqlite database to get list of next available characters after the search keyword in a string field.
for example, if the search keyword is ’and’
and let the strings be a list of names like :
Andy Xyz
Andrew Xyz
Xyz Andon
Xyz Miranda
then i should get the characters [y,r,o,a].
I tried the query with substr(names,1,1), but substr needs to specify the start index which will be different in each strings. Is it possible to fetch these characters using sqlite query?
You need substr() and instr():
select
substr(names, instr(lower(names), lower('and')) + length('and'), 1) nextchar
from tablename
where
names like '%' || 'and' || '_%'
See the demo
You can replace 'and' with any string you wish in the above query.
You could utilise the instr function to ascertain the start of the substr e.g. :-
SELECT *, substr(names,instr(lower(names),'and') + length('and'),1) AS onechar
FROM mytable WHERE names LIKE ('%and%');
A working example :-
DROP TABLE IF EXISTS mytable;
CREATE TABLE IF NOT EXISTS mytable (names TEXT);
INSERT INTO mytable VALUES('Andy Xyz'),('Andrew Xyz'),
('Xyz Andon'),('Xyz Miranda');
SELECT *, substr(names,instr(lower(names),'and') + length('and'),1) AS onechar FROM mytable WHERE names LIKE ('%and%');
This results in :-
as per your expected results.

SQLIte how to insert unique data on change of column value

I am using SQLite Database for my application. I have 4 columns- Student_Name,Student_Enroll, Student_Mob, Student_Address in my database. Now I can add new record if and only if one of four column value is different or all values are different. If all column values are same then no new record should be generated.
Can you please guide me to solve this issue?
To enforce that a set of columns must be unique, add a UNIQUE constraint:
create table Students (
/* ID INTEGER PRIMARY KEY, */
Student_Name TEXT,
Student_Enroll TEXT,
Student_Mob TEXT,
Student_Address TEXT,
UNIQUE (Student_Name, Student_Enroll, Student_Mob, Student_Address)
);
This allows new rows only if at least one of the four columns has a different value.
With a plain INSERT, attempting to insert a duplicate row will result in an error. If you simply want to ignore it instead, use INSERT OR IGNORE:
INSERT OR IGNORE INTO Students ...;
Despite of set your column as UNIQUE you also need to resolve the conflict created on each column when you try to insert new data.
To do so, define the behavior to solve the conflict:
"CREATE TABLE table (your columns here...(UNIQUE unique colums here...) ON CONFLICT REPLACE);"
During Create Database line insert UNIQUE ...for each column to insert only unique record.
Solution 1: (Simple)
Define all columns as unique:
create table TableName (id integer primary key autoincrement,
Student_Name text not null unique,
Student_Enroll text not null unique,
Student_Mob text not null unique);
You can add Student_Address as well, if you need to
Solution 2: (bit complex)
Use AND Operator with WHERE clause
INSERT INTO TableName (Student_Name, Student_Enroll, Student_Mob)
SELECT varStudentName, varStudentEnroll, varStudentMob
WHERE NOT EXISTS(SELECT 1 FROM TableName WHERE Student_Name = varStudentName OR Student_Enroll = varStudentEnroll OR Student_Mob = varStudentMob );
//If a record already contains a row, then the insert operation will be ignored.
You can find more information at the sqlite manual.
Live Example:
Open SQLite Online
Paste following code:
INSERT INTO demo (id,name,hint)
SELECT 4, 'jQuery', 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML'
WHERE NOT EXISTS(SELECT 1 FROM demo WHERE name = 'jQuery' OR hint = 'is a cross-platform JavaScript library designed to simplify the client-side scripting of HTML' );
SELECT * from demo
Hit RUN
This won't insert 4th record and if you modify both values of WHERE clause then record will be inserted.

Sort varchar datatype with numeric characters in sqlite3-- Android

I have a varchar column that needs to be sorted by the number included in it. The data is similar to:
L1,L10,L11,L12,L2,L20,L21
I want the output like this where the value is sorted by the number.
L1,L2,L10,L11,L12,L20,L21
I would suggest to split your table into two columns.
One for the "alphabetical" part and one for the numeric part.
Then you could easily sort it by using a select like this:
SELECT * FROM your_table WHERE your_conditions ORDER BY numeric_column ASC;

Search String in column value of Sqlite

I am trying to search a String in column of my table .The values are stored in
column in this format
My Search String is similar as above. i.e: comma separated String
My query is to find out whether any value in search String is present is my column or not.
Things I have Tried:
using Like : Like does it.But it matches individual values i.e for 3 search string values I have to make 15 like condition(costly for large table)
SELECT * from A WHERE mycol LIKE 'myval,%' or mycol LIKE '%, myval,%' or mycol or LIKE '%, myval'
using instr function : instr matches the String but only the First Occurance.
e.g: select * from A where instr ('123' ,'12')
using In : This donot search within the String .But Matches the values individually.
I have tried Like function Like(X , Y) from docs Here
So my Question is there a way , instead of Individually searching my search string in the column using Like Operator or In function . I could search my values values in single query something like combination of In and Any(not supported in Sqlite) function does in other Db
i.e select * from A where Any('my search string') in ('my column value')
Any Answer or comment is HIGHLY Appreciated.Hoping for reply.
You have problems because your database is not properly normalized.
To have multiple search IDs for each MyTable row, create a second table that can have multiple rows, with one search ID in each row:
CREATE TABLE MyTable (
MyTableID INTEGER PRIMARY KEY,
[...]
);
CREATE TABLE MyTableSearchIDs (
MyTableID INTEGER REFERENCES MyTable(MyTableID),
SearchID INTEGER -- or TEXT or whatever
);
To search for a MyTable row, search its ID first:
SELECT *
FROM MyTable
WHERE MyTableID IN (SELECT MyTableID
FROM MyTableSearchIDs
WHERE SearchID = 'myvalue')
The same can be done with a join:
SELECT MyTable.*
FROM MyTable
JOIN MyTableSearchIDs USING (MyTableID)
WHERE MyTableSearchIDs.SearchID = 'myvalue'

SQLite Fts select query

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<?)

Categories

Resources