Алекс Jenter - Программирование на Visual C++. Архив рассылки

Тут можно читать онлайн Алекс Jenter - Программирование на Visual C++. Архив рассылки - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Программирование на Visual C++. Архив рассылки
  • Автор:
  • Жанр:
  • Издательство:
    неизвестно
  • Год:
    неизвестен
  • ISBN:
    нет данных
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание

Программирование на Visual C++. Архив рассылки - описание и краткое содержание, автор Алекс Jenter, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.

Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)

Программирование на Visual C++. Архив рассылки - читать книгу онлайн бесплатно, автор Алекс Jenter
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать
Вызов процедур

Хранимая процедура вызывается при помощи SQL-оператора CALL. Обратите внимание, что использование этого оператора является обязательным требованием к ODBC-программе, даже если СУБД поддерживает другой оператор вызова процедур (например, EXEC[UTE] в SQL Server).

Выполнение оператора CALL осуществляется с помощью функции CDatabase::ExecuteSQL. Сам оператор заключается в фигурные скобки. Рассмотрим пример вызова процедуры spClear, не требующей параметров (она очищает таблицу tPeople, выполняя оператор DELETE * FROM tPeople).

Db.ExecuteSQL("{CALL spClear}");

Вызов процедур с параметрами

Вызов хранимой процедуры с параметрами осуществляется при помощи той же команды, но после имени процедуры в скобках через запятую записывается список параметров.

Модифицируем хранимую процедуру из предыдущего примера так, чтобы она принимала параметр paramName и удаляла из таблицы tPeople только людей с заданным именем (то есть выполняла оператор DELETE * FROM tPeople WHERE Name=paramName). Теперь мы можем удалить из таблицы всех Александров, выполнив:

Db.ExecuteSQL("{CALL spClear('Alexander')}");

Это наиболее простой способ, но он имеет ряд ограничений. В частности, невозможно получить доступ к выходным параметрам функции. Чтобы снять эти ограничения, необходимо связать нужные нам параметры с переменными. Связывание производится в функции CDatabase::BindParameter, которую для этой цели нужно перегрузить. Это, в свою очередь, означает, что нам придётся порождать новый класс от CDatabase. Для связывания каждого параметра с переменной используется функция SQLBindParameters из ODBC API. Вместо каждого связанного с переменной параметра в вызов процедуры вставляется вопросительный знак.

Рассмотрим пример вызова хранимой процедуры spCount, которая возвращает количество людей с заданным именем в таблице tPeople. В СУБД SQL Server такую процедуру можно создать, выполнив запрос:

CREATE PROC spCount(@paramName CHAR(50), @paramCount INT OUTPUT)

AS SELECT @paramCount = COUNT(*) FROM tPeople WHERE Name=@paramName

Теперь, чтобы посчитать количество Александров, необходимо написать следующий код.

// Порождаем новый класс от CDatabase

class CMyDatabase : public CDatabase {

public:

char m_paramName[50];

int m_paramCount;

void BindParameters(HSTMT);

};

void CMyDatabase::BindParameters(HSTMT hStmt) {

SQLBindParameter( // Связываем @paramName с m_paramName

hStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR,

SQL_CHAR, 50, 0, m_paramName, 50, NULL);

SQLBindParameter( // Связываем @paramCount с m_paramCount

hStmt, 2, SQL_PARAM_OUTPUT, SQL_C_SLONG,

SQL_INTEGER, 0, 4, &m_paramCount, 4, NULL);

}

:

CMyDatabase Db;

Db.OpenEx(

"DRIVER={SQL Server};SERVER=(local);DATABASE=tPeople;UID=sa;PWD=",

CDatabase::noOdbcDialog);

strcpy(Db.m_paramName, "Alexander");

Db.ExecuteSQL("{CALL spCount(?,?)}");

// Db.m_paramCount содержит результат!

Как видно из этого примера, входные параметры тоже можно связывать с переменными, и если нам нужно много раз вызывать хранимую процедуру с различными параметрами, это гораздо удобнее, чем формировать запросы при помощи sprintf.

Вызов процедур, возвращающих наборы записей

