Использование ODBC в Visual C++ - Записи в CRecordset

ОГЛАВЛЕНИЕ

Записи в CRecordset

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

void CDatebaseDlg::OnOpen() 
{
CRecordset cr(NULL);
try
{
cr.Open(CRecordset::snapshot, "SELECT Family,Count FROM TABLE1",
CRecordset::readOnly );
CDBVariant var;
short index=0;
cr.Move(0);
while (!cr.IsEOF())
{
cr.GetFieldValue(index,var);
AfxMessageBox(*var.m_pstring);
cr.MoveNext();
}
cr.Close();
}
catch(CDBException cdb)
{
AfxMessageBox(cdb.m_strStateNativeOrigin);
}
}

Переменная типа CDBVariant принимает значение поля и может принять любое значение. Описание этой переменной. Только это класс, а не переменная :-)

// Указатели на данные в этом классе
m_dwType
m_boolVal
m_chVal
m_iVal
m_lVal
m_fltVal
m_dblVal
m_pdate
m_pstring
m_pbinary

Конструктор этого класса не имеет параметров, и поэтому в коде я так спокойно объявил объект класса. Команда Move перемещает указатель на заданную позицию. Я ставлю 0 и перемещаю в первую позицию. После этого задаю цикл, проверяя с помощью IsEOF достижение конца выборки (источника строк).

Функция GetFieldValue данные из указанного столбца в переменную. Эта функция перегруженная и может иметь несколько возможных параметров. Я применил этот вариант.

void GetFieldValue( short nIndex, CDBVariant& varValue,
short nFieldType = DEFAULT_FIELD_TYPE );
throw( CDBException, CMemoryException );

Зная, что в этом столбце находится строка, я взял соотвествующий ей указатель m_pstring. Проверить это можно запустив в режиме отладки до строки AfxMessageBox.

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

Для того, чтобы показать все записи я использую функцию MoveNext, которая перемещает меня на следующую запись, и так до достижения окончания записей, которые тестируются функцией IsEOF.

При использовании обьекта CRecordset возникает необходимость подсчитать сумму в поле. Возникает желание пробежаться по всем полям с помощью MoveNext и произвести подсчет. Это можно. На всякий случай задумайтесь о другом варианте. В примере ниже я подсчитаю сумму на основе оператора SQL SELECT:

void int_AfxMessageBox(int i)
{
char t[10];
itoa(i,t,10);
AfxMessageBox(t);
}

void CDatebaseDlg::OnOpen()
{
CRecordset cr(NULL);
try
{
// Внимание тестировалось на ACCESS 97
cr.Open(CRecordset::snapshot,
"SELECT Sum(TABLE1.Count) AS SumCount FROM TABLE1",
CRecordset::readOnly );
cr.Move(0);
CDBVariant var;
short index=0;
cr.GetFieldValue(index,var);
double count=var.m_dblVal;
int_AfxMessageBox((int)count);
cr.Close();
}
catch(CDBException cdb)
{
AfxMessageBox(cdb.m_strStateNativeOrigin);
}
}

И простите меня за столь лобовое приведение типа, дабы показать результат. Неохото мне было использовать перевод double - char, да и данные в моей таблице в сумме дают 332 :-). Если отвлечься от этих мелочей, то я построил SQL оператор, который считает сумму в колонке. Ну и что здесь такого ? Конечно ничего, если записей мало. А вот если их много (скажем тысячи) и эту операцию сделает сервер с парочкой процессоров Pentium II и передаст это на Ваш клиент на базе Pentium 133 эффект будет потрясающий.