2014-11-11 3 views
1

Я создал этот NOACCENT COLLATION в Python3, чтобы использовать его в SQL-программе sqlite, которую я пытаюсь написать.SQLITE custom Функция сопоставления Accent и LIKE-запросы

Моя цель состоит в том, чтобы сделать акцентированные вокалы нечувствительными поисками и сделать ввод данных insenstive для акцентов слишком, чтобы (то есть) значение «González» не было допущено, если в поле таблицы есть значение «Gonzalez».

То, что я делал хорошо для второй части (ограничивать значения) и для полного поиска значений. Я не могу заставить его работать для SELECT ... LIKE выражений. Я знаю о ограничении LIKE COLLATE NOCASE в SQLite для символов unicode из a-z, A-Z, но почему это ограничение применяется, когда я использую свой собственный определенный NOKCENT сортировки? Потому что, похоже, это то, что происходит.

Пример:

cur.execute(""" CREATE TABLE Demo(
      Id INTEGER PRIMARY KEY, 
      Nombre TEXT COLLATE NOACCENT UNIQUE)""") 

cur.execute("INSERT INTO Demo(Nombre) VALUES ('álberto')") 
cur.execute("INSERT INTO Demo(Nombre) VALUES ('alberta')") 
cur.execute("INSERT INTO Demo(Nombre) VALUES ('Álbertu')") 
cur.execute("INSERT INTO Demo(Nombre) VALUES ('Álberte')") 
cur.execute("INSERT INTO Demo(Nombre) VALUES ('Albertczo')") 
cur.execute("INSERT INTO Demo(Nombre) VALUES ('albertai')") 

Если я:

cur.execute("SELECT * FROM Demo WHERE Nombre='ALBERTO' COLLATE NOACCENT") 

я получаю:

(1, 'álberto) 

Что такое хорошо. Это работает с любой комбинацией верхнего и нижнего регистра и любого акцента в любом вокале слова («ALBERTÓ», «Älbèrtô» ...)

Если я попытаюсь вставить значение «ALBERTÓ», я получаю сообщение об ошибке к уникальному ограничению, так что это хорошо работает.

Проблема заключается в том, когда я пытаюсь использовать LIKE выражения:

cur.execute("SELECT * FROM Demo WHERE Nombre LIKE 'ALBERT%' COLLATE NOACCENT") 

Это возвращает:

(2, 'alberta') 
(5, 'Albertczo') 
(6, 'albertai') 

Значения без акцента.

Есть ли какое-либо решение для этого из самой базы данных или мне придется выполнять частичный поиск (например, «albert») через программное обеспечение.

Надеюсь, мой вопрос достаточно ясен.

Заранее спасибо.


def noaccent(string): # eliminate accented vocals 
    vocals = ['a', 'e', 'i', 'o', 'u'] * 4 
    acc_vocals = ['á', 'é', 'í', 'ó', 'ú','à', 'è', 'ì', 'ò', 'ù', 'ä', 'ë', 'ï', 'ö', 'ü', 'â', 'ê', 'î', 'ô', 'û'] 
    no_acc = string 
    for letter in acc_vocals: 
     no_acc = no_acc.replace(letter, vocals[acc_vocals.index(letter)]) 
    return no_acc 

def collate_noaccent(string1, string2): 
    str1 = noaccent(string1.lower()) 
    str2 = noaccent(string2.lower()) 
    if str1 < str2: 
     return -1 
    elif str1 > str2: 
     return 1 
    else: 
     return 0 
+0

Какую библиотеку python/ORM вы используете для доступа к базе данных? – dpassage

+0

@dpassage: 'sqlite3' предположительно, но это вряд ли имеет значение. –

+0

@dpassage py-sqlite – Scotty

ответ

0

LIKE игнорирует параметры сортировки, и всегда использует правила ASCII.

Если вы хотите использовать шаблон LIKE для сопоставления с другими сортировками, вы должны store a normalized form of the text in another column.

+0

Спасибо. Это означало бы дублировать довольно много столбцов в моей базе данных. Тогда не может быть обходным путем? – Scotty

0

Я решил эту проблему, создав свою собственную функцию «как» в классе SqliteUnicode, который я разработал. Это замедляет поиск в 8 раз. Поскольку класс еще не оптимизирован, я предпочитаю не размещать его здесь сейчас, если вы не спросите.

link = sqlite.connect(db_file_s) 
    extension = SqliteUnicode() 
    link.create_collation("france", extension.collate) 
    link.create_function("like", 2, extension.like)