<% ASP на блюдечке %>. Часть 1
Интерфейс к базе данных с помощью ASP
Постановка задачи
Предположим, перед нами стоит задача создания газетного сайта, причем некоторые из его читателей должны иметь право пополнять его новыми статьями, снабжаемыми фотографиями непосредственно с самого сайта и без программирования. Предположим также, что такой сайт должен иметь возможности удаления статей, их поиска, а также сортировки. С первого взгляда может показаться, что решение такой задачи не под силу начинающему программисту ASP, однако, как вы скоро увидите, это далеко не так.
Для начала давайте все-таки разберемся, что же от нас требуется. По сути, необходимо создать базу данных всех статей, подготовить несколько HTML-форм для загрузки статей на сервер, их поиска, сортировки, удаления и, наконец, отображения результата.
Я почти уверен, что подобная задача актуальна применительно практически к любому сайту, тем более что подобным образом (разве что без возможностей поиска, сортировки и удаления) работает большинство гостевых книг (guestbook).
Что нам понадобится
Для реализации вышеизложенной задачи нам потребуется персональный компьютер с Microsoft Windows NT или Windows 2000 (можно и Workstation, и Server), установленный IIS (Internet Information Server), какой-нибудь HTML-редактор (советую использовать Macromedia Dreamweaver), Microsoft Access (версии 95, 97 или 2000) и самый обычный текстовый редактор.
Создание и подготовка базы данных
Прежде всего создадим базу данных статей, для чего:
- запустим приложение Microsoft Access;
- любым из известных способов создадим новую базу данных. Назовем ее «Articles»;
- в созданной базе данных создадим таблицу с именем, например «Articles»;
- пользуясь инструментом «Конструктор», определим поля нашей таблицы и типы принимаемых ими значений (рис. 1);
- заполним таблицу несколькими статьями в соответствии с созданными полями (рис. 2);
- сохраним базу данных в файле «ArticlesDB.mdb».
Далее необходимо прописать нашу базу данных в соответствующем разделе источников данных системы, для этого:
- запустим программу-конфигуратор источников данных (Data Sources ODBC) — Start->Settings->Control Panel->Administrative Tools->Data Sources ODBC;
- перейдем во вкладку «System DSN» и создадим новый источник данных, нажав на «Add…»;
- в появившемся списке драйверов выберем драйвер баз данных Microsoft Access — «Microsoft Access Driver (*.mdb)» и нажмем на «Finish»;
- в строке «Data Source Name» зададим имя нашей базы данных, например «Articles» (это то имя, по которому мы в дальнейшем будем обращаться к ней);
- нажмем на «Select…», выберем подготовленный нами файл «ArticlesDB.mdb» и нажмем «OK».
В результате в списке источников данных в вашей системе появится строка, представленная на рис. 3.
Оформляем главную страницу (index.asp)
С ASP работать очень просто. Для этого надо всего лишь вставить текст скрипта ASP в пару тэгов <% %>. В остальном ASP-файл ничем не отличается от HTML-файла (за исключением, пожалуй, расширения). Комментарии в HTML, как известно, вставляются в пару тэгов <!-- текст комментария -->, в ASP же закомментировать строку можно при помощи символа ‘ (апостроф) в ее начале.
<html> <head> <title>Наш газетный сайт — первые шаги в ASP</title> </head> <body> <center> <!-- … оформление страницы … … можно показать дату … --> Тoday is: <% D = Date() ‘ Получаем значение текущей даты D = FormatDateTime(D,2) ‘Преобразуем в нужный формат Response.Write D ‘Отображаем на экране в текущей позиции %> <!-- <! -- Определим основные линки --> <a href="http://localhost/List.asp" class="antiLine"> Список статей</a><br> <a href="http:// localhost /SearchForm.asp" class="antiLine"> Поиск статьи</a><br> <a href="http:// localhost /UploadForm.asp" class="antiLine"> Загрузка статьи</a><br> <% Set db = Server.CreateObject("ADODB.Connection") ‘Создаем переменную ActiveX Data Object ‘для соединения с базой данных db.Open "Articles" ‘открываем нашу базу данных sSQL = "SELECT * FROM Articles" ‘Формируем SQL запрос Set rs = db.Execute(sSQL) ‘и выполняем его, а результат заносим ‘в переменную rs If rs.Fields ("Article").value <> "No Text" Then ‘Если поле Article не пустое, Link = "<a href= http://localhost/ArtTempl.asp?id=" & ‘то формируем линк на файл с шаблоном rs.Fields("ID").value & ">" & ‘HTML и передаем туда параметр rs.Fields("Title").value & "</a>" ‘с идентификатором статьи из поля ID End If Response.Write Link & "<br>" ‘Отображаем переменную Link Response.Write "<i>By " & ‘Отображаем содержимое поля rs.Fields("Author").value ‘Author & "</i><br>" ANN = rs.Fields("Annotation").value If ANN <> "NA" Then ‘Отображаем содержимое поля Response.Write ANN ‘Annotation, если оно не пусто End If db.Close ‘Закрываем базу данных Set db = Nothing ‘и обнуляем переменную - указатель %> </center> </body> </html>
Теперь давайте разберемся. Во-первых, как вы наверняка заметили, ASP-код легко сочетается с HTML-тэгами; в этом его достоинство. Так, к примеру, строка Response.Write Link & "<br>" отображает на экране браузера клиента подготовленное сервером значение переменной Link и HTML-тэг <br>, то есть перевод строки. Особый интерес вызывает переменная rs. Для искушенных программистов сразу скажу — это указатель. Однако в ASP с целью облегчения работы начинающих указатели маскируются. Здесь не встретишь громоздких С’шных конструкций, типа «я знаю, что ты знаешь, что я знаю», или, выражаясь программистским языком, указатель на указатель… Однако сделано это так искусно, что гибкость программирования при этом не теряется, нет лишь прямой работы с указателями, а только работа с помощью специальных функций, скрывающих от программиста рутину и защищающих указатели от некорректных действий. Таким образом, выражение rs.Fields ("Article").value означает значение поля "Article" текущего значения указателя на элемент базы данных (в нашем случае статей) и содержит текст статьи, которая соответствует текущей позиции указателя на все статьи. Переход к следующему элементу базы (смещение указателя) выполняется с помощью инструкции Rs.MoveNext. В приведенном выше примере это не делается, а попросту формируется ссылка на текст статьи в виде ее названия и отображается комментарий самой первой статьи, соответствующей результату запроса. Давайте попробуем отобразить все статьи нашей базы данных на главной странице в виде HTML. И еще, обратите особое внимание на директиву:
Link = "<a href= http://localhost/ArtTempl.asp?id=" & rs.Fields("ID").value & ">" & rs.Fields("Title").value & "</a>"
Она по сути формирует ссылку на файл, содержащий шаблон отображения самой статьи, причем передает идентификатор статьи ему в качестве параметра. Полностью файл шаблона приведен в приложении к настоящей статье, а механизм его работы может быть кратко представлен следующим образом:
<% TheID = Request.QueryString("id") Set db = Server.CreateObject("ADODB.Connection") db.Open "Articles" sSQL = "SELECT * FROM Articles Where ID =" & TheID Set rs = db.Execute(sSQL) Session("IDsDel") = rs.Fields("ID").value Link = "<b><a href= http://localhost/Remove/RemoveForm.asp?id=" & rs.Fields("ID").value & ">" & "Remove the article" & "</a></b>" Response.Write Link & "<br>" Response.Write rs.Fields("Title").value Response.Write "<i><b>By " & rs.Fields("Author").value & "</b>" Response.Write "<br>Subject: " & rs.Fields("Subject").value Response.Write "Published: " & rs.Fields("Published").value & "</i><br>" Response.Write rs.Fields("Article").value db.Close Set db = Nothing %>
Первая строчка скрипта шаблона HTML присваивает переменной TheID значение, переданное ссылкой с использованием метода Request.QueryString. Далее открывается база данных, из которой читается статья (запись), соответствующая идентификатору, переданному из главного скрипта (index.asp).
<html> <head> <title>Наш газетный сайт - первые шаги в ASP</title> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> </head> <body> <center> <p><font size="3" color="#000000"><b>Главная страница</b> <table BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="640" > <! -- Создадим таблицу шириной 640 пиксел --> <tr> <td WIDTH="640" BGCOLOR="#FFCC99" valign = top> Список всех статей нашей базы данных: </td> </tr> <! -- Наша таблица будет содержать всего одну колонку, напишем в ней пока заголовок --> <% Set db = Server.CreateObject("ADODB.Connection") db.Open "Articles" sSQL = "SELECT * FROM Articles" Set rs = db.Execute(sSQL) Cnt = 0 ‘Заводим счетчик статей Do While NOT Rs.EOF ‘Пока в базе есть статьи (начало цикла) %> <tr> <!--Новый ряд в таблице -- > <td> <!--Новая ячейка -- > <% If rs.Fields ("Article").value <> "No Text" Then Link = "<a href= http://localhost/ArtTempl.asp?id=" & rs.Fields("ID").value & ">" & rs.Fields("Title").value & "</a>" End If Response.Write Link & "<br>" Response.Write "<i>By " & rs.Fields("Author").value & "</i><br>" ANN = rs.Fields("Annotation").value If ANN <> "NA" Then Response.Write ANN End If %> </td> <!--Конец ячейки -- > </tr> <!-- Конец ряда -- > <% Rs.MoveNext ‘Переход к следующей записи в базе статей Cnt = Cnt + 1 ‘ Увеличение счетчика статей Loop ‘ Конец цикла db.Close Set db = Nothing %> <p><font size="3" color="#000000"><i> <% Response.Write " Всего - " & Cnt & "статей" %> </i></font> </font></p> </table> </center> </body> </html>
Создаем главную страницу
Таким образом в таблицу в цикле будут добавляться ряды со ссылками на статьи и с аннотациями, пока не будут отображены все статьи из базы данных. Следует обратить внимание на переменную Cnt. По окончании цикла она будет содержать число обработанных статей (рядов таблицы).
Язык структурированных запросов — SQL
Настала пора разобраться с тем, что таится за строчками:
sSQL = "SELECT * FROM Articles" Set rs = db.Execute(sSQL)
По сути, именно за этими двумя строчками кроется работа с нашей базой данных: первая представляет собой текстовую строку с запросом к базе данных (текстовые строки в ASP записываются в двойных кавычках); вторая — содержит директиву выполнения этого запроса с одновременным присвоением результата переменной (указателю на записи в базе данных). В рамках настоящей статьи мы не будем рассматривать SQL (Structured Query Language) во всех деталях, а остановимся лишь на тех его операторах, без понимания которых дальнейшая работа будет невозможна. Для тех, кому этого покажется недостаточным, советую посетить отобранные мною сайты с детальной документацией по SQL.
Для полноценной работы нам необходимо познакомиться с четырьмя операторами этого мощного языка, предназначенного специально для работы с базами данных.
DELETE [LOW_PRIORITY] FROM «Имя Таблицы» [WHERE Определение]
DELETE удаляет те ряды из «Имя Таблицы», которые удовлетворяют условию, определенному в «Определении», и возвращает число удаленных рядов. Если выполнить команду DELETE без условия WHERE, то все ряды указанной таблицы будут удалены. В этом случае DELETE возвратит 0. Ключевое слово LOW_PRIORITY откладывает выполнение операции DELETE до завершения работы чтения из таблицы других клиентов.
Пример:
DELETE FROM Articles WHERE ID = 1 <!--Удалить все те статьи (записи), чьи параметры ID равны 1--> SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [DISTINCT | ALL] Выражение_Select,... [INTO OUTFILE имя_файла' опции_экспорта] [FROM ссылки_на_таблицы [WHERE where_определение] [GROUP BY имя_столбца,...] [HAVING where_определение] [ORDER BY {беззнаковое_целое | имя_столбца } [ASC | DESC] ,...] [LIMIT [смещение,] ряды] [PROCEDURE имя_процедуры] ]
SELECT используется для извлечения рядов (записей) из одной или более таблиц. Выражение_Select определяет столбцы таблицы, значения которых необходимо извлечь. Все ключевые поля должны быть заданы в строгой последовательности. К примеру, выражение HAVING должно следовать за любым выражением GROUP BY и до любого выражения ORDER BY.
Выражение_Select можно заменить псевдонимом (alias) с помощью ключевого слова AS. Псевдоним используется в качестве идентификатора имени столбца и может быть использован наряду с ключевыми словами ORDER BY или HAVING.
Примеры:
select concat (Фамилия, ', ' , Имя) AS Полное_Имя from Таблица ORDER BY Полное_Имя select * from Таблица LIMIT 5 <!-- извлечет первые 5 рядов из таблицы--> SELECT * FROM Articles Where IsTopNew = '1' Order By ID DESC <!--те статьи таблицы Articles, значение поля (столбца) IsTopNew - '1', отсортированные в порядке убывания значений поля (столбца) ID-->
Выражение HAVING может относиться к любому столбцу или псевдониму в Выражении_Select. Оно применяется к запросу в последнюю очередь, непосредственно перед посылкой данных клиенту. SELECT ... INTO OUTFILE 'имя_файла' заносит отобранные записи в файл. Файл создается непосредственно на сервере и не может «уже существовать» (одна из основных причин такого механизма заключается в предотвращении случайного «затирания» различных важных файлов).
INSERT используется для добавления новых записей в существующую таблицу. Допустимо две формы использования INSERT.
Форма 1:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] Имя_Таблицы [(имя_столбца,...)] VALUES (выражение,...),(...),...
Форма 2:
INSERT [LOW_PRIORITY | DELAYED] [IGNORE] [INTO] Имя_Таблицы [(имя_столбца,...)] SELECT ...
Первая форма — INSERT ... VALUES — вставляет ряды на основании заданных значений. Вторая форма — INSERT ... SELECT — вставляет ряды, выбранные из другой таблицы.
Примеры:
INSERT INTO Имя_Таблицы (Поле1,Поле2) VALUES(15,Поле1*2);
Ключевое слово LOW_PRIORITY откладывает выполнение операции до завершения работы чтения из таблицы других клиентов. Ключевое слово IGNORE в команде INSERT позволяет избегать вставки повторяющихся строк (используется в сочетании с ключевыми словами PRIMARY или UNIQUE). Для второй формы INSERT INTO ... SELECT операция не может содержать выражения ORDER BY. Таблица, в которую производится добавление записей, не может присутствовать в выражении FROM части SELECT запроса потому, что запрещено производить выделение из той же самой таблицы, в которую производится вставка.
REPLACE служит для редактирования содержимого таблицы и работает в точности как INSERT, за исключением того, что если старая запись в таблице имеет то же значение, что и записываемая, то старая запись удаляется прежде, чем добавляется новая.
Форма 1:
REPLACE [LOW_PRIORITY | DELAYED] [INTO] Имя_Таблицы [(имя_поля,...)] VALUES (выражение,...)
Форма 2:
REPLACE [LOW_PRIORITY | DELAYED] [INTO] Имя_Таблицы [(имя_поля,...)] SELECT ...
Форма 3:
REPLACE [LOW_PRIORITY | DELAYED] [INTO] Имя_Таблицы SET имя_поля = выражение, имя_поля = выражение,... UPDATE [LOW_PRIORITY] Имя_Таблицы SET имя_поля1=выр1,имя_поля2=выр2,... [WHERE определение_where]
UPDATE обновляет поля существующей таблицы новыми значениями. Выражение SET показывает, какие поля (столбцы) должны быть изменены, и значения, которые должны быть им присвоены. Выражение WHERE, если оно есть, указывает, какие ряды должны быть обновлены. В противном случае операция применяется ко всем рядам таблицы. Ключевое слово LOW_PRIORITY откладывает выполнение операции до завершения работы чтения из таблицы других клиентов. Выражения UPDATE выполняются слева направо.
Примеры:
Update WAPassword Set Password = 'passw' Where ID = 1
Обновляет значение поля Password в таблице WAPassword, записывая в поле, чей идентификатор ID равен 1 значение 'passw'.
UPDATE Счетчик SET counter=counter+1
Увеличивает значение поля counter таблицы Счетчик на 1.
UPDATE persondata SET age=age*2, age=age+1
Удваивает поле age, а затем прибавляет 1 к его значению в таблице persondata.
Что такое Global.asa
Global.asa позволяет выполнять определенные скрипты в начале работы клиентской сессии или при инициализации IIS. Примером тому может служить простейший счетчик числа посещений сайта. Более того, допустимо использовать множественные файлы Global.asa. Однако следует помнить, что ASP-скрипт ищет самый близкий (расположенный в том же каталоге) файл Global.asa и использует именно его.
По сути, этот файл может содержать четыре скрипта: первый будет выполняться при инициализации службы IIS/PWS (Application_OnStart), второй — при остановке службы IIS/PWS (Application_OnEnd) (обычно эти первые два скрипта отрабатывают в процессе перезагрузки компьютера), и еще два скрипта выполняются дополнительно при инициализации сессии пользователя (Session_OnStart) и по ее окончании (Session_OnEnd). Данная схема очень сильно напоминает пары «конструктор-деструктор». Неспроста всякая переменная, которая должна быть использована (например, в текущей сессии), может быть инициализирована в Session_OnStart с тем, чтобы быть использованной в процессе работы сессии, она же уничтожается (обнуляется) в Session_OnEnd.
Global.asa не может содержать тэгов HTML. Недопустимо использование JavaScript. Не рекомендуется писать файл Global.asa с помощью каких-либо HTML-редакторов, для этого гораздо лучше использовать NotePad. И еще один совет: прежде чем вставлять скрипт в файл Global.asa, попробуйте его в работе в обычном ASP-файле.
<OBJECT RUNAT=Server SCOPE=Session ID=Tool1 PROGID="MSWC.Tools"> </OBJECT> <SCRIPT LANGUAGE = "VBScript" RUNAT="Server"> Sub Session_OnStart Dim strUserLogon Dim StrUserSecurity ' Эти переменные сессии будут держать ' значения имени пользователя ( logon) и права его доступа strUserLogon = Request.ServerVariables("USER_LOGON" ) strUserSecurity = "PUBLIC" End Sub Sub Session_OnEnd ' Этот код уничтожает компонент Tools для текущей сессии. Set Tool1 = Nothing 'А этот обнуляет переменные сессии. strUserLogon = "" strUserSecurity = "" ‘ Внимание!: Данный код применять в этом смысле совсем не обязательно ' так как объекты будут выгруженны из памяти web сервером ' автоматически по закрытии текущей сессии. End Sub </SCRIPT>
Пример файла Global.asa
Добавляем новую статью (UploadForm.asp и Upload2DBS.asp)
Теперь, когда мы разобрались с SQL, можно приступать к добавлению новой статьи, причем делать мы это будем прямо с сайта, а если быть точнее — непосредственно с HTML-формы. Для этого сначала создадим файл с самой формой и определим скрипт-реакцию на подтверждение (кнопку «Publish the article!»). (Предполагается, что читатель знаком с азами построения HTML-форм, поэтому мы рассмотрим этот процесс, не вдаваясь в детали построения форм.)
Прежде всего следует уточнить задачу на этом этапе. Итак, очевидно следующее:
- на загрузку статьи с сайта должен иметь право не каждый (следовательно, желательно предусмотреть пароль для доступа к этой функции);
- у каждой статьи есть определенная тема (рубрика), причем она не может быть произвольной, а должна выбираться из списка;
- список можно хранить непосредственно в HTML-файле и, каждый раз изменяя его, изменять сам файл. Это самый простой и быстрый способ;
- однако для того, чтобы позволить динамически изменять и пополнять этот список, рекомендуется держать его в базе данных. Это позволит пользователям произвольным образом изменять его содержимое и не потребует переделки формы. Для простоты сначала рассмотрим вариант со встроенным («жестко прошитым») рубрикатором.
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <title>Загрузка статьи</title> </head> <body> <FORM NAME="mainform" METHOD="GET" ENCTYPE="multipart/form-data" ACTION="http://localhost/Upload2DBS.asp"> <b>Author: (*)</b><br> <input type=TEXT size=56 name="Author"><br> <! -- Поле имени автора статьи -- > <b>Title: (*)</b><br> <input type="text" name="Title" size="56"><br> <! — Поле заголовка статьи -- > <b>Article Annotation:</b><br> <textarea name="Annotation" cols="56"></textarea><br> <! — Поле аннотации к статье -- > <b>Article Text:</b><br> <textarea cols="56" name="Article" rows="15"></textarea><br> <! — Поле текста самой статьи -- > <b>Subject: (*) and type of the article</b><br> <! — Поле рубрикатора статьи -- > <select name="Subject"> <option>Economics</option> <option>Education</option> <option>Entertainment</option> <option>Finances</option> <option>Health</option> <option>Lesure</option> <option>Medecine</option> <option>News&Media</option> <option>Other</option> <option>PC Software</option> <option>PC Hardware</option> <option>Politics</option> <option>Society</option> <option>Science</option> <option>Sports</option> <option>Travel</option> </select> <b>Database access password: (*)</b><br> <input type="password" name="Password"> <input type=SUBMIT value="Publish the Article!" name="SUBMIT"> <input type="reset" name="Reset" value="Reset Article Form"> </FORM> </body> </html>
Как видим, передача управления осуществляется благодаря директиве ACTION="http://localhost/Upload2DBS.asp"> в тэге формы. Тем самым указывается скрипт-ответ на реакцию пользователя после нажатия на кнопку «Publish the article!». Теперь остановимся на селекторе рубрик. Как уже отмечалось, желательно перевести его содержимое в базу данных. Для этого в нашей базе данных (файл ArticlesDB.mdb) создадим новую таблицу с именем, к примеру «Topics», в которой с помощью конструктора определим всего одно поле — «Topic» типа «текст». Далее заполним эту таблицу произвольными значениями нашего рубрикатора и отсортируем полученный список в алфавитном порядке. После чего следует заменить тэг <select> в вышеприведенной форме на следующий вариант:
<select name="Subject"> <% Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=Articles;UID=sa;PWD=;" SQLQuery = "Select * From Topics" Set rs = db.Execute(SQLQuery) Do While NOT Rs.EOF Response.Write "<option>" & rs.Fields("Topic").value & "</option>" Rs.MoveNext Loop %> </select>
… и все.
Теперь давайте разберемся с самой сутью дальнейшей работы. Что же должен делать наш скрипт-реакция?
Во-первых, следует позаботиться о том, чтобы все обязательные поля (а они отмечены звездочкой) были введены. Наиболее правильным способом проверки этого является скрипт, написанный на любом языке описания скриптов (например, JavaScript), который будет проверять, введены ли значения обязательных полей. Для этого достаточно добавить в определение тэга формы параметр onsubmit="preprocess();", где preprocess() — имя функции-скрипта, который и будет осуществлять проверку. Здесь как нельзя кстати видно преимущество языков описания сценариев (JavaScript, Jscript, VBScript) перед ASP. ASP выполняется на стороне сервера, а перегружать связь «клиент-сервер» простой проверкой типа «введены ли значения», согласитесь, неправильно. Однако специально в целях обучения мы будем делать это с помощью ASP.
И еще. Прежде чем приступить к выполнению нашей задачи, следует сказать еще об одной небольшой проблеме: когда мы будем вставлять в ячейку базы данных текст, его форматирование (даже самое простое) не сохранится, и в дальнейшем его невозможно будет корректно отобразить на HTML-странице, поскольку поле Memo хранит неформатированную строку текста. Чтобы избежать этого, следует написать функцию, которая позволит производить примитивное HTML-форматирование введенного текста статьи, перед тем как записать его в базу данных. Другими словами, в самом примитивном случае (хотя бы для того, чтобы сохранить исходную разбивку на строки) функция должна вставлять символы конца строки там, где во входном потоке имеются символы переноса строк.
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> </head> <body> <% Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=Articles;UID=sa;PWD=;" SQLQuery = "Select * From WAPassword Where ID = 1" Set rs = db.Execute(SQLQuery) DBP = rs.Fields("Password").value db.Close Set db = Nothing Function FormatStr(InString) on Error resume next InString = Replace(InString, CHR(13) & CHR(10), "<br>") InString = Replace(InString, CHR(10) & CHR(10), "</P><P>") InString = Replace(InString, CHR(10), "<BR>") InString = Replace(InString, "'", "`") InString = Replace(InString, CHR(34), "/") FormatStr = InString End Function ErrA = 0 ErrT = 0 ErrP = 0 ErrC = 0 AUT = Request.QueryString ("Author") If AUT = "" Then ErrA = 1 End If AUT = FormatStr(AUT) TIT = Request.QueryString ("Title") If TIT = "" Then ErrT = 1 End If TIT = FormatStr(TIT) ART = Request.QueryString ("Article") If ART = "" Then ART = "No Text" If File1 = "No" Then ErrC = 1 End If End If ART = FormatStr(ART) SBJ = Request.QueryString ("Subject") IsTopNew = Upload.Form("IsTopNewSelector") ANN = Request.QueryString ("Annotation") ANN = FormatStr(ANN) If ANN = "" Then ANN = "NA" End If Password = Request.QueryString ("Password") If Password = DBP Then If ErrA = 0 and ErrT = 0 Then Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=Articles;UID=sa;PWD=;" sSQL = "insert into Articles (Author,Title,Article,Subject,Published,Annotation) values('" & AUT & "', '" & TIT & "','" & ART & "','" & SBJ & "','" & TIM &"', '" & ANN & "')" Set rs = db.Execute(sSQL) db.Close Set db = Nothing End If Else ErrP = 1 End If N = Now() If ErrP = 0 and ErrA = 0 and ErrT = 0 and ErrC = 0 Then Response.Write "Article uploaded successfully at " & N &"<br>" End If If ErrP = 1 Then Response.Write "Error! Article database access denied! Incorrect password!" End If If ErrA = 1 Then Response.Write "<br>" & "Error! No Author specified!" End If If ErrT = 1 Then Response.Write "<br>" & "Error! No Title specified!" End If If ErrC = 1 Then Response.Write "<br>" & "Error! You should specify article text!" End If </body> </html>
Удаляем статью (RemoveForm.asp и Rem.asp)
Было бы неплохо предусмотреть возможность удаления статьи с нашего сайта: во-первых, она может устареть, а во-вторых, в процессе ее подготовки не исключены ошибки или опечатки. Останавливаться на форме удаления статьи не будем, скажем лишь, что она содержит единственные элементы с запросом пароля и кнопкой удаления (см. файл RemoveForm.asp), и сразу перейдем к рассмотрению непосредственно процесса удаления:
<% variable = Session("IDsDel") session.abandon P = Request.QueryString("P") Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=Articles;UID=sa;PWD=;" SQLQuery = "Select * From WAPassword Where ID = 1" Set rs = db.Execute(SQLQuery) DBP = rs.Fields("Password").value Err = 0 If P <> DBP Then Response.Write "Error! Incorrect Password!" Err = 1 End If db.Close Set db = Nothing If Err = 0 Then Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=Articles;UID=sa;PWD=;" SQLQuery = "Delete * From Articles Where ID =" & variable Set rs = db.Execute(SQLQuery) Response.Write "The article has been successfully removed!" db.Close Set db = Nothing End If %>
Особое внимание следует уделить первым двум строкам. Они получают значение глобальной переменной текущего сеанса (сессии) работы со значением идентификатора текущей статьи (в нашем случае удаляемой), которая была инициализирована (файл ArtTmp.htm) следующей строкой:
Session("IDsDel") = rs.Fields("ID").value
Таким образом, в текущий скрипт передается в качестве параметра сеансовая переменная с идентификатором текущей статьи, которую необходимо удалить. Имеется в виду, что ссылка на удаление присутствует в странице с шаблоном (файл ArtTmp.htm) и удаляемая статья является текущей.
Организуем поиск (SearchForm.asp и SearchDBS.asp)
Как известно, без поиска навигация в сколь-нибудь солидной базе данных невозможна в принципе. Попробуем организовать поиск статьи по ее реквизитам, причем постараемся организовать булев (логический) поиск, соединяя отдельные значения критериев поиска с помощью логики «И/ИЛИ».
Опять же не заостряя внимание на поисковой форме (файл SearchForm.asp), перейдем непосредственно к самому процессу поиска:
<% '------ Прочитать данные с поисковой формы -------------------------------- AUT = Request.QueryString("Author") TIT = Request.QueryString("Title") SBJ = Request.QueryString("Subject") DUR = Request.QueryString("During") ORD = Request.QueryString("Order") TitleConjunctor = Request.QueryString("TitleSelector") AuthorConjunctor = Request.QueryString("AuthorSelector") SubjectConjunctor = Request.QueryString("SubjectSelector") If TitleConjunctor = 1 Then ' Получить значение первого селектора TConjunctor = "and" Else TConjunctor = "or" End If If AuthorConjunctor = 1 Then ' Получить значение второго селектора AConjunctor = "and" Else AConjunctor = "or" End If If SubjectConjunctor = 1 Then ' Получить значение третьего селектора SConjunctor = "and" Else SConjunctor = "or" End If '---Соединение с базой данных и формирование сложного SQL запроса из составных компонент ------------ Set db = Server.CreateObject("ADODB.Connection") db.Open "DSN=Articles;UID=sa;PWD=;" GenerQuery = "Select * From Articles " 'Основной запрос WhereQuery = "Where" 'Where_Выражение TitleQuery = " Title Like '" & TIT & "%' " 'Критерий для поля Заголовка AuthorQuery = " Author Like '" & AUT & "%' " 'Критерий для поля Автора SubjectQuery = " Subject Like '" & SBJ & "' " 'Критерий для поля рубрикатора OrderQuery = "Order By '" & ORD & "' DESC" 'Критерий для поля сортировки If SBJ = "Any" Then 'Любой рубрикатор If AUT = "" Then If TIT = "" Then SQLQuery = GenerQuery 'Оба поля (Автор и заголовок) пусты Else SQLQuery = GenerQuery + WhereQuery + TitleQuery 'Поле Автор пусто End If Else If TIT = "" Then SQLQuery = GenerQuery + WhereQuery + AuthorQuery 'Поле Заголовок пусто Else SQLQuery = GenerQuery + WhereQuery + AuthorQuery + AConjunctor + TitleQuery 'Оба не пусты End If End If Else 'Была указана рубрика If AUT = "" Then If TIT = "" Then SQLQuery = GenerQuery + WhereQuery + SubjectQuery Else SQLQuery = GenerQuery + WhereQuery + TitleQuery + TConjuctor + SubjectQuery End If Else If TIT = "" Then SQLQuery = GenerQuery + AuthorQuery + AConjunctor + SubjectQuery Else SQLQuery = GenerQuery + WhereQuery + AuthorQuery + AConjunctor + TitleQuery + TConjunctor + SubjectQuery End If End If End If If ORD <> "Default" Then 'Добавляем установленный режим сортировки If ORD = "Published" Then ORD = "ID" End If SQLQuery = SQLQuery + OrderQuery 'Формирование окончательного запроса End If 'Response.Write SQLQuery '--------- Выполняем SQL запрос и формируем таблицу с результатами поиска ------------------------------------ Set rs = db.Execute(SQLQuery) If rs.Eof Then S = "Извините,совпадений не найденно." Response.Write S End If Cnt = 0 Do While NOT Rs.EOF %> <tr><td> <% If rs.Fields("Article").value <> "No Text" Then Link = "<a href= http://localhost/ArtTempl.asp?id=" & rs.Fields("ID").value & ">" & rs.Fields("Title").value & "</a>" End If Response.Write Link & "<br>" Response.Write "<i>By " & rs.Fields("Author").value & "</i><br>" Response.Write "<i>Published: " & rs.Fields("Published").value & "</i> " Response.Write "<i>(Subject: " & rs.Fields("Subject").value & ")</i><br>" ANN = rs.Fields("Annotation").value If ANN <> "NA" Then Response.Write ANN End If %> <hr NOSHADE WIDTH="100%"></td></tr> <% Rs.MoveNext Cnt = Cnt + 1 Loop db.Close Set db = Nothing %> <b><%Response.Write Cnt Response.Write " статей найдено<br>"%> </b>
Самое интересное происходит при формировании запроса к базе из составляющих:
GenerQuery = "Select * From Articles " WhereQuery = "Where" TitleQuery = " Title Like '" & TIT & "%' " AuthorQuery = " Author Like '" & AUT & "%' " SubjectQuery = " Subject Like '" & SBJ & "' " OrderQuery = "Order By '" & ORD & "' DESC"
В зависимости от введенной пользователем комбинации исходных полей из этих компонентов формируется окончательный запрос, в частности для полей «Author» и «Title». Возможны четыре случая: оба поля пусты, пусто первое поле, пусто второе поле и оба поля не пусты. Соответствующая строка SQL-запроса в каждом из этих случаев формируется по-своему. То же самое относится к состоянию селекторов рубрик статей и порядку их сортировки. При добавлении той или иной подстроки учитывается состояние «радиокнопок» И/ИЛИ и соответствующая подстрока добавляется в SQL-запрос, предваряясь логическим элементом «and» или «or» соответственно. После того как окончательный запрос сформирован, он выполняется, а результирующая страница формируется исходя из списка статей, удовлетворяющих критериям.
Полный код приведенных в статье примеров, включая файл базы данных, находится на нашем CD-ROM.
И в заключение
Напоследок хотелось бы сориентировать разработчиков ASP-страниц в мире документации и инструментальных средств. Дело в том, что автор настоящей статьи провел не один день сидя в Интернете в поисках всевозможных исходных текстов, документации, инструментальных средств и теоретических основ этого мощного средства.
Среди множества инструментальных средств, служащих для облегчения создания ASP-приложений, выделяются два: Easy ASP© Eric Banker, 2000 и Microsoft InterDev из комплекта Microsoft Visual Studio 6.0. Первый — очень удобное, несложное и небольшое средство для быстрого создания ASP-приложений. Второй представляет собой мощный, тяжеловесный интегрированный пакет в духе Microsoft для разработки всевозможных Web-приложений.
Временная версия EasyASP 4.0 находится на нашем CD-ROM.
Среди огромного числа сайтов мною были отобраны те, посещение которых было для меня особенно полезным и с которыми хотелось ознакомить читателей, а именно:
http://www.15seconds.com/issue/000210.htm — создание динамичных JavaScript-скриптов с помощью ASP и интерфейсов к базам данных
http://phpclub.unet.ru/ — русский PHP-клуб
http://www.alphasierrapapa.com/iisdev/ — сайт, посвященный разработке серверов IIS с помощью ASP
http://developer.irt.org/script/asp.htm — база часто задаваемых вопросов по ASP
http://www.webclub.ru/materials/aspobjects/index.html — обзор встроенных объектов ASP
http://www.websiteresources.com/ — огромная база исходных текстов всевозможных Web-программ
http://www.zdnet.com/devhead/filters/0,9429,2133219,00.html — ZDNet Developer (масса полезных ASP-исходников)
Примеры ASP-кода для профессионалов
http://msdn.microsoft.com/library/psdk/iisref/devs1c4z.htm — огромная база исходников, документации по ASP. ASP-форумы
http://www.asptoday.com/search.asp?category=ASP Tricks — масса полезных советов для начинающих программировать на ASP
http://www.oreilly.com/catalog/aspnut/ — замечательная книга популярнейшей серии «In a Nutshell» всемирно известного издательства O’REILLY «ASP in a Nutshell A Desktop Quick Reference». На сайте бесплатно размещена одна из глав книги
http://www.chilisoft.net/ — версии ASP для различных платформ можно скачать с этого сайта
http://www.willcam.com/sql/ — введение в структурированный язык запросов SQL
SQL Reference and Example Site — хорошо структурированный материал по SQL
http://vb-world.net/databases/ — азы разработки баз данных с помощью Microsoft SQL Server 7
КомпьютерПресс 9'2000