Страница 8 из 17 Записи в 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 эффект будет потрясающий. |