Compartilhar via


SQL: personalizando a instrução SQL do conjunto de registros (ODBC)

Este tópico explica:

  • Como a estrutura constrói uma instrução SQL

  • Como substituir a instrução SQL

Observação

Essas informações aplicam-se às classes ODBC do MFC. Se estiver trabalhando com as classes DAO do MFC, confira o tópico "Comparação do SQL e SQL ANSI do Mecanismo de Banco de Dados Jet da Microsoft" na Ajuda do DAO.

Construção de instrução SQL

Seu conjunto de registros baseia a seleção de registro principalmente em uma instrução SQL SELECT. Quando você declara sua classe com um assistente, ela grava uma versão de substituição da função membro GetDefaultSQL que tem aparência semelhante à mostrada a seguir (para uma classe de conjunto de registros chamada CAuthors).

CString CAuthors::GetDefaultSQL()
{
    return "AUTHORS";
}

Por padrão, essa substituição retorna o nome da tabela especificado com o assistente. No exemplo, o nome da tabela é "AUTHORS". Quando você mais tarde chama a função membro Open do conjunto de registros, Open constrói uma instrução SELECT final do formulário:

SELECT rfx-field-list FROM table-name [WHERE m_strFilter]
       [ORDER BY m_strSort]

em que table-name é obtido chamando GetDefaultSQL, e rfx-field-list é obtido das chamadas de função RFX em DoFieldExchange. Isso é o que você obtém para uma instrução SELECT, a menos que você a substitua por uma versão de substituição em tempo de execução, embora você também possa modificar a instrução padrão com parâmetros ou um filtro.

Observação

Se você especificar um nome de coluna que contenha (ou possa conter) espaços, precisará colocar o nome entre colchetes. Por exemplo, o nome "Primeiro Nome" deverá ser "[Primeiro Nome]".

Para substituir a instrução SELECT padrão, passe uma cadeia de caracteres contendo uma instrução SELECT completa quando você chamar Open. Em vez de construir uma cadeia de caracteres padrão própria, o conjunto de registros usa a cadeia de caracteres que você fornece. Se sua instrução de substituição contiver uma cláusula WHERE, não especifique um filtro m_strFilter porque você teria duas instruções de filtro. Da mesma forma, se sua instrução de substituição contiver uma cláusula ORDER BY, não especifique uma classificação em m_strSort para que você não tenha duas instruções de classificação.

Observação

Se você usar cadeias de caracteres literais em seus filtros (ou em outras partes da instrução SQL), talvez seja necessário "citar" (cercar de delimitadores especificados) essas cadeias de caracteres com um prefixo literal específico do DBMS e um caractere (ou caracteres) de sufixo literal.

Você também pode encontrar requisitos sintáticos especiais para operações como as junções externas, dependendo do DBMS. Use funções ODBC para obter essas informações do driver para o DBMS. Por exemplo, chame ::SQLGetTypeInfo para um tipo de dados específico, como SQL_VARCHAR, para solicitar os caracteres LITERAL_PREFIX e LITERAL_SUFFIX. Se você estiver escrevendo código independente do banco de dados, confira Apêndice C: Gramática do SQL na Referência de Programador de ODBC para obter informações detalhadas de sintaxe.

Um objeto de conjunto de registros constrói a instrução SQL que ele usa para selecionar registros, a menos que você passe uma instrução SQL personalizada. O modo como isso é feito depende principalmente do valor que você passa no parâmetro lpszSQL da função membro Open.

A forma geral de uma instrução SQL SELECT é:

SELECT [ALL | DISTINCT] column-list FROM table-list
    [WHERE search-condition][ORDER BY column-list [ASC | DESC]]

Uma maneira de adicionar a palavra-chave DISTINCT à instrução SQL do conjunto de registros é inserir a palavra-chave na primeira chamada de função RFX em DoFieldExchange. Por exemplo:

...
    RFX_Text(pFX, "DISTINCT CourseID", m_strCourseID);
...

Observação

Use essa técnica apenas com um conjunto de registros aberto como somente leitura.

Substituindo a instrução SQL

A tabela a seguir mostra as possibilidades para o parâmetro lpszSQL para Open. Os casos na tabela são explicados seguindo a tabela.

O parâmetro lpszSQL e a cadeia de caracteres SQL resultante

Case O que você passa no lpszSQL A instrução SELECT resultante
1 NULO SELECT rfx-field-list FROM table-name

CRecordset::Open chama GetDefaultSQL para obter o nome da tabela. A cadeia de caracteres resultante é um dos casos de 2 a 5, dependendo do que é retornado por GetDefaultSQL.
2 Um nome de tabela SELECT rfx-field-list FROM table-name

