Механизмы выборки данных
Связывание данных
Функция, выполняющая предварительное связывание данных, имеет следующее формальное описание:
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.