6.1Основные особенности Perl
6.1.1Введение
6.2Взаимодействие с СУБД
6.2.1Взаимодействие с Oracle
6.2.1.1Основные функции доступа
6.2.1.2Дополнительные функции
6.2.1.3Переменные
6.2.1.4Переменные для подстановки
6.4Обработка файлов формата DBF
Perl - интерпретируемый язык, приспособленный для обработки произвольных
текстовых файлов, извлечения из них необходимой информации и выдачи сообщений.
Perl также удобен для написания различных системных программ. Этот язык прост
в использовании, эффективен, но про него трудно сказать, что он элегантен и
компактен. Perl сочитает в себе лучшие черты C, shell, sed и awk,
поэтому для тех, кто знаком с ними, изучение Perl-а не представит
особого труда.
Cинтаксис выражений Perl-а близок к синтаксису C. В отличие от большинства
утилит ОС UNIX Perl не ставит ограничений на объем обрабатываемых данных и если
хватает ресурсов, то весь файл обрабатывается как одна строка. Рекурсия может
быть произвольной глубины. Хотя Perl приспособлен для обработки текстовых
файлов, он может обрабатывать так же двоичные данные и создавать .dbm файлы,
подобные ассоциативным массивам. Perl позволяет использовать регулярные
выражения, создавать объекты, вставлять в программу на С или C++ куски
кода на Perl-е, а также позволяет осуществлять доступ к базам данных, в том числе
Oracle.
Этот язык часто используется для написания CGI-модулей, которые, в свою очередь, могут
обращаться к базам данных. Таким образом может осуществляться доступ к
базам данных через WWW.
Perl позволяет осуществлять доступ к различным СУБД. Здесь будет освещен вопрос
доступа к СУБД Oracle
.
Мы приведем здесь пример программы, которая создает таблицу, помещает в нее некоторые данные и потом производит выборку строк из этой таблицы.
#!/usr/local/bin/perl use Oraperl; # подключаем модуль Oraperl $system_id = 'T:bdhost.com:Base'; $lda = &ora_login($system_id,'scott','tiger'); # вход в систему $st = 'create table EMP (name varchar2(100), organization varchar2(100))'; $csr = &ora_open($lda,$st) || die $ora_errstr; &ora_close($csr); # создание таблицы в базе данных $st = 'insert into EMP values (\'John Smit\', \'NATO\')'; $csr = &ora_open($lda, $st); &ora_close($csr); # помещение строки в таблицуВ результате в базе создалась таблица из двух столбцов с одной записью:
Name | Organization |
John Smit | NATO |
$st = 'select name from EMP where organization = \'NATO\''; $csr = &ora_open($lda,$st); # выбираем из таблицы значения столбца name, # которым сответствует значение столбца organization # равное 'NATO' @result = &ora_fetch($csr); # помещаем эти значения в массив @result &ora_close($csr); print @result; &ora_logoff($lda); # выход из системы
Для взаимодействия с Oracle
в Perl есть специальный модуль Oraperl.pm
.
Основными функциями для доступа к базе данных являются:
&ora_login
$lda = &ora_login($system_id,$username,$password)Для того, чтобы получить доступ к информации, хранимой в
Oracle
необходимо сначала
войти в систему. Это осуществляется вызовом функции &ora_login()
. Эта функция
имеет три параметра: системный идентификатор базы данных, имя пользователя в базе
и пароль пользователя. Возвращается идентификатор регистрации в системе (Oracle Login Data Area
).
Несколько доступов могут осуществляться одновременно. Эта функция
эквивалентна функции OCI(Oracle Call Interface) olon
или orlon
.
$csr = &ora_open($lda, $statement [,$cache])Для определения SQL-запроса в базу данных программа должна вызывать функцию
&ora_open
. Эта функция имеет как минимум два параметра: идентификатор регистрации
и SQL выражение. Необязательный третий параметр описывает размер буфера строк для
SELECT оператора. Возвращается курсор Oracle
. Если третий параметр опущен,
то используется стандартный размер буфера.
$csr = &ora_open($lda,'select ename, sal from emp order by ename',10);Эта функция эквивалентна функции OCI
oopen
или oparse
.
&ora_bind($csr, $var, ...)Если SQL выражение содержит обращение к переменным языка Perl, то необходимо подставить вместо имен значения переменных. Для этого используется функция
&ora_bind
.
$csr = &ora_open($lda, 'insert into emp values (:1,:2)'); &ora_bind($csr,$ename,$sal);- подставляет в SQL выражение вместо :1 и :2 значения переменных
$ename
и $sal
.
$nfields = &ora_fetch($csr[, trunc]); @array = &ora_fetch($csr);Эта функция используется с оператором SQL SELECT для извлечения информации из базы данных и имеет только один обязательный параметр - идентификатор курсора, полученный в результате вызова функции
&ora_open
. В скалярном
контексте она возвращает число выбранных строк, в списковом - массив выбранных
строк. Второй необязательный параметр содержит информацию о том, можно ли обрезать
данные типов LONG
и LONG RAW
или выдавать сообщение об ошибке. Если параметр
опущен, то информация берется из переменной $ora_trunc
.
Если произошло обрезание данных, то переменная $ora_errno
принимает значение
1406. Эта функция эквивалентна функции OCI ofetch
.
&ora_close($csr)Если открытый курсор не будет больше использоваться, то его нужно закрыть вызовом функции
&ora_close
. Это эквивалентно функции OCI oclose
.
&ora_do($lda,$statement)Не все SQL-выражения возвращают данные или содержат переменные для подстановки. В таких случаях функция
&ora_do
выступает в качестве альтернативы &ora_open
и &ora_close
. Первым параметром является идентификатор регистрации, вторым --
SQL выражение.
&ora_do($lda,'drop table employee');это эквивалентно:
&ora_close(&ora_open($lda, 'drop table employee'));
&ora_logoff($lda)Для выхода из системы используется функция
&ora_logoff
. Она эквивалентна функции OCI ologoff
.
Дополнительные возможности предоставляются функциями
&ora_titles()
&ora_length()
&ora_types()
&ora_autocommit()
&ora_commit()
&ora_rollback()
&ora_version()
&ora_titles
@titles = &ora_titles($csr)Программа может определить название полей, содержимое которых будет извлечено запросом, вызовом функции
&ora_title
. Эта функция имеет один параметр - курсор. Заголовки обрезаются
до длины поля.
@length = &ora_length($csr)Программа может определить длину каждого из полей, возвращенных запросом, с помощью вызова функции
&ora_length
. Она имеет только один параметр - курсор и
возвращает массив целых чисел.
@types = &ora_types($csr)Программа может определить тип каждого из полей, возвращенных запросом, с помощью вызова функции
&ora_types
. Она имеет один параметр - курсор и возвращает
массив целых чисел. Эти типы определяются в документации по OCI и в файле
oraperl.ph
для Oracle v6
.
&ora_autocommit($lda,$on_or_off)Режим автоматического завершения транзакций можно установить или отменить вызовом функции
&ora_autocommit
. Эта функция имеет два параметра:
идентификатор регистрации и булевскую переменную, которая указывает
действие, которое нужно выполнить. Если значение переменной ненулевое, то
режим включается, если нулевое, то отключается. По умолчанию режим не включен.
Режим включается на продолжительность пребывания в системе. Если есть
необходимость включать его только для одного оператора, то лучше делать
несколько регистраций и использовать для каждого оператора отдельный
идентификатор регистрации.
&ora_commit($lda) &ora_rollback($lda)Изменения в базе данных могут быть сохранены или отменены вызовом этих функций. Они имеют один параметр - идентификатор регистрации в системе. Транзакции, результат которых уже был сохранен не могут быть отменены
&ora_rollback
. Эти функции также действуют на все время пребывания в
системе, а не на отдельные операторы.
&ora_version()Эта функция печатает версию и информацию об авторских правах, касающуюся
Oraperl
. Она не возвращает ничего.
В модуле Oraperl.pm есть шесть специальных переменных:
$ora_cache
$ora_long
$ora_trunc
$ora_errno
$ora_errstr
$ora_verno
Эти переменные
используются для определения поведения Oraperl
в определенных условиях.
$ora_cache
Эта переменная определяет размер буфера для функции
&ora_open()
и SELECT-выражения, если точный размер буфера не указан.
Как правило устанавливается размер буфера равный пяти. Присваивание этой
переменной значения, равного нулю, устанавливает значение этой переменной
равным первоначальному значению. Присваивание отрицательной величины
приводит к ошибке.
$ora_long
Обычно Oraperl
спрашивает базу данных о длине каждого поля и соответствующим
образом распределяет буферное пространство. Это невозможно для полей типа
LONG
и LONGRAW
. Распределение пространства в предположении максимально
возможной длины (65535 bytes
) привело бы к излишним тратам памяти. Поэтому
когда &ora_open()
определяет, что поле имеет тип LONG
, память распределяется
согласно значению переменной $ora_long
. При инициализации она принимает
значение 80 (для совместимости с продуктами Oracle
), но в программе ее
можно устанавливать произвольным образом.
$ora_trunc
Так как Oraperl
не может точно определять длину значений
типа LONG
, возникают ситуации, когда значение $ora_long
недостаточно для
хранения полученных данных. В таком случае, если у &ora_fetch
есть
необязательный второй параметр, происходит обрезание данных. Если второй
параметр опущен, то вместо него используется значение $ora_trunc
.
$ora_errno
Содержит код ошибки произошедшей при последнем вызове
какой-либо функции. Есть два интересных случая, касающихся &ora_fetch()
.
В первом случае, если произошло обрезание данных типа LONG
или LONGRAW
и
обрезание было разрешено, тогда выполнение этой функции полностью успешно,
но $ora_errno
принимает значение 1406, для индикации того, что произошло
обрезание. Во втором случае, если &ora_fetch()
возвратила false
, то
$ora_errno
принимает значение 0 в случае конца данных или код ошибки,
если действительно произошла ошибка.
$ora_errstr
Содержит сообщение об ошибке, соответствующее значению
$ora_errno
.
$ora_verno
Содержит версию Oraperl
в формате v.ppp, где v -
основной номер версии, а ppp - patchlevel.
Oraperl
позволяет SQL выражению содержать обращение к переменным языка Perl. Они
состоят из двоеточия и следующего за ним номера. Например:
$csr = &ora_open($lda,"insert into tel values(:1,:2)");Эти два имени :1 и :2 называются переменными для подстановки. Функция
&ora_bind()
используется для привязывания переменных к их значениям.
&ora_bind($csr, "Annette","3-222-2-22-22-22"); &ora_bind($csr,$name,$telephone);Номера переменных должны следовать в порядке возрастания начиная с 1, так как
&ora_bind
выполняет подстановку именно в таком порядке.
Язык Perl очень широко используется при написании исполняемых модулей
CGI (Common Gateway Interface) для Web.
Это обусловлено прежде всего тем, что Perl предоставляет разработчикам
простые и удобные средства обработки текста и взаимодействия с базами
данных. Наша цель - лишь дать пример
использования Perl для написания CGI-модуля.
Рассмотрим простую подпрограмму разбора входного потока CGI-программы
(при передаче параметров используется метод POST
).
#!/usr/local/bin/perl sub Print { $len = 100; $buf = ""; read(STDIN, $buf,$len); # считываем из стандартного потока ввода # в переменную $buf количество символов # $len @ar = split(/[&=]/,$buf); # разбиваем строку в массив строк, # разделителями служат & и =. $output = "Content-type: text/html\n\n # посылает тип MIME передаваемого документа <HTML><HEAD><TITLE>Result</TITLE></HEAD> <BODY BGCOLOR=\"#FFAAAA\"> <H1>Hi there</H1><HR><BR>"; $i = 0; while ($i <= $#ar) { $ar[$i] =~ s/\+/ /g; # заменяем в элементах массива + на пробел $output .= "$ar[$i]\n"; # конкатенация переменной $output с # элементом массива $i++; } $output .="<HR></BODY></HTML>"; # завершаем HTML страницу print $output; } eval &Print; # выполняем подпрограмму осуществляющую # считывание, обработку и вывод информацииВ данном примере был проиллюстрирован случай считывания параметров из входного потока. Если параметры передаются CGI-модулю в командной строке, то они помещаются в служебный массив
@ARGV
. Например, если параметры пишуться в URL: http://www.host.ru/cgi-bin/name.cgi?123+resource+time+12
.
Для взаимодействия с файлами этого формата существует специальный модуль - Xbase.pm
На текущий момент поддерживается только возможность чтения таких файлов.
Этот модуль подключается стандартным образом: use Xbase;
Новый Xbase
объект создается следующим образом:
$database = new Xbase;Будет создан объект
$database
, который в дальнейшем будет использоваться для
взаимодействия со всевозможными методами, которые поддерживает модуль.
Доступ к базе данных осуществляется следующим образом:
$database->open_dbf($dbf_name,$idx_name);Мы ассоциировали DBF-файл и необязательный индексный файл с объектом. Чтобы определить тип (database type) можно сделать следующее:
print $database->dbf_type;Вернется строка, которая, если
Xbase
файл открыт, будет содержать значение
DBF3, DBF4 или FOX.
Чтобы узнать дату последнего обновления делается следующее:
print $database->last_update;Возвращает строку с датой.
$end=$database->lastrec;Вернется номер последней записи в файле с базой данных.
$database->dbf_stat;В стандартный выходной поток будет напечатана информация о статусе и структуре базы данных. Этот метод работает аналогично команде
display status
.idx_stat
:
$database->idx_stat;Печатает в стандартный выходной поток (STDOUT) информацию о статусе открытого IDX-файла.
go_top
:
$database->go_top;Передвигает курсор чтения на физическое начало файла,если индексы не существуют и на первую запись, соответствующую порядку, который задается индексом, в противоположном случае.
go_bottom
:
$database->go_bottom;Передвигает курсор чтения на физический конец файла,если индексы не существуют и на последнюю запись, соответствующую порядку, который задается индексом, в противоположном случае.
go_next
:
$database->go_next;Эквивалентно команде
skip 1
, которая передвигает курсор на следующую запись.go_prev
:
$database->go_prev;Эквивалентно команде
skip -1
, которая передвигает курсор на предыдущую запись.$stat=$database->seek($keyvalue);Эта команда устанавливает курсор на первую запись, соответствующую данному ключу. Но в данном случае база данных должна быть открыта с соответствующим индексом, в противоположном случае будет выдано сообщение об ошибке и исполнение прекратиться. Возвращается значение, содержащее информацию о том, был ключ найден или нет.
$current_rec=$database->recno;Метод
bof
возвращает значение true
, если курсор находится в самом начале файла.
if ($database->bof) { print " At the very top of the file \n"; }Аналогично действует метод
eof
:
if ($database->eof) { print " At the very end of the file \n"; }Чтобы прочитать содержимое какого-либо поля записи можно поступить так:
print $database->get_field("NAME");Возвращает строку с содержимым поля. Если данная запись помечена для удаления, то использует псевдоимя поля
_DELETED
.@fields = $database->get_record;В массиве они будут располагаться в такой же последовательности, как и в базе данных.
close_dbf
.
$database->close_dbf;Закрывает файл с базой данных, индексами и комментариями. В завершение приведем небольшой пример программы, которая распечатывает статус базы данных и индексного файла, а также дату последнего обновления и количество записей в базе данных.
#!/usr/bin/perl use Xbase; # подключение модуля $database = new Xbase; # создание объекта $d = "/home/smit/employee.dbf"; # имя файла с базой $i = "/home/smit/employee.cdx"; # имя индексного файла $database->open_dbf($d,$i); # открываем базу данных $database->dbf_stat; # печатаем статус и структуру # базы данных $database->idx_stat; # печатаем статус и структуру # индексов @fields = $database->get_record; print @fields,"\n"; # печатаем содержимое текущей записи print $database->last_update, "\n"; # печатаем дату последнего обновления $end = $database->lastrec; print $end; #печатаем номер последней записи
Полная спецификация языка Perl приводиться в Приложении 2 к отчету.