Función SQLSetPos

Conformidad
Versión introducida: Cumplimiento de estándares odbc 1.0: ODBC

Resumen
SQLSetPos establece la posición del cursor en un conjunto de filas y permite que una aplicación actualice los datos del conjunto de filas o actualice o elimine los datos del conjunto de resultados.

Sintaxis

  
SQLRETURN SQLSetPos(  
      SQLHSTMT        StatementHandle,  
      SQLSETPOSIROW   RowNumber,  
      SQLUSMALLINT    Operation,  
      SQLUSMALLINT    LockType);  

Argumentos

StatementHandle
[Entrada] Identificador de instrucción.

RowNumber
[Entrada] Posición de la fila del conjunto de filas en la que se va a realizar la operación especificada con el argumento Operation . Si RowNumber es 0, la operación se aplica a cada fila del conjunto de filas.

Para obtener más información, vea "Comentarios".

operación
[Entrada] Operación que se va a realizar:

SQL_POSITION SQL_REFRESH SQL_UPDATE SQL_DELETE

Nota

El valor de SQL_ADD para el argumento Operation ha quedado en desuso para ODBC 3.x. Los controladores ODBC 3.x tendrán que admitir SQL_ADD para la compatibilidad con versiones anteriores. Esta funcionalidad se ha reemplazado por una llamada a SQLBulkOperations por una operación de SQL_ADD. Cuando una aplicación ODBC 3.x funciona con un controlador ODBC 2.x , el Administrador de controladores asigna una llamada a SQLBulkOperations con una operación de SQL_ADD a SQLSetPos con una operación de SQL_ADD.

Para obtener más información, vea "Comentarios".

LockType
[Entrada] Especifica cómo bloquear la fila después de realizar la operación especificada en el argumento Operation .

SQL_LOCK_NO_CHANGE SQL_LOCK_EXCLUSIVE SQL_LOCK_UNLOCK

Para obtener más información, vea "Comentarios".

Devoluciones

SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NEED_DATA, SQL_STILL_EXECUTING, SQL_ERROR o SQL_INVALID_HANDLE.

Diagnóstico

Cuando SQLSetPos devuelve SQL_ERROR o SQL_SUCCESS_WITH_INFO, se puede obtener un valor SQLSTATE asociado llamando a SQLGetDiagRec con un HandleType de SQL_HANDLE_STMT y un identificador de StatementHandle. En la tabla siguiente se enumeran los valores SQLSTATE devueltos normalmente por SQLSetPos y se explica cada uno en el contexto de esta función; la notación "(DM)" precede a las descripciones de SQLSTATEs devueltas por el Administrador de controladores. El código de retorno asociado a cada valor SQLSTATE es SQL_ERROR, a menos que se indique lo contrario.

Para todos los SQLSTATEs que pueden devolver SQL_SUCCESS_WITH_INFO o SQL_ERROR (excepto 01xxx SQLSTATEs), SQL_SUCCESS_WITH_INFO se devuelve si se produce un error en una o varias filas de una operación de varias filas y SQL_ERROR se devuelve si se produce un error en una operación de una sola fila.

SQLSTATE Error Descripción
01000 Advertencia general Mensaje informativo específico del controlador. (Function devuelve SQL_SUCCESS_WITH_INFO).
01001 Conflicto de la operación del cursor El argumento Operation se SQL_DELETE o SQL_UPDATE, y no se eliminaron ni actualizaron filas ni más de una fila. (Para obtener más información sobre las actualizaciones de más de una fila, vea la descripción del atributo SQL_ATTR_SIMULATE_CURSOR en SQLSetStmtAttr). (Function devuelve SQL_SUCCESS_WITH_INFO).

El argumento Operation se SQL_DELETE o SQL_UPDATE, y se produjo un error en la operación debido a la simultaneidad optimista. (Function devuelve SQL_SUCCESS_WITH_INFO).
01004 Truncamiento derecho de datos de cadena El argumento Operation se SQL_REFRESH, y los datos binarios o de cadena devueltos para una columna o columnas con un tipo de datos de SQL_C_CHAR o SQL_C_BINARY provocaron el truncamiento de datos binarios no de caracteres noblank o no NULL.
01S01 Error en la fila El argumento RowNumber era 0 y se produjo un error en una o varias filas al realizar la operación especificada con el argumento Operation .

(SQL_SUCCESS_WITH_INFO se devuelve si se produce un error en una o varias filas de una operación de varias filas, pero no todas, y se devuelve SQL_ERROR si se produce un error en una operación de una sola fila).

(Esta instrucción SQLSTATE solo se devuelve cuando se llama a SQLSetPos después de SQLExtendedFetch, si el controlador es un controlador ODBC 2.x y no se usa la biblioteca de cursores).
01S07 Truncamiento fraccional El argumento Operation se SQL_REFRESH, el tipo de datos del búfer de aplicación no se SQL_C_CHAR ni SQL_C_BINARY, y los datos devueltos a los búferes de aplicación para una o varias columnas se truncaron. En el caso de los tipos de datos numéricos, la parte fraccionarcional del número se trunca. En el caso de los tipos de datos time, timestamp y interval que contienen un componente de hora, la parte fraccionarcional de la hora se trunca.

(Function devuelve SQL_SUCCESS_WITH_INFO).
07006 Infracción de atributo de tipo de datos restringido El valor de datos de una columna del conjunto de resultados no se pudo convertir en el tipo de datos especificado por TargetType en la llamada a SQLBindCol.
07009 Índice de descriptor no válido El argumento Operation se SQL_REFRESH o SQL_UPDATE, y una columna estaba enlazada con un número de columna mayor que el número de columnas del conjunto de resultados.
21S02 El grado de tabla derivada no coincide con la lista de columnas El argumento Operation se SQL_UPDATE y no se pudo actualizar ninguna columna porque todas las columnas no estaban enlazadas, de solo lectura o el valor del búfer de longitud o indicador enlazado se SQL_COLUMN_IGNORE.
22001 Datos de cadena, truncamiento derecho El argumento Operation se SQL_UPDATE y la asignación de un carácter o valor binario a una columna dio como resultado el truncamiento de caracteres noblank (para caracteres) o caracteres no NULL (para caracteres binarios) o bytes.
22003 Valor numérico fuera del intervalo El argumento Operation se SQL_UPDATE y la asignación de un valor numérico a una columna del conjunto de resultados provocó que toda la parte (en lugar de fraccionar) del número se truncase.

