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

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

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

Связывание данных

Функция, выполняющая предварительное связывание данных, имеет следующее формальное описание:

SQLRETURN SQLBindCol(
     SQLHSTMT     StatementHandle,
     SQLUSMALLINT     ColumnNumber,
     SQLSMALLINT     TargetType,
     SQLPOINTER     TargetValuePtr,
     SQLINTEGER     BufferLength,
     SQLLEN *     StrLen_or_Ind);

Значения параметров функции SQLBindCol аналогичны значениям параметров функции SQLGetData. Но функция SQLBindCol указывается только один раз для каждого поля, а затем выборка данных выполняется автоматически при вызове функции SQLFetch. А при отсутствии связывания функция SQLGetData должна вызываться каждый раз для каждого поля после выполнения функции SQLFetch.

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

Например:

#define NAME_LEN 50
#define PHONE_LEN 10

SQLCHAR      szName[20], szPhone[15];
SQLINTEGER   sID, cbName, cbID, cbPhone;
SQLHSTMT      hstmt;
SQLRETURN   retcode;

retcode = SQLExecDirect(hstmt,
            "SELECT CID, NAME, PHONE FROM TBL1
             ORDER BY 2, 1, 3", 
SQL_NTS);
if (retcode == SQL_SUCCESS || 
    retcode == SQL_SUCCESS_WITH_INFO) {
/* Связывание столбцов 1, 2 и 3 */
SQLBindCol(hstmt, 1, 
           SQL_C_ULONG, 
           &sCID, 0, 
           &cbCID);
SQLBindCol(hstmt, 2, 
           SQL_C_CHAR, 
           szName, 20, 
           &cbName);
SQLBindCol(hstmt, 3, 
           SQL_C_CHAR, 
           szPhone, 15, 
           &cbPhone);
while (TRUE) {
retcode = SQLFetch(hstmt);
if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {
show_error();
      }
if (retcode == SQL_SUCCESS || 
    retcode == SQL_SUCCESS_WITH_INFO){
// Значения полей успешно извлечены из 
// результирующего набора
} else {
break;
      }
   }
}

Применение ESCAPE-последовательностей

Escape-последовательности позволяют передавать значения даты и времени, скалярных функций и функций даты/времени, строки в предикате LIKE, внешних соединений, процедурных вызовов, одинаково определяемых в стандарте, в различные источники данных. ODBC-драйвер в зависимости от используемого источника данных приводит передаваемый SQL-оператор в соответствующую форму, заменяя значение escape-последовательности. Преобразованный ODBC-драйвером текст SQL-оператора можно посмотреть, вызвав метод SQLNativeSql.

Escape-последовательность указывается в фигурных скобках.

Для определения значений даты и времени используется следующая форма escape-последовательности:

{тип_значения 'значение'}.

Тип значения указывается следующими символами:

  • d - для типа Date формата yyyy-mm-dd
  • t - для типа Time формата hh:mm:ss
  • ts - для типа Timestamp формата yyyy-mm-dd hh:mm:ss[.f...]

Следующий пример иллюстрирует два способа определения даты: в первом случае с применением escape-последовательности, а во втором - с использованием естественного синтаксиса Oracle. При этом код, использующий естественный синтаксис Oracle, не является интероперабельным.

Пример:

UPDATE tbl1 SET OpenDate= {d '2004-01-24'} 
    WHERE FieldID=1010
UPDATE tbl1 SET OpenDate= '24-Jan-2004' 
    WHERE FieldID=1010

Escape-последовательность может передаваться как значение параметра SQL-оператора. Применение параметра позволяет в последующих реализациях быстро переходить от значения в виде escape-последовательности ("{d '2004-01-24'}") к значению, использующему естественное обозначение в соответствии с конкретным драйвером ("24-Jan-2004").

Например:

SQLCHAR    Date1[56]; // Размер даты равен 55
SQLINTEGER Date1LenOrInd = SQL_NTS;
// Определение параметров
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, 
 SQL_TYPE_DATE, 0, 0,
 Date1, sizeof(Date1), 
 &Date1LenOrInd);
// Задание значения переменной Date1 как 
// escape-последовательности.
strcpy(Date1, "{d '2004-01-24'}");
// Выполнение SQL-оператора
SQLExecDirect(hstmt, "UPDATE tbl1 SET Date1=? 
   WHERE FieldID = 1010", SQL_NTS);

Другим способом определения значения даты посредством параметра является применение структуры SQL_DATE_STRUCT. В большинстве случаев этот способ бывает более эффективен.

Например:

SQL_DATE_STRUCT Date1;
SQLINTEGER      Date1Ind = 0;
// Определение параметра
SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, 
 		SQL_C_TYPE_DATE, SQL_TYPE_DATE, 0, 0,
 		&Date1, 0, &Date1Len);
// Определение полей структуры Date1
Date1.year = 2004;
Date1.month = 1;
Date1.day = 24;
// Выполнение SQL-оператора
SQLExecDirect(hstmt, "UPDATE tbl2 SET Date1=? 
    WHERE FieldID = 1010", SQL_NTS);

Для определения того, поддерживает ли конкретный ODBC-драйвер escape-последовательности для представления значений типа даты и времени, применяется функция SQLGetTypeInfo (если источник данных поддерживает типы данных для даты и времени, то он также должен поддерживать и соответствующие escape-последовательности).

Для определения того, поддерживает ли конкретный ODBC-драйвер представление значений даты и времени в виде, определяемом спецификацией ANSI SQL-92, применяется функция SQLGetInfo с опцией SQL_ANSI_SQL_DATETIME_LITERALS.

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