Введение
DBI -- это интерфейс прикладных программ к СУБД, использующим SQL в качестве
языка запросов. Сам DBI определяет только набор функций, переменных и
соглашений. Вся непосредственная работа выполняется Database Drivers (DBD) --
модулями, обеспечивающими связь с СУБД. DBI только обеспечивает стандартный
интерфейс для этих драйверов.
Полная схема архитектуры при работе DBI выглядит примерно так:
+----------------------+
| Прикладная программа |
+----------------------+
| DBI |
+----------------------+
| DBD |
+----------------------+
| СУБД |
+----------------------+
Подсоединение к СУБД
обеспечивается при помощи метода connect класса DBI:
$dbh = DBI->connect($dsn, $user, $auth, {options});
- $dbh
Это объект, при помощи его методов осуществляются взаимодействия с
СУБД.
- $dsn
Строка, определяющая к какой базе данных подсоединятся и другие
параметры. Зависит от DBD. На сегодняшний момент стандарта нет, но
рекомендовано использовать стиль ODBC:
&dbi:<имя DBD>:databasename=<название БД>;host=<Имя хоста>;port=<порт>&;
- $user
Имя пользователя.
- $auth
Нечто, авторизующее пользователя. Обычно пароль.
- options
Параметры DBI, передаются через анонимный хеш. В настоящее время
понимаются три параметра:
- RaiseError
если установлен, то при любой ошибке DBI убивает
программу
- PrintError
если установлен, то при ошибке DBI вызывает warn
- AutoCommit
определяет порядок работы с транзакциями.
Например:
$dbh = DBI->connect('dbi:Pg:dbname=apavel', 'apavel', 'SomeSecret',
{RaiseError=>1, AutoCommit=>0});
Означает: Подсоедение к СУБД PostgreSQL, к базе данных apavel, с именем
пользователя apavel и паролем. Все ошибки будут вызывать die, что удобно при
отладке, а все изменения будут внесены только при подтверждении (commit)
транзакций.
Отсоединение обеспечивается при помощи метода disconnect: $dbh->disconnect();
Механизм курсоров и подготовки запросов
При работе с базами данных при помощи DBI используются курсоры -- специальные
объекты, обеспечивающие последовательный доступ к результатам запросов. (В
простейших случаях можно обойтись и без них, я расскажу об этом дальше.)
Пример таблицы, используемый в дальнейшем:
foo.sql
create table foo (
bar varchar(50),
baz int
)
Получение данных
$cursor = $dbh->prepare('select bar, baz from foo');
# теперь $cursor -- курсор, и его необходимо исполнить
$cursor->execute;
# После исполнения запроса, результат можно получить из курсора при помощи
# метода fetchrow_array
while (($bar, $baz) = $cursor->fetchrow_array) {
print "bar is: $bar, baz: $baz\n";
}
Placeholders
Очень часто бывает надо подготовить какой-либо запрос, а потом использовать
его с разными значениями данных. DBI предлагает для механизм placeholders:
В запросе на месте таких данных указываются вопросительные знаки, а сами
значения передаются в метод execute() курсора. Например:
$cursor = $dbh->prepare('select bar from foo where baz=?');
$cursor->execute($baz);
Особенно удобно это в случае вставки данных:
$cursor = $dbh->prepare('insert into foo(bar, baz) values(?, ?)');
while ( ... ) {
$cursor->execute($bar, $baz);
}
Таким образом, СУБД разбирает запрос только один раз, а затем просто
исполняет его, что экономит время. (Естественно, это верно только для DBMS с
раздельными parse и execute, сейчас ни MySQL, ни PostgreSQL такое не
поддерживают, поэтому их реализации DBD просто сохраняют запрос переданный
$dbh->prepare() и затем подставляют в него данные при каждом $sth->execute().)
Работа без курсоров
DBI предоставляет несколько методов для такого рода работы:
Методы для запросов:
- selectrow_array
Возвращает одну строку запроса в виде
массива
- selectall_arrayref
Возвращает весь ответ сервера в виде
массива ссылок на массивы.
Методы для выражений, не возвращающих значений
- do
исполняет запрос
Пример:
#получить значение bar при baz=3
($bar) = $dbh->selectrow_array('select bar from foo where baz=3');
# установить baz в некоторое значение при bar='somestring'
$dbh->do("update set baz=1 where bar='somestring'");
Можно несколькими способами:
1. Просто прокручивая курсор:
$c = $dbh->prepare('select baz, bar from foo');
$c->execute;
# если нужна последовательность с 26 по 50
for ($k = 0; $k < 26; $k++) {
$c->fetchrow_array;
}
# теперь можно вывести данные
print "<table border=1><tr><th>bar</th><th>baz</th></tr>\n";
while (($bar, $baz) = $c->fetchtrow_array) {
print "<tr><td>$bar</td><td>$baz</td></tr>\n";
}
$c->finish; # Закрыть курсор
print "</table>";
2. Используя курсоры СУБД
# Показан синтаксис PostgeSQL
$dbh->do('declare mycursor cursor for select bar, baz from foo');
$dbh->do('move 25');
# И теперь будем получать данные
$c = $dbh->prepare('fetch forward 25 in mycursor');
while (($bar, $baz) = $c->fetchrow_array) {
print ....;
}
$c->finish;
$dbh->do('close mycursor');
3. Для MySQL можно использовать директиву LIMIT
$c = $dbh->prepare('select bar, baz from foo limit 26,25');
while (($bar, $baz) = $c->fetchrow_array) {
print ....;
}
$c->finish;
- В книжных магазинах сейчас обширный набор книг по SQL. (От рекомендаций
воздержусь -- ни одну из них я не читал)
- На MCP personal bookshelf (
http://pbs.mcp.com) есть книга
"Teach yourself SQL in 21 days" -- весьма рекомендую, очень хорошая книга.
- На citforum (
http://www.citforum.ru) были какие-то руководства
Вроде как можно при помощи DBD::FreeTDS
Содержание