El argumento Operation se SQL_REFRESH y devolver el valor numérico de una o varias columnas enlazadas habría provocado una pérdida de dígitos significativos.
22007 Formato datetime no válido El argumento Operation se SQL_UPDATE y la asignación de un valor de fecha o marca de tiempo a una columna del conjunto de resultados hizo que el campo year, month o day estuviera fuera del intervalo.

El argumento Operation se SQL_REFRESH y devolver el valor de fecha o marca de tiempo de una o varias columnas enlazadas habría provocado que el campo year, month o day esté fuera del intervalo.
22008 Desbordamiento de campo de fecha y hora El argumento Operation se SQL_UPDATE, y el rendimiento de la aritmética datetime en los datos que se envían a una columna del conjunto de resultados dio lugar a un campo datetime (el campo year, month, day, hour, minute o second) del resultado que está fuera del intervalo permitido de valores para el campo o que no es válido en función de las reglas naturales del calendario gregoriano para datetimes.

El argumento Operation se SQL_REFRESH, y el rendimiento de la aritmética datetime en los datos que se recuperan del conjunto de resultados dio lugar a un campo datetime (el campo year, month, day, hour, minute o second) del resultado que está fuera del intervalo permitido de valores para el campo o que no es válido en función de las reglas naturales del calendario gregoriano para datetimes.
22015 Desbordamiento de campo de intervalo El argumento Operation se SQL_UPDATE y la asignación de un tipo numérico o intervalo exacto de C a un tipo de datos SQL interval causó una pérdida de dígitos significativos.

El argumento Operation se SQL_UPDATE; al asignar a un tipo SQL de intervalo, no había ninguna representación del valor del tipo C en el tipo SQL interval.

El argumento Operation se SQL_REFRESH y la asignación de un tipo SQL numérico o de intervalo exacto a un tipo C de intervalo causó una pérdida de dígitos significativos en el campo inicial.

El argumento Operation se SQL_ REFRESH; al asignar a un tipo de C de intervalo, no había ninguna representación del valor del tipo SQL en el tipo C del intervalo C.
22018 Valor de carácter no válido para la especificación de conversión Se SQL_REFRESH el argumento Operation ; el tipo C era un numérico exacto o aproximado, una fecha y hora o un tipo de datos interval; el tipo SQL de la columna era un tipo de datos de caracteres; y el valor de la columna no era un literal válido del tipo C enlazado.

El argumento Operación se SQL_UPDATE; el tipo SQL era un numérico exacto o aproximado, una fecha y hora o un tipo de datos interval; el tipo C se SQL_C_CHAR; y el valor de la columna no era un literal válido del tipo SQL enlazado.
23000 Infracción de restricción de integridad El argumento Operation se SQL_DELETE o SQL_UPDATE, y se infringió una restricción de integridad.
24000 Estado de cursor no válido StatementHandle estaba en un estado ejecutado, pero ningún conjunto de resultados estaba asociado a StatementHandle.

(DM) Se ha abierto un cursor en StatementHandle, pero no se ha llamado a SQLFetch o SQLFetchScroll .

Se había abierto un cursor en StatementHandle y se había llamado a SQLFetch o SQLFetchScroll , pero el cursor se colocaba antes del inicio del conjunto de resultados o después del final del conjunto de resultados.

El argumento Operation se SQL_DELETE, SQL_REFRESH o SQL_UPDATE, y el cursor se colocaba antes del inicio del conjunto de resultados o después del final del conjunto de resultados.
40001 Error de serialización La transacción se revierte debido a un interbloqueo de recursos con otra transacción.
40003 Finalización de instrucciones desconocida Error en la conexión asociada durante la ejecución de esta función y no se puede determinar el estado de la transacción.
42000 Error de sintaxis o infracción de acceso El controlador no pudo bloquear la fila según sea necesario para realizar la operación solicitada en el argumento Operation.

El controlador no pudo bloquear la fila como se solicitó en el argumento LockType.
44000 Infracción de WITH CHECK OPTION El argumento Operation se SQL_UPDATE y la actualización se realizó en una tabla vista o en una tabla derivada de la tabla vista que se creó especificando WITH CHECK OPTION, de modo que una o varias filas afectadas por la actualización ya no estarán presentes en la tabla vista.
HY000 Error general Se produjo un error para el que no había ningún SQLSTATE específico y para el que no se definió SQLSTATE específico de la implementación. El mensaje de error devuelto por SQLGetDiagRec en el búfer *MessageText describe el error y su causa.
HY001 Error de asignación de memoria El controlador no pudo asignar memoria necesaria para admitir la ejecución o finalización de la función.
HY008 Operación cancelada El procesamiento asincrónico se ha habilitado para StatementHandle. Se llamó a la función y antes de completar la ejecución, se llamó a SQLCancel o SQLCancelHandle en StatementHandle y, a continuación, se llamó a la función de nuevo en StatementHandle.

Se llamó a la función y antes de completar la ejecución, se llamó a SQLCancel o SQLCancelHandle en statementHandle desde un subproceso diferente en una aplicación multiproceso.
HY010 Error de secuencia de función (DM) Se llamó a una función de ejecución asincrónica para el identificador de conexión asociado a StatementHandle. Esta función asincrónica todavía se estaba ejecutando cuando se llamó a la función SQLSetPos.

