Шрифт:
c.commit
c.close
Стоит напомнить, что встроенная функция enumerate создает список пар номер–значение, например:
Листинг
>>> print [i for i in enumerate(['a', 'b', 'c'])]
[(0, 'a'), (1, 'b'), (2, 'c')]
Из приведенного примера ясно, что метод executemany объекта–курсора использует второй параметр — последовательность — для массового ввода данных с помощью SQL–инструкции INSERT.
Предположим, что телепрограмма задана в файле tv.csv в формате CSV (он уже обсуждался):
Листинг
10.02.2003 9.00|ОРТ|Новости|Новости|9.15
10.02.2003 9.15|ОРТ|«НЕЖНЫЙ ЯД»|Сериал|10.15
10.02.2003 10.15|ОРТ|«Маски–шоу»|Юмористическая программа|10.45
10.02.2003 10.45|ОРТ|«Человек и закон»||11.30
10.02.2003 11.30|ОРТ|«НОВЫЕ ПРИКЛЮЧЕНИЯ СИНДБАДА»|Сериал|12.00
Следующая программа разбирает CSV–файл и записывает данные в таблицу tv:
Листинг
import calendar, csv
import sqlite as db
from sqlite.main import Time, Date ## Только для
db.Date, db.Time = Date, Time ## sqlite
c = db.connect(database=«tvprogram»)
cu = c.cursor
input_file = open(«tv.csv», «rb»)
rdr = csv.DictReader(input_file,
fieldnames=['begt', 'channel', 'prname', 'prgenre', 'endt'])
for rec in rdr:
bd, bt = rec['begt'].split
bdd, bdm, bdy = map(int, bd.split('.'))
bth, btm = map(int, bt.split('.'))
eth, etm = map(int, rec['endt'].split('.'))
rec['wd'] = calendar.weekday(bdy, bdm, bdd)
rec['begd'] = db.Date(bdy, bdm, bdd)
rec['begt'] = db.Time(bth, btm, 0)
rec['endt'] = db.Time(eth, etm, 0)
cu.execute(""«INSERT INTO tv
(tvdate, tvweekday, tvchannel, tvtime1, tvtime2, prname, prgenre)
VALUES (
%(begd)s, %(wd)s, %(channel)s, %(begt)s, %(endt)s,
%(prname)s, %(prgenre)s);""", rec)
input_file.close
c.commit
Большая часть преобразований связана с получением дат и времен (приходится разбивать строки на части в соответствии с форматом даты и времени). День недели получен с помощью функции из модуля calendar.
Примечание:
Из–за небольшой ошибки в пакете sqlite конструкторы Date, Time и т.д. не попадают из модуля sqlite.main при импорте из sqlite, поэтому пришлось добавить две строки, специфичные для sqlite, в универсальный «модуль» с именем db.
В этом же примере было продемонстрировано использование словаря для вставки значений в таблицу базы данных. Следует заметить, что подстановка выполняется внутри вызова execute в соответствии с типами переданных значений. SQL–инструкция INSERT была бы некорректной при попытке выполнить подстановку самостоятельно, например, операцией форматирования %.
Выборки из базы данных
Базы данных создаются для удобства хранения и извлечения больших объемов. Следующий нехитрый пример позволяет проверить, правильно ли были введены в таблицу дни недели:
Листинг
import sqlite as db
c = db.connect(database=«tvprogram»)
cu = c.cursor
cu.execute(«SELECT weekday, wdname FROM wd ORDER BY weekday;")
for i, n in cu.fetchall:
print i, n
Если все было сделано правильно, получится:
Листинг
0 Воскресенье
1 Понедельник
2 Вторник
3 Среда
4 Четверг
5 Пятница
6 Суббота
7 Воскресенье
Несложно догадаться, как сделать выборку телепрограммы:
Листинг
import sqlite as db
c = db.connect(database=«tvprogram»)
cu = c.cursor
cu.execute("""
SELECT tvdate, tvtime1, wd.wdname, tvchannel, prname, prgenre
FROM tv, wd
WHERE wd.weekday = tvweekday
ORDER BY tvdate, tvtime1;""")
for rec in cu.fetchall:
dt = rec[0] + rec[1]
weekday = rec[2]
channel = rec[3]
name = rec[4]
genre = rec[5]
print "%s, %02i.%02i.%04i %s %02i:%02i %s (%s)» % (
weekday, dt.day, dt.month, dt.year, channel,
dt.hour, dt.minute, name, genre)
В этом примере в качестве типа для даты и времени используется тип из mx.DateTime. Именно поэтому стало возможным получить год, месяц, день, час и минуту обращением к атрибуту. Кстати, datetime–объект стандартного модуля datetime имеет те же атрибуты. В общем случае для даты и времени может использоваться другой тип, поэтому если получаемые из базы даты будут проходить более глубокую обработку, их следует переводить во внутреннее представление сразу после получения по запросу. Тем самым тип даты из модуля DB–API не будет влиять на другие части программы.