Шаг 205.
Основы языка Python.
Доступ к базе данных SQLite из Python. Поиск без учета регистра символов

    На этом шаге мы рассмотрим использование метода create_function().

    Как уже говорилось на 192 шаге, сравнение строк и поиск с помощью оператора LIKE для русских букв производится с учетом регистра символов. Поэтому следующие выражения вернут значение 0:

>>> cur.execute("SELECT 'строка' = 'Строка'")
<sqlite3.Cursor object at 0x02426DA0>
>>> print(cur.fetchone()[0]) # Результат: 0 (не равно)
0
>>> cur.execute("SELECT 'строка' LIKE 'Строка'")
<sqlite3.Cursor object at 0x02426DA0>
>>> print(cur.fetchone()[0]) # Результат: 0 (не равно)
0

    Одним из вариантов решения проблемы является преобразование символов обеих строк к верхнему или нижнему регистру. Но встроенные функции SQLite UPPER () и LOWER () с русскими буквами также работают некорректно. Модуль sqlite3 позволяет создать пользовательскую функцию и связать ее с названием функции в SQL-запросе. Таким образом, можно создать пользовательскую функцию преобразования регистра символов, а затем указать связанное с ней имя в SQL-запросе.

    Связать название функции в SQL-запросе с пользовательской функцией в программе позволяет метод create_function() объекта соединения. Формат метода:

  create_function(<Название функции в SQL-запросе в виде строки>, 
    <Количество параметров>, 
    <Ссылка на функцию>)

    В первом параметре в виде строки указывается название функции, которое будет использоваться в SQL-командах. Количество параметров, принимаемых функцией, задается во втором параметре, причем параметры могут быть любого типа. Если функция принимает строку, то ее типом данных будет str. В третьем параметре указывается ссылка на пользовательскую функцию в программе. Для примера произведем поиск рубрики без учета регистра символов:

# -*- coding: utf-8 -*-
import sqlite3
# Пользовательская функция изменения регистра
def myfunc(s):
    return s.lower()

con = sqlite3.connect("catalog.db")
# Связываем имя "mylower" с функцией myfunc()
con.create_function("mylower", 1, myfunc)
cur = con.cursor()
string = "%МуЗЫка%"	#  Строка для поиска
# Поиск без учета регистра символов
sql = """SELECT * FROM rubr
   WHERE mylower(name_rubr) LIKE ?"""
cur.execute(sql,(string.lower(),))
print(cur.fetchone()[1]) # Результат:   Музыка
cur.close()
con.close()
input()
Архив с файлом можно взять здесь.

    Результат работы приложения:

Музыка

    В этом примере предполагается, что значение переменной string получено от пользователя. Обратите внимание на то, что строку для поиска в метод execute () мы передаем в нижнем регистре. Если этого не сделать и указать преобразование в SQL-запросе, то лишнее преобразование регистра будет производиться при каждом сравнении.

    Метод create_function() используется не только для создания функции изменения регистра символов, но и для других целей. Например, в SQLite нет специального типа данных для хранения даты и времени. При этом дату и время можно хранить разными способами - например, в числовом поле как количество секунд, прошедших с начала эпохи. Для преобразования количества секунд в другой формат следует создать пользовательскую функцию форматирования:

# -*- coding: utf-8 -*-
import sqlite3
import time
def myfunc(d):
    return time.strftime("%d.%m.%Y", time.localtime(d))

con = sqlite3.connect(":memory:")
# Связываем имя "mytime" с функцией myfunc()
con.create_function("mytime", 1, myfunc)
cur = con.cursor()
cur.execute("SELECT mytime(1429100920)")
print(cur.fetchone()[0]) # Результат: 15.04.2015
cur.close()
con.close()
input()
Архив с файлом можно взять здесь.

    Результат работы приложения:

15.04.2015

    На следующем шаге мы рассмотрим создание агрегатных функций.




Предыдущий шаг Содержание Следующий шаг