Эта статья вкратце познакомит вас с основами использования модулей Qt для работы с реляционными базами данных. Предполагается, что знание SQL у вас уже имеется, хотя и не является столь критичным для понимания представленных примеров.
Рассматриваются базовые операции, необходимые для начала работы:
- Открытие базы данных;
- Выполнение запросов;
- Выборка записей.
Подключение модуля sql к Qt-проекту
Для того, чтобы встроенные в Qt возможности для работы с SQL заработали, необходимо добавить в pro-файл следующую инструкцию:
1 |
QT += sql |
Однако учитывайте, что драйвера различных баз данных устанавливаются в виде плагинов и могут отсутствовать в вашем дистрибутиве Qt. Особенно актуальной это проблема является под Windows в связи с лицензионными ограничениями на распространение бинарных пакетов. О том, как собрать нужный плагин, мы поговорим в другой раз.
Подключение к базе данных QSQLITE
Для простоты воспользуемся драйвером QSQLITE (предназначен для работы с SQLite), поскольку он предустановлен во всех известных мне дистрибутивах Qt. К тому же, вам не потребуется устанавливать отдельную систему управлениями базами данных.
Рассмотрим соответствующий код подключения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <QDebug> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlRecord> #include <QSqlError> #include <QDate> int main() { QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLITE" ); db.setDatabaseName( "test" ); if( !db.open() ) { qDebug() << db.lastError().text(); return 1; } return 0; } |
Если все прошло нормально, то в результате работы этого кода у вас появится пустой файл test в рабочем каталоге приложения. Так же обратите внимание на следующие функции-члены класса QSqlDatabase, которые потребуются вам, когда вы решите воспользоваться внешним сервером баз данных:
- isValid();
- setHostName();
- setPort();
- setDatabaseName();
- setUserName();
- setPassword();
Выполнение запросов с помощью QSqlQuery
Создадим в открытой базе данных новую таблицу с помощью QSqlQuery:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <QDebug> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlRecord> #include <QSqlError> #include <QDate> int main() { // Предыдущий код убран для краткости QSqlQuery query( db ); if( !query.exec( "CREATE TABLE User(" " login VARCHAR( 200 ) NOT NULL," " registration_date DATE NOT NULL" ")" ) ) { qDebug() << db.lastError().text(); return 1; } return 0; } |
Аналогичным образом с помощью функции-члена exec() можно выполнять любые запросы к базе данных. Однако имеется одна тонкость.
Вставка записей в базу данных
Если запрос использует внешние данные, то в целях безопасности не вставляйте их напрямую, а используйте комбинацию prepare() и bindValue():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <QDebug> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlRecord> #include <QSqlError> #include <QDate> int main() { // Предыдущий код убран для краткости query.prepare( "INSERT INTO User( login, registration_date ) " " VALUES( :login, :registration_date )" ); query.bindValue( ":login", "Hello" ); query.bindValue( ":registration_date", QDate::currentDate() ); if( !query.exec() ) { qDebug() << db.lastError().text(); return 1; } return 0; } |
Выборка записей из базы данных
Теперь рассмотрим способ получения записей из базы данных:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include <QDebug> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlRecord> #include <QSqlError> #include <QDate> int main() { // Предыдущий код убран для краткости if( !query.exec( "SELECT * FROM User" ) ) { qDebug() << db.lastError().text(); return 1; } QSqlRecord rec = query.record(); const int loginIndex = rec.indexOf( "login" ); const int registrationDateIndex = rec.indexOf( "registration_date" ); while( query.next() ) { qDebug() << query.value( loginIndex ) << query.value( registrationDateIndex ); } return 0; } |
Заключение
Подводя итоги приведу полный листинг рассмотренного примера (обратите внимание на его завершение, дополненное кодом удаления таблицы и закрытия соединения с базой данных):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
#include <QDebug> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlRecord> #include <QSqlError> #include <QDate> int main() { QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLITE" ); db.setDatabaseName( "test" ); if( !db.open() ) { qDebug() << db.lastError().text(); return 1; } QSqlQuery query( db ); if( !query.exec( "CREATE TABLE User(" " login VARCHAR( 200 ) NOT NULL," " registration_date DATE NOT NULL" ")" ) ) { qDebug() << db.lastError().text(); return 1; } query.prepare( "INSERT INTO User( login, registration_date ) " " VALUES( :login, :registration_date )" ); query.bindValue( ":login", "Hello" ); query.bindValue( ":registration_date", QDate::currentDate() ); if( !query.exec() ) { qDebug() << db.lastError().text(); return 1; } if( !query.exec( "SELECT * FROM User" ) ) { qDebug() << db.lastError().text(); return 1; } QSqlRecord rec = query.record(); const int loginIndex = rec.indexOf( "login" ); const int registrationDateIndex = rec.indexOf( "registration_date" ); while( query.next() ) { qDebug() << query.value( loginIndex ) << query.value( registrationDateIndex ); } // Удаляем таблицу перед выходом query.exec( "DROP TABLE User" ); // Не обязательно, но в крупной системе лучше закрывать соединение с БД, когда оно больше не требуется db.close(); return 0; } |