(DM) El statementHandle especificado no estaba en un estado ejecutado. Se llamó a la función sin llamar primero a SQLExecDirect, SQLExecute o una función de catálogo.

(DM) Se llamó a una función de ejecución asincrónica (no esta) para StatementHandle y todavía se estaba ejecutando cuando se llamó a esta función.

(DM) se llamó a SQLExecute, SQLExecDirect, SQLBulkOperations o SQLSetPos para statementHandle y devolvió SQL_NEED_DATA. Se llamó a esta función antes de enviar datos para todos los parámetros o columnas de datos en ejecución.

(DM) El controlador era un controlador ODBC 2.x y se llamó a SQLSetPos para un StatementHandle después de llamar a SQLFetch .
HY011 El atributo no se puede establecer ahora (DM) El controlador era un controlador ODBC 2.x ; se estableció el atributo de instrucción SQL_ATTR_ROW_STATUS_PTR; a continuación, se llamó a SQLSetPos antes de llamar a SQLFetch, SQLFetchScroll o SQLExtendedFetch .
HY013 Error de administración de memoria No se pudo procesar la llamada de función porque no se pudo tener acceso a los objetos de memoria subyacentes, posiblemente debido a condiciones de memoria baja.
HY090 Longitud de búfer o cadena no válida El argumento Operation se SQL_UPDATE, un valor de datos era un puntero nulo y el valor de longitud de columna no era 0, SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NULL_DATA o menor o igual que SQL_LEN_DATA_AT_EXEC_OFFSET.

El argumento Operation se SQL_UPDATE; un valor de datos no era un puntero nulo; el tipo de datos C se SQL_C_BINARY o SQL_C_CHAR; y el valor de longitud de columna era menor que 0, pero no igual a SQL_DATA_AT_EXEC, SQL_COLUMN_IGNORE, SQL_NTS o SQL_NULL_DATA, o menor o igual que SQL_LEN_DATA_AT_EXEC_OFFSET.

El valor de un búfer de longitud/indicador se SQL_DATA_AT_EXEC; el tipo SQL era SQL_LONGVARCHAR, SQL_LONGVARBINARY o un tipo de datos largo específico del origen de datos; y el tipo de información SQL_NEED_LONG_DATA_LEN en SQLGetInfo era "Y".
HY092 Identificador de atributo no válido (DM) El valor especificado para el argumento Operation no era válido.

(DM) El valor especificado para el argumento LockType no era válido.

El argumento Operation se SQL_UPDATE o SQL_DELETE y el atributo de instrucción SQL_ATTR_CONCURRENCY se SQL_ATTR_CONCUR_READ_ONLY.
HY107 Valor de fila fuera del intervalo El valor especificado para el argumento RowNumber era mayor que el número de filas del conjunto de filas.
HY109 Posición del cursor no válida El cursor asociado a StatementHandle se definió como de solo avance, por lo que el cursor no se pudo colocar dentro del conjunto de filas. Vea la descripción del atributo SQL_ATTR_CURSOR_TYPE en SQLSetStmtAttr.

El argumento Operation se SQL_UPDATE, SQL_DELETE o SQL_REFRESH, y la fila identificada por el argumento RowNumber se había eliminado o no se había capturado.

(DM) El argumento RowNumber era 0 y el argumento Operation se SQL_POSITION.

Se llamó a SQLSetPos después de llamar a SQLBulkOperations y antes de llamar a SQLFetchScroll o SQLFetch.
HY117 La conexión se suspende debido al estado de transacción desconocido. Solo se permiten funciones de desconexión y de solo lectura. (DM) Para obtener más información sobre el estado suspendido, vea Función SQLEndTran.
HYC00 Característica opcional no implementada El controlador o el origen de datos no admiten la operación solicitada en el argumento Operation ni en el argumento LockType .
HYT00 Tiempo de espera agotado El período de tiempo de espera de la consulta expiró antes de que el origen de datos devolva el conjunto de resultados. El período de tiempo de espera se establece a través de SQLSetStmtAttr con un atributo de SQL_ATTR_QUERY_TIMEOUT.
HYT01 Se ha agotado el tiempo de espera de la conexión. El período de tiempo de espera de conexión expiró antes de que el origen de datos responda a la solicitud. El período de tiempo de espera de conexión se establece a través de SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT.
IM001 El controlador no admite esta función (DM) El controlador asociado a StatementHandle no admite la función .
IM017 El sondeo está deshabilitado en modo de notificación asincrónica Cada vez que se usa el modelo de notificación, el sondeo está deshabilitado.
IM018 No se ha llamado a SQLCompleteAsync para completar la operación asincrónica anterior en este identificador. Si la llamada de función anterior en el identificador devuelve SQL_STILL_EXECUTING y si el modo de notificación está habilitado, se debe llamar a SQLCompleteAsync en el identificador para realizar el posprocesamiento y completar la operación.

Comentarios

Precaución

Para obtener información sobre la instrucción indica que se puede llamar a SQLSetPos en y lo que debe hacer para la compatibilidad con las aplicaciones ODBC 2.x , vea Bloquear cursores, cursores desplazables y compatibilidad con versiones anteriores.

Argumento RowNumber

El argumento RowNumber especifica el número de la fila del conjunto de filas en el que se va a realizar la operación especificada por el argumento Operation . Si RowNumber es 0, la operación se aplica a cada fila del conjunto de filas. RowNumber debe ser un valor comprendido entre 0 y el número de filas del conjunto de filas.

Nota

En el lenguaje C, las matrices se basan en 0 y el argumento RowNumber se basa en 1. Por ejemplo, para actualizar la quinta fila del conjunto de filas, una aplicación modifica los búferes del conjunto de filas en el índice de matriz 4, pero especifica un valor RowNumber de 5.

Todas las operaciones colocan el cursor en la fila especificada por RowNumber. Las siguientes operaciones requieren una posición del cursor:

  • Instrucciones update y delete posicionadas.

  • Llama a SQLGetData.

  • Llama a SQLSetPos con las opciones de SQL_DELETE, SQL_REFRESH y SQL_UPDATE.

