Выполнение SQL-запросов
Класс QSqlQuery предоставляет интерфейс для выполнения SQL-запросов и навигации по результатам запроса.
Классы QSqlQueryModel и QSqlTableModel, описанные в следующем разделе, предоставляют интерфейс более высокого уровня для доступа к базам данных. Если вы не знакомы с SQL, возможно, вам следует перейти непосредственно к следующему разделу (Использование классов модели SQL).
Выполнение запроса
Для выполнения SQL-запроса просто создайте объект QSqlQuery и вызовите QSqlQuery::exec() следующим образом:
Конструктор QSqlQuery принимает необязательный объект QSqlDatabase, который указывает, какую базу данных использовать. В приведенном выше примере мы не указываем никакой связи, поэтому используется стандартное подключение.
Если произошла ошибка, exec() возвращает false. Ошибка затем доступна в виде QSqlQuery::lastError().
Навигация по набору результатов
QSqlQuery обеспечивает доступ к набору результатов по одному записям за раз. После вызова exec() внутренний указатель QSqlQuery находится в позиции перед первой записью. Мы должны вызывать QSqlQuery::next() один раз, чтобы перейти к первой записи, а затем next() снова многократно, чтобы получить доступ к другим записям, пока он не вернёт false. Вот типичный цикл, который итерируется по всем записям в порядке:
Функция QSqlQuery::value() возвращает значение поля в текущей записи. Поля указываются как индексы, начиная с нуля. QSqlQuery::value() возвращает QVariant, тип, который может содержать различные типы данных C++ и Qt Core, такие как int, QString и QByteArray. Разные типы баз данных автоматически отображаются на наиболее близкие эквиваленты Qt. В фрагменте кода мы вызываем QVariant::toString() и QVariant::toInt() для преобразования вариантов в QString и int.
Для обзора рекомендуемых типов для использования с поддерживаемыми Qt базами данных, обратитесь к этой таблице.
Вы можете перемещаться по набору данных с помощью QSqlQuery::next(), QSqlQuery::previous(), QSqlQuery::first(), QSqlQuery::last() и QSqlQuery::seek(). Текущий индекс строки возвращается QSqlQuery::at(), а общее количество строк в наборе результатов доступно как QSqlQuery::size() для баз данных, которые поддерживают эту функцию.
Чтобы определить, поддерживает ли драйвер базы данных данную функцию, используйте QSqlDriver::hasFeature(). В следующем примере мы вызываем QSqlQuery::size() для определения размера набора результатов базовой базы данных, которая поддерживает эту функцию; в противном случае мы переходим к последней записи и используем позицию запроса, чтобы узнать, сколько записей существует.
Если вы перемещаетесь по набору результатов и используете next() и seek() только для просмотра вперед, вы можете вызвать QSqlQuery::setForwardOnly(true) перед вызовом exec(). Это простое оптимизация, которая значительно ускорит запрос при работе с большими наборами результатов.
Вставка, обновление и удаление записей
QSqlQuery может выполнять произвольные SQL-запросы, а не только SELECT. Следующий пример вставляет запись в таблицу с помощью INSERT:
Если вы хотите вставить несколько записей одновременно, часто более эффективно отделить запрос от фактических вставляемых значений. Это можно сделать с помощью плейсхолдеров. Qt поддерживает два синтаксиса плейсхолдеров: именованные ссылки и позиционные ссылки. Вот пример именованных ссылок:
Вот пример позиционных ссылок:
Оба синтаксиса работают со всеми драйверами баз данных, предоставляемыми Qt. Если база данных поддерживает этот синтаксис нативно, Qt просто пересылает запрос в СУБД; в противном случае Qt моделирует синтаксис плейсхолдера путем предварительной обработки запроса. Фактический запрос, который в конечном итоге выполняется СУБД, доступен в виде QSqlQuery::executedQuery().
При вставке нескольких записей вам нужно вызвать QSqlQuery::prepare() только один раз. Затем вы вызываете bindValue() или addBindValue(), за которым следует exec(), столько раз, сколько необходимо.
Помимо производительности, одним из преимуществ плейсхолдеров является то, что вы можете легко указывать произвольные значения, не беспокоясь об экранировании специальных символов.
Обновление записи аналогично её вставке в таблицу:
Вы также можете использовать именованные или позиционные ссылки для сопоставления параметров с фактическими значениями.
Наконец, вот пример DELETE запроса:
Транзакции
Если базовая система управления базами данных поддерживает транзакции, QSqlDriver::hasFeature(QSqlDriver::Transactions) вернёт true. Вы можете использовать QSqlDatabase::transaction() для начала транзакции, за которым следуют SQL-команды, которые нужно выполнить в контексте транзакции, а затем либо QSqlDatabase::commit(), либо QSqlDatabase::rollback(). При использовании транзакций вы должны начать транзакцию перед созданием запроса.
Пример:
Транзакции могут использоваться для обеспечения атомарности сложной операции (например, поиска внешнего ключа и создания записи) или для предоставления способа отмены сложного изменения в середине.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/sql-sqlstatements.html