Share via


SQLCopyDesc, fonction

Conformité
Version introduite : Conformité aux normes ODBC 3.0 : ISO 92

Résumé
SQLCopyDesc copie les informations de descripteur d’un handle de descripteur vers un autre.

Syntaxe

  
SQLRETURN SQLCopyDesc(  
     SQLHDESC     SourceDescHandle,  
     SQLHDESC     TargetDescHandle);  

Arguments

SourceDescHandle
[Entrée] Handle de descripteur source.

TargetDescHandle
[Entrée] Handle de descripteur cible. L’argument TargetDescHandle peut être un handle pour un descripteur d’application ou un IPD. TargetDescHandle ne peut pas être défini sur un handle sur un IRD, ou SQLCopyDesc retourne SQLSTATE HY016 (Impossible de modifier un descripteur de ligne d’implémentation).

Retours

SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_ERROR ou SQL_INVALID_HANDLE.

Diagnostics

Lorsque SQLCopyDesc retourne SQL_ERROR ou SQL_SUCCESS_WITH_INFO, une valeur SQLSTATE associée peut être obtenue en appelant SQLGetDiagRec avec un HandleType de SQL_HANDLE_DESC et un Handle de TargetDescHandle. Si un Code SourceDescHandle non valide a été passé dans l’appel, SQL_INVALID_HANDLE sera retourné, mais aucune valeur SQLSTATE ne sera retournée. Le tableau suivant répertorie les valeurs SQLSTATE couramment retournées par SQLCopyDesc et explique chacune d’elles dans le contexte de cette fonction ; la notation « (DM) » précède les descriptions de SQLSTATEs retournées par le Gestionnaire de pilotes. Le code de retour associé à chaque valeur SQLSTATE est SQL_ERROR, sauf indication contraire.

Lorsqu’une erreur est retournée, l’appel à SQLCopyDesc est immédiatement abandonné et le contenu des champs du descripteur TargetDescHandle n’est pas défini.

Étant donné que SQLCopyDesc peut être implémenté en appelant SQLGetDescField et SQLSetDescField, SQLCopyDesc peut retourner des SQLSTATEs retournés par SQLGetDescField ou SQLSetDescField.

SQLSTATE Error Description
01000 Avertissement général Message d’information spécifique au pilote. (La fonction retourne SQL_SUCCESS_WITH_INFO.)
08S01 Échec de la liaison de communication La liaison de communication entre le pilote et la source de données à laquelle le pilote a été connecté a échoué avant que la fonction n’ait terminé le traitement.
HY000 Erreur générale Une erreur s’est produite pour laquelle il n’y avait pas de SQLSTATE spécifique et pour laquelle aucun SQLSTATE spécifique à l’implémentation n’a été défini. Le message d’erreur retourné par SQLGetDiagRec dans la mémoire tampon *MessageText décrit l’erreur et sa cause.
HY001 Erreur d’allocation de mémoire Le pilote n’a pas pu allouer la mémoire nécessaire pour prendre en charge l’exécution ou l’achèvement de la fonction.
HY007 L’instruction associée n’est pas préparée SourceDescHandle a été associé à un IRD et le handle d’instruction associé n’était pas à l’état préparé ou exécuté.
HY010 Erreur de séquence de fonction (DM) Le handle de descripteur dans SourceDescHandle ou TargetDescHandle a été associé à un StatementHandle pour lequel une fonction d’exécution asynchrone (et non celle-ci) était appelée et s’exécutait toujours lorsque cette fonction était appelée.

(DM) Le handle de descripteur dans SourceDescHandle ou TargetDescHandle a été associé à un StatementHandle pour lequel SQLExecute, SQLExecDirect, SQLBulkOperations ou SQLSetPos a été appelé et retourné SQL_NEED_DATA. Cette fonction a été appelée avant l’envoi des données pour toutes les colonnes ou paramètres de données au moment de l’exécution.

(DM) Une fonction d’exécution asynchrone a été appelée pour le handle de connexion associé à SourceDescHandle ou TargetDescHandle. Cette fonction asynchrone était toujours en cours d’exécution lorsque la fonction SQLCopyDesc a été appelée.

