Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

QSQLITE — SQLite версии 3 и выше,

QSQLITE2 — SQLite версии 2,

QTDS — Sybase Adaptive Server.

Из-за лицензионных ограничений не все драйверы входят в состав издания Qt с открытым исходным кодом (Qt Open Source Edition). При настройке конфигурации Qt драйверы SQL можно либо непосредственно включить в состав Qt, либо использовать как подключаемые модули (plugins). Qt поставляется вместе с SQLite — общедоступной, не нуждающейся в сервере базой данных.

Для пользователей, хорошо знакомых с синтаксисом SQL, класс QSqlQuery предоставляет средства, позволяющие непосредственно выполнять произвольные команды SQL и обрабатывать их результаты. Для пользователей, предпочитающих иметь дело с высокоуровневым интерфейсом базы данных, который не требует знания синтаксиса SQL,

классы QSqlTableModel и QSqlRelationalTableModel являются подходящими абстракциями. Эти классы представляют таблицы SQL в том же виде, как и классы других моделей Qt (рассмотренных в главе 10 ). Они могут использоваться самостоятельно для кодирования в программе просмотра и редактирования данных или могут подключаться к представлениям, с помощью которых конечные пользователи будут сами просматривать и редактировать данные.

Qt также позволяет легко программировать такие распространенные идиомы баз данных, как отображение зависимых представлений для записей, связанных отношением «главная—подчиненные» (master—detail), и возможность многократной детализации выводимых на экран данных (drill-down), что продемонстрируют некоторые примеры этой главы.

Соединение с базой данных и выполнение запросов

Для выполнения запросов SQL мы должны сначала установить соединение с базой данных. Обычно настройка соединений с базой данных выполняется отдельной функцией, которую мы вызываем при запуске приложения. Например:

01 bool createConnection

02 {

03 QSqlDatabase *db = QSqlDatabase::addDatabase("QOCI8");

04 db->setHostName("mozart.konkordia.edu");

05 db->setDatabaseName("musicdb");

06 db->setUserName("gbatstone");

07 db->setPassword("T17aV44");

08 if (!db->open) {

09 db->lastError.showMessage;

10 return false;

11 }

12 return true;

13 }

Во-первых, мы вызываем функцию QSqlDatabase::addDatabase для создания объекта QSqlDatabase. Первый аргумент функции addDatabase задает драйвер базы данных, который Qt должна использовать для доступа к базе данных. В данном случае мы используем MySQL (??? — в коде QOCI, Oracle Call Interface).

Затем мы устанавливаем имя хоста базы данных, имя базы данных, имя пользователя и пароль, и мы открываем соединение. Если функция open завершается неудачей, мы выводим сообщение об ошибке, используя QSqlError::showMessage.

Обычно функцию createConnection вызывают в main:

01 int main(int argc, char *argv[])

02 {

03 QApplication app(argc, argv);

04 if (!createConnection)

05 return 1;

06 return app.exec;

07 }

После установки соединения мы можем применять QSqlQuery для выполнения любой инструкции SQL, поддерживаемой используемой базой данных. Ниже приводится пример выполнения команды SELECT:

QSqlQuery query;

query.exec("SELECT title, year FROM cd WHERE year >= 1998");

После вызова функции exec мы можем просмотреть результат запроса:

while (query.next) {

QString title = query.value(0).toString;

int year = query.value(1).toInt;

cerr << qPrintable(title) << ": " << year << endl;

}

Мы

вызываем функцию next один раз для позиционирования QSqlQuery на первую запись полученного набора. Последующие вызовы next продвигают указатель записи на одну позицию дальше, пока не будет достигнут конец, когда функция next возвращает false. Если результирующий набор (result set) пустой (или запрос завершается неудачей), первый вызов функции next возвратит false.

Функция value возвращает значение поля, как QVariant. Поля пронумерованы начиная с 0 в порядке их указания в команде SELECT. Класс QVariant может содержать многие типы С++ и Qt, включая int и QString. Другие типы данных, которые могут храниться в базе данных, преобразуются в соответствующие типы С++ и Qt и хранятся в QVariant. Например, VARCHAR представляется в виде QString, a DATETIME — в виде QDateTime.

Класс QSqlQuery содержит некоторые другие функции для просмотра результирующего набора: first, last, previous и seek. Эти функции удобны, но для некоторых баз данных они могут выполняться медленнее и расходовать памяти больше, чем функция next. При работе с большими наборами данных мы можем осуществить простую оптимизацию, вызывая функцию QSqlQuery::setForwardOnly(true) перед вызовом exec, и только затем использовать next для просмотра результирующего набора.

Ранее мы задавали запрос SQL в аргументе функции QSqlQuery::exec, но, кроме того, мы можем передавать его непосредственно конструктору, который сразу же выполнит его:

QSqlQuery query("SELECT title, year FROM cd WHERE year >= 1998");

Мы можем проверить наличие ошибки, вызывая функцию isActive для запроса:

if (!query.isActive)

QMessageBox::warning(this, tr("Database Error"),

query.lastError.text);

Если ошибки нет, запрос становится «активным» и мы можем использовать next для перемещения по результирующему набору.

Выполнение команды INSERT осуществляется почти так же просто, как и команды SELECT:

QSqlQuery query("INSERT INTO cd (id, artistid, title, year) "

"VALUES (203, 102, 'Living in America', 2002)");

После этого функция numRowsAffected возвращает количество строк, которые были изменены инструкцией SQL (или —1, если возникла ошибка).

Если нам необходимо вставлять много записей или если мы хотим избежать преобразования значений в строковые данные (и правильного преобразования специальных символов), мы можем использовать функцию prepare для указания полей в шаблоне запроса и затем присваивания им необходимых нам значений. Qt поддерживает как стиль Oracle, так и стиль ODBC для всех баз данных, применяя, где возможно, «родной» интерфейс базы данных или имитируя его в противном случае. Ниже приводится пример, в котором используется синтаксис Oracle для представления поименованных полей:

Поделиться с друзьями: