Основы проектирования приложений баз данных

   Панели из мдф по низким ценам в интернет-магазине Леруа Мерлен. |     

Обработка результирующего набора


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

Извлечение данных из результирующего набора в переменные может быть выполнено:

  • вызовом функции SQLFetch или SQLFetchScroll;
  • вызовом функции SQLGetData.

Функции SQLFetch или SQLFetchScroll всегда выполняют продвижение курсора на следующую запись. При этом функция SQLFetch, реализует механизм "однонаправленного курсора", а функция SQLFetchScroll позволяет, в зависимости от используемого источника данных, реализовывать механизм "двунаправленного курсора" и механизм "прямой выборки".

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

Функция SQLFetch имеет следующее формальное описание:

SQLRETURN SQLFetch( SQLHSTMT StatementHandle);

Параметр StatementHandle ([Input]) указывает дескриптор оператора.

Функция SQLGetData имеет следующее формальное описание:

SQLRETURN SQLGetData( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValuePtr, SQLINTEGER BufferLength, SQLINTEGER * StrLen_or_IndPtr);

Параметр StatementHandle ([Input]) указывает дескриптор оператора.

Параметр ColumnNumber ([Input]) указывает номер связываемого столбца результирующего набора (начиная с 1). По умолчанию столбец номер 0 является столбцом маркера строки, в том случае, если маркеры доступны.

Параметр TargetType ([Input]) определяет C-тип данных для буфера*TargetValuePtr в соответствии со следующей таблицей.

Идентификатор C-типа ODBC C typedefТип C
SQL_C_CHARSQLCHAR *unsigned char *
SQL_C_SSHORTSQLSMALLINTShort int
SQL_C_USHORTSQLUSMALLINTunsigned short int
SQL_C_SLONGSQLINTEGERlong int
SQL_C_ULONGSQLUINTEGERunsigned long int
SQL_C_FLOATSQLREALfloat
SQL_C_DOUBLESQLDOUBLE, SQLFLOATdouble
SQL_C_BITSQLCHARunsigned char
SQL_C_STINYINTSQLSCHARSigned char
SQL_C_UTINYINTSQLCHARunsigned char
SQL_C_SBIGINTSQLBIGINT_int64
SQL_C_UBIGINTSQLUBIGINTunsigned _int64
SQL_C_BINARYSQLCHAR *unsigned char *
SQL_C_BOOKMARKBOOKMARKunsigned long int
SQL_C_VARBOOKMARKSQLCHAR *unsigned char *
SQL_C_TYPE_DATESQL_DATE_STRUCTstruct tagDATE_STRUCT { SQLSMALLINT year; SQLUSMALLINT month; SQLUSMALLINT day; } DATE_STRUCT;
SQL_C_TYPE_TIMESQL_TIME_STRUCTstruct tagTIME_STRUCT { SQLUSMALLINT hour; SQLUSMALLINT minute; SQLUSMALLINT second; } TIME_STRUCT;
SQL_C_TYPE_TIMESTAMPSQL_TIMESTAMP_STRUCTstruct tagTIMESTAMP_STRUCT { SQLSMALLINT year; SQLUSMALLINT month; SQLUSMALLINT day; SQLUSMALLINT hour; SQLUSMALLINT minute; SQLUSMALLINT second; SQLUINTEGER fraction; } TIMESTAMP_STRUCT;
SQL_C_NUMERICSQL_NUMERIC_STRUCTStruct tagSQL_NUMERIC_STRUCT { SQLCHAR precision; SQLSCHAR scale; SQLCHAR sign[g]; SQLCHAR val[SQL_MAX_NUMERIC_LEN]; } SQL_NUMERIC_STRUCT;
SQL_C_GUIDSQLGUIDstruct tagSQLGUID { DWORD Data1; WORD Data2; WORD Data3; BYTE Data4[8]; } SQLGUID;
Все интервальные C типы данныхSSQL_INTERVAL_STRUCTtypedef struct tagSQL_INTERVAL_STRUCT { SQLINTERVAL interval_type; SQLSMALLINT interval_sign; union { SQL_YEAR_MONTH_STRUCT year_month; SQL_DAY_SECOND_STRUCT day_second; } intval; } SQL_INTERVAL_STRUCT; typedef enum {

SQL_IS_YEAR = 1, SQL_IS_MONTH = 2, SQL_IS_DAY = 3, SQL_IS_HOUR = 4, SQL_IS_MINUTE = 5, SQL_IS_SECOND = 6, SQL_IS_YEAR_TO_MONTH = 7, SQL_IS_DAY_TO_HOUR = 8, SQL_IS_DAY_TO_MINUTE = 9, SQL_IS_DAY_TO_SECOND = 10, SQL_IS_HOUR_TO_MINUTE = 11, SQL_IS_HOUR_TO_SECOND = 12, SQL_IS_MINUTE_TO_SECOND = 13 } SQLINTERVAL; typedef struct tagSQL_YEAR_MONTH { SQLUINTEGER year; SQLUINTEGER month; } SQL_YEAR_MONTH_STRUCT; typedef struct tagSQL_DAY_SECOND { SQLUINTEGER day; SQLUINTEGER hour; SQLUINTEGER minute; SQLUINTEGER second; SQLUINTEGER fraction; } SQL_DAY_SECOND_STRUCT;