Por ejemplo, si RowNumber es 2 para una llamada a SQLSetPos con una operación de SQL_DELETE, el cursor se coloca en la segunda fila del conjunto de filas y se elimina esa fila. La entrada de la matriz de estado de fila de implementación (a la que apunta el atributo de instrucción SQL_ATTR_ROW_STATUS_PTR) de la segunda fila se cambia a SQL_ROW_DELETED.

Una aplicación puede especificar una posición de cursor cuando llama a SQLSetPos. Por lo general, llama a SQLSetPos con la operación SQL_POSITION o SQL_REFRESH para colocar el cursor antes de ejecutar una instrucción update o delete posicionada o llamando a SQLGetData.

Argumento operation

El argumento Operation admite las siguientes operaciones. Para determinar qué opciones admite un origen de datos, una aplicación llama a SQLGetInfo con el SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 o SQL_STATIC_CURSOR_ATTRIBUTES1 tipo de información (según el tipo de cursor).

operación

Argumento
Operación
SQL_POSITION El controlador coloca el cursor en la fila especificada por RowNumber.

El contenido de la matriz de estado de fila a la que apunta el atributo de instrucción SQL_ATTR_ROW_OPERATION_PTR se omite para la operación de SQL_POSITION.
SQL_REFRESH El controlador coloca el cursor en la fila especificada por RowNumber y actualiza los datos en los búferes del conjunto de filas para esa fila. Para obtener más información sobre cómo el controlador devuelve datos en los búferes del conjunto de filas, vea las descripciones del enlace de fila y de columna en SQLBindCol.

SQLSetPos con una operación de SQL_REFRESH actualiza el estado y el contenido de las filas dentro del conjunto de filas capturado actual. Esto incluye la actualización de los marcadores. Dado que los datos de los búferes se actualizan pero no se vuelven a capturar, la pertenencia al conjunto de filas es fija. Esto es diferente de la actualización realizada por una llamada a SQLFetchScroll con una FetchOrientation de SQL_FETCH_RELATIVE y rowNumber igual a 0, que vuelve a capturar el conjunto de filas del conjunto de resultados para que pueda mostrar datos agregados y quitar datos eliminados si el controlador y el cursor admiten esas operaciones.

Una actualización correcta con SQLSetPos no cambiará un estado de fila de SQL_ROW_DELETED. Las filas eliminadas dentro del conjunto de filas se seguirán marcando como eliminadas hasta la siguiente captura. Las filas desaparecerán en la siguiente captura si el cursor admite el empaquetado (en el que un sqlFetch o SQLFetchScroll posterior no devuelve filas eliminadas).

Las filas agregadas no aparecen cuando se realiza una actualización con SQLSetPos . Este comportamiento es diferente de SQLFetchScroll con un valor FetchType de SQL_FETCH_RELATIVE y rowNumber igual a 0, que también actualiza el conjunto de filas actual, pero mostrará registros agregados o registros eliminados del paquete si el cursor admite estas operaciones.

Una actualización correcta con SQLSetPos cambiará un estado de fila de SQL_ROW_ADDED a SQL_ROW_SUCCESS (si existe la matriz de estado de fila).

Una actualización correcta con SQLSetPos cambiará un estado de fila de SQL_ROW_UPDATED al nuevo estado de la fila (si existe la matriz de estado de fila).

Si se produce un error en una operación SQLSetPos en una fila, el estado de la fila se establece en SQL_ROW_ERROR (si existe la matriz de estado de fila).

En el caso de un cursor abierto con un atributo de instrucción SQL_ATTR_CONCURRENCY de SQL_CONCUR_ROWVER o SQL_CONCUR_VALUES, una actualización con SQLSetPos podría actualizar los valores de simultaneidad optimista utilizados por el origen de datos para detectar que la fila ha cambiado. Si esto ocurre, las versiones de fila o los valores usados para asegurarse de que la simultaneidad del cursor se actualiza cada vez que se actualizan los búferes del conjunto de filas desde el servidor. Esto ocurre para cada fila que se actualiza.

El contenido de la matriz de estado de fila a la que apunta el atributo de instrucción SQL_ATTR_ROW_OPERATION_PTR se omite para la operación de SQL_REFRESH.
SQL_UPDATE El controlador coloca el cursor en la fila especificada por RowNumber y actualiza la fila subyacente de datos con los valores de los búferes del conjunto de filas (el argumento TargetValuePtr en SQLBindCol). Recupera las longitudes de los datos de los búferes de longitud o indicador (el argumento StrLen_or_IndPtr en SQLBindCol). Si la longitud de cualquier columna es SQL_COLUMN_IGNORE, la columna no se actualiza. Después de actualizar la fila, el controlador cambia el elemento correspondiente de la matriz de estado de fila a SQL_ROW_UPDATED o SQL_ROW_SUCCESS_WITH_INFO (si existe la matriz de estado de fila).

Se define el comportamiento del controlador si se llama a SQLSetPos con un argumento Operation de SQL_UPDATE en un cursor que contiene columnas duplicadas. El controlador puede devolver un SQLSTATE definido por el controlador, puede actualizar la primera columna que aparece en el conjunto de resultados o realizar otro comportamiento definido por el controlador.

La matriz de operaciones de fila a la que apunta el atributo de instrucción SQL_ATTR_ROW_OPERATION_PTR se puede usar para indicar que se debe omitir una fila del conjunto de filas actual durante una actualización masiva. Para obtener más información, vea "Status and Operation Arrays" más adelante en esta referencia de función.
SQL_DELETE El controlador coloca el cursor en la fila especificada por RowNumber y elimina la fila subyacente de datos. Cambia el elemento correspondiente de la matriz de estado de fila a SQL_ROW_DELETED. Una vez eliminada la fila, las siguientes instrucciones no son válidas para la fila: instrucciones update y delete posicionadas, llamadas a SQLGetData y llamadas a SQLSetPos con Operation establecida en cualquier cosa excepto SQL_POSITION. Para los controladores que admiten el empaquetado, la fila se elimina del cursor cuando se recuperan nuevos datos del origen de datos.