(DM) SQLExecute, SQLExecDirect ou SQLMoreResults a été appelé pour l’un des handles d’instruction associés à SourceDescHandle ou TargetDescHandle et retourné SQL_PARAM_DATA_AVAILABLE. Cette fonction a été appelée avant la récupération des données pour tous les paramètres diffusés.
HY013 Erreur de gestion de la mémoire L’appel de fonction n’a pas pu être traité, car les objets de mémoire sous-jacents n’ont pas pu être consultés, peut-être en raison de conditions de mémoire insuffisantes.
HY016 Impossible de modifier un descripteur de ligne d’implémentation TargetDescHandle a été associé à un IRD.
HY021 Informations de descripteurs incohérentes Les informations de descripteur vérifiées lors d’une vérification de cohérence n’étaient pas cohérentes. Pour plus d’informations, consultez « Vérifications de cohérence » dans SQLSetDescField.
HY092 Identificateur d’attribut/d’option non valide L’appel à SQLCopyDesc a demandé un appel à SQLSetDescField, mais *ValuePtr n’était pas valide pour l’argument FieldIdentifier sur TargetDescHandle.
HY117 La connexion est suspendue en raison d’un état de transaction inconnu. Seules les fonctions de déconnexion et de lecture seule sont autorisées. (DM) Pour plus d’informations sur l’état suspendu, consultez FONCTION SQLEndTran.
HYT01 Délai d’attente de la connexion expiré Le délai d’expiration de la connexion a expiré avant que la source de données réponde à la demande. La période de délai d’expiration de la connexion est définie via SQLSetConnectAttr, SQL_ATTR_CONNECTION_TIMEOUT.
IM001 Le pilote ne prend pas en charge cette fonction (DM) Le pilote associé à SourceDescHandle ou TargetDescHandle ne prend pas en charge la fonction.

Commentaires

Un appel à SQLCopyDesc copie les champs du handle de descripteur source dans le handle de descripteur cible. Les champs ne peuvent être copiés que dans un descripteur d’application ou un IPD, mais pas dans un IRD. Les champs peuvent être copiés à partir d’une application ou d’un descripteur d’implémentation.

Les champs ne peuvent être copiés à partir d’un IRD que si le handle d’instruction est à l’état préparé ou exécuté ; sinon, la fonction retourne SQLSTATE HY007 (l’instruction associée n’est pas préparée).

Les champs peuvent être copiés à partir d’un IPD, qu’une instruction ait été préparée ou non. Si une instruction SQL avec des paramètres dynamiques a été préparée et que la population automatique de l’IPD est prise en charge et activée, l’IPD est renseigné par le pilote. Lorsque SQLCopyDesc est appelé avec l’IPD comme SourceDescHandle, les champs renseignés sont copiés. Si l’IPD n’est pas renseigné par le pilote, le contenu des champs d’origine dans l’IPD est copié.

Tous les champs du descripteur, à l’exception de SQL_DESC_ALLOC_TYPE (qui spécifie si le handle de descripteur a été alloué automatiquement ou explicitement), sont copiés, que le champ soit défini ou non pour le descripteur de destination. Les champs copiés remplacent les champs existants.

Le pilote copie tous les champs de descripteur si les arguments SourceDescHandle et TargetDescHandle sont associés au même pilote, même si les pilotes se trouvent sur deux connexions ou environnements différents. Si les arguments SourceDescHandle et TargetDescHandle sont associés à des pilotes différents, le Gestionnaire de pilotes copie les champs définis par ODBC, mais ne copie pas les champs définis par le pilote ou les champs qui ne sont pas définis par ODBC pour le type de descripteur.

L’appel à SQLCopyDesc est immédiatement abandonné si une erreur se produit.

Lorsque le champ SQL_DESC_DATA_PTR est copié, une vérification de cohérence est effectuée sur le descripteur cible. Si la vérification de cohérence échoue, SQLSTATE HY021 (informations de descripteurs incohérentes) est retourné et l’appel à SQLCopyDesc est immédiatement abandonné. Pour plus d’informations sur les vérifications de cohérence, consultez « Vérifications de cohérence » dans la fonction SQLSetDescRec.

