SQL: personalizzazione dell'istruzione SQL del recordset (ODBC)
In questo argomento:
Come il framework costruisce un'istruzione SQL
Come eseguire l'override dell'istruzione SQL
Nota
Queste informazioni sono valide per le classi ODBC MFC. Se si lavora con le classi DAO MFC, vedere l'argomento "Confronto tra Microsoft Jet motore di database SQL e SQL ANSI" nella Guida di DAO.
Costruzione di istruzioni SQL
Il recordset basa principalmente la selezione dei record in un'istruzione SQL SELECT . Quando si dichiara la classe con una procedura guidata, scrive una versione di override della GetDefaultSQL
funzione membro simile alla seguente (per una classe recordset denominata CAuthors
).
CString CAuthors::GetDefaultSQL()
{
return "AUTHORS";
}
Per impostazione predefinita, questa sostituzione restituisce il nome della tabella specificato con la procedura guidata. Nell'esempio il nome della tabella è "AUTHORS". Quando in seguito si chiama la funzione membro del Open
recordset, Open
crea un'istruzione SELECT finale del form:
SELECT rfx-field-list FROM table-name [WHERE m_strFilter]
[ORDER BY m_strSort]
dove table-name
viene ottenuto chiamando GetDefaultSQL
e rfx-field-list
viene ottenuto dalle chiamate di funzione RFX in DoFieldExchange
. Questo è ciò che si ottiene per un'istruzione SELECT a meno che non venga sostituito con una versione di override in fase di esecuzione, anche se è anche possibile modificare l'istruzione predefinita con parametri o un filtro.
Nota
Se si specifica un nome di colonna contenente (o può contenere) spazi, è necessario racchiudere il nome tra parentesi quadre. Ad esempio, il nome "First Name" deve essere "[First Name]".
Per eseguire l'override dell'istruzione SELECT predefinita, passare una stringa contenente un'istruzione SELECT completa quando si chiama Open
. Anziché costruire la propria stringa predefinita, il recordset usa la stringa specificata. Se l'istruzione replacement contiene una clausola WHERE , non specificare un filtro in m_strFilter
perché si dispone di due istruzioni di filtro. Analogamente, se l'istruzione di sostituzione contiene una clausola ORDER BY , non specificare un ordinamento in m_strSort
modo da non disporre di due istruzioni di ordinamento.
Nota
Se si usano stringhe letterali nei filtri (o in altre parti dell'istruzione SQL), potrebbe essere necessario "virgolette" (racchiudere nei delimitatori specificati) tali stringhe con un prefisso letterale specifico di DBMS e un carattere suffisso letterale (o caratteri).
È anche possibile che si verifichino requisiti sintattici speciali per operazioni come outer join, a seconda del sistema DBMS. Usare le funzioni ODBC per ottenere queste informazioni dal driver per DBMS. Ad esempio, chiamare ::SQLGetTypeInfo
per un tipo di dati specifico, ad esempio SQL_VARCHAR
, per richiedere i caratteri LITERAL_PREFIX e LITERAL_SUFFIX. Se si scrive codice indipendente dal database, vedere Appendice C: Grammatica SQL nella guida di riferimento per programmatori ODBC per informazioni dettagliate sulla sintassi.
Un oggetto recordset costruisce l'istruzione SQL usata per selezionare i record, a meno che non si passi un'istruzione SQL personalizzata. La modalità di esecuzione dipende principalmente dal valore passato nel parametro lpszSQL della Open
funzione membro.
La forma generale di un'istruzione SQL SELECT è:
SELECT [ALL | DISTINCT] column-list FROM table-list
[WHERE search-condition][ORDER BY column-list [ASC | DESC]]
Un modo per aggiungere la parola chiave DISTINCT all'istruzione SQL del recordset consiste nell'incorporare la parola chiave nella prima chiamata di funzione RFX in DoFieldExchange
. Ad esempio:
...
RFX_Text(pFX, "DISTINCT CourseID", m_strCourseID);
...
Nota
Usare questa tecnica solo con un recordset aperto come di sola lettura.
Override dell'istruzione SQL
La tabella seguente illustra le possibilità per il parametro lpszSQL in Open
. I case nella tabella sono illustrati seguendo la tabella.
Il parametro lpszSQL e la stringa SQL risultante
Case | Cosa si passa in lpszSQL | Istruzione SELECT risultante |
---|---|---|
1 | NULL | SELECT rfx-field-list FROM table-nameCRecordset::Open chiama GetDefaultSQL per ottenere il nome della tabella. La stringa risultante è uno dei casi da 2 a 5, a seconda di ciò che GetDefaultSQL restituisce. |
2 | Un nome di tabella | SELECT rfx-field-list FROM table-name L'elenco di campi viene ricavato dalle istruzioni RFX in DoFieldExchange . Se m_strFilter e m_strSort non sono vuoti, aggiunge le clausole WHERE e/o ORDER BY . |
3* | Istruzione SELECT completa, ma senza una clausola WHERE o ORDER BY | Come passato. Se m_strFilter e m_strSort non sono vuoti, aggiunge le clausole WHERE e/o ORDER BY . |
4 * | Istruzione SELECT completa con una clausola WHERE e/o ORDER BY | Come passato. m_strFilter e/o m_strSort devono rimanere vuoti oppure vengono generate due istruzioni di filtro e/o ordinamento. |
5 * | Chiamata a una stored procedure | Come passato. |
* m_nFields
deve essere minore o uguale al numero di colonne specificate nell'istruzione SELECT . Il tipo di dati di ogni colonna specificata nell'istruzione SELECT deve corrispondere al tipo di dati della colonna di output RFX corrispondente.
Case 1 lpszSQL = NULL
La selezione del recordset dipende da ciò che GetDefaultSQL
restituisce quando CRecordset::Open
lo chiama. I casi da 2 a 5 descrivono le possibili stringhe.
Case 2 lpszSQL = a Table Name
Il recordset usa lo scambio di campi di record (RFX) per compilare l'elenco di colonne dai nomi di colonna forniti nelle chiamate di funzione RFX nell'override della classe recordset di DoFieldExchange
. Se è stata usata una procedura guidata per dichiarare la classe recordset, questo caso ha lo stesso risultato del case 1 (purché venga passato lo stesso nome di tabella specificato nella procedura guidata). Se non si usa una procedura guidata per scrivere la classe, il caso 2 è il modo più semplice per costruire l'istruzione SQL.
Nell'esempio seguente viene creata un'istruzione SQL che seleziona i record da un'applicazione di database MFC. Quando il framework chiama la GetDefaultSQL
funzione membro, la funzione restituisce il nome della tabella, SECTION
.
CString CEnrollSet::GetDefaultSQL()
{
return "SECTION";
}
Per ottenere i nomi delle colonne per l'istruzione SQL SELECT , il framework chiama la DoFieldExchange
funzione membro.
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);
}
Al termine, l'istruzione SQL è simile alla seguente:
SELECT CourseID, InstructorID, RoomNo, Schedule, SectionNo
FROM SECTION
Case 3 lpszSQL = un'istruzione SELECT/FROM
Specificare l'elenco di colonne manualmente anziché basarsi su RFX per crearlo automaticamente. È possibile eseguire questa operazione quando:
Si vuole specificare la parola chiave DISTINCT dopo SELECT.
L'elenco di colonne deve corrispondere ai nomi e ai tipi di colonna nello stesso ordine in cui sono elencati in
DoFieldExchange
.È necessario recuperare manualmente i valori delle colonne usando la funzione
::SQLGetData
ODBC anziché basarsi su RFX per associare e recuperare le colonne automaticamente.È possibile, ad esempio, che si voglia contenere nuove colonne che un cliente dell'applicazione ha aggiunto alle tabelle di database dopo la distribuzione dell'applicazione. È necessario aggiungere questi membri dati di campo aggiuntivi, che non erano noti al momento della dichiarazione della classe con una procedura guidata.
L'elenco di colonne deve corrispondere ai nomi e ai tipi di colonna nello stesso ordine in cui sono elencati in
DoFieldExchange
, seguiti dai nomi delle colonne associate manualmente. Per altre informazioni, vedere Recordset: Binding dinamico di colonne di dati (ODBC).Si desidera unire tabelle specificando più tabelle nella clausola FROM .
Per informazioni e un esempio, vedere Recordset: Esecuzione di un join (ODBC).
Caso 4 lpszSQL = SELECT/FROM Plus WHERE e/o ORDER BY
Specificare tutti gli elementi: l'elenco di colonne (in base alle chiamate RFX in DoFieldExchange
), l'elenco di tabelle e il contenuto di una clausola WHERE e/o ORDER BY . Se si specificano le clausole WHERE e/o ORDER BY in questo modo, non utilizzare m_strFilter
e/o m_strSort
.
Caso 5 lpszSQL = una chiamata a stored procedure
Se è necessario chiamare una query predefinita, ad esempio una stored procedure in un database di Microsoft SQL Server, è necessario scrivere un'istruzione CALL nella stringa passata a lpszSQL. Le procedure guidate non supportano la dichiarazione di una classe recordset per chiamare una query predefinita. Non tutte le query predefinite restituiscono record.
Se una query predefinita non restituisce record, è possibile usare direttamente la CDatabase
funzione ExecuteSQL
membro. Per una query predefinita che restituisce record, è anche necessario scrivere manualmente le chiamate RFX in DoFieldExchange
per tutte le colonne restituite dalla routine. Le chiamate RFX devono essere nello stesso ordine e restituire gli stessi tipi, come la query predefinita. Per altre informazioni, vedere Recordset: Dichiarazione di una classe per una query predefinita (ODBC).
Vedi anche
SQL: tipi di dati SQL e C++ (ODBC)
SQL: esecuzione di chiamate SQL dirette (ODBC)