Смекни!
smekni.com

Бази даних у Internet (стр. 2 из 3)

Тепер, коли користувач може шукати у вашій БД за будь-яким критерієм, наступним логічним питанням є те, як додати або перемістити інформацію до бази даних. Ви могли, звичайно, б зробити це вручну, але було б добре дозволити пряме маніпулювання базою даних з Web безпосередньо. Приємно, що це не важко.

У маніпулюванні базою даних безпосередньо різниця між розмежованою і базою даних з записами фіксованої довжини стає важливою. З розмежованим текстом, ви не маєте легкого шляху для визначення місця, де один запис закінчується та інший починається. Таким чином, щоб змінити або викреслити один запис, необхідно переписати всю базу даних. Так в малих базах даних, це не є дійсно великою проблемою, але якщо ваша база даних є великою достатньо, для того, щоб це стало проблемою, можливо буде хорошою ідеєю проглянути використання сервера бази даних.

З базами даних з незмінної довжиною поля, однак, не необхідно переписати повну базу даних, щоб змінити запис. Через те, що довжина кожного запису відома, функції подібні до seek() і tell() (або їхній еквівалент у вашій улюбленій мові) можуть використатися, щоб переписати лише шматок файлу, змінюючи або вилучаючи дані.

Як і з інтерфейсом до пошукового CGI, проста HTML-форма - це все що вимагається, щоб дати споживачам можливість безпосередньо змінити вашу базу даних. Тут знову є приклад адресної книги:

<HTML><HEAD><TITLE>My Address Book</title></head>
<BODY>
<h4>Fill out the form below to add an entry to the address book</h4>
<FORM ACTION="add.cgi" METHOD="POST">
Name: <INPUT SIZE=45 NAME="name"><br>
Phone: <INPUT SIZE=45 NAME="phone"><br>
Street: <INPUT SIZE=45 NAME="street"><br>
City: <INPUT SIZE=20 NAME="city"> State: <INPUT SIZE=3 NAME="state">
Zip: <INPUT SIZE=6 NAME="zip">
<br><br>
<INPUT TYPE=SUBMIT VALUE=" Add Entry ">
<INPUT TYPE=RESET VALUE=" Reset Form ">
</form></body></html>

Ця форма майже однакова до той, яку було виготовлено для пошуку. Різниця в тому, як дані обслуговуються програмою CGI. У цьому випадку, скрипт CGI для додавання запису є набагато простішим, ніж пошуковий скрипт. У цьому випадку, ми допускатимемо, що база даних є файл з дозволом запису.

#!/bin/perl

require cgi_head; # Ініціалізація CGI-оточення

while (-e "datalock") { sleep 1; } # зачекати, доки звільниться БД
system("touch datalock"); # Зачинити БД

open (DAT, "database.txt"); # Відкрити БД для запису
while (<DAT>) { $line = $_; } # зчитати останній рядок
close DAT;
if ($line =~ /:/) {
@field = split (/:/, $line);
$num = $field[0]; # Знайти останній ID номер
$num++;
} else { $num = 0; } # Створити новий ID

open (DAT, ">>database.txt"); # Відкрити БД для додавання

# Додати запис до БД
print DAT
"$num:$FORM{'name'}:$FORM{'phone'}:$FORM{'street'}:$FORM{'city'}:$FORM{'state'}:
В$FORM{'zip'}&bsol;n";

close DAT;
system ("rm datalock");
print <<EOF;
<HTML><HEAD><TITLE>Addition Successful</title></head>
<BODY>
<h4>Your entry has been added to the address book</h4>
<A HREF="add.html">Go</a> back to the form to add another user.
</body></html>
EOF

Насправді, цей скрипт CGI просто приєднує новий запис до бази даних. Якщо хтось інший змінює базу даних в той же час, одна із змін буде втрачена або повна база даних стане зіпсованою. Щоб обійти це, ми використовуємо lock-файл, щоб сказати, чи хтось інший пише до бази даних. Це далеко не найелегантніше вирішення, і більшість систем забезпечують функцію flock(), щоб більш ефективно замкнути файл від паралельної вибірки. По-друге, номер ID запису повинен бути визначений. У цьому випадку, ми можемо допускати, що записи будуть послідовно нумеровані і, що останній вхід матиме останній номер ID. Так що ми просто читаємо останню лінію бази даних, захоплюємо номер ID від нього, і потім прирощуємо його, щоб одержати новий номер ID.

