Опубликован: 22.12.2005 | Уровень: для всех | Доступ: свободно
Лекция 10:

Работа с базой данных

< Лекция 9 || Лекция 10: 12345 || Лекция 11 >

Наполнение базы данных

Теперь можно наполнить таблицы значениями. Следует начать с расшифровки числовых значений для дней недели:

weekdays = ["Воскресенье", "Понедельник", "Вторник", "Среда",
               "Четверг", "Пятница", "Суббота", "Воскресенье"]

   import sqlite as db

   c = db.connect(database="tvprogram")
   cu = c.cursor()
   cu.execute("""DELETE FROM wd;""")
   cu.executemany("""INSERT INTO wd VALUES (%s, %s);""",
              enumerate(weekdays))
   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 не будет влиять на другие части программы.

< Лекция 9 || Лекция 10: 12345 || Лекция 11 >
Сергей Крупко
Сергей Крупко

Добрый день.

Я сейчас прохожу курс  повышения квалификации  - "Профессиональное веб-программирование". Мне нужно получить диплом по этому курсу. Я так полагаю нужно его оплатить чтобы получить диплом о повышении квалификации. Как мне оплатить этот курс?

 

Павел Ялганов
Павел Ялганов

Скажите экзамен тоже будет ввиде теста? или там будет какое то практическое интересное задание?

Сергей Грабовский
Сергей Грабовский
Россия, Тольятти
Андрей Бабенко
Андрей Бабенко
Украина, Харьков