Саммерфилд - Программирование на Python 3 (1077331), страница 116
Текст из файла (страница 116)
Имя режиссера, введенное пользователем, может присутствовать, а может отсутствовать в таблице б1гес!ога, поэтому мы предусмотрели функцию цег апб ае1 б! гес!ог(), которая добавляет имя режиссера, если оно еще отсутствует в базе данных, и в любом случае возвращает его идентификатор для вставки в таблицу буба. Собрав все данные, функция выполняет инструкцию 1МБЕВТ языка ЗЯЬ. Здесь не требуется указывать идентификатор записи, потому что база данных ЗЯЬ(Се подставит его автоматически.
Знаки вопроса в тексте запроса используются в качестве символов-заполнителей. Каждый знак? замещается соответствующим значением из последовательности, следующей за строкой с инструкцией ЗЯЬ. Имеется также возможность использовать именованные символы-заполнители, она будет продемонстрирована в функции редактирования записи. Несмотря на то, что существует возможность отказаться от использования символов-заполнителей простым форматированием строки ЗЯЬ, внедряя в нее необходимые данные, тем не менее мы рекомендуем всегда использовать символы-заполнители, а бремя корректного кодирования и экранирования служебных символов в элементах данных перекладывать на модуль базы данных.
Еще одно преимущество использования символов-заполнителей состоит в том, что они повышают уровень безопасности, предотвращая возможность инъекции в запрос злонамеренного кода ЗЯЬ. баг ца! апб 55! 61гассог(бь, О1гас1ог); О!гас!Ьг зб = цаг б)гасгог !О(ОЬ, б!гасгог) з( бзгес!ог Гб Га пО! Мопа: га!Нгп 01гес!ог !б согаог = ОЬ.согаог() согаог.ехесо!е("1МЯЕМТ !МТО б1гес!ога (паве) НАЕОЕЯ (?)", (О1гесгог, )) ОЬ.соаа1!() ге10гп де! б1гес!ог зб(бь, О!гас!ог) Эта функция возвращает идентификатор указанного имени режиссера и в случае необходимости добавляет новую запись в таблицу О1гес!о га.
Глава 11. Программирование приложений баз данных Если была добавлена новая запись, идентификатор режиссера извле- кается с помощью повторного вызова функции де! б!гес!ог Тб(). беГ де! бдгес!Ьг !б(бЬ, б!гес!Ьг); сигаог = би.сигаог() сигаог,ехеси!е("БЕ(ЕСТ !б РВОМ б1гес!огз ИНЕВЕ паве= ?", (б1гес!ог,)) 11е1ба = сигаог.(е!сиопа() ге!игп Г1е1ба(0) ьГ Г1е1ба !з по! Мале е1ае Мопс Функция де! б!гес!Ог бчб() возвращает идентификатордля заданного имени режиссера или Мопе, если такого имени в базе данных не существует. Здесь используется метод Ге!с Попе( ), потому что для данного имени может существовать либо одна запись, либо ни одной.
(Дубликатов записей не может существовать, потому что поле паве в таблице б! гес!ога имеет ограничение ОМ100Е, и в любом случае, прежде чем добавить новое имя режиссера в таблицу, мы проверяем его существование.) Методы извлечения записей всегда возвращают последовательность полей (или Мопе, если все записи были извлечены), даже если, как в данном случае, выполняется попытка извлечь единственное поле. беГ еб!! бчб(бЬ)'. !х!1е, !беп!д!у = Г!пб бчб(бЬ, "еб!!") !Г !!!1е !а Моле: ге!игп !1!1е = Сопао1е.де! а!г!пд("Т!!1е", "!!!1е", !д!1е) !Г по! !1!1е; ге!игп сигепг = бЬ.сигесг() сигаьг.ехеси!е("ЕЕ(ЕСТ бчба.уеаг, бчба.бига!1оп, ангес!Ьга.паве " "РВОМ бчба, бхгес!ога " "ИНЕВЕ бчба.б!гес!ог 1б = б!гес!Ьгз.!б АМО " "бчба. 1б=:!б", б!с!(1б=1беп!!!у)) уеаг, бага!ьоп, б!гес!Ьг = сигзсг.(е!Ьпопе() б!гас!ог = Сипаи!е.де! а!г!пд("О!гес!Ьг", "б!гес!Ьг", б1гес!Ьг) !Г по! б!гес!Ьг: ге!игп уеаг = Сопзо1е.де! !и!адег("уеаг", "уааг", уааг, 1896, ба!е!!ве.ба!е.!Ьбау().уеаг) сига!1оп = Сппао1е.де! !и!едег("Оига!1оп (в1пи!еа)", "в1пи!ез", бага!1оп, в1п!вив=д, вахдвив=60*48) б1гес!ог !б = де! апб ае! б!гес!Ьг(би, б!гес!Ьг) сигаог.ехеси!е("ОРОАТЕ бчба ЯЕТ !!!1е=:!!!1е, уеаг=:уеаг, "сига!1оп=;бига!1сп, б!гес!Ьг дб=.б1гес!Ьг !б " "ИНЕВЕ !б=.!б", 1оса1з()) ба.савв!!() Чтобы отредактировать запись с информацией о диске, ее сначала необходимо отыскать.
Если запись будет найдена, пользователю предоставляется возможность изменить название фильма. Затем извлекаются значения остальных полей, которые будут использоваться в качест- Базы данных 5() Е 519 ве значений по умолчанию, чтобы минимизировать ввод с клавиатуры, так как пользователю достаточно будет проото нажать клавишу Еп(ег, чтобы принять значение по умолчанию. В этой функции иопользуются именованные символы-заполнители (в форме: паве), и поэтому значения для них должны поставляться в виде отображения.
Для инструкции БЕЗВЕСТ был использован вновь созданный словарь, а для инструкции ОРОАТŠ— словарь, полученный вызовом функции 1оса)в(). В обоих случаях можно было бы создавать новый словарь, и тогда для инструкции ОРОАТЕ вместо вызова функции 1оса1в() можно было бы указать словарь б!сг(!!!1е=г!!1е, уеаг=уеаг, бога!!оп=бога!!оп, бзгес!Ьг зб=б!гесгог зб, !б=!бепС!!у). Как только у нас будут значения всех полей и пользователь внесет все необходимые изменения, из базы данных извлекается идентификатор режиссера (при этом в случае необходимооти вставляется новая запись) и затем выполняется запись обновленных данных в базу.
Мы предприняли упрощенный подход, выполняя обновление сразу всех полей запиои, вместо того чтобы выявлять и обновлять только те, которые действительно изменились. При использовании базы данных ЭВМ название диска использовалось в качестве ключа, поэтому при изменении названия создавался новый элемент ключ-значение, а прежний элемент удалялся. В данном же случае запись имеет уникальный идентификатор (поле зб), который определяется в момент ее добавления, поэтому можно без всяких ограничений изменять значение любого другого поля без необходимости выполнять какие-либо дополнительные действия.
беГ Гзпб боб(бЬ, аевваде): аевваде = "(В!аг! ог) гз!1е со " а аевваде согвог = бЬ.оогвог() аш1е Тгое; в!аг! = Сопво1а.де! в!г!пд(аавваде, ?т!!1е") зг по! вгагг; ге!огп (Иове, Иове) согвог.ехесо!а("БЕ(ЕСТ с!11е, зб РВОМ бнбв " ТИНЕВЕ г!!1а Е1КЕ ? СВОЕВ ВУ !!11е", (вгаг! + "%")) гасогбв = согвог.ге!спа11() зГ 1еп(георгов) == О: рггп!("тпеге ага по боба вгаг!гпд а!!и", вгаг!) соп!!пое в!!Г 1ап(георгов) == 1. ге!ого гесогбв(О] е1!Г 1ап(гесогбв) > 01ВРЕА? Е1М1Т: ргзп!("Тоо аапу боба ((0)) в!аг! аз!Ь (1), !гу еп!ег!пд "аогв ог гпа г!!1в".гогаа!(1еп(гесогбв), вгаг!)) соп!зпое е1ве: Гог з, гесогб !и епоаегаге(гесогбв); 520 Глава 11. Программирование приложений баз данных рг1пг("(0); (1)".Тогааг(1 е 1, гесогб[0])) нтсЬ = Сопво1е,де1 хпгедег("МоеЬег (ог 0 (а сапсе1)", "поаЬег", а(п1воа=1, еах]еоа=1еп(гесогбв)) гегигп гесогбв[ньтсь - 1] хг н(цсь ! = 0 е1ве (моле, лопе) Эта функция играет ту же роль, что и функция (1пб буб() из программы гврс(в-с(Ьт.ру, и возвращает кортеж из двух элементов (название, идентификатор диска) или (Иоле, Иоле) в зависимости от того, была ли найдена требуемая запись.
Вместо того чтобы выполнять итерации по всем данным, здесь используется оператор шаблонного символа ВЯЬ (%), поэтому из базы данных извлекаются только необходимые записи. А поскольку ожидается, что число записей будет невелико, выполняется извлечение сразу всех записей в последовательность последовательностей. Если будет найдено более одной записи, соответствующей условию поиска, или не настолько много, чтобы все они одновременно не поместились на экране„функция выводит их, предваряя каждую запись порядковым номером, чтобы пользователь смог сделать выбор вводом числа, как это делалось в программе бис(в-г(Ьтру. беГ 11в( буба(бЫ'. согвог = бо.согвог() вц1 = ("ВЕ1ЕСТ буба.
(Ы1е, буба.уеаг, бубе.бсгвмоп, "0(гес(огв.папе ГНОМ буба, б!гесгогв " "ХНЕНЕ буба.б1гесгог 1б = 01гесгогв. 10") в(агг = Мопе гг буб соопг(бЫ > 01ВР(АУ 11м1т: вгаг( = Сопво1е.де( в(г1пд("11вг (лове в(аггьпд ныл " "[еп(ег=а11]", "вгагг") вц1 а= " ПМО буба.(111е ЕЕКЕ ?" вц1 а= " ОНОЕН ВУ буба. 1111е" ртпг() 1Г вгаг( 1в Моле: согвог, ехесо1е(вц1) е1ве: ссгвог.ехесоге(вц1, (в1аг( е "%",)) Гог гесогб 1п согвог: рмпг("(0[0]) ((О[1))) (0[2]) запотев, ьу (0[3])".Тогеаг( гесогб)) Чтобы получить сведения о каждом диске, создается запрос ВЕЕЕСТ, выполняющий объединение двух таблиц. Если число записей в базе данных (возвращается функцией буб соопг()) оказывается больше, чем может поместиться на экране, в предложение АРМЕНЕ добавляется второй элемент, вводящий дополнительное ограничение.