Les handles de descripteurs peuvent être copiés entre les connexions même si les connexions se trouvent dans des environnements différents. Si le Gestionnaire de pilotes détecte que les handles source et de descripteur de destination n’appartiennent pas à la même connexion et que les deux connexions appartiennent à des pilotes distincts, il implémente SQLCopyDesc en effectuant une copie champ par champ à l’aide de SQLGetDescField et SQLSetDescField.

Lorsque SQLCopyDesc est appelé avec un SourceDescHandle sur un pilote et un TargetDescHandle sur un autre pilote, la file d’attente d’erreurs de SourceDescHandle est effacée. Cela se produit parce que SQLCopyDesc dans ce cas est implémenté par des appels à SQLGetDescField et SQLSetDescField.

Notes

Une application peut être en mesure d’associer un handle descripteur explicitement alloué à un StatementHandle, plutôt que d’appeler SQLCopyDesc pour copier des champs d’un descripteur à un autre. Un descripteur explicitement alloué peut être associé à un autre InstructionHandle sur le même ConnectionHandle en définissant l’attribut d’instruction SQL_ATTR_APP_ROW_DESC ou SQL_ATTR_APP_PARAM_DESC sur le handle du descripteur explicitement alloué. Lorsque cela est fait, SQLCopyDesc n’a pas besoin d’être appelé pour copier les valeurs de champ de descripteur d’un descripteur à un autre. Toutefois, un handle de descripteur ne peut pas être associé à un InstructionHandle sur un autre ConnectionHandle ; Pour utiliser les mêmes valeurs de champ de descripteur sur StatementHandles sur des ConnectionHandles différentes, SQLCopyDesc doit être appelé.

Pour obtenir une description des champs d’un en-tête ou d’un enregistrement de descripteur, consultez FONCTION SQLSetDescField. Pour plus d’informations sur les descripteurs, consultez Descripteurs.

Copie de lignes entre des tables

Une application peut copier des données d’une table vers une autre sans copier les données au niveau de l’application. Pour ce faire, l’application lie les mêmes mémoires tampons de données et informations de descripteur à une instruction qui extrait les données et à l’instruction qui insère les données dans une copie. Pour ce faire, vous pouvez partager un descripteur d’application (liaison d’un descripteur explicitement alloué en tant que ARD à une instruction et APD dans une autre) ou en utilisant SQLCopyDesc pour copier les liaisons entre l’ARD et l’APD des deux instructions. Si les instructions se trouvent sur des connexions différentes, SQLCopyDesc doit être utilisé. En outre, SQLCopyDesc doit être appelé pour copier les liaisons entre l’IRD et l’IPD des deux instructions. Lors de la copie d’instructions sur la même connexion, le type d’informations SQL_ACTIVE_STATEMENTS retourné par le pilote pour un appel à SQLGetInfo doit être supérieur à 1 pour que cette opération réussisse. (Ce n’est pas le cas lors de la copie entre les connexions.)

Exemple de code

Dans l’exemple suivant, les opérations de descripteur sont utilisées pour copier les champs de la table PartsSource dans la table PartsCopy. Le contenu de la table PartsSource est extrait dans les mémoires tampons d’ensemble de lignes dans hstmt0. Ces valeurs sont utilisées comme paramètres d’une instruction INSERT sur hstmt1 pour remplir les colonnes de la table PartsCopy. Pour ce faire, les champs de l’IRD de hstmt0 sont copiés dans les champs de l’IPD de hstmt1, et les champs de l’ARD de hstmt0 sont copiés dans les champs de l’APD de hstmt1. Utilisez SQLSetDescField pour définir l’attribut SQL_DESC_PARAMETER_TYPE de l’IPD sur SQL_PARAM_INPUT lorsque vous copiez des champs IRD d’une instruction avec des paramètres de sortie vers des champs IPD qui doivent être des paramètres d’entrée.

#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  
Pour obtenir des informations sur Consultez
Obtention de plusieurs champs de descripteur SQLGetDescRec, fonction
Définition d’un champ de descripteur unique SQLSetDescField, fonction
Définition de plusieurs champs de descripteur SQLSetDescRec, fonction

Voir aussi

Informations de référence sur l’API ODBC
Fichiers d’en-tête ODBC