Московский государственный университет имени М.В.Ломоносова
Опубликован: 20.12.2005 | Доступ: свободный | Студентов: 3149 / 373 | Оценка: 4.22 / 3.86 | Длительность: 12:03:00
ISBN: 978-5-9556-0068-0
Лекция 4:

Механизмы выборки данных

< Лекция 3 || Лекция 4: 123 || Лекция 5 >

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

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

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

  • вызовом функции 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_CHAR SQLCHAR * unsigned char *
SQL_C_SSHORT SQLSMALLINT Short int
SQL_C_USHORT SQLUSMALLINT unsigned short int
SQL_C_SLONG SQLINTEGER long int
SQL_C_ULONG SQLUINTEGER unsigned long int
SQL_C_FLOAT SQLREAL float
SQL_C_DOUBLE SQLDOUBLE, SQLFLOAT double
SQL_C_BIT SQLCHAR unsigned char
SQL_C_STINYINT SQLSCHAR Signed char
SQL_C_UTINYINT SQLCHAR unsigned char
SQL_C_SBIGINT SQLBIGINT _int64
SQL_C_UBIGINT SQLUBIGINT unsigned _int64
SQL_C_BINARY SQLCHAR * unsigned char *
SQL_C_BOOKMARK BOOKMARK unsigned long int
SQL_C_VARBOOKMARK SQLCHAR * unsigned char *
SQL_C_TYPE_DATE SQL_DATE_STRUCT
struct tagDATE_STRUCT {     
  SQLSMALLINT year;      
  SQLUSMALLINT month;     
  SQLUSMALLINT day; 
} DATE_STRUCT;
SQL_C_TYPE_TIME SQL_TIME_STRUCT
struct tagTIME_STRUCT {
  SQLUSMALLINT hour;     
  SQLUSMALLINT minute;     
  SQLUSMALLINT second; 
} TIME_STRUCT;
SQL_C_TYPE_TIMESTAMP SQL_TIMESTAMP_STRUCT
struct tagTIMESTAMP_STRUCT {
  SQLSMALLINT year;      
  SQLUSMALLINT month;      
  SQLUSMALLINT day;     
  SQLUSMALLINT hour;      
  SQLUSMALLINT minute;      
  SQLUSMALLINT second;      
  SQLUINTEGER fraction; 
} TIMESTAMP_STRUCT;
SQL_C_NUMERIC SQL_NUMERIC_STRUCT
Struct tagSQL_NUMERIC_STRUCT {   
  SQLCHAR precision;    
  SQLSCHAR scale;     
  SQLCHAR sign[g];     
  SQLCHAR          
    val[SQL_MAX_NUMERIC_LEN]; 
} SQL_NUMERIC_STRUCT;
SQL_C_GUID SQLGUID
struct tagSQLGUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} SQLGUID;
Все интервальные C типы данных SSQL_INTERVAL_STRUCT
typedef 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
< Лекция 3 || Лекция 4: 123 || Лекция 5 >