SQL : Personnalisation de l’instruction SQL du recordset (ODBC)
Cette rubrique explique :
Comment l’infrastructure construit une instruction SQL
Comment remplacer l’instruction SQL
Remarque
Ces informations s’appliquent aux classes ODBC MFC. Si vous utilisez les classes DAO MFC, consultez la rubrique « Comparaison SQL entre le moteur de base de données Microsoft Jet et ANSI » dans l’aide de DAO.
Construire des instructions SQL
Votre recordset base sa sélection d’enregistrements principalement sur une instruction SQL SELECT. Lorsque vous déclarez votre classe avec un Assistant, il écrit une version de substitution de la fonction membre GetDefaultSQL
qui ressemble à ceci (pour une classe recordset appelée CAuthors
).
CString CAuthors::GetDefaultSQL()
{
return "AUTHORS";
}
Par défaut, cette substitution retourne le nom de table que vous avez spécifié avec l’Assistant. Dans l’exemple, le nom de la table est « AUTHORS ». Lorsque vous appelez ultérieurement la fonction membre Open
du recordset, Open
construit une instruction SELECT finale du formulaire :
SELECT rfx-field-list FROM table-name [WHERE m_strFilter]
[ORDER BY m_strSort]
où table-name
est obtenu en appelant GetDefaultSQL
, et rfx-field-list
est obtenu à partir des appels de fonction RFX dans DoFieldExchange
. C’est ce que vous obtenez pour une instruction SELECT, sauf si vous la remplacez par une version substituée au moment de l’exécution, bien que vous puissiez également modifier l’instruction par défaut par des paramètres ou par un filtre.
Remarque
Si vous spécifiez un nom de colonne qui contient (ou peut contenir) des espaces, vous devez placer le nom entre crochets. Par exemple, le nom d’une colonne « Nom de famille » doit être écrit « [Nom de famille] ».
Pour remplacer l’instruction SELECT par défaut, transmettez une chaîne contenant une instruction SELECT complète lorsque vous appelez Open
. Au lieu de construire sa propre chaîne par défaut, le recordset utilise la chaîne que vous fournissez. Si votre instruction de remplacement contient une clause WHERE, ne spécifiez pas de filtre dans m_strFilter
, car vous auriez alors deux instructions de filtre. De même, si votre instruction de remplacement contient une clause ORDER BY, ne spécifiez pas de tri dans m_strSort
pour ne pas vous retrouver avec deux instructions de tri.
Remarque
Si vous utilisez des chaînes littérales dans vos filtres (ou d’autres parties de l’instruction SQL), vous devrez peut-être « citer » (placer dans des délimiteurs spécifiés) ces chaînes avec un caractère (ou des caractères) de préfixe littéral spécifique au système de gestion de base de données (SGBD) et de suffixe littéral.
Vous pouvez également rencontrer des exigences syntactiques spéciales pour les opérations telles que les jointures externes, en fonction de votre SGBD. Utilisez des fonctions ODBC pour obtenir ces informations auprès de votre pilote pour le SGBD. Par exemple, appelez ::SQLGetTypeInfo
pour un type de données particulier, tel que SQL_VARCHAR
, pour demander les caractères LITERAL_PREFIX et LITERAL_SUFFIX. Si vous écrivez du code indépendant de la base de données, consultez Annexe C : Grammaire SQL dans Référence du programmeur ODBC pour obtenir des informations détaillées sur la syntaxe.
Un objet recordset construit l’instruction SQL qu’il utilise pour sélectionner des enregistrements, sauf si vous passez une instruction SQL personnalisée. La façon dont cela est fait dépend principalement de la valeur que vous passez dans le paramètre lpszSQL de la fonction membre Open
.
La forme générale d’une instruction SQL SELECT est la suivante :
SELECT [ALL | DISTINCT] column-list FROM table-list
[WHERE search-condition][ORDER BY column-list [ASC | DESC]]
Une façon d’ajouter le mot clé DISTINCT à l’instruction SQL de votre recordset consiste à incorporer le mot clé dans le premier appel de fonction RFX dans DoFieldExchange
. Par exemple :
...
RFX_Text(pFX, "DISTINCT CourseID", m_strCourseID);
...
Remarque
Utilisez cette technique uniquement avec un recordset ouvert en lecture seule.
Substitution de l’instruction SQL
Le tableau suivant présente les possibilités pour le paramètre lpszSQL de Open
. Les cas du tableau sont expliqués en suivant le tableau.
Le paramètre lpszSQL et la chaîne SQL résultante
Case | Ce que vous passez dans lpszSQL | Instruction SELECT résultante |
---|---|---|
1 | NULL | SELECT rfx-field-list FROM table-nameCRecordset::Open appelle GetDefaultSQL pour obtenir le nom de la table. La chaîne résultante est l’un des cas de 2 à 5, selon ce que GetDefaultSQL retourne. |
2 | Un nom de table | SELECT rfx-field-list FROM table-name La liste de champs est extraite des instructions RFX dans DoFieldExchange . Si m_strFilter et m_strSort ne sont pas vides, ajoute les clauses WHERE et/ou ORDER BY. |
3* | Instruction SELECT complète, mais sans clause WHERE ou ORDER BY | Tel qu’il a été passé. Si m_strFilter et m_strSort ne sont pas vides, ajoute les clauses WHERE et/ou ORDER BY. |
4* | Instruction SELECT complète avec une clause WHERE et/ou ORDER BY | Tel qu’il a été passé. m_strFilter et/ou m_strSort doivent rester vides, ou deux instructions de filtre et/ou de tri sont produites. |
5 * | Un appel à une procédure stockée | Tel qu’il a été passé. |
* m_nFields
doit être inférieur ou égal au nombre de colonnes spécifiées dans l’instruction SELECT. Le type de données de chaque colonne spécifiée dans l’instruction SELECT doit être identique au type de données de la colonne de sortie RFX correspondante.
Cas 1 lpszSQL = NULL
La sélection du recordset dépend de ce que GetDefaultSQL
retourne quand CRecordset::Open
l’appelle. Les cas 2 à 5 décrivent les chaînes possibles.
Cas 2 lpszSQL = un nom de table
Le recordset utilise Record Field Exchange (RFX) pour générer la liste des colonnes à partir des noms de colonnes fournis dans les appels de fonction RFX dans le remplacement de la classe recordset de DoFieldExchange
. Si vous avez utilisé un Assistant pour déclarer votre classe de recordset, ce cas a le même résultat que le cas 1 (à condition que vous transmettiez le même nom de table que celui que vous avez spécifié dans l’Assistant). Si vous n’utilisez pas d’Assistant pour écrire votre classe, le cas 2 est le moyen le plus simple de construire l’instruction SQL.
L’exemple suivant construit une instruction SQL qui sélectionne les enregistrements d’une application de base de données MFC. Lorsque l’infrastructure appelle la fonction membre GetDefaultSQL
, la fonction retourne le nom de la table, SECTION
.
CString CEnrollSet::GetDefaultSQL()
{
return "SECTION";
}
Pour obtenir les noms des colonnes de l’instruction SQL SELECT, l’infrastructure appelle la fonction membre DoFieldExchange
.
void CEnrollSet::DoFieldExchange(CFieldExchange* pFX)
{
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text(pFX, "CourseID", m_strCourseID);
RFX_Text(pFX, "InstructorID", m_strInstructorID);
RFX_Text(pFX, "RoomNo", m_strRoomNo);
RFX_Text(pFX, "Schedule", m_strSchedule);
RFX_Text(pFX, "SectionNo", m_strSectionNo);
}
Une fois terminée, l’instruction SQL ressemble à ceci :
SELECT CourseID, InstructorID, RoomNo, Schedule, SectionNo
FROM SECTION
Cas 3 lpszSQL = une instruction SELECT/FROM
Vous spécifiez la liste de colonnes vous-même plutôt que de compter sur RFX pour la construire automatiquement. Vous pouvez le faire lorsque :
Vous souhaitez spécifier le mot clé DISTINCT après SELECT.
Votre liste de colonnes doit correspondre aux noms et types de colonnes dans le même ordre qu’ils sont répertoriés dans
DoFieldExchange
.Pour certaines raisons, vous voulez récupérer manuellement les valeurs de colonne à l’aide de la fonction ODBC
::SQLGetData
plutôt que de compter sur RFX pour lier et récupérer des colonnes pour vous.Par exemple, vous souhaiterez peut-être prendre en charge de nouvelles colonnes ajoutées par un client de votre application aux tables de base de données après la distribution de l’application. Vous devez ajouter ces membres de données de champ supplémentaires, qui n’étaient pas connus au moment où vous avez déclaré la classe avec un Assistant.
Votre liste de colonnes doit correspondre aux noms et types de colonnes dans le même ordre qu’ils sont répertoriés dans
DoFieldExchange
, suivis des noms des colonnes liées manuellement. Pour plus d’informations, consultez Recordset : liaison dynamique de colonnes de données (ODBC).Vous souhaitez joindre des tables en spécifiant plusieurs tables dans la clause FROM.
Pour plus d’informations et pour obtenir un exemple, consultez Recordset : Création d’une jointure (ODBC).
Cas 4 lpszSQL = SELECT/FROM + WHERE et/ou ORDER BY
Vous spécifiez tout : la liste de colonnes (basée sur les appels RFX dans DoFieldExchange
), la liste de tables et le contenu d’une clause WHERE et/ou ORDER BY. Si vous spécifiez vos clauses WHERE et/ou ORDER BY ainsi, n’utilisez pas m_strFilter
et/ou m_strSort
.
Cas 5 lpszSQL = un appel de procédure stockée
Si vous devez appeler une requête prédéfinie (par exemple, une procédure stockée dans une base de données Microsoft SQL Server), vous devez écrire une instruction CALL dans la chaîne que vous passez à lpszSQL. Les Assistants ne prennent pas en charge la déclaration d’une classe recordset pour appeler une requête prédéfinie. Toutes les requêtes prédéfinies ne retournent pas d’enregistrements.
Si une requête prédéfinie ne retourne pas d’enregistrements, vous pouvez utiliser directement la fonction membre CDatabase
ExecuteSQL
. Pour une requête prédéfinie qui retourne des enregistrements, vous devez également écrire manuellement les appels RFX dans DoFieldExchange
pour toutes les colonnes retournées par la procédure. Les appels RFX doivent être dans le même ordre et retourner les mêmes types que la requête prédéfinie. Pour plus d’informations, consultez Recordset : Déclaration d’une classe pour une requête prédéfinie (ODBC).
Voir aussi
SQL : types de données SQL et C++ (ODBC)
SQL : appels SQL directs (ODBC)