SQL: Personalizar la instrucción SQL del conjunto de registros (ODBC)

En este tema se explica:

  • Cómo construye el marco de trabajo una instrucción SQL

  • Cómo invalidar la instrucción SQL

Nota:

Esta información es aplicable a las clases ODBC de MFC. Si trabaja con las clases DAO de MFC, consulte el tema "Comparación del código SQL del motor de base de datos Microsoft Jet y el código SQL ANSI" en la ayuda de DAO.

Construcción de la instrucción SQL

El conjunto de registros basa principalmente la selección de registros en una instrucción SELECT de SQL. Cuando declara la clase con un asistente, este escribe una versión de invalidación de la función miembro GetDefaultSQL que tiene un aspecto similar al siguiente (para una clase de conjunto de registros llamada CAuthors).

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

De manera predeterminada, esta invalidación devuelve el nombre de tabla que especificó con el asistente. En el ejemplo, el nombre de la tabla es "AUTHORS". Cuando más adelante llame a la función miembro Open del conjunto de registros, Open construye una instrucción SELECT final con el formato:

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

donde table-name se obtiene mediante una llamada a GetDefaultSQL y rfx-field-list se obtiene de las llamadas a la función RFX en DoFieldExchange. Esto es lo que obtiene para una instrucción SELECT a menos que lo reemplace por una versión de invalidación en tiempo de ejecución, aunque también puede modificar la instrucción predeterminada con parámetros o un filtro.

Nota:

Si especifica un nombre de columna que contiene (o podría contener) espacios, debe incluir el nombre entre corchetes. Por ejemplo, el nombre "First Name" debe ser "[First Name]".

Para invalidar la instrucción SELECT predeterminada, pase una cadena que contenga una instrucción SELECT completa al llamar a Open. En lugar de construir su propia cadena predeterminada, el conjunto de registros usa la cadena que le proporcione. Si la instrucción de reemplazo contiene una cláusula WHERE, no especifique un filtro en m_strFilter porque así tendría dos instrucciones de filtro. De forma similar, si la instrucción de reemplazo contiene una cláusula ORDER BY, no especifique una ordenación en m_strSort porque así tendría dos instrucciones de ordenación.

Nota:

Si usa cadenas literales en los filtros (u otras partes de la instrucción SQL), es posible que tenga que incluir entre "comillas" (incluir entre los delimitadores especificados) estas cadenas con un prefijo literal específico del DBMS y un carácter (o caracteres) de sufijo literal.

También puede encontrar requisitos sintácticos especiales para operaciones como las combinaciones externas, según el DBMS. Utilice las funciones de ODBC para obtener esta información del controlador sobre el DBMS. Por ejemplo, llame a ::SQLGetTypeInfo para un tipo de datos determinado, como SQL_VARCHAR, para solicitar los caracteres LITERAL_PREFIX y LITERAL_SUFFIX. Si está escribiendo código independiente de la base de datos, consulte el Apéndice C: Gramática de SQL en la Referencia del programador de ODBC para obtener información detallada sobre la sintaxis.

Un objeto de conjunto de registros construye la instrucción SQL que usa para seleccionar los registros a menos que le pase una instrucción SQL personalizada. La forma en la que esto se realiza depende principalmente del valor que pase en el parámetro lpszSQL de la función miembro Open.

La forma general de una instrucción SELECT de SQL es:

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

Una manera de agregar la palabra clave DISTINCT a la instrucción SQL del conjunto de registros es insertar la palabra clave en la primera llamada de función RFX en DoFieldExchange. Por ejemplo:

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

Nota:

Use esta técnica solo con un conjunto de registros abierto como de solo lectura.

Invalidación de la instrucción SQL

En la tabla siguiente, se muestran las posibilidades del parámetro lpszSQL en Open. Los casos de la tabla se explican después de la tabla.

Parámetro lpszSQL y cadena SQL resultante

Caso Lo que se pasa en lpszSQL Instrucción SELECT resultante
1 NULL SELECT rfx-field-list FROM table-name

CRecordset::Open llama a GetDefaultSQL para obtener el nombre de la tabla. La cadena resultante es uno de los casos entre el 2 y el 5, en función de lo que devuelva GetDefaultSQL.
2 Un nombre de tabla SELECT rfx-field-list FROM table-name

La lista de campos se toma de las instrucciones RFX de DoFieldExchange. Si m_strFilter y m_strSort no están vacíos, agrega las cláusulas WHERE y ORDER BY.
3* Instrucción SELECT completa, pero sin cláusula WHERE ni ORDER BY Tal y como se pasa. Si m_strFilter y m_strSort no están vacíos, agrega las cláusulas WHERE y ORDER BY.
4 * Una instrucción SELECT completa con una cláusula WHERE y/o ORDER BY Tal y como se pasa. m_strFilter y/o m_strSort deben permanecer vacíos o se generan dos instrucciones de filtro y ordenación.
5 * Una llamada a un procedimiento almacenado Tal y como se pasa.

