Поделиться через


SQL: Настройка SQL-запроса набора записей (ODBC)

В этом разделе рассматриваются следующие вопросы.

  • Как платформа создает инструкцию SQL

  • Переопределение инструкции SQL

Примечание.

Эта информация относится к классам ODBC библиотеки MFC. Если вы работаете с классами DAO MFC, см. тему "Сравнение SQL ядра СУБД Microsoft Jet и ANSI SQL" в справке DAO.

Построение инструкций SQL

Набор записей основывается на выборе данных главным образом с помощью инструкции SQL SELECT. При объявлении класса с помощью мастера он записывает переопределяющую версию функции-члена GetDefaultSQL, которая для класса набора записей CAuthors выглядит примерно так.

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

По умолчанию это переопределение возвращает имя таблицы, указанное в мастере. В примере имя таблицы — "АВТОРЫ". При последующем вызове функции-члена Open набора Open записей создается окончательная инструкция SELECT формы:

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

где table-name получается путем вызова GetDefaultSQL и rfx-field-list получается из вызовов функции RFX в DoFieldExchange. Это то, что вы получаете для инструкции SELECT , если вы не замените ее переопределяющей версией во время выполнения, хотя вы также можете изменить инструкцию по умолчанию с параметрами или фильтром.

Примечание.

Если указать имя столбца, которое содержит пробелы (или может содержать), необходимо заключить имя в квадратные скобки. Например, имя "First Name" должно быть "[First Name]".

Чтобы переопределить инструкцию SELECT по умолчанию, передайте строку, содержащую полную инструкцию SELECT, когда вы вызываете Open. Вместо создания собственной строки по умолчанию набор записей использует заданную строку. Если оператор замены содержит предложение WHERE, не указывайте фильтр в m_strFilter, поскольку иначе у вас будет два фильтра. Аналогичным образом, если инструкция замены содержит предложение ORDER BY, не указывайте сортировку в m_strSort, чтобы не было двух инструкций сортировки.

Примечание.

Если вы используете литеральные строки в своих фильтрах (или других частях инструкции SQL), может потребоваться их цитирование — заключение в указанные разделители — с использованием префикса и суффикса, специфичных для СУБД, или множества символов.

Вы также можете столкнуться со специальными синтаксическими требованиями для таких операций, как внешние соединения, в зависимости от СУБД. Используйте функции ODBC для получения этих сведений от драйвера для СУБД. Например, чтобы запросить символы LITERAL_PREFIX и LITERAL_SUFFIX для конкретного типа данных, вызовите ::SQLGetTypeInfo, такого как SQL_VARCHAR. Если вы пишете независимый от базы данных код, ознакомьтесь с приложением C: Грамматика SQL в справочнике программиста ODBC для получения подробных сведений о синтаксисе.

Объект набора записей создает инструкцию SQL, которая используется для выбора записей, если только не передается настраиваемая инструкция SQL. Как это делается, главным образом зависит от значения параметра lpszSQL функции-члена Open.

Общая форма инструкции SQL SELECT :

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

Одним из способов добавления ключевого слова DISTINCT в SQL-инструкцию набора записей является включение его в первый вызов функции RFX в DoFieldExchange. Рассмотрим пример.

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

Примечание.

Используйте этот метод только с набором записей, открываемым только для чтения.

Переопределение инструкции SQL

В следующей таблице показаны возможности для параметра lpszSQLOpen. Примеры в таблице объясняются после таблицы.

Параметр lpszSQL и результирующая строка SQL

Кейс То, что вы передаете в lpszSQL Результирующая инструкция SELECT
1 Отсутствует SELECTrfx-field-listFROMtable-name

CRecordset::Open вызывает GetDefaultSQL для получения имени таблицы. Результирующая строка является одной из возможных ситуаций от 2 до 5, в зависимости от того, что возвращает GetDefaultSQL.
2 Имя таблицы SELECTrfx-field-listFROMtable-name

