Capturar datos de resultados

Una aplicación ODBC tiene tres opciones para capturar los datos de resultados.

La primera opción está basada en SQLBindCol. Antes de capturar el conjunto de resultados, la aplicación usa SQLBindCol para enlazar cada columna del conjunto de resultados a una variable de programa. Una vez enlazadas las columnas, el controlador transfiere los datos de la fila actual en las variables enlazadas a las columnas de conjunto de resultados cada vez que la aplicación llama a SQLFetch o a SQLFetchScroll. El controlador administra las conversiones de datos si la columna de conjunto de resultados y la variable de programa tienen tipos de datos distintos. Si la aplicación tiene establecido SQL_ATTR_ROW_ARRAY_SIZE en un valor mayor que 1, puede enlazar las columnas de resultado a las matrices de variables, que se llenarán todas en cada llamada a SQLFetchScroll.

La segunda opción está basada en SQLGetData. La aplicación no utiliza SQLBindCol para enlazar las columnas de conjunto de resultados a las variables de programa. Después de cada llamada a SQLFetch, la aplicación llama una vez a SQLGetData para cada columna del conjunto de resultados. SQLGetData indica al controlador que transfiera los datos de una columna de conjunto de resultados concreta a una variable de programa concreta y especifica los tipos de datos de la columna y de la variable. Esto permite al controlador convertir los datos si la columna de resultado y la variable de programa tienen tipos de datos distintos. Las columnas text, ntext e image son normalmente demasiado grandes para caber en una variable de programa pero se pueden recuperar todavía con SQLGetData. Si los datos text, ntext o image de la columna de resultado son mayores que la variable de programa, SQLGetData devuelve SQL_SUCCESS_WITH_INFO y SQLSTATE 01004 (datos de cadena, truncados a la derecha). Las llamadas sucesivas a SQLGetData devuelven los fragmentos sucesivos de los datos text o image. Cuando se llega al final de los datos, SQLGetData devuelve SQL_SUCCESS. Cada captura devuelve un conjunto de filas, si SQL_ATTR_ROW_ARRAY_SIZE es mayor que 1. Antes de usar SQLGetData, debe usar primero SQLSetPos para especificar una fila concreta dentro del conjunto de filas como la fila actual.

La tercera opción es utilizar una combinación de SQLBindCol y SQLGetData. Por ejemplo, una aplicación podría enlazar las diez primeras columnas de un conjunto de resultados y, a continuación, en cada captura, llamar a SQLGetData tres veces para recuperar los datos de tres columnas independientes. Esto se utilizaría normalmente cuando un conjunto de resultados contiene una o varias columnas text o image.

Dependiendo del conjunto de opciones de cursor para el conjunto de resultados, una aplicación puede utilizar también las opciones de desplazamiento de SQLFetchScroll para desplazarse en el conjunto de resultados.

El uso excesivo de SQLBindCol para enlazar una columna de conjunto de resultados a una variable de programa es caro porque SQLBindCol hace que un controlador ODBC asigne memoria. Al enlazar una columna de resultado a una variable, ese enlace permanece en vigor hasta que llame a SQLFreeHandle para liberar el identificador de instrucciones o llame a SQLFreeStmt con fOption establecida en SQL_UNBIND. Los enlaces no se deshacen automáticamente cuando se completa la instrucción.

Esta lógica le permite solucionar eficazmente la ejecución de la misma instrucción SELECT varias veces con parámetros diferentes. Dado que el conjunto de resultados mantiene la misma estructura, puede enlazar una vez el conjunto de resultados, procesar todas las instrucciones SELECT y llamar a SQLFreeStmt con fOption establecido en SQL_UNBIND después de la última ejecución. No debe llamar a SQLBindCol para enlazar las columnas de un conjunto de resultados sin antes llamar a SQLFreeStmt con fOption establecido en SQL_UNBIND para liberar cualquier enlace anterior.

Al utilizar SQLBindCol, puede hacer un enlace de modo de fila o de modo de columna. El enlace de modo de fila es algo más rápido que el enlace de modo de columna.