Процедуры, возвращающие наборы записей, также вызываются с помощью оператора CALL, но в функции CRecordset::Open. Соответственно, полученное множество записей будет связано с объектом класса CRecordset. Если у хранимой процедуры есть параметры, можно передать их напрямую или связать с ними переменные. Связывание переменных, в отличие от предыдущего случая, происходит в функции CRecordset::DoFieldExchange при помощи макросов RFX_* (то есть практически ни чем не отличается от связывания переменных с полями результирующего набора записей). Нужно только вызвать CFieldExchange::SetFieldType с параметром CFieldExchange::inputParam, чтобы сообщить MFC, что мы связываем параметры, а не поля. Важно также записать количество связываемых параметров в переменную CRecordset::m_nParams. Обычно это делается в конструкторе класса.

Рассмотрим пример вызова хранимой процедуры spGetByName, которая находит в таблице tPeople всех людей с заданным именем. В СУБД SQL Server такую процедуру можно создать, выполнив запрос:

CREATE PROC spGetByName(@paramName CHAR(50))

AS SELECT * FROM tPeople WHERE Name=@paramName

Построить набор записей, в который входят все Александры из таблицы, теперь можно так (напоминаю, что нам придётся порождать новый класс от CRecordset).

class CPeople : public CRecordset {

public:

CPeople(CDatabase *pDatabase = NULL) : CRecordset(pDatabase) {

m_nFields = 2, m_nParams = 1;

};

CString m_Name;

Time m_DateOfBirth;

String m_paramName;

void DoFieldExchange(CFieldExchange *pFX);

};

void CPeople::DoFieldExchange(CFieldExchange *pFX) {

pFX->SetFieldType(CFieldExchange::outputColumn);

RFX_Text(pFX, "Name", m_Name, 50);

RFX_Date(pFX, "DateOfBirth", m_DateOfBirth);

pFX->SetFieldType(CFieldExchange::inputParam);

RFX_Text(pFX, "paramName", m_paramName);

}

:

CPeople Rs(&Db);

Rs.m_paramName = "Alexander";

Rs.Open(CRecordset::snapshot, "{CALL spGetByName(?)}");

О чём ещё полезно знать

В заключительном разделе я рассмотрю несколько не связанных между собою тем, знакомство с которыми может оказаться полезным.

Транзакции

Транзакция – это блок команд, которые выполняются как единое целое. Другими словами, они либо выполняются все, либо не выполняется ни одна. Транзакция начинается вызовом CDatabase::BeginTrans и завершается вызовом CDatabase::CommitTrans. Все операции по изменению, добавлению и удалению данных вступят в силу только после вызова CommitTrans, причём в любой момент до вызова этой функции транзакцию можно полностью отменить, вызвав функцию CDatabase::Rollback. Используйте CDatabase::CanTransact, чтобы определить, поддерживает ли используемый вами драйвер транзакции.

CRecordset и его потомки

В первой части статьи мы рассмотрели, как использовать CRecordset, порождая от него новые классы. Возникает вопрос: а можно ли использовать этот класс напрямую? Ответ на этот вопрос звучит так: CRecordset может использоваться для доступа к множеству записей, построенному только на основе запроса (а не имени таблицы), и только в режиме read only. Обратиться к значениям конкретных полей в этом случае можно, используя функцию CRecordset::GetFieldValue. Функции CRecordset::Move* используются, как и раньше.

Следующий фрагмент выводит фамилии всех авторов из БД pubs. Так как нам требуется доступ к таблице authors в режиме , мы можем использовать класс CRecordset напрямую.

CRecordset Rs(&Db);

Rs.Open(CRecordset::forwardOnly, "SELECT aau_lname FROM authors");

while (!Rs.IsEOF()) {

CString lname;

Rs.GetFieldValue((short)0, lname);

printf ("%s\n", lname);

Rs.MoveNext();

}

Как обмануть IntelliSense

Мы уже умеем конструировать объекты класса CRecordset, передавая конструктору указатель на соединение:

CRecordset Rs(&Db);

Существует ещё одна эквивалентная форма создания объекта CRecordset:

CRecordset Rs;

Rs.m_pDatabase = &Db;

Зачем она может понадобиться, спросите вы. Дело в том, что система Microsoft IntelliSense, которая услужливо выдаёт вам списки членов класса и параметров функции прямо, очень болезненно реагирует на конструкторы с параметром: в коде, который следует за вызовом такого конструктора, подсказки попросту перестают появляться. Если вы столкнулись с такой проблемой, смело используйте второй вариант конструирования объекта CRecordset.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Алекс Jenter читать все книги автора по порядку

Алекс Jenter - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Программирование на Visual C++. Архив рассылки отзывы


Отзывы читателей о книге Программирование на Visual C++. Архив рассылки, автор: Алекс Jenter. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x