Тепер, коли будь-хто може додати записи до адресної книги, може стати необхідним, викреслити або змінити записи. Щоб зробити, це, однак, має бути деякий спосіб для користувача, щоб вказати на бажаний вхід який треба змінити або викреслити. Замість створення всієї нової форми для цього, ми можемо додати ці функціональні можливості до нашого існуючого CGІ-пошуку. Якщо пошук користувача повертає точно один результат, лінія може бути додана до сторінки результату HTML, яка пропонує на вибір змінити або викреслити цей вхід. (Це могло б бути зроблене для більш ніж одного результату досить легко, але ми працюємо з одним заради стислості). Це може бути зроблено за допомогою зміни наступних ліній в дні пошуку CGI:

print <<EOH;
</pre><br>
Thank you for using my address book.
<A HREF="addrbk.html">Go</a> back to the form to make another search.
</body></html>
EOH

на:

print "</pre><br>&bsol;nThank you for using my address book.&bsol;n";
print "<A HREF=&bsol;"addrbk.html&bsol;">Go</a> back to the form to make another search.<br>&bsol;n";
if ($#results == 0) {
print "<A HREF=&bsol;"change.cgi?a=d&n=$result[0]&bsol;">Delete</a> this entry.<br>&bsol;n";
print "<A HREF=&bsol;"change.cgi?a=c&n=$result[0]&bsol;">Modify</a> this entry.<br>&bsol;n";
}
print "</body></html>&bsol;n";

Додаткові лінії друкують зв'язки з новою програмою CGI, передаючи два значення: вказання параметра - викреслювання або модифікація потрібна, і номер ID запису, щоб викреслити або змінити.

Через те, що наша база даних розмежена, нам буде необхідно відродити повну базу даних, щоб зробити зміну, як показано:

#!/bin/perl

require cgi_head; # Ініціалізація CGI-оточення

while ( -e "datalock" ) { sleep 1; } # зачекати, доки не звільниться БД
system ("touch datalock"); # Замкнути БД.

# Завантажити БД
open (DAT, "database.txt") || die "Can't open the database: $! !.&bsol;n";
$maxn = 0; # Лічильик записів.
while (<DAT>) {
chop;
@field = split(/:/); # розбити запис на поля.
$n = $field[0]; # перше поле є ID
$add[$n]{'name'} = $field[1]; # ім'я
$add[$n]{'phone'} = $field[2]; # телефон
$add[$n]{'street'} = $field[3]; # адреса
$add[$n]{'city'} = $field[4]; # місто
$add[$n]{'state'} = $field[5]; # країна
$add[$n]{'zip'} = $field[6]; # поштовий індекс
$add[$n]{'line'} = $_ . "&bsol;n"; # весь рядок
}
$maxn = $n;

close DAT;