Puede utilizar SQLGetData para recuperar los datos columna a columna en lugar de enlazar las columnas de conjunto de resultados mediante SQLBindCol. Si un conjunto de resultados contiene sólo algunas filas, el uso de SQLGetData en lugar de SQLBindCol es más rápido; si no, SQLBindCol proporciona el máximo rendimiento. Si no siempre coloca los datos en el mismo conjunto de variables, debe utilizar SQLGetData en lugar de volver a enlazar constantemente. Sólo puede utilizar SQLGetData en las columnas que están en la lista de selección una vez enlazadas todas las columnas con SQLBindCol. La columna debe aparecer también después de las columnas en las que ya haya utilizado SQLGetData.

Las funciones ODBC que solucionan el traslado de datos a o desde variables de programa, como SQLGetData, SQLBindCol y SQLBindParameter, admiten la conversión implícita de tipos de datos. Por ejemplo, si una aplicación enlaza una columna entera a una variable de programa de cadena de caracteres, el controlador convierte automáticamente los datos enteros en caracteres antes de incluirlos en la variable de programa.

Se debe minimizar la conversión de los datos en las aplicaciones. A menos que se requiera la conversión de datos para el procesamiento realizado por la aplicación, las aplicaciones deben enlazar las columnas y los parámetros a las variables de programa del mismo tipo de datos. Si los datos se deben convertir de un tipo a otro, sin embargo, es más eficaz hacer que el controlador haga la conversión que hacerla en la aplicación. El controlador ODBC de SQL Server Native Client normalmente sólo transfiere directamente los datos desde los búferes de la red a las variables de la aplicación. La solicitud al controlador de realizar la conversión de datos fuerza al controlador a almacenar en búfer los datos y usar los ciclos de CPU para convertir los datos.

Las variables de programa deben tener un tamaño suficiente para contener los datos transferidos desde una columna, salvo los datos text, ntext e image. Si una aplicación intenta recuperar datos del conjunto de resultados y colocarlos en una variable que es demasiado pequeña para contenerlos, el controlador genera una advertencia. Esto obliga al controlador a asignar memoria para el mensaje y los dos, el controlador y la aplicación, tienen que utilizar ciclos de CPU para procesar el mensaje y realizar el tratamiento de errores. La aplicación debe asignar una variable bastante grande para contener los datos que se van a recuperar o usar la función SUBSTRING de la lista de selección para reducir el tamaño de la columna del conjunto de resultados.

Se deben extremar las precauciones al utilizar SQL_C_DEFAULT para especificar el tipo de la variable C. SQL_C_DEFAULT especifica que el tipo de la variable C coincide con el tipo de datos SQL de la columna o parámetro. Si se especifica SQL_C_DEFAULT para las columnas ntext, nchar o nvarchar, se devuelven datos Unicode a la aplicación. Esto puede producir varios problemas si la aplicación no ha estado codificada para administrar los datos Unicode. Los mismos tipos de problemas se pueden producir con el tipo de datos uniqueidentifier (SQL_GUID).

Los datos text, ntext e image son habitualmente demasiado grandes para caber en una sola variable de programa y normalmente se procesan con SQLGetData en lugar de SQLBindCol. Al utilizar los cursores del servidor, el controlador ODBC de SQL Server Native Client se optimiza para no transmitir las columnas text, ntext o image independientes en el momento en que se captura la fila. Los datos text, ntext o image en realidad no se recuperan del servidor hasta que la aplicación emite SQLGetData para la columna.

Esta optimización se puede aplicar a las aplicaciones para que ningún dato text, ntext o image se muestre cuando un usuario desplaza hacia arriba o abajo el cursor. Después de que el usuario selecciona una fila, la aplicación puede llamar a SQLGetData para recuperar los datos text, ntext o image. Esto ahorra la transmisión de datos text, ntext o image de las filas que el usuario no selecciona y puede ahorrar la transmisión de cantidades muy grandes de datos.

Vea también

Conceptos