Выборка итоговых данных

Приложение ODBC имеет три параметра для выборки данных результата.

Первый параметр основан на функции SQLBindCol. До выборки результирующего набора приложение использует функцию SQLBindCol для привязки каждого столбца в результирующем наборе к программной переменной. После того, как все столбцы будут привязаны, драйвер передает данные текущей строки в переменные, привязанные к столбцам результирующего набора каждый раз, когда приложение вызывает функцию SQLFetch или функцию SQLFetchScroll. Если столбец результирующего набора и программная переменная имеют разные типы данных, драйвер обрабатывает преобразования данных. Если в приложении SQL_ATTR_ROW_ARRAY_SIZE установлен в значение, большее 1, то оно может привязать столбцы результата к массивам переменных; все они будут заполнены при каждом вызове функции SQLFetchScroll.

Второй параметр основан на функции SQLGetData. Приложение не использует функцию SQLBindCol для привязки столбцов результирующего набора к переменным программы. После каждого вызова функции SQLFetch приложение вызывает функцию SQLGetData один раз для каждого столбца результирующего набора. Функция SQLGetData указывает драйверу передавать данные из конкретного столбца результирующего набора в конкретную программную переменную и указывает типы данных столбца и переменной. Это позволяет драйверу преобразовать данные, если столбец результата и программная переменная имеют разные типы данных. Столбцы типа Text, ntext, и image обычно слишком большие для того, чтобы соответствовать программной переменной, но они все равно могут быть получены при помощи функции SQLGetData. Если данные столбца типа text, ntext, или image в столбце результата больше, чем программная переменная, функция SQLGetData возвращает значение SQL_SUCCESS_WITH_INFO и SQLSTATE, равный 01004 (строковые данные, усеченные справа). Успешные вызовы функции SQLGetData возвращают успешные фрагменты данных столбцов типа text или image. Когда достигается конец данных, функция SQLGetData возвращает SQL_SUCCESS. Если значение SQL_ATTR_ROW_ARRAY_SIZE больше 1, каждая выборка возвращает набор строк. Перед использованием функции SQLGetData необходимо использовать функцию SQLSetPos для указания конкретной строки в наборе строк в качестве текущей.

Третий параметр использует сочетание функций SQLBindCol и SQLGetData. Приложение может, например, связать первые десять столбцов результирующего набора, а затем для каждой выборки три раза вызвать функцию SQLGetData для получения данных из трех несвязанных столбцов. Это возможность обычно используется, если результирующий набор содержит один или более столбец типа text или image.

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

Злоупотребление использованием функции SQLBindCol для привязки столбца результирующего набора к программной переменной очень ресурсоемко, так как функция SQLBindCol вызывает драйвер ODBC для выделения памяти. При привязке столбца результата к переменной эта привязка действует как до вызова функции SQLFreeHandle для очистки дескриптора инструкции, так и до вызова функции SQLFreeStmt со параметра fOption, равным SQL_UNBIND. По завершении инструкции привязки автоматически не снимаются.

Эта логика позволяет эффективно выполнять инструкцию SELECT несколько раз с различными параметрами. Так как результирующий набор сохраняет ту же структуру, можно один раз привязать результирующий набор, выполнить все инструкции SELECT, а затем, после последнего выполнения инструкции, вызвать функцию SQLFreeStmt со значением параметра fOption, равным SQL_UNBIND. Не следует вызывать функцию SQLBindCol для привязки столбцов в результирующем наборе без предварительного вызова функции SQLFreeStmt с параметром fOption, равным SQL_UNBIND для удаления всех предшествующих привязок.

При использовании функции SQLBindCol можно осуществлять привязку параметров как на уровне строк, так и на уровне столбцов. Привязка параметров как на уровне строк быстрее, чем привязка на уровне столбцов.

Можно использовать функцию SQLGetData для получения данных каждого столбца вместо привязки столбцов результирующего набора при помощи функции SQLBindCol. Если результирующий набор содержит мало строк, использование функции SQLGetData вместо функции SQLBindCol будет быстрее, в противном случае, функция SQLBindCol покажет лучшую производительность. Если данные не всегда помещаются в один и тот же набор переменных, следует использовать функцию SQLGetData вместо постоянной повторной привязки. Использовать функцию SQLGetData можно только для столбцов, которые находятся в списке выбора после столбцов, привязанных при помощи функции SQLBindCol. Столбец также должен располагаться после всех столбцов, для которых уже использовалась функция SQLGetData.

Функции ODBC, работающие с перемещением данных в программные переменные или из них, такие, как SQLGetData, SQLBindCol и SQLBindParameter, поддерживают неявные преобразования типов данных. Например, если приложение привязывает целочисленный столбец к строковой программной переменной, драйвер автоматически преобразует данные из целочисленного в символьный тип перед тем, как поместить их в программную переменную.

Количество преобразований данных в приложениях должно быть минимальным. Если преобразование данных не требуется для вычислений, производимых приложением, приложения привяжут столбцы и параметры к программным переменным того же типа данных. Однако, если данные должны быть преобразованы из одного типа в другой, более эффективным будет преобразовать данные с помощью драйвера, чем делать это в приложении. Драйвер для собственного клиента ODBC SQL Server нормально только передает данные непосредственно из сетевых буферов в переменные приложения. Запроса драйверу на добавление преобразования данных приведет к буферизации данных драйвером и использованию времени ЦП для преобразования данных.

Программные переменные должны быть достаточно большими для того, чтобы сохранить данные, переданные в форме столбца, за исключением данных столбцов типа text, ntext и image. Если приложение пытается получить результирующий набор данных и сохранить его в переменную недостаточного размера, драйвер формирует предупреждение. Это заставит драйвер выделить память для сообщения, и драйвер и приложение будут вынуждены тратить время ЦП на обработку сообщения и ошибок. Приложение должно либо выделить достаточно большую переменную для сохранения полученных данных, либо использовать функцию SUBSTRING в списке выбора для уменьшения размера столбца в результирующем наборе.

Следует соблюдать осторожность при использовании SQL_C_DEFAULT для указания типа переменной C. SQL_C_DEFAULT указывает, что тип переменной C соответствует типу данных SQL столбца или параметра. Если SQL_C_DEFAULT указан для столбцов ntext, nchar или nvarchar, приложение возвращает данные в Юникоде. Это может привести к возникновению различным проблем, если приложение не было настроено для обработки данных в Юникоде. Такие же проблемы могут возникать при работе с типом данных uniqueidentifier (SQL_GUID).

Данные столбцов типа text, ntext и image обычно слишком большие для того, чтобы соответствовать одной программной переменной, и они обычно вычисляются при помощи функции SQLGetData вместо функции SQLBindCol. При использовании серверных курсоров драйвер для собственного клиента ODBC SQL Server оптимизирован, чтобы не передавать данные для несвязанных столбцов типа text, ntext или image в то время, как выбирается строка. Получение столбцов типа text, ntext или image с сервера не производится до тех пор, пока приложение не выполнит для столбца команду SQLGetData.

Эта оптимизация может применятся к приложениям таким образом, что никакие столбцы типа text, ntext или image не отображаются в то время, как пользователь прокручивает курсор вверх и вниз. После того как пользователь выберет строку, приложение может вызвать функцию SQLGetData для получения столбцов типа text, ntext или image. Это экономит передачу столбцов типа text, ntext или image для любой строки, которую пользователь не выбрал, и может сэкономить передачу очень большого объема данных.

См. также

Основные понятия