Отображаем сообщения из базы Оглавление Упражнение

Выполняем SQL-запросы к базе данных

База данных MS Access и многие другие локальные (или, как их еще называют, десктопные СУБД) не позволяют подключаться к ним по сети, также бывает, что невозможно осуществить соединение по порту базы данных из-за межсетевых экранов (firewall'ов, брендмауера или прокси-серверов). В таких случаях полезно иметь CGI-программу, которая позволит нам выполнять SQL-запросы через Internet. Такая CGI-программа - просто незаменимый инструмент при разработке интерактивных веб-сайтов на основе баз данных. HTML-форма для выполнения sql-запросов выглядит следующим образом:

HTML-код приведен ниже:
<form action="/cgi-bin/sql_query.exe">
<input type=hidden name=dsn value=gb>

<textarea name=query rows=10 cols=80></textarea>
<input type=submit value="Отправить запрос">
</form>
Данная программа соединяется с источником данных dsn, выполняет sql-запрос query и возвращает пользователя на страницу с HTML-формой для SQL-запроса, в случае, если результатом запроса не является таблица. Создайте еще один проект в среде MS Visual Studio с именем sql_query. Ниже приведен исходный код функции _tmain с комментариями:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{

        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
        return -1;


CString test;
CDatabase  db;
CString dsn, query;


//получаем параметры из HTML-формы
GetParamByName("dsn", dsn);
GetParamByName("query", query);



//соединяемся с базой
try
{
 db.OpenEx("DSN="+dsn, CDatabase::noOdbcDialog);
}
catch(CDBException* e) 
{
 printError("Error: %s\nState: %s\n", e->m_strError, 
             e->m_strStateNativeOrigin);
 goto LABEL_END;
}


//определяем тип запроса
//если SELECT, то результатом будет таблица, которую мы и печатаем
//иначе просто выполняем запрос, ничего не печатая
test=query;
test.MakeUpper();
if( test.Find("SELECT",0)==0 )
{
        
        CRecordset rs(&db);
        
        //выполняем sql-запрос
        try
        {
                rs.Open(CRecordset::dynaset,query);
        }
 catch(CDBException* e) 
 {
  printError("%s\n%s\nquery=%s\n", e->m_strError, 
             e->m_strStateNativeOrigin, query);
  goto LABEL_END;
 }

        //если запрос выполнен успешно, печатаем HTTP-заголовок
        printf("Content-type: text/html\n\n");
        
        //и выводим таблицу
        printf("<table border=1><tr>\n");

        CODBCFieldInfo info;
        int i;

        //печатаем названия колонок
        for (i=0;i<rs.GetODBCFieldCount();i++)
        {
        rs.GetODBCFieldInfo(i,info);
  printf("<td><font color=green>%s</font></td>\n",
         info.m_strName);
        }
        printf("</tr>");


        //печатаем записи таблицы
        while (!rs.IsEOF())
        {
                printf("<tr>\n");
                CString col;
                for (int i=0;i<rs.GetODBCFieldCount();i++)
                {
                        rs.GetFieldValue(i,col);
                        printf(" <td>%s\n",col);
                }
                rs.MoveNext();
        }
        printf("</table>\n");

        if (rs.IsOpen())
                rs.Close();

}

else
{
 try
 {
  db.ExecuteSQL(query);
 }
 catch(CDBException* e)
 {
  printError("%s\n%s\nquery=%s", e->m_strError, 
              e->m_strStateNativeOrigin, query);
  goto LABEL_END;
 }

printf("Location: %s\n\n",getenv("HTTP_REFERER"));
}



LABEL_END:
if (db.IsOpen())
         db.Close();

return 0;
}
Соберите этот проект и выполните несколько sql-запросов при помощи этой программы.