Работа с бази данни

Лектори
Георги Пенков gpenkov@phreedom.org
Марин Маринов mmarinov@phreedom.org
Петър Пенчев roam@ringlet.net
Николай Бачийски nbachiyski@developer.bg
Уеб страница
http://perl.phreedom.org/

Въведение

Въведение в SQL

Въведение в SQL (1/2)

Въведение в SQL (2/2)

Визуален пример

Въведение в DBI

Въведение в DBI (2/2)

DBI — визуален пример

Осъществяване на връзка към базата (1/2)

Осъществяване на връзка към базата (2/2)

Стандартен цикъл на работа

Основни методи на DBI

Малко повече за placeholder-ите

Извличане на данни от база (1/2)

Извличане на данни от база (2/2)

  • Всички select* методи могат да получават като втори параметър (подобно на do) атрибути и като следващи — параметри, които „попълват“ placeholder-ите (ако такива са включени в описането на заявката). Например:
    @row_ary = $dbh->selectrow_array($statement, \%attr, @bind_values);

Многократно използване на една и съща подготвена заявка (1/2)

  • 1) Подготовка на SQL заявката
    • $sth = $dbh->prepare($statement);
    • подготвя (кешира) дадена заявка.
    • $sth се нарича statement handle. Веднъж „подготвен“, той може да бъде използван многократно в следващите стадии
    • в $statement може да има placeholder-и
  • 2) Изпълнение на заявката с дадени параметри
    • $sth->execute( @params );
    • Изпълнява заявката, като евентуално използва стойностите от елементите на @params за стойности на динамичните полета в заявката.

Многократно използване на една и съща подготвена заявка (1/2)

  • 3) Извличане на резултати (при SELECT заявки):
    • @row_ary = $sth->fetchrow_array;
    • $ary_ref = $sth->fetchrow_arrayref;
    • $hash_ref = $sth->fetchrow_hashref;
  • 4) Приключване на работа с тази заявка:
    • $sth->finish();
    • Повторно изпълнение (execute) и извличане на данни от същата заявка е възможно само ако тя е била приключена преди това.
  • Свързване на променливи със заявка

    • Вместо използване на placeholder-и, може да бъдат свързани избрани променливи с динамичните полета в текста на SQL заявка.
    • Това става с помощта на:
      • $sth->bind_param($p_num, $bind_value, $bind_type); # съдържанието на $bind_value се копира на мястото на параметър p_num
      • $sth->bind_col($column_number, \$var_to_bind); # $var_to_bind се променя автоматично всеки път, когато # бъде извлечен нов ред.

    Транзакции (1/2)

    • Транзакциите позволяват капсулирането на няколко последователни операции. Това позволява капсулация на данните и запазване на консистентността, когато се променят не една, а няколко таблици.
    • Всяка транзакция може да бъде отменена както по желание на client приложението, така и при възникване на грешка.
    • По този начин, когато възникне грешка в операция, съставена от множество обръщения към базата, може лесно да се върне старото състояние на данните, без да се получи загуба на такива.

    Транзакции (2/2)

    • За контрол на транзакциите има три основни команди:
      • $dbh->begin # започване на транзакция
      • $dbh->commit # запазване на извършените операции, считано от последния begin
      • $dbh->rollback # отмяна на извършените до момента операции
    • По подразбиране DBI не използва транзакции, но ги поддържа напълно.

    Абстракция с Class::DBI

    • Class::DBI е нов OOP модул, който позволява свързването на таблица от базата и данните в нея с обект.
    • Приложенията, които използват Class::DBI, го наследяват и описват таблиците, с които се свързват дефинираните в тях класове. Описват се и релациите между отделните таблици.
    • Впоследствие достъп и работа с данните в базата става през методи на класовете.
    • Елиминира се напълно нуждата от писане на SQL код, тъй като за това се грижи Class::DBI.
    • Недостатък на този подход е, че при Class::DBI не винаги се генерира оптимален SQL и брой заявки, което може да доведе до ненужни забавяния.

    Пример за Class::DBI

  • package Music::Artist; use strict; use base 'Class::DBI::Pg'; # специфичният за Postgresql Class::DBI extension # указва се с коя таблица е асоцииран класа Music::Artist->table('artist'); # описват се колоните на таблицата Music::Artist->columns(All => qw/artistid name popularity/); #създаване на нов запис: my %hash = (artistid=>1, name=>'sublime'); my $obj1 = Music::Artist->create(\%hash); # получаване на всички записи или на даден запис my @obj = Music::Artist->retrieve_all; # намиране на точно определени записи my @cds = Music::CD->search(title => "Greatest Hits", year => 1990); # достъп до данните в дадена колона print $cd->artist; foreach my $cd ( @cds );
  • Използвани материали

    • CPAN.org
      • DBI
      • DBD::Pg
      • DBD::mysql
      • Class::DBI
    • Class::DBI homepage — http://www.class-dbi.com/
    • Database Docs:
      • PostgreSQL — http://postgresql.org/docs
      • MySQL — http://dev.mysql.com/doc/
    • Полезни връзки за SQL:
      • http://sqlzoo.net/
      • http://www.w3schools.com/sql/sql_intro.asp