Si la fila permanece visible depende del tipo de cursor. Por ejemplo, las filas eliminadas son visibles para cursores estáticos y controlados por conjuntos de claves, pero invisibles para los cursores dinámicos.

La matriz de operaciones de fila a la que apunta el atributo de instrucción SQL_ATTR_ROW_OPERATION_PTR se puede usar para indicar que se debe omitir una fila del conjunto de filas actual durante una eliminación masiva. Para obtener más información, vea "Status and Operation Arrays" más adelante en esta referencia de función.

Argumento LockType

El argumento LockType proporciona una manera de que las aplicaciones controlen la simultaneidad. En la mayoría de los casos, los orígenes de datos que admiten niveles de simultaneidad y transacciones solo admitirán el valor SQL_LOCK_NO_CHANGE del argumento LockType . El argumento LockType solo se usa normalmente para la compatibilidad basada en archivos.

El argumento LockType especifica el estado de bloqueo de la fila después de ejecutar SQLSetPos . Si el controlador no puede bloquear la fila para realizar la operación solicitada o para satisfacer el argumento LockType , devuelve SQL_ERROR y SQLSTATE 42000 (error de sintaxis o infracción de acceso).

Aunque se especifica el argumento LockType para una sola instrucción, el bloqueo concede los mismos privilegios a todas las instrucciones de la conexión. En concreto, un bloqueo adquirido por una instrucción en una conexión se puede desbloquear mediante una instrucción diferente en la misma conexión.

Una fila bloqueada a través de SQLSetPos permanece bloqueada hasta que la aplicación llama a SQLSetPos para la fila con LockType establecida en SQL_LOCK_UNLOCK, o hasta que la aplicación llame a SQLFreeHandle para la instrucción o SQLFreeStmt con la opción SQL_CLOSE. Para un controlador que admite transacciones, se desbloquea una fila bloqueada a través de SQLSetPos cuando la aplicación llama a SQLEndTran para confirmar o revertir una transacción en la conexión (si un cursor se cierra cuando se confirma o se revierte una transacción, como se indica en los tipos de información de SQL_CURSOR_COMMIT_BEHAVIOR y SQL_CURSOR_ROLLBACK_BEHAVIOR devueltos por SQLGetInfo).

El argumento LockType admite los siguientes tipos de bloqueos. Para determinar qué bloqueos son compatibles con un origen de datos, una aplicación llama a SQLGetInfo con el SQL_DYNAMIC_CURSOR_ATTRIBUTES1, SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1, SQL_KEYSET_CURSOR_ATTRIBUTES1 o SQL_STATIC_CURSOR_ATTRIBUTES1 tipo de información (según el tipo del cursor).

Argumento LockType Tipo de bloqueo
SQL_LOCK_NO_CHANGE El controlador o el origen de datos garantiza que la fila está en el mismo estado bloqueado o desbloqueado que antes de llamar a SQLSetPos . Este valor de LockType permite que los orígenes de datos que no admitan el bloqueo explícito de nivel de fila usen cualquier bloqueo requerido por los niveles de aislamiento de transacciones y simultaneidad actuales.
SQL_LOCK_EXCLUSIVE El controlador o el origen de datos bloquea la fila exclusivamente. No se puede usar una instrucción en una conexión diferente o en otra aplicación para adquirir ningún bloqueo en la fila.
SQL_LOCK_UNLOCK El controlador o el origen de datos desbloquea la fila.

Si un controlador admite SQL_LOCK_EXCLUSIVE pero no admite SQL_LOCK_UNLOCK, una fila bloqueada permanecerá bloqueada hasta que se produzca una de las llamadas de función descritas en el párrafo anterior.

Si un controlador admite SQL_LOCK_EXCLUSIVE pero no admite SQL_LOCK_UNLOCK, una fila bloqueada permanecerá bloqueada hasta que la aplicación llame a SQLFreeHandle para la instrucción o SQLFreeStmt con la opción SQL_CLOSE. Si el controlador admite transacciones y cierra el cursor al confirmar o revertir la transacción, la aplicación llama a SQLEndTran.

Para las operaciones de actualización y eliminación en SQLSetPos, la aplicación usa el argumento LockType de la siguiente manera:

  • Para garantizar que una fila no cambia después de recuperarla, una aplicación llama a SQLSetPos con Operation establecido en SQL_REFRESH y LockType establecido en SQL_LOCK_EXCLUSIVE.

  • Si la aplicación establece LockType en SQL_LOCK_NO_CHANGE, el controlador garantiza que una operación de actualización o eliminación solo se realizará correctamente si la aplicación especificó SQL_CONCUR_LOCK para el atributo de instrucción SQL_ATTR_CONCURRENCY.

  • Si la aplicación especifica SQL_CONCUR_ROWVER o SQL_CONCUR_VALUES para el atributo de instrucción SQL_ATTR_CONCURRENCY, el controlador compara las versiones de fila o los valores y rechaza la operación si la fila ha cambiado desde que la aplicación capturó la fila.

  • Si la aplicación especifica SQL_CONCUR_READ_ONLY para el atributo de instrucción SQL_ATTR_CONCURRENCY, el controlador rechaza cualquier operación de actualización o eliminación.

Para obtener más información sobre el atributo de instrucción SQL_ATTR_CONCURRENCY, vea SQLSetStmtAttr.

Matrices de estado y operación