* m_nFields debe ser menor o igual que el número de columnas especificado en la instrucción SELECT. El tipo de datos de cada columna especificada en la instrucción SELECT debe ser el mismo que el tipo de datos de la columna de salida de RFX correspondiente.

Caso 1: lpszSQL = NULL

La selección del conjunto de registros depende de lo que devuelva GetDefaultSQL cuando lo llama CRecordset::Open. Los casos del 2 al 5 describen las cadenas posibles.

Caso 2: lpszSQL = un nombre de tabla

El conjunto de registros usa el intercambio de campos de registros (RFX) para crear la lista de columnas a partir de los nombres de columna proporcionados en las llamadas de función de RFX en la invalidación de DoFieldExchange de la clase del conjunto de registros. Si ha utilizado un asistente para declarar la clase del conjunto de registros, este caso tiene el mismo resultado que el caso 1 (siempre que pase el mismo nombre de tabla que especificó en el asistente). Si no utilizó un asistente para escribir la clase, el caso 2 es la manera más sencilla de construir la instrucción SQL.

En el ejemplo siguiente, se crea una instrucción SQL que selecciona registros de una aplicación de base de datos de MFC. Cuando el marco de trabajo llama a la función miembro GetDefaultSQL, la función devuelve el nombre de la tabla, SECTION.

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

Para obtener los nombres de las columnas de la instrucción SELECT de SQL, el marco de trabajo llama a la función miembro 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);
}

Cuando haya finalizado, la instrucción SQL tiene el siguiente aspecto:

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

Caso 3: lpszSQL = una instrucción SELECT/FROM

Especifique la lista de columnas manualmente en lugar de confiar en RFX para construirla automáticamente. Es posible que quiera hacer esto cuando:

  • Quiere especificar la palabra clave DISTINCT después de SELECT.

    La lista de columnas debe coincidir con los nombres y los tipos de columna en el mismo orden en el que se muestran en DoFieldExchange.

  • Tiene motivos para recuperar manualmente los valores de columna mediante la función ::SQLGetData de ODBC en lugar de confiar en RFX para enlazar y recuperar automáticamente las columnas.

    Por ejemplo, podría querer dar cabida a las nuevas columnas que un cliente de la aplicación agregó a las tablas de base de datos después de distribuir la aplicación. Debe agregar estos miembros de datos de campo adicionales, que no se conocían en el momento en el que declaró la clase con un asistente.

    La lista de columnas debe coincidir con los nombres y los tipos de columna en el mismo orden en el que se muestran en DoFieldExchange, seguidos de los nombres de las columnas enlazadas manualmente. Para más información, consulte Conjunto de registros: enlazar dinámicamente columnas de datos (ODBC).

  • Quiere combinar tablas especificando varias tablas en la cláusula FROM.

    Para obtener información y un ejemplo, consulte Conjunto de registros: realizar una combinación (ODBC).

Caso 4: lpszSQL = SELECT/FROM más WHERE y/o ORDER BY

Especifique todo: la lista de columnas (basada en las llamadas RFX de DoFieldExchange), la lista de tablas y el contenido de una cláusula WHERE y/o una cláusula ORDER BY. Si especifica las cláusulas WHERE y ORDER BY de esta manera, no use m_strFilter ni m_strSort.

Caso 5: lpszSQL = una llamada a un procedimiento almacenado

Si tiene que llamar a una consulta predefinida (por ejemplo, un procedimiento almacenado en una base de datos de Microsoft SQL Server), debe escribir una instrucción CALL en la cadena que pase a lpszSQL. Los asistentes no admiten la declaración de una clase de conjunto de registros para llamar a una consulta predefinida. No todas las consultas predefinidas devuelven registros.

Si una consulta predefinida no devuelve registros, puede usar la función miembro ExecuteSQL de CDatabase directamente. Para una consulta predefinida que devuelve registros, también debe escribir manualmente las llamadas RFX de DoFieldExchange para cualquier columna que devuelva el procedimiento. Las llamadas RFX deben estar en el mismo orden y devolver los mismos tipos que la consulta predefinida. Para obtener más información, consulte Conjunto de registros: declarar una clase para una consulta predefinida (ODBC).

Consulte también

SQL: Tipos de datos de SQL y C++ (ODBC)
SQL: Realizar llamadas directas a SQL (ODBC)