Compartir vía


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 a una aplicación actualizar los datos del conjunto de filas o actualizar o eliminar datos en el conjunto de resultados.

Sintaxis

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

Argumentos

StatementHandle
[Entrada] Identificador de instrucciones.

RowNumber
[Entrada] Posición de la fila del conjunto de filas en el 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 SQLSTATE que pueden devolver SQL_SUCCESS_WITH_INFO o SQL_ERROR (excepto 01xxx SQLSTATEs), se devuelve SQL_SUCCESS_WITH_INFO si se produce un error en una o varias filas de una operación multirow y se devuelve SQL_ERROR 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, consulte la descripción de la SQL_ATTR_SIMULATE_CURSOR Atributo en SQLSetStmtAttr.) (La función 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 nulos o caracteres no nulos.
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 multirow, pero no todas, y se devuelve SQL_ERROR si se produce un error en una operación de una sola fila).

(Este valor 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 fraccionario El argumento Operation se SQL_REFRESH, el tipo de datos del búfer de la 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. Para los tipos de datos numéricos, la parte fraccionaria del número se ha truncado. En el caso de los tipos de datos time, timestamp y interval que contienen un componente de hora, se trunca la parte fraccionaria de la hora.

(Function devuelve SQL_SUCCESS_WITH_INFO).
07006 Infracción de atributo de tipo de datos restringido No se pudo convertir el valor de datos de una columna del conjunto de resultados 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 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 fraccionaria) del número se truncase.

El argumento Operation se SQL_REFRESH y devolver el valor numérico para una o varias columnas enlazadas habría causado 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 provocó 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 para una o varias columnas enlazadas habría provocado que el campo year, month o day estuviera fuera del intervalo.
22008 Desbordamiento de campos 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 año, mes, día, hora, minuto o segundo campo) del resultado que está fuera del intervalo permitido de valores para el campo, o no es válido en función de las reglas naturales del calendario gregoriano para las fechas y horas.

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 año, mes, día, hora, minuto o segundo) 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 las fechas y horas.
22015 Desbordamiento de campo de intervalo El argumento Operation se SQL_UPDATE y la asignación de un tipo numérico exacto o de intervalo C a un tipo de datos SQL interval provocó 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 provocó una pérdida de dígitos significativos en el campo inicial.

El argumento Operation se SQL_ REFRESH; al asignar a un tipo de intervalo C, 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 El argumento Operation se SQL_REFRESH; el tipo C era un numérico exacto o aproximado, un tipo de datos datetime 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 Operation se SQL_UPDATE; el tipo SQL era un numérico exacto o aproximado, un tipo de datos datetime o un intervalo; 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 ha abierto un cursor en StatementHandle y se ha llamado a SQLFetch o SQLFetchScroll, pero el cursor se ha colocado 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 colocó 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.
44 000 Infracción de WITH CHECK OPTION El argumento Operation se SQL_UPDATE y la actualización se realizó en una tabla vista o 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 funciones (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 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 que ejecuta de forma 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 el 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 específico del origen de datos largo; 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. Consulte 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 las funciones de desconexión y 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 Se ha agotado el tiempo de espera 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 respondiera 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 procesamiento posterior 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 necesita 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 de 0 al número de filas del conjunto de filas.

Nota:

En el lenguaje C, las matrices se basan en 0 y el argumento RowNumber está basado 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 de cursor:

  • Instrucciones update y delete posicionadas.

  • Llama a SQLGetData.

  • Llama a SQLSetPos con las opciones 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 esa fila se elimina. 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 de actualización o eliminación 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 del cursor).

Operación

argument
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 de 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 filas y de columnas 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 actualizar los marcadores. Dado que los datos de los búferes se actualizan pero no se vuelven a capturar, se fija la pertenencia al conjunto de filas. Esto es diferente de la actualización realizada por una llamada a SQLFetchScroll con 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 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 una instrucción 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 FetchType de SQL_FETCH_RELATIVE y rowNumber igual a 0, que también actualiza el conjunto de filas actual, pero mostrará registros agregados o paquetes eliminados 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).

Para 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 garantizar que la simultaneidad del cursor se actualice cada vez que se actualicen 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 una instancia de SQLSTATE definida 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 establecidas 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 se cierra un cursor cuando se confirma o se revierte una transacción, como se indica en el SQL_CURSOR_COMMIT_BEHAVIOR y SQL_CURSOR_ROLLBACK_BEHAVIOR tipos de información 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 (dependiendo del tipo de cursor).

Argumento LockType Tipo de bloqueo
SQL_LOCK_NO_CHANGE El controlador o el origen de datos garantizan que la fila esté en el mismo estado bloqueado o desbloqueado que antes de llamar a SQLSetPos . Este valor de LockType permite a los orígenes de datos que no admiten el bloqueo explícito de nivel de fila para usar cualquier bloqueo que requieran 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 se realizará correctamente solo 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 o valores de fila 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 siguientes matrices de estado y operación se usan al llamar a SQLSetPos:

  • La matriz de estado de fila (como apunta el campo SQL_DESC_ARRAY_STATUS_PTR del 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 apunta 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, consulte 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 columnas de datos en ejecución. Normalmente se usan 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 largo específico del origen de datos 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 de datos en ejecución son similares a las columnas data-at-execution, el valor devuelto por SQLParamData es diferente para cada uno.

    Nota:

    Los parámetros de datos en ejecución 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 el que los datos se enviarán 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 en el 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 de caracteres, binarios o específicos del origen de datos o al enviar datos binarios de C a una columna con un carácter, tipo de datos binario o específico del origen de datos.

  5. Llama a SQLParamData de nuevo para indicar que todos los datos se han enviado 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 de 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 todavía necesita 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 en la matriz de operaciones de fila a la que apunta SQL_ATTR_ROW_OPERATION_PTR atributo de instrucción. Este es 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 un valor RowNumber igual a 0 devolverá SQLSTATE HY109 (posición de cursor no válida).

Si se produce un error que pertenece a todo el conjunto de filas, como SQLSTATE HYT00 (tiempo de espera expirado), el controlador devuelve SQL_ERROR y 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 procesar el error o la advertencia, devuelve SQL_ERROR.

Si el controlador devuelve advertencias, como SQLSTATE 01004 (datos truncados), devuelve advertencias que se aplican a todo el conjunto de filas o a filas desconocidas del conjunto de filas antes de devolver 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 para omitir 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 del 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 se establecieran en SQL_ROW_PROCEED.

  • Establecer un elemento en SQL_ROW_PROCEED no garantiza que la operación se produzca en esa fila concreta. 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 y actualización de filas en el conjunto de filas con SQLSetPos.

Para obtener información sobre Vea
Enlazar un búfer a una columna de un conjunto de resultados Función SQLBindCol
Realización de 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
Obtención de un único campo de un descriptor Función SQLGetDescField
Obtención de varios campos de un descriptor Función SQLGetDescRec
Establecimiento de 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