Las matrices de operaciones y de estado siguientes se usan al llamar a SQLSetPos:

  • La matriz de estado de fila (como apunta el campo SQL_DESC_ARRAY_STATUS_PTR en el IRD y el atributo de instrucción SQL_ATTR_ROW_STATUS_ARRAY) contiene valores de estado para cada fila de datos del conjunto de filas. El controlador establece los valores de estado de esta matriz después de una llamada a SQLFetch, SQLFetchScroll, SQLBulkOperations o SQLSetPos. El atributo de instrucción SQL_ATTR_ROW_STATUS_PTR apunta a esta matriz.

  • La matriz de operaciones de fila (como señala el campo SQL_DESC_ARRAY_STATUS_PTR en el ARD y el atributo de instrucción SQL_ATTR_ROW_OPERATION_ARRAY) contiene un valor para cada fila del conjunto de filas que indica si se omite o se realiza una llamada a SQLSetPos para una operación masiva. Cada elemento de la matriz se establece en SQL_ROW_PROCEED (valor predeterminado) o SQL_ROW_IGNORE. El atributo de instrucción SQL_ATTR_ROW_OPERATION_PTR apunta a esta matriz.

El número de elementos de las matrices de estado y operación debe ser igual al número de filas del conjunto de filas (tal como se define en el atributo de instrucción SQL_ATTR_ROW_ARRAY_SIZE).

Para obtener información sobre la matriz de estado de fila, vea SQLFetch. Para obtener información sobre la matriz de operaciones de fila, vea "Omitir una fila en una operación masiva", más adelante en esta sección.

Uso de SQLSetPos

Antes de que una aplicación llame a SQLSetPos, debe realizar la siguiente secuencia de pasos:

  1. Si la aplicación llamará a SQLSetPos con Operation establecida en SQL_UPDATE, llame a SQLBindCol (o SQLSetDescRec) para cada columna para especificar su tipo de datos y enlazar búferes para los datos y la longitud de la columna.

  2. Si la aplicación llamará a SQLSetPos con Operation establecida en SQL_DELETE o SQL_UPDATE, llame a SQLColAttribute para asegurarse de que las columnas que se van a eliminar o actualizar son actualizables.

  3. Llame a SQLExecDirect, SQLExecute o una función de catálogo para crear un conjunto de resultados.

  4. Llame a SQLFetch o SQLFetchScroll para recuperar los datos.

Para obtener más información sobre el uso de SQLSetPos, vea Actualización de datos con SQLSetPos.

Eliminación de datos mediante SQLSetPos

Para eliminar datos con SQLSetPos, una aplicación llama a SQLSetPos con RowNumber establecido en el número de la fila que se va a eliminar y operación establecida en SQL_DELETE.

Una vez eliminados los datos, el controlador cambia el valor de la matriz de estado de fila de implementación para la fila adecuada a SQL_ROW_DELETED (o SQL_ROW_ERROR).

Actualización de datos mediante SQLSetPos

Una aplicación puede pasar el valor de una columna en el búfer de datos enlazado o con una o varias llamadas a SQLPutData. Las columnas cuyos datos se pasan con SQLPutData se conocen como columnasde datos en ejecución. Estos se usan normalmente para enviar datos para SQL_LONGVARBINARY y SQL_LONGVARCHAR columnas y se pueden mezclar con otras columnas.

Para actualizar datos con SQLSetPos, una aplicación:

  1. Coloca valores en los búferes de datos y longitud/indicador enlazados con SQLBindCol:

    • Para las columnas normales, la aplicación coloca el nuevo valor de columna en el búfer *TargetValuePtr y la longitud de ese valor en el búfer *StrLen_or_IndPtr . Si no se debe actualizar la fila, la aplicación coloca SQL_ROW_IGNORE en el elemento de esa fila de la matriz de operaciones de fila.

    • Para las columnas de datos en ejecución, la aplicación coloca un valor definido por la aplicación, como el número de columna, en el búfer *TargetValuePtr . El valor se puede usar más adelante para identificar la columna.

      La aplicación coloca el resultado de la macro SQL_LEN_DATA_AT_EXEC(length) en el búfer *StrLen_or_IndPtr . Si el tipo de datos SQL de la columna es SQL_LONGVARBINARY, SQL_LONGVARCHAR o un tipo de datos específico del origen de datos largo y el controlador devuelve "Y" para el tipo de información de SQL_NEED_LONG_DATA_LEN en SQLGetInfo, la longitud es el número de bytes de datos que se enviarán para el parámetro; de lo contrario, debe ser un valor no negativo y se omite.

  2. Llama a SQLSetPos con el argumento Operation establecido en SQL_UPDATE para actualizar la fila de datos.

    • Si no hay columnas de datos en ejecución, el proceso se completa.

    • Si hay columnas de datos en ejecución, la función devuelve SQL_NEED_DATA y continúa con el paso 3.

  3. Llama a SQLParamData para recuperar la dirección del búfer *TargetValuePtr para procesar la primera columna de datos en ejecución. SQLParamData devuelve SQL_NEED_DATA. La aplicación recupera el valor definido por la aplicación del búfer *TargetValuePtr .

    Nota

    Aunque los parámetros data-at-execution son similares a las columnas data-at-execution, el valor devuelto por SQLParamData es diferente para cada uno.

    Nota

    Los parámetros data-at-execution son parámetros en una instrucción SQL para la que los datos se enviarán con SQLPutData cuando la instrucción se ejecute con SQLExecDirect o SQLExecute. Se enlazan con SQLBindParameter o estableciendo descriptores con SQLSetDescRec. El valor devuelto por SQLParamData es un valor de 32 bits pasado a SQLBindParameter en el argumento ParameterValuePtr .

    Nota

    Las columnas de datos en ejecución son columnas de un conjunto de filas para las que se enviarán datos con SQLPutData cuando se actualice una fila con SQLSetPos. Se enlazan con SQLBindCol. El valor devuelto por SQLParamData es la dirección de la fila del búfer *TargetValuePtr que se está procesando.

  4. Llama a SQLPutData una o varias veces para enviar datos para la columna. Se necesita más de una llamada si no se pueden devolver todos los valores de datos en el búfer *TargetValuePtr especificado en SQLPutData; solo se permiten varias llamadas a SQLPutData para la misma columna cuando se envían datos de caracteres C a una columna con un tipo de datos específico del origen de datos, binarios o caracteres, o cuando se envían datos binarios de C a una columna con un tipo de datos específico del origen de datos, binarios o caracteres.

  5. Llama a SQLParamData de nuevo para indicar que se han enviado todos los datos para la columna.

    • Si hay más columnas de datos en ejecución, SQLParamData devuelve SQL_NEED_DATA y la dirección del búfer TargetValuePtr para la siguiente columna de datos en ejecución que se va a procesar. La aplicación repite los pasos 4 y 5.

    • Si no hay más columnas de datos en ejecución, el proceso se completa. Si la instrucción se ejecutó correctamente, SQLParamData devuelve SQL_SUCCESS o SQL_SUCCESS_WITH_INFO; si se produjo un error en la ejecución, devuelve SQL_ERROR. En este momento, SQLParamData puede devolver cualquier SQLSTATE que SQLSetPos pueda devolver.

