Leonid Semyonov
Leonid Semyonov

Reputation: 493

LIKE case-insensitive for not English letters

I want to retrieve rows whose TITLE field meets some pattern (case-insensitive), and this field contains only non-English letters.

I tried this:

SEARCH * FROM TABLE_NAME WHERE UPPER(column_name) LIKE UPPER('%pattern%');

However, this doesn't work, may be because the table contains only non-English letters.

UPDATE:

Example:

SELECT * FROM PartnersTable WHERE UPPER(TitleColumn) LIKE UPPER('%pattern%');

Where:

TitleColumn may contain "Газпром", "Лукойл", "Йотафон", "Мечта ювелира",

pattern may contain "газ", "Ювелир" etc.

Upvotes: 10

Views: 9091

Answers (4)

Michał Szkudlarek
Michał Szkudlarek

Reputation: 1502

I tried it with using COLLATE NOCASE added to the column definition. If you are able to do it, then this is the way to go.

What I tested:

CREATE TABLE PartnersTable 
    (`id` , `TitleColumn` COLLATE NOCASE )
;

Added same data as in your question:

INSERT INTO PartnersTable
    (`id`, `TitleColumn`)
VALUES
 (1, 'Газпром'), (2, 'Лукойл'), (3, 'Йотафон'), (4, 'Мечта ювелира')
;

Then tried to select it:

select *
from PartnersTable
where TitleColumn like '%Ювелир%'

It works.

Demo here: http://sqlfiddle.com/#!7/ae8f8/2

Edit: You can also use it with without UPPER. By default LIKE is case insensitive. As per documentation:

Any other character matches itself or it's lower/upper case equivalent (i.e. case-insensitive matching). (A bug: SQLite only understands upper/lower case for ASCII characters. The LIKE operator is case sensitive for unicode characters that are beyond the ASCII range. For example, the expression 'a' LIKE 'A' is TRUE but 'æ' LIKE 'Æ' is FALSE.)."

Demo here: http://sqlfiddle.com/#!7/c9b5d/1

Upvotes: 4

Magnus
Magnus

Reputation: 18748

If your data contains only a limited set of international letters, one quick and simple solution is to use replace() to manually change the case of the international letters.

For example in my case, I am expecting only [a-z], [A-Z] and [åäöÅÄÖ]:

// First, use application code to make the search string lowercase.
searchStr = searchStr.toLower(); 

// The SQLite function lower() will not affect ÅÄÖ, so we need 
// to manually replace them with their lowercase versions.
sql = "SELECT * "+
  " FROM table1 "+
  " WHERE "+
  "   replace(replace(replace( lower(name) , 'Å','å'), 'Ä','ä'), 'Ö','ö') LIKE ?";

db.prepare(sql, ["%"+searchStr+"%"]);

Upvotes: 0

kyo
kyo

Reputation: 162

The code is not working because UPPER is working for only ASCII characters(link). To solve this I implemented User-Defined function with BindFunction for .NET as below.

// for System.Data.SQLite
connection.BindFunction(
    new SQLiteFunctionAttribute("myupper", 1, FunctionType.Scalar),
    (Func<object[], object>)((object[] args) => ((string)((object[])args[1])[0]).ToUpper()),
    null);
        
// for Microsoft.Data.Sqlite
connection.CreateFunction(
    "myupper",
    (string arg) => (arg).ToUpper());

var command = connection.CreateCommand();
command.CommandText =
@"
    SELECT *
    FROM PartnersTable 
    WHERE MYUPPER(TitleColumn) LIKE MYUPPER('%pattern%')
";
      
command.ExecuteQuery()

However it takes longer to execute the query.

Following links might help too

https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/user-defined-functions https://learn.microsoft.com/en-us/dotnet/standard/data/sqlite/compare

Upvotes: 3

anefeletos
anefeletos

Reputation: 702

Redifine Like function (This uses the Sqlite .NET wrapper). Also note VB like uses asterisk wildcard. If you want % replace the string or redefine GLOB instead.

     public static void OverrideLikeFunction()
 {
    SQLiteSpace.SQLiteFunction.RegisterFunction(typeof(SQLiteHelper.Ulike));

}

[System.Data.SQLite.SQLiteFunction(FuncType=System.Data.SQLite.FunctionType.Scalar, Name="Like")]
;
        Public Class Ulike;
            Inherits System.Data.SQLite.SQLiteFunction;
            Public Overrides Function Invoke(args() As object) As object;
            try
            {
                    if (System.Convert.IsDBNull(args(0)) || System.Convert.IsDBNull(args(1)))
                    {
                        return false;
                    }
                    return (Microsoft.VisualBasic.CompilerServices.StringType.StrLike(System.Convert.ToString(args(1)).ToUpperInvariant(), System.Convert.ToString(args(0)).ToUpperInvariant(), Microsoft.VisualBasic.CompareMethod.Binary));
                }
                catch (Exception ex)
                {
                                   return null;
                }
            }

        }

Upvotes: 0

Related Questions