Универсальный интерфейс к базам данных - DBI
Унификация доступа к реляционным базам данных основана на разделении программного механизма доступа на несколько логических слоев. Первый слой предоставляет программисту стандартный набор операций для подключения к источнику данных и обработки данных из этого источника с помощью запросов на языке SQL. Второй слой отвечает за взаимодействие с конкретными базами данных с учетом их особенностей. Взаимодействие с конкретным источником данных возлагается на драйвер базы данных, который выступает посредником между первым слоем механизма доступа и базой данных, скрывая от программиста технические детали взаимодействия и специфические особенности БД. Драйверы баз данных обычно разрабатывают производители СУБД для своих продуктов. На этих принципах многослойной архитектуры основаны такие широко известные универсальные интерфейсы к базам данных, как ODBC (Open DataBase Connectivity) и JDBC (Java DataBase Connectivity).
Аналогичную архитектуру имеет и DBI (DataBase Interface) - основной интерфейс для доступа к базам данных в Perl. Основным компонентом этого интерфейса является модуль DBI, предоставляющий унифицированные сервисы для взаимодействия с базами данных. Благодаря методам модуля DBI программист получает в свое распоряжение единый инструмент для работы с самыми разными базами данных: и теми, что находятся на этом же компьютере, и теми, что располагаются на удаленном сервере баз данных. Модуль DBI во время работы загружает нужные компоненты, модули драйверов конкретных баз данных (DataBase Driver, DBD), например: DBD::DB2, DBD::InterBase, DBD::mysql, DBD::Oracle, DBD::Sybase. Доступ к любой базе данных при помощи DBI выполняется в несколько этапов. Перечислим основные из них.
- Соединение с базой данных выполняется конструктором connect() класса DBI, которому передается строка с описанием источника данных, имя пользователя и пароль, а кроме того, дополнительные параметры:
$dbh = DBI->connect($data_source, $user, $password, \%parms);
В описании источника данных (data source) указывается драйвер базы данных и необходимые для его работы параметры. При успешном соединении c СУБД этот метод возвращает манипулятор базы данных (database handler), через который в дальнейшем выполняется взаимодействие с базой данных.
- Подготовка команды к базе данных выделяется в отдельный этап, поскольку это действие требует значительных ресурсов СУБД. Подготовка команды выполняется методом prepare() манипулятора базы данных, которому передается строка, содержащая команду языка запросов SQL:
$sth = $dbh->prepare($sql_statement);
В команде SQL могут присутствовать слоты (placeholders), в которые при выполнении команды будут подставлены конкретные значения данных. Эта схема похожа на подстановку значений в поледержатели формата отчета. Подготовленная команда доступна через манипулятор команды (statement handler), возвращаемый методом prepare(), и может выполняться многократно. - Выполнение команды может производиться несколькими методами. Подготовленную ранее команду выполняет метод командного манипулятора execute(), которому могут передаваться значения для подстановки в выполняемое SQL-предложение:
$sth->execute(@bind_values); # выполнить со списком значений
Или же SQL-команду можно выполнить без предварительной подготовки методом do() манипулятора базы данных:
$dbh->do($sql_statement); # выполнить команду без подготовки - Обработка полученных данных может выполняться одной из многочисленных команд, предоставляемых интерфейсом DBI.
- Отсоединение от базы данных выполняется методом disconnect() манипулятора базы данных, который производит необходимые завершающие действия и освобождает используемые ресурсы:
$dbh->disconnect; # отключиться от БД
Приведенная схема проста и логична, поэтому работа с базами данных через DBI быстро осваивается программистами. Но прежде чем перейти к примерам использования DBI, нужно сделать еще несколько пояснений.
В языке структурированных запросов SQL используется небольшой набор команд, но они позволяют выполнять все необходимые действия над информацией в базе данных. Основные команды SQL: создание базы данных (CREATE), добавление записей (INSERT), их изменение (UPDATE) и удаление (DELETE), а также выборка записей (SELECT) по указанному условию. Изучение языка SQL выходит за рамки этого курса, поэтому в примерах будут применяться только самые простые их формы, и смысл этих команд будет понятен из контекста.
Слоты для подстановки параметров в SQL-команду обозначаются знаками вопроса '?' и выглядят таким образом:
$sth = $dbh->prepare( 'SELECT name, area FROM mollusc WHERE id>? AND id<?');
При выполнении этой команды с параметрами 1000 и 9000 будут выбраны записи со значениями колонки id в заданном диапазоне. При подстановке значений аргументов в команду слоты заполняются слева направо:
$sth->execute(1000, 9000); # подставить числа вместо ?
После подстановки значений будет выполнена команда, означающая "выбрать значения столбцов name и area из таблицы mollusc у тех записей, где значение столбца id больше 1000 и меньше 9000":
SELECT name, area FROM mollusc WHERE id>1000 AND id<9000
Кроме средств выполнения SQL-команд механизм DBI предоставляет множество методов для выборки из базы данных информации в виде массивов или хэшей для более удобной обработки в программе на Perl. Более подробно с ними можно познакомиться, если почитать системную документацию, выведенную по команде
perldoc DBI
$sth = $dbh->prepare( ' SELECT name, area FROM mollusc WHERE id>? AND id<?');
При выполнении этой команды с параметрами 1000 и 9000 будут выбраны записи со значениями колонки id в заданном диапазоне. При подстановке значений аргументов в команду слоты заполняются слева направо:
$sth->execute(1000, 9000); # подставить числа вместо ?
После подстановки значений будет выполнена команда, означающая "выбрать значения столбцов name и area из таблицы mollusc у тех записей, где значение столбца id больше 1000 и меньше 9000":
SELECT name, area FROM mollusc WHERE id>1000 AND id<9000
Кроме средств выполнения SQL-команд механизм DBI предоставляет множество методов для выборки из базы данных информации в виде массивов или хэшей для более удобной обработки в программе на Perl. Более подробно с ними можно познакомиться, если почитать системную документацию, выведенную по команде
perldoc DBI
Покажем приемы работы с интерфейсом DBI на примере класса доступа к уже знакомым DBF-файлам - модуля DBD::XBase. Этот модуль нужно установить описанным ранее способом прежде, чем работать с базами данных в формате XBase. В первом примере программа создает таблицу базы данных SQL-командой CREATE:
use DBI; # использовать DBI my $path = '.'; # каталог, где расположены таблицы БД my $table = 'mollusc'; # DBF-файл # подсоединиться к БД, используя драйвер DBD::XBase my $dbh = DBI->connect("dbi:XBase:$path") or die $DBI::errstr; # создать таблицу определенной структуры $dbh->do("CREATE TABLE $table (id INT, name CHAR(35), latin CHAR(30), area CHAR(45))"); $dbh->disconnect; # отсоединиться от БД
Следующая программа в цикле заполняет созданную таблицу данными из текстового файла, добавляя в нее записи SQL-командой INSERT:
use DBI; # используем DBI my $path = '.'; # каталог с таблицами БД my $table = 'mollusc'; # DBF-файл # подключаемся к БД, используя драйвер DBD::XBase my $dbh = DBI->connect("dbi:XBase:$path") or die $DBI::errstr; # подготовим SQL-команду для многократного выполнения my $sth = $dbh->prepare("INSERT INTO $table (id, name, latin, area) VALUES (?, ?, ?, ?)") or die $dbh->errstr(); # в цикле читаем строки для загрузки в БД open my $text, '<', 'mollusc.txt' or die; # файл, откуда while (my $data = <$text>) { # читаем данные, chomp($data); # удаляя \n # и разбивая строку на поля по разделителю ';': my ($id, $name, $latin, $area) = split(';', $data); # добавляем запись, подставляя значения в команду $sth->execute($id, $name, $latin, $area) or die; } close $text; # закрываем тестовый файл $dbh->disconnect; # отсоединяемся от БД
Далее можно выполнять различные действия с данными в таблице, используя команды SQL, как это сделано в программе, где изменяются значения перечисленных колонок в записи с указанным идентификатором и удаляется запись по уникальному номеру:
use DBI; # использовать DBI my $path = '.'; # каталог, где расположены таблицы БД my $table = 'mollusc'; # DBF-файл # соединиться с БД, используя драйвер DBD::XBase my $dbh = DBI->connect("dbi:XBase:$path") or die $DBI::errstr; # изменить запись с указанным идентификатором, # заменяя значения перечисленных полей на новые $dbh->do("UPDATE $table SET name=?,area=? WHERE id=?", undef, 'Жемчужная пинктада', 'Австралия', 89147) or die;
# удалить запись с идентификатором 93749 $dbh->do("DELETE FROM $table WHERE id=93749") or die;
$dbh->disconnect; # отсоединиться от БД
Для выборки данных из таблицы используется SQL-команда SELECT, в которой можно указывать, данные из каких колонок записи нужно включить в выборку, а также по какому условию отбирать строки таблицы:
use DBI; # использовать DBI my $path = '.'; # каталог, где расположены таблицы БД my $table = 'mollusc'; # DBF-файл # соединиться с БД, используя драйвер DBD::XBase my $dbh = DBI->connect("dbi:XBase:$path") or die $DBI::errstr; # выбрать у всех строк таблицы указанные поля my $sth = $dbh->prepare("SELECT name,area FROM $table WHERE id>?") or die $dbh->errstr; $sth->execute(1000) or die $sth->errstr(); # выполнить команду while (my @row = $sth->fetchrow_array) { # и напечатать print "@row\n"; # выбранные строки } # в цикле по одной $dbh->disconnect; # отсоединиться от БД
Для отображения информации из базы данных можно разработать клиентское приложение с графическим интерфейсом, используя библиотеку Perl/Tk, как это показано на рис. 15.1.
Рис. 15.1. Клиентская программа на Perl/Tk для работы с базой данных