Si se han actualizado los datos, el controlador cambia el valor de la matriz de estado de fila de implementación para la fila adecuada a SQL_ROW_UPDATED.

Si se cancela la operación o se produce un error en SQLParamData o SQLPutData, después de que SQLSetPos devuelva SQL_NEED_DATA y antes de que se envíen datos para todas las columnas de datos en ejecución, la aplicación solo puede llamar a SQLCancel, SQLGetDiagField, SQLGetDiagRec, SQLGetFunctions, SQLParamData o SQLPutData para la instrucción o la conexión asociada a la instrucción . Si llama a cualquier otra función para la instrucción o la conexión asociada a la instrucción , la función devuelve SQL_ERROR y SQLSTATE HY010 (error de secuencia de función).

Si la aplicación llama a SQLCancel mientras el controlador sigue necesitando datos para las columnas de datos en ejecución, el controlador cancela la operación. Después, la aplicación puede llamar a SQLSetPos de nuevo; la cancelación no afecta al estado del cursor ni a la posición actual del cursor.

Cuando la lista SELECT de la especificación de consulta asociada al cursor contiene más de una referencia a la misma columna, si se genera un error o el controlador omite las referencias duplicadas y realiza las operaciones solicitadas está definida por el controlador.

Realización de operaciones masivas

Si el argumento RowNumber es 0, el controlador realiza la operación especificada en el argumento Operation para cada fila del conjunto de filas que tiene un valor de SQL_ROW_PROCEED en su campo de la matriz de operaciones de fila a la que apunta SQL_ATTR_ROW_OPERATION_PTR atributo de instrucción. Se trata de un valor válido del argumento RowNumber para un argumento Operation de SQL_DELETE, SQL_REFRESH o SQL_UPDATE, pero no SQL_POSITION. SQLSetPos con una operación de SQL_POSITION y rowNumber igual a 0 devolverá SQLSTATE HY109 (posición del cursor no válida).

Si se produce un error que pertenece a todo el conjunto de filas, como SQLSTATE HYT00 (ha expirado el tiempo de espera), el controlador devuelve SQL_ERROR y el SQLSTATE adecuado. El contenido de los búferes del conjunto de filas no está definido y la posición del cursor no cambia.

Si se produce un error que pertenece a una sola fila, el controlador:

  • Establece el elemento de la fila de la matriz de estado de fila al que apunta el atributo de instrucción SQL_ATTR_ROW_STATUS_PTR en SQL_ROW_ERROR.

  • Publica uno o varios SQLSTATEs adicionales para el error en la cola de errores y establece el campo SQL_DIAG_ROW_NUMBER en la estructura de datos de diagnóstico.

Después de procesar el error o la advertencia, si el controlador completa la operación de las filas restantes del conjunto de filas, devuelve SQL_SUCCESS_WITH_INFO. Por lo tanto, para cada fila que devolvió un error, la cola de errores contiene cero o más SQLSTATEs adicionales. Si el controlador detiene la operación después de haber procesado el error o la advertencia, devuelve SQL_ERROR.

Si el controlador devuelve advertencias, como SQLSTATE 01004 (truncado de datos), devuelve advertencias que se aplican a todo el conjunto de filas o a filas desconocidas del conjunto de filas antes de que devuelva la información de error que se aplica a filas específicas. Devuelve advertencias para filas específicas junto con cualquier otra información de error sobre esas filas.

Si RowNumber es igual a 0 y Operation es SQL_UPDATE, SQL_REFRESH o SQL_DELETE, el número de filas en las que funciona SQLSetPos apunta al atributo de instrucción SQL_ATTR_ROWS_FETCHED_PTR.

Si RowNumber es igual a 0 y Operation es SQL_DELETE, SQL_REFRESH o SQL_UPDATE, la fila actual después de la operación es la misma que la fila actual antes de la operación.

Omitir una fila en una operación masiva

La matriz de operaciones de fila se puede usar para indicar que se debe omitir una fila del conjunto de filas actual durante una operación masiva mediante SQLSetPos. Para dirigir al controlador que omita una o varias filas durante una operación masiva, una aplicación debe realizar los pasos siguientes:

  1. Llame a SQLSetStmtAttr para establecer el atributo de instrucción SQL_ATTR_ROW_OPERATION_PTR para que apunte a una matriz de SQLUSMALLINTs. Este campo también se puede establecer llamando a SQLSetDescField para establecer el campo de encabezado SQL_DESC_ARRAY_STATUS_PTR de ARD, que requiere que una aplicación obtenga el identificador del descriptor.

  2. Establezca cada elemento de la matriz de operaciones de fila en uno de los dos valores:

    • SQL_ROW_IGNORE, para indicar que la fila se excluye para la operación masiva.

    • SQL_ROW_PROCEED, para indicar que la fila se incluye en la operación masiva. Este es el valor predeterminado.

  3. Llame a SQLSetPos para realizar la operación masiva.