<
Например:

SQLCHAR ValuePtr[50]; SQLINTEGER ValueLenOrInd; SQLGetData(hstmt, 1, SQL_C_CHAR, ValuePtr, sizeof(ValuePtr), &ValueLenOrInd);

В параметре TargetType также можно указывать идентификатор типа SQL_C_DEFAULT: в этом случае драйвер самостоятельно выбирает тип данных С, основываясь на типе данных поля источника данных.

Параметр TargetValuePtr ([Output]) определяет буфер, в который выполняется извлечение данных, а параметр ([Input]) определяет размер этого буфера в байтах. Для данных, имеющих фиксированную длину, таких как целочисленные значения, драйвер игнорирует значение параметра BufferLength.

Параметр StrLen_or_IndPtr ([Output]) определяет буфер, в котором возвращается размер данных или индикатор и может содержать следующие значения:

  • размер данных в байтах;
  • SQL_NO_TOTAL - индикатор, указывающий, что размер не может быть определен;
  • SQL_NULL_DATA - индикатор, указывающий, что данные имеют значение NULL.


Следующий пример иллюстрирует применение механизма извлечения данных при помощи функции SQLGetData.

//OBDC_Connect.cpp #include "stdafx.h" #include "Test_ODBC_connect.h" #include <iostream>

#ifdef _DEBUG #define new DEBUG_NEW #endif CWinApp theApp; // Объявление объекта приложения using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { _tprintf(_T("Ошибка инициализации MFC\n")); nRetCode = 1; } else { std::cout<<"Begin"<<std::endl; SQLHENV henv; // Дескриптор окружения SQLHDBC hdbc; // Дескриптор соединения SQLHSTMT hstmt; // Дескриптор оператора SQLRETURN retcode; // Код возврата /*Инициализация дескриптора окружения */ retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { std::cout<<"SQLAllocHandle создан успешно"<<std::endl; /* Определение версии ODBC */ retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { /* Инициализация дескриптора соединения */ retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { std::cout<<"SQLAllocHandle создан успешно "<<std::endl; retcode = SQLConnect(hdbc, (SQLCHAR*) "MySQLDB", SQL_NTS, (SQLCHAR*) "", SQL_NTS, (SQLCHAR*) "", SQL_NTS); if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){ /* Инициализация дескриптора оператора */ retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); SQLCHAR sqf3[50]; SQLINTEGER sqf1,sqf2,sbf1,sbf2,sbf3; SQLCHAR selecttxt[] ="SELECT f1, f2, f3 FROM tbl1"; /* Создание результирующего набора */ retcode = SQLExecDirect(hstmt, selecttxt, SQL_NTS); if (retcode == SQL_SUCCESS) { while (TRUE) { /* Выборка данных */ retcode = SQLFetch(hstmt); if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) { } if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){ /* Извлечение данных трех полей результирующего набора */ SQLGetData(hstmt, 1, SQL_C_ULONG, &sqf1, 0, &sbf1); SQLGetData(hstmt, 2, SQL_C_ULONG, &sqf2, 0, &sbf2); SQLGetData(hstmt, 3, SQL_C_CHAR, sqf3, 50, &sbf3); /* Запись в поток вывода строк результирующего набора */ std::cout<< "1: "<<sqf1<<" 2: "<<sqf2<<" 3: "<< sqf3<<" "<<std::endl; } else { break; } } } /* Освобождение дескрипторов */ if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) { SQLFreeHandle(SQL_HANDLE_STMT, hstmt); } SQLDisconnect(hdbc); } SQLFreeHandle(SQL_HANDLE_DBC, hdbc); } } SQLFreeHandle(SQL_HANDLE_ENV, henv); } return nRetCode; } }

//OBDC_Connect.h #pragma once #include "resource.h" #ifndef _AFX_NOFORCE_LIBS //////////////////////////////////////////////////////////////// // Win32 библиотеки #pragma comment(lib, "odbc32.lib") #pragma comment(lib, "odbccp32.lib") #endif //!_AFX_NOFORCE_LIBS #ifndef __SQL #include <sql.h> // ядро #endif #ifndef __SQLEXT #include <sqlext.h> // расширение #endif


Содержание раздела