Función SQLCopyDesc
Conformidad
Versión introducida: Cumplimiento de estándares ODBC 3.0: ISO 92
Resumen
SQLCopyDesc copia información de descriptor de un identificador de descriptor a otro.
Sintaxis
SQLRETURN SQLCopyDesc(
SQLHDESC SourceDescHandle,
SQLHDESC TargetDescHandle);
Argumentos
SourceDescHandle
[Entrada] Identificador de descriptor de origen.
TargetDescHandle
[Entrada] Identificador del descriptor de destino. El argumento TargetDescHandle puede ser un identificador para un descriptor de aplicación o un IPD. TargetDescHandle no se puede establecer en un identificador de IRD o SQLCopyDesc devolverá SQLSTATE HY016 (no se puede modificar un descriptor de fila de implementación).
Devoluciones
SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR o SQL_INVALID_HANDLE.
Diagnóstico
Cuando SQLCopyDesc devuelve SQL_ERROR o SQL_SUCCESS_WITH_INFO, se puede obtener un valor SQLSTATE asociado llamando a SQLGetDiagRec con un HandleType de SQL_HANDLE_DESC y un identificador de TargetDescHandle. Si se pasó un sourceDescHandle no válido en la llamada, se devolverá SQL_INVALID_HANDLE pero no se devolverá SQLSTATE. En la tabla siguiente se enumeran los valores SQLSTATE devueltos normalmente por SQLCopyDesc 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.
Cuando se devuelve un error, la llamada a SQLCopyDesc se anula inmediatamente y el contenido de los campos del descriptor TargetDescHandle no está definido.
Dado que SQLCopyDesc se puede implementar llamando a SQLGetDescField y SQLSetDescField, SQLCopyDesc puede devolver SQLSTATEs devueltos por SQLGetDescField o SQLSetDescField.
SQLSTATE | Error | Descripción |
---|---|---|
01000 | Advertencia general | Mensaje informativo específico del controlador. (Function devuelve SQL_SUCCESS_WITH_INFO). |
08S01 | Error de vínculo de comunicación | Se produjo un error en el vínculo de comunicación entre el controlador y el origen de datos al que se conectó el controlador antes de que la función completara el procesamiento. |
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 la memoria necesaria para admitir la ejecución o finalización de la función. |
HY007 | La instrucción asociada no está preparada | SourceDescHandle estaba asociado a un IRD y el identificador de instrucción asociado no estaba en estado preparado o ejecutado. |
HY010 | Error de secuencia de funciones | (DM) El identificador de descriptor en SourceDescHandle o TargetDescHandle estaba asociado a un StatementHandle para el que se llamó a una función de ejecución asincrónica (no esta) y todavía se estaba ejecutando cuando se llamó a esta función. (DM) El identificador de descriptor en SourceDescHandle o TargetDescHandle estaba asociado a un StatementHandle para el que se llamó a SQLExecute, SQLExecDirect, SQLBulkOperations o SQLSetPos 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) Se llamó a una función de ejecución asincrónica para el identificador de conexión asociado con SourceDescHandle o TargetDescHandle. Esta función asincrónica todavía se estaba ejecutando cuando se llamó a la función SQLCopyDesc . (DM) SE llamó a SQLExecute, SQLExecDirect o SQLMoreResults para uno de los identificadores de instrucción asociados a SourceDescHandle o TargetDescHandle y se devolvió SQL_PARAM_DATA_AVAILABLE. Se llamó a esta función antes de recuperar los datos para todos los parámetros transmitidos. |
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. |
HY016 | No se puede modificar un descriptor de fila de implementación | TargetDescHandle estaba asociado a un IRD. |
HY021 | Información de descriptor incoherente | La información del descriptor activada durante una comprobación de coherencia no era coherente. Para obtener más información, vea "Comprobaciones de coherencia" en SQLSetDescField. |
HY092 | Identificador de atributo o opción no válido | La llamada a SQLCopyDesc solicitaba una llamada a SQLSetDescField, pero *ValuePtr no era válida para el argumento FieldIdentifier en TargetDescHandle. |
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. |
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 SourceDescHandle o TargetDescHandle no admite la función . |
Comentarios
Una llamada a SQLCopyDesc copia los campos del identificador de descriptor de origen en el identificador del descriptor de destino. Los campos solo se pueden copiar en un descriptor de aplicación o en un IPD, pero no en un IRD. Los campos se pueden copiar desde una aplicación o un descriptor de implementación.
Los campos solo se pueden copiar de un IRD si el identificador de instrucción está en estado preparado o ejecutado; De lo contrario, la función devuelve SQLSTATE HY007 (la instrucción Associated no está preparada).
Los campos se pueden copiar de un IPD tanto si se ha preparado una instrucción como si no. Si se ha preparado una instrucción SQL con parámetros dinámicos y se admite y se habilita el rellenado automático del IPD, el controlador rellena el IPD. Cuando se llama a SQLCopyDesc con el IPD como SourceDescHandle, se copian los campos rellenados. Si el controlador no rellena el IPD, se copia el contenido de los campos originalmente en el IPD.
Todos los campos del descriptor, excepto SQL_DESC_ALLOC_TYPE (que especifica si el identificador del descriptor se asignó automáticamente o explícitamente), se copian, independientemente de si el campo está definido o no para el descriptor de destino. Los campos copiados sobrescriben los campos existentes.
El controlador copia todos los campos descriptores si los argumentos SourceDescHandle y TargetDescHandle están asociados al mismo controlador, incluso si los controladores están en dos conexiones o entornos diferentes. Si los argumentos SourceDescHandle y TargetDescHandle están asociados a controladores diferentes, el Administrador de controladores copia los campos definidos por ODBC, pero no copia los campos definidos por el controlador o los campos que no están definidos por ODBC para el tipo de descriptor.
La llamada a SQLCopyDesc se anula inmediatamente si se produce un error.
Cuando se copia el campo SQL_DESC_DATA_PTR, se realiza una comprobación de coherencia en el descriptor de destino. Si se produce un error en la comprobación de coherencia, se devuelve SQLSTATE HY021 (información de descriptor incoherente) y se anula inmediatamente la llamada a SQLCopyDesc . Para obtener más información sobre las comprobaciones de coherencia, vea "Comprobaciones de coherencia" en la función SQLSetDescRec.
Los identificadores de descriptor se pueden copiar entre conexiones incluso si las conexiones están en entornos diferentes. Si el Administrador de controladores detecta que los identificadores de descriptor de origen y destino no pertenecen a la misma conexión y las dos conexiones pertenecen a controladores independientes, implementa SQLCopyDesc realizando una copia de campo por campo mediante SQLGetDescField y SQLSetDescField.
Cuando se llama a SQLCopyDesc con sourceDescHandle en un controlador y un targetDescHandle en otro controlador, se borra la cola de errores de SourceDescHandle. Esto ocurre porque SQLCopyDesc en este caso se implementa mediante llamadas a SQLGetDescField y SQLSetDescField.
Nota:
Es posible que una aplicación pueda asociar un identificador de descriptor asignado explícitamente a un StatementHandle, en lugar de llamar a SQLCopyDesc para copiar campos de un descriptor a otro. Un descriptor asignado explícitamente se puede asociar a otro StatementHandle en el mismo ConnectionHandle estableciendo el atributo de instrucción SQL_ATTR_APP_ROW_DESC o SQL_ATTR_APP_PARAM_DESC en el identificador del descriptor asignado explícitamente. Cuando esto se hace, no es necesario llamar a SQLCopyDesc para copiar valores de campo de descriptor de un descriptor a otro. Sin embargo, un identificador de descriptor no se puede asociar con un StatementHandle en otro ConnectionHandle; para usar los mismos valores de campo descriptor en StatementHandles en diferentes ConnectionHandles, se debe llamar a SQLCopyDesc.
Para obtener una descripción de los campos de un encabezado o registro de descriptor, vea Función SQLSetDescField. Para obtener más información sobre los descriptores, vea Descriptores.
Copiar filas entre tablas
Una aplicación puede copiar datos de una tabla a otra sin copiar los datos en el nivel de aplicación. Para ello, la aplicación enlaza los mismos búferes de datos e información de descriptor a una instrucción que captura los datos y la instrucción que inserta los datos en una copia. Esto se puede lograr mediante el uso compartido de un descriptor de aplicación (enlazar un descriptor asignado explícitamente como ARD a una instrucción y el APD en otro) o mediante SQLCopyDesc para copiar los enlaces entre el ARD y el APD de las dos instrucciones. Si las instrucciones están en diferentes conexiones, se debe usar SQLCopyDesc . Además, se debe llamar a SQLCopyDesc para copiar los enlaces entre IRD y el IPD de las dos instrucciones. Al copiar entre instrucciones en la misma conexión, el SQL_ACTIVE_STATEMENTS tipo de información devuelto por el controlador para una llamada a SQLGetInfo debe ser mayor que 1 para que esta operación se realice correctamente. (Este no es el caso al copiar entre conexiones).
Ejemplo de código
En el ejemplo siguiente, las operaciones de descriptor se usan para copiar los campos de la tabla PartsSource en la tabla PartsCopy. El contenido de la tabla PartsSource se captura en búferes de conjunto de filas en hstmt0. Estos valores se usan como parámetros de una instrucción INSERT en hstmt1 para rellenar las columnas de la tabla PartsCopy. Para ello, los campos del IRD de hstmt0 se copian en los campos del IPD de hstmt1 y los campos del ARD de hstmt0 se copian en los campos del APD de hstmt1. Use SQLSetDescField para establecer el atributo SQL_DESC_PARAMETER_TYPE del IPD en SQL_PARAM_INPUT al copiar campos IRD desde una instrucción con parámetros de salida en campos IPD que deben ser parámetros de entrada.
#define ROWS 100
#define DESC_LEN 50
#define SQL_SUCCEEDED(rc) (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
// Template for a row
typedef struct {
SQLINTEGER sPartID;
SQLINTEGER cbPartID;
SQLUCHAR szDescription[DESC_LENGTH];
SQLINTEGER cbDescription;
REAL sPrice;
SQLINTEGER cbPrice;
} PartsSource;
PartsSource rget[ROWS]; // rowset buffer
SQLUSMALLINT sts_ptr[ROWS]; // status pointer
SQLHSTMT hstmt0, hstmt1;
SQLHDESC hArd0, hIrd0, hApd1, hIpd1;
// ARD and IRD of hstmt0
SQLGetStmtAttr(hstmt0, SQL_ATTR_APP_ROW_DESC, &hArd0, 0, NULL);
SQLGetStmtAttr(hstmt0, SQL_ATTR_IMP_ROW_DESC, &hIrd0, 0, NULL);
// APD and IPD of hstmt1
SQLGetStmtAttr(hstmt1, SQL_ATTR_APP_PARAM_DESC, &hApd1, 0, NULL);
SQLGetStmtAttr(hstmt1, SQL_ATTR_IMP_PARAM_DESC, &hIpd1, 0, NULL);
// Use row-wise binding on hstmt0 to fetch rows
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER) sizeof(PartsSource), 0);
// Set rowset size for hstmt0
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);
// Execute a select statement
SQLExecDirect(hstmt0, "SELECT PARTID, DESCRIPTION, PRICE FROM PARTS ORDER BY 3, 1, 2"",
SQL_NTS);
// Bind
SQLBindCol(hstmt0, 1, SQL_C_SLONG, rget[0].sPartID, 0,
&rget[0].cbPartID);
SQLBindCol(hstmt0, 2, SQL_C_CHAR, &rget[0].szDescription, DESC_LEN,
&rget[0].cbDescription);
SQLBindCol(hstmt0, 3, SQL_C_FLOAT, rget[0].sPrice,
0, &rget[0].cbPrice);
// Perform parameter bindings on hstmt1.
SQLCopyDesc(hArd0, hApd1);
SQLCopyDesc(hIrd0, hIpd1);
// Set the array status pointer of IRD
SQLSetStmtAttr(hstmt0, SQL_ATTR_ROW_STATUS_PTR, sts_ptr, SQL_IS_POINTER);
// Set the ARRAY_STATUS_PTR field of APD to be the same
// as that in IRD.
SQLSetStmtAttr(hstmt1, SQL_ATTR_PARAM_OPERATION_PTR, sts_ptr, SQL_IS_POINTER);
// Set the hIpd1 records as input parameters
rc = SQLSetDescField(hIpd1, 1, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);
rc = SQLSetDescField(hIpd1, 2, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);
rc = SQLSetDescField(hIpd1, 3, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)SQL_PARAM_INPUT, SQL_IS_INTEGER);
// Prepare an insert statement on hstmt1. PartsCopy is a copy of
// PartsSource
SQLPrepare(hstmt1, "INSERT INTO PARTS_COPY VALUES (?, ?, ?)", SQL_NTS);
// In a loop, fetch a rowset, and copy the fetched rowset to PARTS_COPY
rc = SQLFetchScroll(hstmt0, SQL_FETCH_NEXT, 0);
while (SQL_SUCCEEDED(rc)) {
// After the call to SQLFetchScroll, the status array has row
// statuses. This array is used as input status in the APD
// and hence determines which elements of the rowset buffer
// are inserted.
SQLExecute(hstmt1);
rc = SQLFetchScroll(hstmt0, SQL_FETCH_NEXT, 0);
} // while
Funciones relacionadas
Para obtener información sobre | Vea |
---|---|
Obtención de varios campos de descriptor | Función SQLGetDescRec |
Establecimiento de un único campo descriptor | Función SQLSetDescField |
Establecimiento de varios campos de descriptor | Función SQLSetDescRec |