Las reglas siguientes se aplican a la matriz de operaciones de fila:

  • SQL_ROW_IGNORE y SQL_ROW_PROCEED afectan solo a las operaciones masivas que usan SQLSetPos con una operación de SQL_DELETE o SQL_UPDATE. No afectan a las llamadas a SQLSetPos con una operación de SQL_REFRESH o SQL_POSITION.

  • El puntero se establece en NULL de forma predeterminada.

  • Si el puntero es null, todas las filas se actualizan como si todos los elementos estuvieran establecidos en SQL_ROW_PROCEED.

  • Establecer un elemento en SQL_ROW_PROCEED no garantiza que la operación se produzca en esa fila determinada. Por ejemplo, si una determinada fila del conjunto de filas tiene el estado SQL_ROW_ERROR, es posible que el controlador no pueda actualizar esa fila independientemente de si la aplicación especificó SQL_ROW_PROCEED. Una aplicación siempre debe comprobar la matriz de estado de fila para ver si la operación se realizó correctamente.

  • SQL_ROW_PROCEED se define como 0 en el archivo de encabezado. Una aplicación puede inicializar la matriz de operaciones de fila en 0 para procesar todas las filas.

  • Si el número de elemento "n" de la matriz de operaciones de fila se establece en SQL_ROW_IGNORE y se llama a SQLSetPos para realizar una operación de actualización o eliminación masivas, la nª fila del conjunto de filas permanece sin cambios después de la llamada a SQLSetPos.

  • Una aplicación debe establecer automáticamente una columna de solo lectura en SQL_ROW_IGNORE.

Omitir una columna en una operación masiva

Para evitar diagnósticos de procesamiento innecesarios generados por las actualizaciones intentadas en una o varias columnas de solo lectura, una aplicación puede establecer el valor en el búfer de longitud o indicador enlazado en SQL_COLUMN_IGNORE. Para obtener más información, vea SQLBindCol.

Ejemplo de código

En el ejemplo siguiente, una aplicación permite a un usuario examinar la tabla ORDERS y actualizar el estado del pedido. El cursor está controlado por conjuntos de claves con un tamaño de conjunto de filas de 20 y usa el control de simultaneidad optimista que compara las versiones de fila. Después de capturar cada conjunto de filas, la aplicación la imprime y permite al usuario seleccionar y actualizar el estado de un pedido. La aplicación usa SQLSetPos para colocar el cursor en la fila seleccionada y realiza una actualización posicionada de la fila. (Se omite el control de errores para mayor claridad).

#define ROWS 20  
#define STATUS_LEN 6  
  
SQLCHAR        szStatus[ROWS][STATUS_LEN], szReply[3];  
SQLINTEGER     cbStatus[ROWS], cbOrderID;  
SQLUSMALLINT   rgfRowStatus[ROWS];  
SQLUINTEGER    sOrderID, crow = ROWS, irow;  
SQLHSTMT       hstmtS, hstmtU;  
  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) rgfRowStatus, 0);  
SQLSetCursorName(hstmtS, "C1", SQL_NTS);  
SQLExecDirect(hstmtS, "SELECT ORDERID, STATUS FROM ORDERS ", SQL_NTS);  
  
SQLBindCol(hstmtS, 1, SQL_C_ULONG, &sOrderID, 0, &cbOrderID);  
SQLBindCol(hstmtS, 2, SQL_C_CHAR, szStatus, STATUS_LEN, &cbStatus);  
  
while ((retcode == SQLFetchScroll(hstmtS, SQL_FETCH_NEXT, 0)) != SQL_ERROR) {  
   if (retcode == SQL_NO_DATA_FOUND)  
      break;  
   for (irow = 0; irow < crow; irow++) {  
      if (rgfRowStatus[irow] != SQL_ROW_DELETED)  
         printf("%2d %5d %*s\n", irow+1, sOrderID, NAME_LEN-1, szStatus[irow]);  
   }  
   while (TRUE) {  
      printf("\nRow number to update?");  
      gets_s(szReply, 3);  
      irow = atoi(szReply);  
      if (irow > 0 && irow <= crow) {  
         printf("\nNew status?");  
         gets_s(szStatus[irow-1], (ROWS * STATUS_LEN));  
         SQLSetPos(hstmtS, irow, SQL_POSITION, SQL_LOCK_NO_CHANGE);  
         SQLPrepare(hstmtU,  
          "UPDATE ORDERS SET STATUS=? WHERE CURRENT OF C1", SQL_NTS);  
         SQLBindParameter(hstmtU, 1, SQL_PARAM_INPUT,  
            SQL_C_CHAR, SQL_CHAR,  
            STATUS_LEN, 0, szStatus[irow], 0, NULL);  
         SQLExecute(hstmtU);  
      } else if (irow == 0) {  
         break;  
      }  
   }  
}  

Para obtener más ejemplos, vea Instrucciones de actualización y eliminación posicionadas yactualización de filas en el conjunto de filas con SQLSetPos.

Para información acerca de Vea
Enlace de un búfer a una columna de un conjunto de resultados SQLBindCol (función)
Realizar operaciones masivas que no se relacionan con la posición del cursor de bloque Función SQLBulkOperations
Cancelación del procesamiento de instrucciones Función SQLCancel
Capturar un bloque de datos o desplazarse por un conjunto de resultados Función SQLFetchScroll
Obtener un único campo de un descriptor Función SQLGetDescField
Obtención de varios campos de un descriptor Función SQLGetDescRec
Establecer un único campo de un descriptor Función SQLSetDescField
Establecimiento de varios campos de un descriptor Función SQLSetDescRec
Establecimiento de un atributo de instrucción Función SQLSetStmtAttr

Consulte también

Referencia de API ODBC
Archivos de encabezado de ODBC