open (DAT, ">database.txt"); # відкрити БД для запису.
if ($FORM{'a'} eq "d") { # Якщо треба знищити запис,
for ($I = 0; $I <= $maxn; $I++) { #видати всі записи,
unless ($I == $FORM{'n'}) { # крім того, який треба зтерти.
print DAT $add[$I]{'line'};
}
}
# видати повідомлення та вийти.
print <<EOP;
<HTML><HEAD><TITLE>Request successful</title></head>
<BODY>
<H3>The selected entry has been deleted.</h3>
<A HREF="addrbk.html">Go</a> back to make another search.
</body></html>
EOP

close DAT;
system ("rm datalock");
die;
} elsif ($FORM{'a'} eq "c") {


# Якщо користувач хоче змінити вхід, все стає трохи хитрішим.
Ми повинні спершу надрукувати зовні форму, подібні до первинної форми, щоб дозволити
користувачеві змінити значення запису.


# змінна.
print <<EOF;
<HTML><HEAD><TITLE>Entry Modification</title></head>
<BODY>
<h4>Make the desired changes in the form below.</h4>
<FORM ACTION="change.cgi" METHOD="POST">
<INPUT TYPE=HIDDEN NAME="a" VALUE="m">
<INPUT TYPE=HIDDEN NAME="n" VALUE="$n">
Name: <INPUT SIZE=45 NAME="name" VALUE="$add[$n]{'name'}"><br>
Phone: <INPUT SIZE=45 NAME="phone" VALUE="$add[$n]{'phone'}"><br>
Street: <INPUT SIZE=45 NAME="street" VALUE="$add[$n]{'street'}"><br>
City: <INPUT SIZE=20 NAME="city" VALUE="$add[$n]{'city'}">
State: <INPUT SIZE=3 NAME="state" VALUE="$add[$n]{'state'}">
Zip: <INPUT SIZE=6 NAME="zip" VALUE="$add[$n]{'zip'}">
<br><br>
<INPUT TYPE=SUBMIT VALUE=" Modify Entry ">
<INPUT TYPE=RESET VALUE=" Reset Form ">
</form></body></html>
EOF
# Ця форма додає два приховані поля, говорячи CGI, який вхід треба
#змінити.
for ($I = 0; $I <= $maxn; $I++) { print DAT $add[$I]{'line'}; }
close DAT;
system ("rm datalock");
die;

} elsif ($FORM{'a'} = "m") {
# внести зміни до необхідного запису
$n = $FORM{'n'}; # Скопіюавти запис до змінної.
# Внести зміни.
$add[$n]{'name'} = $FORM{'name'};
$add[$n]{'phone'} = $FORM{'phone'};
$add[$n]{'street'} = $FORM{'street'};
$add[$n]{'city'} = $FORM{'city'};
$add[$n]{'state'} = $FORM{'state'};
$add[$n]{'zip'} = $FORM{'zip'};
$add[$n]{'line'} =
"$n:$add[$n]{'name'}:$add[$n]{'phone'}:$add[$n]{'street'}:$add[$n]{'city'}:$add[$n]{'state'}:
В$add[$n]{'zip'}&bsol;n";
for ($I = 0; $I <= $maxn; $i++) { print DAT $add[$i]{'line'}; }
close DAT;

print <<EOE;
<HTML><HEAD><TITLE>Modification successful</title></head>
<BODY>
<H4>The requested entry has been modified.</H4>
<A HREF="addrbk.html">Go</a> back to the form to make another search.
</body><//html>
EOE
system ("rm datalock");
die;
} else { die; } # This should never be reached.

Звертання до SQL

Ми можемо використовувати ті ж сторінки форми HTML, які ми використовували, наприклад, для текстової бази даних. Перша форма розшукала існуючу базу даних. Показана відповідна програма CGI.

Пошук у базі даних SQL.

#!/bin/perl

require cgi_read;
use Msql; # завантажити модуль SQL

$dbh = Connect Msql; #під'єднатися до серверу mSQL

SelectDB $dbh "addresses"; # вибрано БД "addresses
$all = "name, phone, street, city, state, zip"; # всі поля адреси
$query = ""; # Встановити змінну для запиту.

foreach (keys %FORM) { # зібрати всі умови в один рядок
$query =. " $_ = $FORM{'$_'} AND";
}
$query =~ s/AND$//;

$sth = Query $dbh "SELECT $all FROM addresses WHERE $query"; # Відправити запит

print "<HTML><HEAD><TITLE>Search Results</title></head><BODY>&bsol;n";

$I = 0; # немає співпадань.
while (@arr = FetchRow $sth) {
if ($I == 0) { $I = 1; } # 1 співпадання
if ($I == 1) {
print "<H4>Your search results are listed below</h4>";
print "<PRE>&bsol;n";
};
$I++;
print <<EOF;
-- --

Name: $arr[0]
Phone: $arr[1]
Street: $arr[2]
City: $arr[3]
State: $arr[4]
Zip: $arr[5]

EOF
}
if ($I == 2) {
print "</pre><br>";
print "<A HREF=&bsol;"addrbk.html&bsol;">Go</a> back to the form to make another
Вsearch.<br>&bsol;n";
print "</body></html>&bsol;n";
} elsif ($I == 0) {
print <<EOE;
<HTML><HEAD><TITLE>Search Failed!</title></head><BODY>
<h4>There are no entries which match your criteria</h4>
<A HREF="addrbk.html">Go</a> back to the form to make another search.
</body></html>
EOE
}

Фактично CGI-код в цьому випадку є в чотири рази менший за рівноцінний у першому прикладі. Крім того, дуже легко додати відповідність підрядку до запитання mSQL. Також помітьте відсутність номерів ID - mSQL є реляційною базою даних прямого доступу. Тобто не потрібно читати всі записи, щоб мати доступ до будь-яких з них.