A lista de campos é obtida das instruções RFX em DoFieldExchange. Se m_strFilter e m_strSort não estiverem vazios, adicionará as cláusulas WHERE e/ou ORDER BY.
3 * Uma instrução SELECT completa, mas sem uma cláusula WHERE ou ORDER BY Conforme passado. Se m_strFilter e m_strSort não estiverem vazios, adicionará as cláusulas WHERE e/ou ORDER BY.
4 * Uma instrução SELECT completa com uma cláusula WHERE e/ou ORDER BY Conforme passado. m_strFilter e/ou m_strSort precisa permanecer vazio, ou duas instruções de filtro e/ou classificação serão produzidas.
5 * Uma chamada para um procedimento armazenado Conforme passado.

* m_nFields precisa ser menor ou igual ao número de colunas especificadas na instrução SELECT. O tipo de dados de cada coluna especificada na instrução SELECT precisa ser o mesmo que o tipo de dados da coluna de saída RFX correspondente.

Caso 1 lpszSQL = NULL

A seleção do conjunto de registros depende do que GetDefaultSQL retorna quando chamada por CRecordset::Open. Os casos 2 a 5 descrevem as cadeias de caracteres possíveis.

Caso 2 lpszSQL = um nome de tabela

O conjunto de registros usa a RFX (troca de campo de registro) para criar a lista de colunas com base nos nomes de coluna fornecidos nas chamadas de função RFX na substituição da classe recordset de DoFieldExchange. Se você usou um assistente para declarar sua classe de conjunto de registros, esse caso terá o mesmo resultado do caso 1 (desde que você passe o mesmo nome de tabela especificado no assistente). Se você não usar um assistente para escrever sua classe, o caso 2 será a maneira mais simples de construir a instrução SQL.

O exemplo a seguir constrói uma instrução SQL que seleciona registros de um aplicativo de banco de dados do MFC. Quando a estrutura chama a função membro GetDefaultSQL, a função retorna o nome da tabela, SECTION.

CString CEnrollSet::GetDefaultSQL()
{
    return "SECTION";
}

Para obter os nomes das colunas para a instrução SQL SELECT, a estrutura chama a função membro 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);
}

Quando concluída, a instrução SQL tem esta aparência:

SELECT CourseID, InstructorID, RoomNo, Schedule, SectionNo
    FROM SECTION

Caso 3 lpszSQL = uma instrução SELECT/FROM

Especifique a lista de colunas manualmente em vez de depender do RFX para construí-la automaticamente. Talvez você queira fazer isso quando:

  • Você deseja especificar a palavra-chave DISTINCT após SELECT.

    Sua lista de colunas deve corresponder aos nomes e tipos de coluna na mesma ordem em que eles estão listados em DoFieldExchange.

  • Você tem motivos para recuperar manualmente valores de coluna usando a função ODBC ::SQLGetData em vez de depender da RFX para associar e recuperar colunas para você.

    Você pode, por exemplo, querer acomodar novas colunas que um cliente do aplicativo adicionou às tabelas de banco de dados depois que o aplicativo foi distribuído. Você precisa adicionar esses membros de dados de campo extras, que não eram conhecidos no momento em que você declarou a classe com um assistente.

    Sua lista de colunas deve corresponder aos nomes e tipos de coluna na mesma ordem em que estão listados em DoFieldExchange, seguidos pelos nomes das colunas associadas manualmente. Para obter mais informações, confira Conjunto de registros: associando dinamicamente colunas de dados (ODBC).

  • Você deseja unir tabelas especificando várias tabelas na cláusula FROM.

    Para obter informações e um exemplo, confira Conjunto de registros: executando uma junção (ODBC).

Caso 4 lpszSQL = SELECT/FROM mais WHERE e/ou ORDER BY

Especifique tudo: a lista de colunas (com base nas chamadas RFX em DoFieldExchange), a lista de tabelas e o conteúdo de uma cláusula WHERE e/ou ORDER BY. Se você especificar suas cláusulas WHERE e/ou ORDER BY dessa forma, não use m_strFilter e/ou m_strSort.

Caso 5 lpszSQL = uma chamada de procedimento armazenado

Se você precisar chamar uma consulta predefinida (como um procedimento armazenado em um banco de dados do Microsoft SQL Server), precisará gravar uma instrução CALL na cadeia de caracteres passada para lpszSQL. Os assistentes não dão suporte à declaração de uma classe de conjunto de registros para chamar uma consulta predefinida. Nem todas as consultas predefinidas retornam registros.

Se uma consulta predefinida não retornar registros, você poderá usar a função membro ExecuteSQL de CDatabase diretamente. Para uma consulta predefinida que retorna registros, você também precisa gravar manualmente as chamadas RFX em DoFieldExchange para quaisquer colunas retornadas pelo procedimento. As chamadas RFX precisam estar na mesma ordem e retornar os mesmos tipos que a consulta predefinida. Para obter mais informações, confira Conjunto de registros: declarando uma classe para uma consulta predefinida (ODBC).

Confira também

SQL: tipos de dados SQL e C++ (ODBC)
SQL: fazendo chamadas SQL diretas (ODBC)