Платформы корпоративных информационных систем


Пример приложения, использующего DBI



Пример приложения, использующего DBI


DBI допускает любые SQL-запросы, поддерживаемые MySQL и mSQL. Например, рассмотрим базу данных, используемую в школе для ведения учета учащихся, состава классов, результатов экзаменов и т. д. База данных должна содержать несколько таблиц: одну для данных о предметах, другую для данных об учащихся, таблицу для списка экзаменов и по одной таблице для каждого экзамена. Возможность MySQL и mSQL выбирать данные из нескольких таблиц, используя объединение таблиц, позволяет совместно использовать таблицы как согласованное целое для создания приложения, облегчающего работу учителя.

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

CREATE TABLE test (

id INT NOT NULL AUTO_INCREMENT, name CHAR(100),

subject INT, num INT

Для каждого отдельного экзамена структура таблицы такая:

CREATE TABLE t7 (

id INT NOT NULL,

q1 INT,

q2 INT,

q3 INT,

q4 INT,

total INT

)

К имени таблицы t присоединен идентификатор экзамена из таблицы test. При создании таблицы пользователь определяет количество вопросов. Поле total содержит сумму баллов по всем вопросам.

Программа, обрабатывающая данные экзаменов, называется test.cgi. Эта программа, текст которой следует ниже, позволяет только добавлять новые экзамены. Просмотр экзаменов и их изменение не реализованы и оставлены в качестве упражнения. Дополнить этот сценарий будет несложной задачей, если воспользоваться в качестве справочного материала другими сценариями, приведенными в данной главе. Этот сценарий хорошо показывает возможности DBI:

#!/usr/bin/perl -w

use strict; require my_end;

use CGI qw(:standard);

my Soutput = new CGI;

use_named_parameters(1);

# Использовать модуль DBI. use DBI;

# DBI::connect() использует формат 'DBI:driver:database', в нашем случае

# используется драйвер MySQL и открывается база данных 'teach',

my $dbh = DBI->connect('DBI:mysql:teach');

# Операция добавления распределена между тремя отдельными функциями. Первая функция, add,

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

sub add {

$subject = param('subject')

if (param('subjects'));

$subject = ""

if $subject eq 'all';

print header, start_html('title'=>'Create a New Test',

'BGCOLOR'=>'white'); print <<END_OF_HTML;

<Н1>Создание нового экзамена</п1> <FORM ACTION="test.cgi" METHOD=POST>

<INPUT TYPE=HIDDEN NAME="action" VALUE="add2"> Предмет: END_OF_HTML

my @ids = (); my %subjects = ();

my $out2 = $dbh->prepare("select id,name from subject order by name" $out2->execute;

# DBI: :fetchrow_array() совершенно аналогична Msql: :fetchrow()

while(my($id,$subject)=$out2->fetchrow_array) {

push(@ids,Sid); $subjects{"$id"} = Ssubject; }

print popup_menu('name'=>'subjects', 'values'=>[@ids], 'default'=>$subject, 'labels'=>\%subjects);

print <<END_OF_HTML; <br>

Число вопросов: <INPUT NAME="num" SIZE=5><br> Название или идентификатор (например, дата) экзамена:

<INPUT NAME="name" SIZE=20>

<Р>

<INPUT TYPE=SUBMIT VALUE=" Следующая страница ">

<INPUT TYPE=RESET> </form></body></html>

END_OF_HTML }

Эта функция выводит форму, позволяющую пользователю выбрать предмет для экзамена, а также количество вопросов и название. Для вывода списка имеющихся предметов выполняется запрос к таблице предметов. При выполнении в DBI запроса SELECT он должен быть сначала подготовлен, а затем выполнен. Функция DBI::prepare полезна при работе с некоторыми серверами баз данных, позволяющими осуществить операции над подготовленными запросами, прежде чем выполнить их. Для MySQL и mSQL это означает лишь запоминание запроса до вызова функции DBI:: execute .

Результаты работы этой функции посылаются функции add2, как по-: казано ниже:

sub add2 {

my Ssubject = param('subjects');

[

my $num = param('num');

$name = param('name') if param('name');

my $out = $dbl»prepare("select name from subject where id=$subject");

$out->execute;

my (Ssubname) = $out->fetchrow_a.rray;

print header, start_html('title'=>"Создание экзамена по предмету $subname", ' BGCOLOR'=>'white');

print <<END_OF_HTML;

<H1> Создание экзамена по предмету $subname</h1> <h2>$name</h2>

<P>

<FORM ACTION="test.cgi" METHOD=POST>

<INPUT TYPE=HIDDEN NAME="action" VALUE="add3">

<INPUT TYPE=HIDDEN NAME="subjects" VALUE="$subject">

<INPUT TYPE=HIDOEN NAME="num" VALUE="$num">

<INPUT TYPE=HIDDEN NAME="name" VALUE="$name">

Введите количество баллов за каждый правильный ответ.

Сумма баллов не обязательно должна равняться 100.

<Р> END_OF_HTML

for (1..$num) {

print qq%$_: <INPUT NAME="q$_" SIZE=3> %; if (not.$_ % 5)

{ print "<br>\n"; } } print <<END_OF_HTML;

<P>

Введите текст экзамена:<br>

<TEXTAREA NAME="test" ROWS=20 COLS=60> </textarea> <p>

<INPUT TYPE=SUBMIT VALUE="Ввести экзамен ">

<INPUT TYPE=RESET> </form></body></html>

END_OF_HTML }

Эта функция динамически генерирует форму для экзамена, основываясь на параметрах, введенных в предыдущей форме. Пользователь может ввести количество баллов для каждого вопроса экзамена и полный текст самого экзамена. Выходные данные этой функции посылаются завершающей функции add3, как показано ниже:

sub add3 {

my $subject = para'm( 'subjects');

my $num = param('num');

$name = param('name') if param('name');

my $qname;

($qname = $name) =" s/'/\\'/g;

my $q1 = "insert into test (id, name, subject, num) values ( '.'-, '$qname', $subject, $num)";

my Sin = $dbh->prepare($q1); $in->execute;

# Извлечем значение ID , которое MySQL создал для нас

my $id = $in->insertid;

my $query = "create table t$id ( id INT NOT NULL,

my $def = "insert into t$id values ( 0, ";

my $total = 0;

my @qs = grep(/^q\d+$/,param);

foreach (@qs) {

$query .= $_ . " INT,\n";

my $value = 0;

$value = param($_) if param($_);

$def .= "lvalue, ";

$total += $value; }

$query .= "total INT\n)"; $def .=-"$total)";

my $in2 = $dbh->prepare($query);

$in2->execute;

my $in3 = $dbh->prepare($def);

$in3->execute;

# Обратите внимание, что мы запоминаем экзамены в отдельных файлах. Это

# полезно при работе с mSQL, поскольку он не поддерживает BLOB.

# (Тип TEXT, поддерживаемый в mSQL 2, можно использовать,

# но это неэффективно.)

# Поскольку мы используем MySQL, можно с таким же успехом

# поместить весь экзамен в BLOB.

open(TEST,">teach/tests/$id") or die("A: $id $!");

print TEST param('test'), "\n";

close TEST;

print header, start_html('title'=>'Экзамен создан', 'BGCOLOR'=>'white');

print <<END_OF_HTML;

<Н1>Экзамен создан</h1> <P>

Экзамен создан.

<р>

<А HREF=".">Перейти</а> на домашнюю страницу 'В помощь учителю'.<br>

<А HREF="test.cgi">nepeimi</a> на главную страницу экзаменов.<br>

<А HREF="test.cgi?actio,n=add">Добавить</a> следующий экзамен.

</body></html>

END_OF_HTML

}

Теперь введем информацию об экзамене в базу данных. При этом мы шагнем дальше обычного ввода данных, который видели до сих пор. Данные по экзаменам достаточно сложны, поэтому каждый экзамен лучше хранить в собственной таблице. Вместо добавления данных в существующую таблицу мы создадим совершенно новую таблицу для каждого экзамена. Сначала мы создадим ID для нового экзамена с помощью функции автоинкрементирования MySQL и введем название и ID экзамена в таблицу с именем test. Эта таблица является просто указателем на экзамены, по ней можно легко найти ID любого экзамена. Затем мы создадим одновременно два запроса. Первый будет запросом CREATE TABLE, который определит наш новый экзамен. Второй запрос будет иметь тип INSERT и запишет в нашу таблицу максимальные баллы по каждому вопросу. Эти запросы будут отправлены серверу базы данных, что завершит весь процесс (после вывода пользователю страницы с сообщением об успешном завершении). Позднее, после сдачи экзамена учащимися, для каждого учащегося будет создана запись в таблице экзамена. Эти записи могут быть сравнены с максимальными значениями для определения оценки учащегося.









Начало  Назад  Вперед


Книжный магазин