Шаг 8 - Записи в 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, посмотрите ниже, как показана данная структура в окне отладки.

8_1.gif (7797 b)

То есть, если Вы даже не предпологаете тип данных, применив данный прием, вы можете попробовать извлечь выводы о типе данных, а самое главное реально прочитанное из данного столбца. Наверно не надо быть Ностардамусом, чтобы догадаться, что если столбец будет иметь тип 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 эффект будет потрясающий.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 20.10.99