Список полей взят из инструкций RFX в DoFieldExchange. Если m_strFilter и m_strSort не пусты, добавляет условия WHERE и/или ORDER BY.
3* Полная инструкция SELECT, но без предложения WHERE или ORDER BY Как прошло. Если m_strFilter и m_strSort не пусты, добавляет условия WHERE и/или ORDER BY.
4* Полная инструкция SELECT с предложением WHERE и/или ORDER BY Как прошло. m_strFilter и (или) m_strSort должны оставаться пустыми, иначе будут созданы два оператора фильтрации и/или сортировки.
5 * Вызов хранимой процедуры Как принято.

* m_nFields должно быть меньше или равно количеству столбцов, указанных в инструкции SELECT . Тип данных каждого столбца, указанного в инструкции SELECT , должен совпадать с типом данных соответствующего выходного столбца RFX.

Случай 1 lpszSQL = NULL

Выбор набора записей зависит от того, что GetDefaultSQL возвращается при CRecordset::Open вызове. В случаях 2–5 описываются возможные строки.

Случай 2 lpszSQL = Имя таблицы

Набор записей использует обмен полями записей (RFX) для создания списка столбцов из имен столбцов, указанных в вызовах функции RFX в переопределении класса DoFieldExchange. Если вы использовали мастер для объявления класса наборов записей, этот случай имеет тот же результат, что и в случае 1 (при условии, что вы передаете то же имя таблицы, которое вы указали в мастере). Если вы не используете мастер для записи класса, вариант 2 является самым простым способом создания инструкции SQL.

В следующем примере создается инструкция SQL, которая выбирает записи из приложения базы данных MFC. Когда платформа вызывает GetDefaultSQL функцию-член, функция возвращает имя таблицы SECTION.

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

Чтобы получить имена столбцов для инструкции SQL SELECT , платформа вызывает 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);
}

По завершении инструкция SQL выглядит следующим образом:

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

Case 3 lpszSQL = инструкция SELECT/FROM

Вы указываете список столбцов вручную, а не полагаетесь на RFX для автоматического создания. Это может потребоваться сделать, когда:

  • Необходимо указать ключевое слово DISTINCT после SELECT.

    Список столбцов должен соответствовать именам и типам столбцов в DoFieldExchangeв том же порядке, в каком они указаны.

  • У вас есть основания вручную извлекать значения столбцов с помощью функции ::SQLGetData ODBC, а не полагаться на RFX для привязки и извлечения столбцов.

    Например, может потребоваться разместить новые столбцы, добавленные клиентом приложения в таблицы базы данных после распространения приложения. Необходимо добавить эти дополнительные элементы данных поля, которые не были известны в то время, когда вы объявили класс с помощью мастера.

    Список столбцов должен соответствовать именам столбцов и типам в том же порядке, в котором они перечислены в DoFieldExchange, после чего следуют имена столбцов, привязанных вручную. Для получения дополнительной информации см. в разделе Recordset: динамическая привязка столбцов данных (ODBC).

  • Вы хотите присоединить таблицы, указав несколько таблиц в предложении FROM .

    Сведения и пример см. в разделе Recordset: Выполнение соединения (ODBC).

Случай 4 lpszSQL = SELECT/FROM Plus WHERE и/или ORDER BY

Вы указываете все: список столбцов (на основе вызовов RFX в DoFieldExchange), список таблиц и содержимое предложения WHERE и/или предложения ORDER BY. Если вы укажете предложения WHERE и/или ORDER BY таким образом, не используйте m_strFilter и/или m_strSort.

Case 5 lpszSQL = вызов хранимой процедуры

Если необходимо вызвать предопределенный запрос (например, хранимую процедуру в базе данных Microsoft SQL Server), необходимо написать инструкцию CALL в строке, передаваемой в lpszSQL. Мастеры не поддерживают объявление класса набора записей для вызова предопределенного запроса. Не все предопределенные запросы возвращают записи.

Если предопределенный запрос не возвращает записи, можно напрямую использовать функцию-член CDatabaseExecuteSQL . Для предопределенного запроса, который возвращает записи, необходимо также вручную записать вызовы DoFieldExchange RFX для любых столбцов, возвращаемых процедурой. Вызовы RFX должны находиться в том же порядке и возвращать те же типы, что и предопределенный запрос. Дополнительные сведения см. в разделе Recordset: Объявление класса для предопределенного запроса (ODBC).

См. также

SQL. Типы данных SQL и C++ (ODBC)
SQL. Выполнение прямых вызовов SQL (ODBC)