Работа с базами данных на Perl::Журнал СА 9.2003
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Архив номеров
Контакты
   

  Опросы
  Статьи

Электронный документооборот  

5 способов повысить безопасность электронной подписи

Область применения технологий электронной подписи с каждым годом расширяется. Все больше задач

 Читать далее...

Рынок труда  

Системные администраторы по-прежнему востребованы и незаменимы

Системные администраторы, практически, есть везде. Порой их не видно и не слышно,

 Читать далее...

Учебные центры  

Карьерные мечты нужно воплощать! А мы поможем

Школа Bell Integrator открывает свои двери для всех, кто хочет освоить перспективную

 Читать далее...

Гость номера  

Дмитрий Галов: «Нельзя сказать, что люди становятся доверчивее, скорее эволюционирует ландшафт киберугроз»

Использование мобильных устройств растет. А вместе с ними быстро растет количество мобильных

 Читать далее...

Прошу слова  

Твердая рука в бархатной перчатке: принципы soft skills

Лауреат Нобелевской премии, специалист по рынку труда, профессор Лондонской школы экономики Кристофер

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9932
Комментарии: 0
Потоковая обработка данных

 Читать далее...

19.03.2018г.
Просмотров: 8142
Комментарии: 0
Релевантный поиск с использованием Elasticsearch и Solr

 Читать далее...

19.03.2018г.
Просмотров: 8248
Комментарии: 0
Конкурентное программирование на SCALA

 Читать далее...

19.03.2018г.
Просмотров: 5224
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 5908
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

Друзья сайта  

 Работа с базами данных на Perl

Архив номеров / 2003 / Выпуск №9 (10) / Работа с базами данных на Perl

Рубрика: Программирование /  Автоматизация

ВЛАДИСЛАВ ГОШКО

Работа с базами данных на Perl

В наше время базы данных широко используются в разных сферах человеческой жизни. Самые простые базы данных – это просто файлы определенной структуры, а сложные – это файлы, имеющие свой формат данных и, естественно, определенную структуру. В данной статье я рассмотрю работу с базами данных на языке программирования Perl. Для удобства пойдем от маленького к большому. Для начала давайте рассмотрим обычный файл как базу данных, т.е. обычный файл можно представить как определенно сформатированный текст. Файл будет отформатирован следующим образом:

Name1|Value1#Value2#Value3#...#ValueN

Name2|Value1#Value2#Value3#...#ValueN

Name3|Value1#Value2#Value3#...#ValueN

...

NameN|Value1#Value2#Value3#...#ValueN

Почему разделителями я выбрал именно «|» и «#»? Потому что они не являются безопасными символами (из RFC 2396). По той же причине можно было выбрать разделителями любой символ, кроме латинских букв, цифр, и вот этих:

";", "/", "?", ":", "@", "&", "=", "+", "$", ",", "-", "_", ".", "!", "~", "*", """, "(", ")"

Эти разделители (кроме вышеописанных символов) могут использоваться в значениях или в именах переменных, только нужно будет использовать модуль URI::Escape, для того чтобы переменные с этими разделителями не испортили структуру. Специально для работы с нашими базами данных создадим модуль simple_db.pm. Итак, начнем:

#!/usr/bin/perl

# создаем пакет

package simple_db;

use Exporter;

# как и говорилось, используем модуль для перевода небезопасных символов в формат %XX

use URI::Escape;

@ISA=("Exporter");

@EXPORT=qw(&opendb &closedb %g);

# экспортируем используемые функции, а также хеш %g, для того чтобы функция знала,

# в какой файл записывать изменения хеша, вводимого в аргументах

sub opendb{

    my($h,$file)=@_;

    my($name,$vals,@values);

    local(*DB);

    open(DB,$file) or return 0;

    # блокируем файл на тот случай, если во время чтения кто-то захочет изменить

    # файл (совместная блокировка – для чтения)

    flock(DB,1);

    while(<DB>){

           chomp;

           ($name,$vals)=split(/\|/,$_,2);

           next if !$name;

           $name = uri_unescape($name);

           @values = split(/#/,$vals);

           # если значений много, создаем анонимный массив, иначе просто

           # присваиваем одно значение

           if($#values){

                 for(0..$#values){

                        # переводим символы из %XX-формата

                        # в нормальный вид

                        $values[$_]=uri_unescape ($values[$_]);

                 }

                 $$h{$name}=[@values];

           }else{

                 $vals = uri_unescape($vals);

                 $$h{$name}=$vals;                

           }

    }

    close(DB);

    # записываем в  глобальный хеш ассоциацию ссылки на хеш

    # с открытым файлом

    $g{$h}=$file;

}

sub сlosedb{

    my($h)=@_;

    my($key,$val,$fn);

    # по имени хеша получаем имя файла

    $fn = $g{$h};

    local(*DB);

    # выходим из функции, если файла не существует

    return if !(-e $fn);

    open(DB,">$fn") or return 0;

    # замыкаем файл

    # (монопольная блокировка – для записи)

    flock(DB,2);

    while(($key,$val) = each %$h){

           # обратно создаем формат, переводя небезопасные

           # символы в формат %XX

           print DB uri_escape($key)."|";

           if(ref $val){

                 for(0..$#$val){

                        $$val[$_]=uri_escape($$val[$_]);

                 }

                 print DB join "#",@$val;

           }else{

                 $val=uri_escape($val);

                 print DB $val;

           }

           print DB "\n";

    }

    close(DB);

}

1;

Если вам нужно открывать файл с определенными правами, то в функциях opendb() и closedb() нужно просто заменить open на sysopen по следующему формату: sysopen FILEHANDLE, FILENAME, MODE, PERMS; и все. Использование довольно простое, возьмем какой-нибудь файл test.pl. В этой же директории должен лежать и модуль simple_db.pm. Вот test.pl:

#!/usr/bin/perl

use simple_db;

# открываем файл test.db и ассоциируем с ним хеш %h,

# иначе умираем

opendb(\%h,"test.db") or die $!;

# добавляем значения в хеш

$h{'supa|var'}=["special#","tes#t"];

# также легко можно добавить массив

@tmp = ("array","tester");

# добавили ...

$h{'arr'}=\@tmp;

# или добавляем массив так

$h{'arr2'}=["some","vars"];

closedb(\%h) or die $!;

Данным образом будет создан файл test.db в текущей директории. С переменной «supa|var» и значениями «speacial#» и «tes#t», и т. д. Я специально использовал небезопасные символы, а со второй и третьей переменной все в порядке – там нет небезопасных символов...

А теперь давайте посмотрим, что записано в файле test.db:

supa%7Cvar|special%23#tes%23t

arr|array#tester

arr2|some#vars

Т.е. эти символы не помешали нашей структуре файла, они всего лишь были переведены в %XX-формат. А теперь просмотрим всю базу:

#!/usr/bin/perl

use simple_db;

opendb(\%h,"test.db") or die $!;

while(($key,$val) = each %h){

    print $key." = ";

    if(ref $val){

           # здесь, если значение переменной ссылка на массив

           print join " ; ",@$val;

    }else{

           print $val;

    }

    print " ";

}

closedb(\%h) or die $!;

При выводе база будет выглядеть так:

supa|var = special# ; tes#t

arr = array ; tester

arr2 = some ; vars

Очищаем базу, просто очищая хеш, т.е. %h=(), или можно просто удалить файл следующим образом:

unlink "test.db" or die $!;

А при открытии базы открыть файл в режиме создания, т.е. перед opendb() сделать следующее:

# $filename - в данном случае имя нашего файла

if(!(-e "$filename")){

    open(FILE,">$filename") or die $!;

    close(FILE);

}

Но эта база не может претендовать на большую скорость и большие размеры и, как вы уже успели заметить, в ней не могут быть созданы сложные структуры. Данная база данных вполне подойдет для небольших объемов информации, например, для небольших сайтов или веб-сервисов. С помощью классов можно создать свою вполне приличную базу данных. А теперь давайте расмотрим другие базы данных. Начнем с портированной в вашу систему базу данных (их может быть несколько). Функция dbmopen() довольна стара и поэтому позволяет использовать лишь ту библиотеку DBM, c которой был построен Perl. Но по ходу статьи рассмотрим и более новые методы.

Вот пример с dbmopen():

#!/usr/bin/perl

use Fcntl;

# специально для таких переменных, как O_RDWR, O_CREAT

# O_RDWR - права: чтение, запись

# O_CREAT - создать файл, если он не существует

dbmopen(%HASH,$FILENAME,O_RDWR|O_CREAT, 0666) or die "Cant open $FILENAME: $! ";

# заносим данные в базу данных

$HASH{KEY}="VALUE";

# проверяем, существует ли ключ

if(exists $HASH{KEY}){

    # что-то делаем с информацией, полученной из базы данных

    $info = $HASH{KEY};

}

# удаляем какой-нибудь ключ из базы

delete $HASH{SOME_KEY};

dbmclose(%HASH);

Также в начале программы можно добавить: use NDBM_File; или use SDBM_File; или use GDBM_File; или use DB_File; – данные модули просто переопределяют стандартный вариант, с которым был построен Perl. Есть также другой способ открытия базы данных – tie и untie. Делается это так:

#!/usr/bin/perl

use DB_File;

# здесь это обязательно, т.к. в функции tie() мы задаем модуль

use Fcntl; 

tie(%HASH,"DB_File",$FILENAME,O_RDWR|O_CREAT, 0666) or die "Can"t open $FILENAME: $! ";

# все те же манипуляции с хешем, которые описывались выше

# ...

# а потом

untie(%HASH);

Очищаются базы так же, как и в моем примере, т.к. я свой пример делал по подобию этих баз. Но так же, как и мой пример, данные базы не могут хранить сложные структуры. Для этого требуется модуль DB_File и модуль MLDBM. Модуль MLDBM может хранить в хеше более сложные структуры, чем просто числа и скаляры. Если его у ваc нет, то вы можете его скачать из Интернета: запускаете программу ppm из дистрибутива Perl. И пишите: «install MLDBM» – все должно пройти успешно. Использование вот такое:

#!/usr/bin/perl

use MLDBM "DB_File";

use Fcntl; # для O_RDWR, O_CREAT и т.д.

tie(%h, "MLDBM", "glob.db", O_RDWR|O_CREAT, 0666) or die "Couldn"t tie DB_File $users: $!; aborting";

$usr{synthetic}->{password}="matrix reloaded";

$h{users}=\%usr;

untie %h;

Таким образом была создана база данных glob.db, в которой есть ключ «users», в котором есть пользователь «synthetic» с еще одним вложенным хешем, в котором есть ключ «password» со значением «matrix reloaded». Такая структура очень удобна и легко запрашиваема. Далее посмотрим, как мы проверяем то, что создали:

#!/usr/bin/perl

use MLDBM "DB_File";

use Fcntl; # для O_RDWR, O_CREAT и т. д.

$access=0;

tie(%h,"MLDBM","glod.db",O_RDWR|O_CREAT,0666) or die "Couldn"t tie DB_File $users: $!; aborting";

while(($key,$val) = each %h){

    if($key eq "users"){

           if($val->{synthetic}->{password} eq "matrix reloaded"){

                 $access=1;last;

                 # если все правильно, завершаем цикл

           }

    }

}

untie(%h);

if($access){

    print "Matrix has you...";

}else{

    print "Follow the white rabbit";

}

С удалением нужно немного по-другому, через временный хеш:

tie(%h,"MLDBM","glob.db",O_RDWR|O_CREAT,0666) or die "Couldn"t tie DB_File $users: $!; aborting";

%tmp=%h;

delete $tmp{users}->{"somebody"};

%h=%tmp;

untie %h;

Добавлять тоже через временный хеш:

tie(%h,"MLDBM","glob.db",O_RDWR|O_CREAT,0666) or die "Couldn"t tie DB_File $users: $!; aborting";

%tmp=%h;

$tmp{users}->{"morpheus"}->{password}="zion";

%h=%tmp;

untie %h;

И в моем примере, и в других базах используется работа с хешами, поэтому давайте рассмотрим несколько примеров работы с хешами...

  • Сортировка ключей хеша по алфавиту:

foreach $key (sort keys %unsorted){

$val = $unsorted{$key};

# здесь переборка ключей хеша по алфавиту

# делаем что-то c $key и $val

}

  • Сортировка по ассоциированным значениям:

foreach $key (sort {$unsorted{$a} cmp $unsorted{$b} } keys %unsorted){

$val = $unsoreted{$key};

# что-то делаем с $key и $val...

}

  • Сортировка по длине значений (почти также, как и просто по значениям): 

foreach $key (sort {length($unsorted{$a}) <=> length($unsorted{$b}) } keys %unsorted){

$val = $unsoreted{$key};

# что-то делаем с $key и $val...

}

Дальше рассмотрим небольшие примеры работы с базами данных MySQL, при помощи модуля DBI и драйвера для работы с MySQL – DBD::mysql. Эти модули также можно установить через ppm. А теперь посмотрим пример работы с MySQL:

#!/usr/bin/perl

use DBI;

# настройки SQL сервера

$user     = "synthetic";       # логин и

$password = "test";            # пароль для доступа к серверу

$host     = "localhost";       # адрес SQL-сервера

$db       = "site";            # база данных, с которой соединяемся

$port     = 3306;              # порт (взят по умолчанию)

$driver   = "mysql";           # это драйвер для базы данных, т.е.  вы можете указать драйвер своей

                               # базы и спокойно соединятся с ней (естественно зная ее семантику)

# данные - просто для проверки

$login = "Vlad";

$pass  = "isitreal";

$conn = "DBI:$driver:database=$db;host=$host;port=$port";

# RaiseError => 1 - сообщать об ошибках

$dbh = DBI->connect($conn, $user, $password, {RaiseError => 1});

# задали название тэйбла - для дальнейшего использования

$table = "users";

# создаем тэйбл "users"

$query = "CREATE TABLE .$table(username char(16) not null,pass char(16) not null)";

# создали

$dbh->do($query);

# отсоединилсь

$dbh->disconnect();

Не особо сложными манипуляциями добавляем данные в тэйбл:

# вся предыдущая инициализация

$query = sprintf("INSERT INTO .$table (username, pass) VALUES ("%s", "%s")", $login, $pass);

# выполнили...

$dbh->do($query);

# и т. д.

Выбираем из базы:

# вся предыдущая инициализация.

# создаем запрос к базе и выбираем все из тэйбла users

$sth = $dbh->prepare("select * from .users");

# выполнили

$sth->execute();

while($row = $sth->fetchrow_arrayref()){

    # в данном случае:

    # $row->[0] - логин (username)

    # $row->[1] - пароль (pass)

    print $row->[0]." ".$row->[1];

}

# обязательно (!) говорим, что завершили

$sth->finish();

Удаляем тэйбл, если он существует:

# вся предыдущая инициализация

$query = "DROP TABLE IF EXISTS .$table";

# выполнили...

$dbh->do($query);

# и т. д.

Вот, собственно, и все, в данной статье я не стал особенно глубоко рассматривать работу с базами SQL, потому как это довольно большая тема и требует отдельной статьи (если не книжки). Удачи в создании систем управления базами данных!


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru