Михаил Шохирев - Язык программирования Perl
[x]. уникальный идентификатор экземпляра (ID) - пятизначное целое число;
[x]. название моллюска по-русски (NAME) - строка длиной до 35 символов;
[x]. латинское название моллюска (LATIN) - строка длиной до 30 символов;
[x]. основные районы обитания (AREA) - строка длиной до 40 символов.
Исходные данные для загрузки в базу данных, которые будут взяты из текстового файла mollusc.txt, имеют такую структуру:
65590;Перловица;Unio pictorum;реки севера России и Скандинавии 56331;Жемчужница речная;Margaritifera margaritifera;север Европы 10616;Морская жемчужница;Pinctada martensii;Японское море 36816;Королевский стромбус;Strombus gigas;Куба
Компактные, простые и быстрые, базы данных в формате Berkeley DB часто используются в операционных системах семейства Unix для хранения системных данных. Существует несколько разновидностей этого формата, которые обобщенно называются файлами DBM (от английского Database Manager). Данные в DBM-файле хранятся в двоичном виде, а логически его можно рассматривать как ассоциативный массив, хранящийся на диске. Средства работы с базами данных этого формата для разных операционных систем можно бесплатно загрузить с сайта www.sleepycat.com. В таких операционных системах, как Linux, FreeBSD или Solaris, Perl часто устанавливается с поддержкой этого формата данных, которая реализована в модуле DB_File. В операционной системе MS Windows этот модуль потребуется установить дополнительно. (О том, как это делается, речь шла в лекции 13. Если используется дистрибутив Active Perl, установка выполняется командой ppm install DB_File.) С помощью этого модуля легко пользоваться базой данных в формате Berkeley DB, потому что с файлом базы данных можно работать как с обычным хэшем. Для этого устанавливается связь между переменной-хэшем и файлом на диске с помощью функции tie(), которой указывается, что для доступа к файлу (например, 'file.db') нужно использовать модуль DB_File. Если указанный файл не существует, он создается. Когда работа с файлом базы данных через хэш-переменную закончена, связь между ними разрывается функцией untie(). Это делается так:
use DB_File; # подключить модуль для работы с Berkeley DB my %hash; # через этот хэш будет происходить работа с БД tie %hash, 'DB_File', 'file.db' or die; # установить связь $hash{'КЛЮЧ'} = 'ЗНАЧЕНИЕ'; # добавить элемент в хэш и БД untie %hash ; # разорвать связь между хэшем и БД
Формат DBM имеет ограничение, присущее всем ассоциативным массивам: с каждым ключом файла базы данных может ассоциироваться только одно значение. Есть много способов (снова принцип TIMTOWTDI!) обойти это ограничение, и один из них заключается в использовании модуля Storable, который предназначен для организации хранения во внешней памяти массивов, хэшей и других программных объектов. Функция Storable::freeze() "замораживает" данные в двоичном виде, например, перед записью на диск, а функция thaw() "оттаивает" информацию, восстанавливая первоначальную структуру данных. Мы воспользуемся этими функциями для преобразования данных при создании DBM-файла таким образом:
use DB_File; # модули для работы с DBM use Storable qw(freeze thaw); # и сохранения данных my %database; # хэш "привязывается"... tie %database, "DB_File", "mollusc.db" or die; # ...к БД open my $text, '<', 'mollusc.txt' or die; # файл, откуда while (my $data = <$text>) { # читаем данные, chomp($data); # удаляя n # и разбивая строку на поля по разделителю ';': my ($id, $name, $latin, $area) = split(';', $data); my %record = ( # заполняем поля записи БД: ID => $id, # идентификатор экземпляра NAME => $name, # наименование моллюска LATIN => $latin, # латинское название AREA => $area); # ареал обитания my $serialized = freeze %record; # "замораживаем" $database{$id} = $serialized; # и сохраняем запись } close $text; # закрываем тестовый файл untie %database; # и базу данных
После того как база данных DBM создана, мы можем обрабатывать в ней данные, используя функции работы с хэшами, хорошо знакомые нам из лекции 6. Например, так будет выглядеть поиск по ключу:
use DB_File; # модули для работы с DBM use Storable qw(freeze thaw); # и сохранения данных my %database; # хэш "привязываем"... tie %database, "DB_File", "mollusc.db" or die; # ...к БД my $id = 65590; # ищем "Перловицу" if (exists $database{$id}) { # по идентификатору my $serialized = $database{$id}; # считываем и my %record = %{ thaw($serialized) }; # "размораживаем" printf "%5d %s %s %sn", # запись БД в хэш $id, $record{NAME}, $record{LATIN}, $record{AREA}; } untie %database; # "отвязываем" БД от хэша # будет выведено: 65590 Перловица Unio pictorum
Для перебора всех записей файла DBM можно пользоваться функциями keys() и each(), а для удаления записи - применить функцию delete().
С широким распространением персональных компьютеров стал популярным формат баз данных, применяемый в "настольных" СУБД dBASE, Clipper и FoxPro, семейство которых обобщенно называется XBase. Базы данных в этом формате хранятся в таблицах с суффиксом DBF (Database File), а для работы с записями такой таблицы широко применяется произвольный доступ к отдельным записям и перебор записей в цикле. (Хотя работать с ними можно также при помощи языка реляционных запросов SQL.) Одно из средств для работы с DBF-таблицами в программах на Perl - это модуль XBase, который можно загрузить из хранилища модулей CPAN. Он предоставляет объектный интерфейс для создания и изменения баз данных в формате XBase. Например, программа создания таблицы DBF будет выглядеть так:
use XBase; # модуль работы с БД в формате DBF my $table = XBase->create( # метод создания таблицы "name" => "mollusc.dbf", # имя файла # имена полей (колонок, столбцов) таблицы: "field_names" => ["ID", "NAME", "LATIN", "AREA"], # типы данных (N - число, C - строка, D - дата): "field_types" => [ "N", "C", "C", "C"], # максимальные длины полей: "field_lengths" => [ 5, 35, 30, 45], # длины дробной части (для чисел): "field_decimals" => [ 0, undef, undef, undef] ); $table->close(); # метод закрытия файла БД
Далее потребуется программа добавления данных в созданную таблицу из текстового файла. Например, такая:
use XBase; # модуль работы с БД в формате DBF my $table = new XBase "mollusc.dbf" # конструктор DBF or die Xbase->errstr; # обработка ошибок my $recno = 0; # добавляемые записи нумеруются с нуля open my $text, '<', 'mollusc.txt' or die; # файл, откуда while (my $data = <$text>) { # читаем данные, chomp($data); # удаляя n # и разбивая строку на поля по разделителю ';': my ($id, $name, $latin, $area) = split(';', $data); # добавляем запись, указывая поля в порядке создания $table->set_record($recno, $id, $name, $latin, $area); $recno++; # и увеличиваем счетчик записей } close $text; # закрываем тестовый файл $table->close(); # и файл базы данных
Модуль XBase предоставляет все необходимые методы для работы с таблицами баз данных. Многие из них основаны на возможности произвольного доступа к любой записи DBF-файла по ее номеру. Например, таким образом можно прочитать, изменить или удалить запись по номеру $record_number:
# считать запись в хэш, с доступом к нему по ссылке: my $hash_ref = $table->get_record_as_hash($record_number); # изменить значение поля NAME на $table->update_record_hash($record_number, 'NAME' => $new); # пометить запись как логически удаленную $table->delete_record($record_number); # восстановить логически удаленную запись $table->undelete_record($record_number);
По поводу двух последних операций нужно сделать следующее пояснение. Дело в том, что записи в DBF-файле не удаляются физически, а только помечаются как удаленные. "Логически" удаленные записи игнорируются при обработке данных, но существуют в таблице "физически". Поэтому запись, помеченную как удаленная, можно восстановить для дальнейшей обработки. Один из способов прочитать записи таблицы - выбрать их во временный список записей, называемый курсором, откуда последовательно извлекать их в цикле. Это делается так:
my $cursor = $table->prepare_select("NAME", "LATIN", "AREA"); while (my @record = $cursor->fetch) { # прочитать запись print "@recordn"; # обработать запись }
В модуле XBase реализовано много других методов для работы с DBF-файлами и дополняющими их индексными файлами, которые предназначены для организации быстрого поиска записей в таблице.
Но разработчики программного обеспечения давно пришли к выводу, что вместо специфических форматов данных и операций по их обработке (без которых, конечно, иногда нельзя обойтись) гораздо перспективнее применять универсальные подходы, основанные на унифицированном доступе к базам данных на базе языка SQL.
Унификация доступа к реляционным базам данных основана на разделении программного механизма доступа на несколько логических слоев. Первый слой предоставляет программисту стандартный набор операций для подключения к источнику данных и обработки данных из этого источника с помощью запросов на языке SQL. Второй слой отвечает за взаимодействие с конкретными базами данных с учетом их особенностей. Взаимодействие с конкретным источником данных возлагается на драйвер базы данных, который выступает посредником между первым слоем механизма доступа и базой данных, скрывая от программиста технические детали взаимодействия и специфические особенности БД. Драйверы баз данных обычно разрабатывают производители СУБД для своих продуктов. На этих принципах многослойной архитектуры основаны такие широко известные универсальные интерфейсы к базам данных, как ODBC (Open DataBase Connectivity) и JDBC (Java DataBase Connectivity).