Qt:Документация 4.3.2/qtsql

Материал из Wiki.crossplatform.ru

(Различия между версиями)
Перейти к: навигация, поиск
(Новая: {{Qt4.3.2_header}} [Предыдущая: Модуль QtOpenGL] [ Модули Qt ] [С...)
 
(1 промежуточная версия не показана)
Строка 1: Строка 1:
{{Qt4.3.2_header}}
{{Qt4.3.2_header}}
-
[Предыдущая: [[Qt:Документация 4.3.2/qtopengl | Модуль QtOpenGL]]] [ [[Qt:Документация 4.3.2/modules | Модули Qt]] ] [Следующая: [[Qt:Документация 4.3.2/qtsvg | Модуль QtSvg]]]
+
[Предыдущая: [[Qt:Документация 4.3.2/qtopengl | Модуль QtOpenGL]] ] [ [[Qt:Документация 4.3.2/modules | Модуль Qt]] ] [Следующая: [[Qt:Документация 4.3.2/qtsvg | Модуль QtSvg]] ]  
=Модуль QtSql<br />=
=Модуль QtSql<br />=
Строка 7: Строка 7:
==Пространства Имен==
==Пространства Имен==
-
 
{|  width="100%"
{|  width="100%"
|- valign="top" class="odd" |  
|- valign="top" class="odd" |  
Строка 15: Строка 14:
==Классы==
==Классы==
-
 
{|  width="100%"
{|  width="100%"
|- valign="top" class="odd" |  
|- valign="top" class="odd" |  
Строка 66: Строка 64:
|Модуль данных для редактирования одной таблицы базы данных
|Модуль данных для редактирования одной таблицы базы данных
|}
|}
-
 
+
<div id="details"></div>
==Подробное описание==
==Подробное описание==
Модуль QtSql помогает реализовать бесшовную реализацию Ваших приложений с базами данных.
Модуль QtSql помогает реализовать бесшовную реализацию Ваших приложений с базами данных.
Классы SQL подразделяются на три слоя:
Классы SQL подразделяются на три слоя:
-
 
{|  width="100%"
{|  width="100%"
|- valign="top" class="qt-style" |  
|- valign="top" class="qt-style" |  
Строка 110: Строка 107:
*[[#presenting-data-in-a-table-view | Отображение данных в представлении-таблице]]
*[[#presenting-data-in-a-table-view | Отображение данных в представлении-таблице]]
*[[#creating-data-aware-forms | Создание дата-ориентироваными форм]]
*[[#creating-data-aware-forms | Создание дата-ориентироваными форм]]
 +
<div id="connecting-to-databases"></div>
 +
===Соединение с базой данных===
-
===Соединение с базой данных===
 
Прежде, чем получить доступ к базе данных с помощью классов [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] или [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]], вы должны установить с базой данных хотя бы одно соединение.
Прежде, чем получить доступ к базе данных с помощью классов [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] или [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]], вы должны установить с базой данных хотя бы одно соединение.
Строка 135: Строка 133:
         QSqlDatabase secondDB = QSqlDatabase::database("second");</source>  
         QSqlDatabase secondDB = QSqlDatabase::database("second");</source>  
Для удаления соединения с базой данных, сначала закройте базу данных с помощью [[Qt:Документация 4.3.2/qsqldatabase#close | QSqlDatabase::close]](), а затем, удалите ее с помощью статического метода [[Qt:Документация 4.3.2/qsqldatabase#removeDatabase | QSqlDatabase::removeDatabase]]().
Для удаления соединения с базой данных, сначала закройте базу данных с помощью [[Qt:Документация 4.3.2/qsqldatabase#close | QSqlDatabase::close]](), а затем, удалите ее с помощью статического метода [[Qt:Документация 4.3.2/qsqldatabase#removeDatabase | QSqlDatabase::removeDatabase]]().
 +
<div id="executing-sql-statements"></div>
 +
===Выполнение инструкций SQL===
-
===Выполнение инструкций SQL===
 
Класс [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] предоставляет интерфейс для выполнения инструкций SQL и навигации по результирующей ваборке запроса.
Класс [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] предоставляет интерфейс для выполнения инструкций SQL и навигации по результирующей ваборке запроса.
Классы [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]] и [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]], описанные в следующем разделе, предоставляют высокоуровневый интерфейс для доступа к базам данных. Если вы не знакомы с SQL, Вам, возможно, захочется сразу перейти к следующему разделу ([[#using-the-sql-model-classes | Использование классов SQL моделей]]).
Классы [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]] и [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]], описанные в следующем разделе, предоставляют высокоуровневый интерфейс для доступа к базам данных. Если вы не знакомы с SQL, Вам, возможно, захочется сразу перейти к следующему разделу ([[#using-the-sql-model-classes | Использование классов SQL моделей]]).
 +
<div id="executing-a-query"></div>
 +
====Выполнение Запроса====
-
====Выполнение Запроса====
 
Для выполнения SQL запросов, просто создают объект [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] и вызывают [[Qt:Документация 4.3.2/qsqlquery#exec | QSqlQuery::exec]](). Например, вот так:
Для выполнения SQL запросов, просто создают объект [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] и вызывают [[Qt:Документация 4.3.2/qsqlquery#exec | QSqlQuery::exec]](). Например, вот так:
<source lang="cpp-qt">        QSqlQuery query;
<source lang="cpp-qt">        QSqlQuery query;
Строка 148: Строка 148:
Если возникает ошибка, [[Qt:Документация 4.3.2/qsqlquery#exec | exec()]] возвращает false. Доступ к ошибке можно получить с помощью [[Qt:Документация 4.3.2/qsqlquery#lastError | QSqlQuery::lastError]]().
Если возникает ошибка, [[Qt:Документация 4.3.2/qsqlquery#exec | exec()]] возвращает false. Доступ к ошибке можно получить с помощью [[Qt:Документация 4.3.2/qsqlquery#lastError | QSqlQuery::lastError]]().
-
 
+
<div id="navigating-the-result-set"></div>
====Навигация по результирующей выборке====
====Навигация по результирующей выборке====
 +
[[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] предоставляет единовременный доступ к результирующей выборке одного запроса. После вызова [[Qt:Документация 4.3.2/qsqlquery#exec | exec()]], внутренний указатель [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] указывает на позицию ''перед'' первой записью.Мы должны вызвать метод [[Qt:Документация 4.3.2/qsqlquery#next | QSqlQuery::next]]() один раз, чтобы переместить указатель к первой записи, затем снова повторять [[Qt:Документация 4.3.2/qsqlquery#next | next()]], чтобы получать доступ к другим записям, до тех пор пока он не вернет false. Вот типичный цикл перебирающий все записи по порядку:
[[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] предоставляет единовременный доступ к результирующей выборке одного запроса. После вызова [[Qt:Документация 4.3.2/qsqlquery#exec | exec()]], внутренний указатель [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] указывает на позицию ''перед'' первой записью.Мы должны вызвать метод [[Qt:Документация 4.3.2/qsqlquery#next | QSqlQuery::next]]() один раз, чтобы переместить указатель к первой записи, затем снова повторять [[Qt:Документация 4.3.2/qsqlquery#next | next()]], чтобы получать доступ к другим записям, до тех пор пока он не вернет false. Вот типичный цикл перебирающий все записи по порядку:
<source lang="cpp-qt">        while (query.next()) {
<source lang="cpp-qt">        while (query.next()) {
Строка 174: Строка 175:
         }</source>  
         }</source>  
Если вы перебираете результирующую выборку только с помощью вызовов next() и seek() с положительными значениями, то можете перед вызовом exec() вызвать QSqlQuery::setForwardOnly(true). Эта небольшая оптимизация сильно ускорит выполнение запросов, возвращающих большие выборки.
Если вы перебираете результирующую выборку только с помощью вызовов next() и seek() с положительными значениями, то можете перед вызовом exec() вызвать QSqlQuery::setForwardOnly(true). Эта небольшая оптимизация сильно ускорит выполнение запросов, возвращающих большие выборки.
-
 
+
<div id="inserting-updating-and-deleting-records"></div>
====Вставка, изменение и удаление записей====
====Вставка, изменение и удаление записей====
 +
[[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] может выполнять произвольные запросы SQL, а не только <tt>SELECT</tt>. Следующий пример вставляет запись в таблицу используя выражение <tt>INSERT</tt>:
[[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] может выполнять произвольные запросы SQL, а не только <tt>SELECT</tt>. Следующий пример вставляет запись в таблицу используя выражение <tt>INSERT</tt>:
<source lang="cpp-qt">        QSqlQuery query;
<source lang="cpp-qt">        QSqlQuery query;
Строка 209: Строка 211:
В конце приведем пример выражения <tt>DELETE</tt>:
В конце приведем пример выражения <tt>DELETE</tt>:
<source lang="cpp-qt">        QSqlQuery query;
<source lang="cpp-qt">        QSqlQuery query;
-
         query.exec("DELETE FROM employee WHERE id = 1007");</source>  
+
         query.exec("DELETE FROM employee WHERE id = 1007");</source> <div id="transactions"></div>
====Транзакции====
====Транзакции====
 +
Если основной движок базы данных поддерживает транзакции, то QSqlDriver::hasFeature([[Qt:Документация 4.3.2/qsqldriver#DriverFeature-enum | QSqlDriver::Transactions]]) возвратит true. Для инициации транзакции вы можете использовать [[Qt:Документация 4.3.2/qsqldatabase#transaction | QSqlDatabase::transaction]](), затем запустить инструкции SQL, которые вы хотите выполнить в пределах транзакции, а после вызвать [[Qt:Документация 4.3.2/qsqldatabase#commit | QSqlDatabase::commit]]() или [[Qt:Документация 4.3.2/qsqldatabase#rollback | QSqlDatabase::rollback]]().
Если основной движок базы данных поддерживает транзакции, то QSqlDriver::hasFeature([[Qt:Документация 4.3.2/qsqldriver#DriverFeature-enum | QSqlDriver::Transactions]]) возвратит true. Для инициации транзакции вы можете использовать [[Qt:Документация 4.3.2/qsqldatabase#transaction | QSqlDatabase::transaction]](), затем запустить инструкции SQL, которые вы хотите выполнить в пределах транзакции, а после вызвать [[Qt:Документация 4.3.2/qsqldatabase#commit | QSqlDatabase::commit]]() или [[Qt:Документация 4.3.2/qsqldatabase#rollback | QSqlDatabase::rollback]]().
Строка 225: Строка 228:
         QSqlDatabase::database().commit();</source>  
         QSqlDatabase::database().commit();</source>  
Транзакции можно использовать для того, чтобы гарантировать атомарность сложного действия (например, просмотр внешних ключей и создание записи) или для возможности отмены сложного действия в процессе его выполнения.
Транзакции можно использовать для того, чтобы гарантировать атомарность сложного действия (например, просмотр внешних ключей и создание записи) или для возможности отмены сложного действия в процессе его выполнения.
-
 
+
<div id="using-the-sql-model-classes"></div>
===Использование классов SQL моделей ===
===Использование классов SQL моделей ===
 +
В дополнение к [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]], Qt предлагает три высокоуровневых класса для работы с базами данных. Это классы [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]], [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] и [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]].
В дополнение к [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]], Qt предлагает три высокоуровневых класса для работы с базами данных. Это классы [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]], [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] и [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]].
Строка 243: Строка 247:
Другое преимущество использования этих классов состоит в том, что они облегчают приспособление кода к другому источнику данных. Например, если вы использовали [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]], а затем решили вместо базы данных использовать XML-файлы для хранения данных, то изменение кода - это вопрос замены одной модели данных на другую.
Другое преимущество использования этих классов состоит в том, что они облегчают приспособление кода к другому источнику данных. Например, если вы использовали [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]], а затем решили вместо базы данных использовать XML-файлы для хранения данных, то изменение кода - это вопрос замены одной модели данных на другую.
-
 
+
<div id="the-sql-query-model"></div>
====Модель: SQL запрос====
====Модель: SQL запрос====
 +
[[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]] предлагает основанную на SQL запросе модель только-для-чтения.
[[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]] предлагает основанную на SQL запросе модель только-для-чтения.
Строка 259: Строка 264:
Также есть перегруженный метод [[Qt:Документация 4.3.2/qsqlquerymodel#setQuery | setQuery()]], который принимает объект [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] и работает с его результирующей выборкой. Это позволяет Вам использовать любые возможности [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] для установки запроса (например, QSqlQuery::prepare()).
Также есть перегруженный метод [[Qt:Документация 4.3.2/qsqlquerymodel#setQuery | setQuery()]], который принимает объект [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] и работает с его результирующей выборкой. Это позволяет Вам использовать любые возможности [[Qt:Документация 4.3.2/qsqlquery | QSqlQuery]] для установки запроса (например, QSqlQuery::prepare()).
 +
<div id="the-sql-table-model"></div>
 +
====Модель: SQL Таблица====
-
====Модель: SQL Таблица====
 
[[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] предлагает модель для чтения и записи, которая работает одновременно только с одной таблицей SQL.
[[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] предлагает модель для чтения и записи, которая работает одновременно только с одной таблицей SQL.
Строка 308: Строка 314:
*Без кэширования может снизиться скорость работы.
*Без кэширования может снизиться скорость работы.
*Если вы изменили первичный ключ, то запись может ускользнуть от Вас, пока вы пытаетесь ее заполнить,.
*Если вы изменили первичный ключ, то запись может ускользнуть от Вас, пока вы пытаетесь ее заполнить,.
-
 
+
<div id="the-sql-relational-table-model"></div>
====Модель: реляционной SQL таблицы====
====Модель: реляционной SQL таблицы====
 +
[[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]] расширяет [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] для предоставления поддержки внешних ключей. Внешний ключ - это связть один-к-одному, установленная между полем одной таблицы и полем первичного ключа другой таблицы. Например, если таблица <tt>book</tt> имеет поле с названием <tt>authorid</tt>, которое ссылается на поле <tt>id</tt> таблицы авторов, вы указываете, что поле <tt>authorid</tt> является первичным ключем.
[[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]] расширяет [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] для предоставления поддержки внешних ключей. Внешний ключ - это связть один-к-одному, установленная между полем одной таблицы и полем первичного ключа другой таблицы. Например, если таблица <tt>book</tt> имеет поле с названием <tt>authorid</tt>, которое ссылается на поле <tt>id</tt> таблицы авторов, вы указываете, что поле <tt>authorid</tt> является первичным ключем.
Строка 325: Строка 332:
         model->setRelation(3, QSqlRelation("country", "id", "name"));</source>  
         model->setRelation(3, QSqlRelation("country", "id", "name"));</source>  
Более подробную информацию см. в описании [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]].
Более подробную информацию см. в описании [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]].
-
 
+
<div id="presenting-data-in-a-table-view"></div>
===Отображение данных в таблице-представлении===
===Отображение данных в таблице-представлении===
 +
Классы [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]], [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] и [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]] могут использоваться в качестве источников данных для классов представлений Qt, таких как [[Qt:Документация 4.3.2/qlistview | QListView]], [[Qt:Документация 4.3.2/qtableview | QTableView]] и [[Qt:Документация 4.3.2/qtreeview | QTreeView]]. На практике, наиболее часто используется [[Qt:Документация 4.3.2/qtableview | QTableView]] в связи с тем, что результирующая SQL выборка, по существу, представляет собой двумерную структуру данных.
Классы [[Qt:Документация 4.3.2/qsqlquerymodel | QSqlQueryModel]], [[Qt:Документация 4.3.2/qsqltablemodel | QSqlTableModel]] и [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]] могут использоваться в качестве источников данных для классов представлений Qt, таких как [[Qt:Документация 4.3.2/qlistview | QListView]], [[Qt:Документация 4.3.2/qtableview | QTableView]] и [[Qt:Документация 4.3.2/qtreeview | QTreeView]]. На практике, наиболее часто используется [[Qt:Документация 4.3.2/qtableview | QTableView]] в связи с тем, что результирующая SQL выборка, по существу, представляет собой двумерную структуру данных.
Строка 399: Строка 407:
Пример [[Qt:Документация 4.3.2/sql-relationaltablemodel | Relational Table Model]] иллюстрирует использование [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]] в совокупности с [[Qt:Документация 4.3.2/qsqlrelationaldelegate | QSqlRelationalDelegate]] для представления таблицы с поддержкой внешнего ключа.
Пример [[Qt:Документация 4.3.2/sql-relationaltablemodel | Relational Table Model]] иллюстрирует использование [[Qt:Документация 4.3.2/qsqlrelationaltablemodel | QSqlRelationalTableModel]] в совокупности с [[Qt:Документация 4.3.2/qsqlrelationaldelegate | QSqlRelationalDelegate]] для представления таблицы с поддержкой внешнего ключа.
 +
<div id="creating-data-aware-forms"></div>
 +
===Создание информационно-связанных форм===
-
===Создание информационно-связанных форм===
 
Использование SQL моделей описано выше, содержимое базы данных может быть представлено в других компонентах модель-представление. Для некоторых приложений достаточно, чтобы представить эти данные используя стандартные элемент-ориентированые представления, такие как [[Qt:Документация 4.3.2/qtableview | QTableView]]. Однако, пользователям  приложений, основанных на манипулировании записями, часто требуется пользовательский интерфейс содержащий формы, в котором данные из определенной строки или колонки в таблице базы данных используются, чтобы заполнять виджет-редактор на форме.
Использование SQL моделей описано выше, содержимое базы данных может быть представлено в других компонентах модель-представление. Для некоторых приложений достаточно, чтобы представить эти данные используя стандартные элемент-ориентированые представления, такие как [[Qt:Документация 4.3.2/qtableview | QTableView]]. Однако, пользователям  приложений, основанных на манипулировании записями, часто требуется пользовательский интерфейс содержащий формы, в котором данные из определенной строки или колонки в таблице базы данных используются, чтобы заполнять виджет-редактор на форме.
Строка 411: Строка 420:
Демонстрация [[Qt:Документация 4.3.2/demos-books | Books]] показывает, как информация может быть представлена для легкого доступа используя [[Qt:Документация 4.3.2/qdatawidgetmapper | QDataWidgetMapper]] и набор простых виджетов ввода.
Демонстрация [[Qt:Документация 4.3.2/demos-books | Books]] показывает, как информация может быть представлена для легкого доступа используя [[Qt:Документация 4.3.2/qdatawidgetmapper | QDataWidgetMapper]] и набор простых виджетов ввода.
-
[Предыдущая: [[Qt:Документация 4.3.2/qtopengl | Модуль QtOpenGL]]] [ [[Qt:Документация 4.3.2/modules | Модули Qt]] ] [Следующая: [[Qt:Документация 4.3.2/qtsvg | Модуль QtSvg]]]
+
[Предыдущая: [[Qt:Документация 4.3.2/qtopengl | Модуль QtOpenGL]] ] [ [[Qt:Документация 4.3.2/modules | Модули Qt]] ] [Следующая: [[Qt:Документация 4.3.2/qtsvg | Модуль QtSvg]] ]  
-
 
+
{{Qt4.3.2_footer}}
{{Qt4.3.2_footer}}

Текущая версия на 10:52, 6 ноября 2008

40px Внимание: Актуальная версия перевода документации находится здесь

__NOTOC__

Image:qt-logo.png

Главная · Все классы · Основные классы · Классы по группам · Модули · Функции

Image:trolltech-logo.png

[Предыдущая: Модуль QtOpenGL ] [ Модуль Qt ] [Следующая: Модуль QtSvg ]

Содержание

[править] Модуль QtSql

Модуль QtSql помогает реализовать бесшовную реализацию ваших приложений с базами данных. Далее...

[править] Пространства Имен

QSql Различные идентификаторы, используемые в разных библиотеках Qt SQL

[править] Классы

QSqlDatabase Предоставляет соединение с базой данных
QSqlDriver Абстрактный базовый класс для доступа к специфическим базам данных SQL
QSqlDriverCreator Класс-шаблон, предоставляющий фабрику драйверов SQL для специфических типов драйверов
QSqlDriverCreatorBase Базовый класс для фабрик драйверов SQL
QSqlDriverPlugin Абстрактный базовый класс для собственных плагинов QSqlDriver
QSqlError Информация об ошибке базы данных SQL
QSqlField Управление полями в таблицах и представлениях базы данных SQL
QSqlIndex Функции для управления индексами базы данных и их описания
QSqlQuery Средства управления выражениями SQL и их выполнения
QSqlQueryModel Модуль данных только-для-чтения результирующей SQL-выборки
QSqlRecord Заключает в себе запись базы данных
QSqlRelation Содержит информацию о внешнем ключе SQL
QSqlRelationalDelegate Делегат, используемый для отображения и редактирования данных модели QSqlRelationalTableModel
QSqlRelationalTableModel Модель данных для редактирования одной таблицы базы данных с поддержкой внешних ключей
QSqlResult Абстрактный интерфейс для доступа к данным специфичной базы SQL
QSqlTableModel Модуль данных для редактирования одной таблицы базы данных

[править] Подробное описание

Модуль QtSql помогает реализовать бесшовную реализацию Ваших приложений с базами данных.

Классы SQL подразделяются на три слоя:

Слой Описание
Слой Драйвера Включает классы QSqlDriver, QSqlDriverCreator<T>, QSqlDriverCreatorBase, QSqlDriverPlugin и QSqlResult. Этот слой предоставляет низкоуровневый мост между определенными базами данных и слоем SQL API. Для получения более подробной информации, см. Драйвера баз данных SQL.
Слой SQL API Эти классы предоставляют доступ к базам данных. Связь устанавливается с помощью класса QSqlDatabase. Взаимодействие с базой данных осуществляется с помощью класса QSqlQuery. В дополнение к классам QSqlDatabase и QSqlQuery, слой SQL API опирается на классы QSqlError, QSqlField, QSqlIndex и QSqlRecord.
Слой пользовательского интерфейса Эти классы связывают данные из базы данных с дата-ориентироваными виджетами. Сюда входят такие классы, как QSqlQueryModel, QSqlTableModel и QSqlRelationalTableModel. Эти классы разработаны для работы с каркасом Qt модель/представление.

Для включения определений классов модуля, используйте следующую директиву:

    #include <QtSql>

Для сборки Вашего проекта с модулем, добавьте в Ваш qmake .pro-файл следующую строку:

    QT += sql

Модуль QtSql входит в состав Qt Console Edition, Qt Desktop Edition и Qt Open Source Edition.

Данный обзор предполагает, что вы имеете, по крайней мере, базовые знания об SQL. Вы должны иметь представления о простейших выражениях SELECT, INSERT, UPDATE и DELETE. Несмотря на то, что класс QSqlTableModel предоставляет интерфейс для просмотра и редактирования базы данных без знания SQL, наличие базовых представлений об SQL настоятельно рекомендуется. Стандартное описание баз данных SQL - это An Introduction to Database Systems (7th Ed.) by C. J. Date, ISBN 0201385902.

Разделы:

[править] Соединение с базой данных

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

Соединения с базой данных идентифицируются с помощью произвольных строк. QSqlDatabase также поддерживает концепцию соединения по умолчанию, которое используется классом Qt SQL если никакое другое соединение не указано. Этот механизм очень удобен для приложений, использующих только одно соединение с базой данных.

Следующий код устанавливает соединение с базой данных MySQL с именем flightdb на хосте bigblue:

        QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
        db.setHostName("bigblue");
        db.setDatabaseName("flightdb");
        db.setUserName("acarlson");
        db.setPassword("1uTbSbAs");
        bool ok = db.open();

Первый аргумент QSqlDatabase::addDatabase() - это имя драйвера. Для получения списка драйверов, см. документацию addDatabase(). Для инициализации данных соединения мы вызываем setHostName(), setDatabaseName(), setUserName() и setPassword().

Так как имя соединения не определено, соединение становится соединением по умолчанию. Для определения имени, передайте его в качестве второго аргумента в QSqlDatabase::addDatabase(). Например:

        QSqlDatabase firstDB = QSqlDatabase::addDatabase("QMYSQL", "first");
        QSqlDatabase secondDB = QSqlDatabase::addDatabase("QMYSQL", "second");

Как только соединение инициализировано, мы должны вызвать QSqlDatabase::open() для открытия бызы данных и получения доступа к данным. Если запрос соединения потерпит неудачу, функция возвратит false; информацию об ошибке можно получить из QSqlDatabase::lastError().

Как только соединение установлено, мы можем получить указатель на него из любого места прораммы, вызвав статическую функцию QSqlDatabase::database(). Если мы вызываем данную функцию без параметра, она возвратит указатель на соединение по умолчанию. Если функция вызывается с идентификатором, использованным при установке соединения, она возвратит ссылку на указанное соединение. Например:

        QSqlDatabase defaultDB = QSqlDatabase::database();
        QSqlDatabase firstDB = QSqlDatabase::database("first");
        QSqlDatabase secondDB = QSqlDatabase::database("second");

Для удаления соединения с базой данных, сначала закройте базу данных с помощью QSqlDatabase::close(), а затем, удалите ее с помощью статического метода QSqlDatabase::removeDatabase().

[править] Выполнение инструкций SQL

Класс QSqlQuery предоставляет интерфейс для выполнения инструкций SQL и навигации по результирующей ваборке запроса.

Классы QSqlQueryModel и QSqlTableModel, описанные в следующем разделе, предоставляют высокоуровневый интерфейс для доступа к базам данных. Если вы не знакомы с SQL, Вам, возможно, захочется сразу перейти к следующему разделу ( Использование классов SQL моделей).

[править] Выполнение Запроса

Для выполнения SQL запросов, просто создают объект QSqlQuery и вызывают QSqlQuery::exec(). Например, вот так:

        QSqlQuery query;
        query.exec("SELECT name, salary FROM employee WHERE salary > 50000");

Конструктор QSqlQuery принимает необязательный аргумент QSqlDatabase, который указывает, какое соединение с базой данных используется. В нижеприведенном примере, мы не указываем соединение, поэтому используется соединение по умолчанию.

Если возникает ошибка, exec() возвращает false. Доступ к ошибке можно получить с помощью QSqlQuery::lastError().

[править] Навигация по результирующей выборке

QSqlQuery предоставляет единовременный доступ к результирующей выборке одного запроса. После вызова exec(), внутренний указатель QSqlQuery указывает на позицию перед первой записью.Мы должны вызвать метод QSqlQuery::next() один раз, чтобы переместить указатель к первой записи, затем снова повторять next(), чтобы получать доступ к другим записям, до тех пор пока он не вернет false. Вот типичный цикл перебирающий все записи по порядку:

        while (query.next()) {
            QString name = query.value(0).toString();
            int salary = query.value(1).toInt();
            qDebug() << name << salary;
        }

Функция QSqlQuery::value() возвращает значение поля текущей записи. Поля задаются индексами начиная с нуля. Функция QSqlQuery::value() возвращает значение типа QVariant, который может хранить значения различных типов C++ и ядра Qt, такие как int, QString и QByteArray. Различные типы значений базы данных автоматически приводятся к ближайшему эквиваленту в Qt. В предыдущем примере кода мы вызывали QVariant::toString() и QVariant::toInt(), чтобы конвертировать возвращенное значение в QString и int соответственно.

Вы можете перемещаться взад и вперед по выборке, используя функции QSqlQuery::next(), QSqlQuery::previous(), QSqlQuery::first(), QSqlQuery::last() и QSqlQuery::seek(). Текущий номер строки можно получить с помощью QSqlQuery::at(), а общее количество строк в выборке, если это поддерживается базой данных, возвращается функцией QSqlQuery::size().

Определить, поддерживает ли драйвер базы данных определенную особенность можно с помощью вызова функции QSqlDriver::hasFeature(). В следующем примере мы вызываем QSqlQuery::size() для определения размера результирующей выборке, только в том случае, если база данных поддерживает такую возможность; в противном случае мы перемещаемся к последней записи и используем ее позицию в выборке для определения количечества записей.

        QSqlQuery query;
        int numRows;
        query.exec("SELECT name, salary FROM employee WHERE salary > 50000");
 
        QSqlDatabase defaultDB = QSqlDatabase::database();
        if (defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)) {
            numRows = query.size();
        } else {
            // this can be very slow
            query.last();
            numRows = query.at() + 1;
        }

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

[править] Вставка, изменение и удаление записей

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

        QSqlQuery query;
        query.exec("INSERT INTO employee (id, name, salary) "
                   "VALUES (1001, 'Thad Beaumont', 65000)");

Если вы хотите одновременно вставить множество записей, то зачастую эффективней отделить запрос от реально вставляемых значений. Это можно сделать с помощью вставки значений через параметры. Qt поддерживает два синтаксиса вставки значений: поименованые параметры и позиционные параметры. В следующем примере показана вставка с помощью поименованного параметра:

        QSqlQuery query;
        query.prepare("INSERT INTO employee (id, name, salary) "
                      "VALUES (:id, :name, :salary)");
        query.bindValue(":id", 1001);
        query.bindValue(":name", "Thad Beaumont");
        query.bindValue(":salary", 65000);
        query.exec();

В этом примере показана вставка с помощью позиционного параметра:

        QSqlQuery query;
        query.prepare("INSERT INTO employee (id, name, salary) "
                      "VALUES (?, ?, ?)");
        query.addBindValue(1001);
        query.addBindValue("Thad Beaumont");
        query.addBindValue(65000);
        query.exec();

Оба синтаксиса работают со всеми драйверами баз данных предоставляемыми Qt. Если база данных поддерживает синтаксис, Qt просто пересылает запрос в СУБД; в противном случае, Qt симулирует синтаксис параметров и осуществляет предобработку запроса. Фактический запрос, который поступает на выполнение в СУБД доступен с помощью QSqlQuery::executedQuery().

При вставке множества записей, Вам требуется вызвать QSqlQuery::prepare() только однажды. После этого вы можете вызвать bindValue() или addBindValue() с последующим вызовом exec() столько раз, сколько потребуется.

Помимо удобства выполнения, вставка через параметры имеет еще и то преимущество, что вы избавлены от необходимости заботиться о преобразовании специальных символов.

Изменение записей очень похоже на вставку в таблицу:

        QSqlQuery query;
        query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003");

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

В конце приведем пример выражения DELETE:

        QSqlQuery query;
        query.exec("DELETE FROM employee WHERE id = 1007");

[править] Транзакции

Если основной движок базы данных поддерживает транзакции, то QSqlDriver::hasFeature( QSqlDriver::Transactions) возвратит true. Для инициации транзакции вы можете использовать QSqlDatabase::transaction(), затем запустить инструкции SQL, которые вы хотите выполнить в пределах транзакции, а после вызвать QSqlDatabase::commit() или QSqlDatabase::rollback().

Пример:

        QSqlDatabase::database().transaction();
        QSqlQuery query;
        query.exec("SELECT id FROM employee WHERE name = 'Torild Halvorsen'");
        if (query.next()) {
            int employeeId = query.value(0).toInt();
            query.exec("INSERT INTO project (id, name, ownerid) "
                       "VALUES (201, 'Manhattan Project', "
                       + QString::number(employeeId) + ")");
        }
        QSqlDatabase::database().commit();

Транзакции можно использовать для того, чтобы гарантировать атомарность сложного действия (например, просмотр внешних ключей и создание записи) или для возможности отмены сложного действия в процессе его выполнения.

[править] Использование классов SQL моделей

В дополнение к QSqlQuery, Qt предлагает три высокоуровневых класса для работы с базами данных. Это классы QSqlQueryModel, QSqlTableModel и QSqlRelationalTableModel.

QSqlQueryModel Модель только-для-чтения, основаннная на произвольных SQL-запросах.
QSqlTableModel Модель для чтения-записи работающая с одной таблицей.
QSqlRelationalTableModel Подкласс QSqlTableModel с поддержкой внешних ключей.

Эти классы происходят от QAbstractTableModel (который в свою очередь происходит от QAbstractItemModel) и могут существенно облегчить представление данных из базы данных в элементно-ориентированых классах таких, как QListView и QTableView. Это подробно объясняется в разделе Отображение данных в таблице-представлении.

Другое преимущество использования этих классов состоит в том, что они облегчают приспособление кода к другому источнику данных. Например, если вы использовали QSqlTableModel, а затем решили вместо базы данных использовать XML-файлы для хранения данных, то изменение кода - это вопрос замены одной модели данных на другую.

[править] Модель: SQL запрос

QSqlQueryModel предлагает основанную на SQL запросе модель только-для-чтения.

Пример:

        QSqlQueryModel model;
        model.setQuery("SELECT * FROM employee");
 
        for (int i = 0; i < model.rowCount(); ++i) {
            int id = model.record(i).value("id").toInt();
            QString name = model.record(i).value("name").toString();
            qDebug() << id << name;
        }

После настройки запроса с помощью QSqlQueryModel::setQuery(), Вы, можете использовать QSqlQueryModel::record(int) для получения доступа к отдельным записям. Также можете использовать QSqlQueryModel::data() и другие функции, унаследованные от QAbstractItemModel.

Также есть перегруженный метод setQuery(), который принимает объект QSqlQuery и работает с его результирующей выборкой. Это позволяет Вам использовать любые возможности QSqlQuery для установки запроса (например, QSqlQuery::prepare()).

[править] Модель: SQL Таблица

QSqlTableModel предлагает модель для чтения и записи, которая работает одновременно только с одной таблицей SQL.

Пример:

        QSqlTableModel model;
        model.setTable("employee");
        model.setFilter("salary > 50000");
        model.setSort(2, Qt::DescendingOrder);
        model.select();
 
        for (int i = 0; i < model.rowCount(); ++i) {
            QString name = model.record(i).value("name").toString();
            int salary = model.record(i).value("salary").toInt();
            qDebug() << name << salary;
        }

QSqlTableModel - это высокоровневая альтернатива QSqlQuery для навигации по и изменения отдельной SQL таблицы. Обычно это требует меньше кода и не требует знания SQL синтаксиса.

Для получения строки таблицы используйте QSqlTableModel::record(), а для ее изменения - QSqlTableModel::setRecord(). Например, следующий код увеличивает зарплату всех сотрудников на 10 процентов:

        for (int i = 0; i < model.rowCount(); ++i) {
            QSqlRecord record = model.record(i);
            double salary = record.value("salary").toInt();
            salary *= 1.1;
            record.setValue("salary", salary);
            model.setRecord(i, record);
        }
        model.submitAll();

Вы можете использовать QSqlTableModel::data() и QSqlTableModel::setData(), которые унаследованные от QAbstractItemModel, для доступа к данным . В следующем примере показано, как изменить запись с помощью setData():

        model.setData(model.index(row, column), 75000);
        model.submitAll();

Здесь показано, как вставить строку и заполнить ее:

        model.insertRows(row, 1);
        model.setData(model.index(row, 0), 1013);
        model.setData(model.index(row, 1), "Peter Gordon");
        model.setData(model.index(row, 2), 68500);
        model.submitAll();

Пример удаления пяти следующих друг за другом строк:

        model.removeRows(row, 5);
        model.submitAll();

В качестве первого элемента QSqlTableModel::removeRows() передается индекс первой удаляемой строки.

После окончания редактирования записи, вы должны вызвать QSqlTableModel::submitAll() для того, чтобы гарантировать запись изменений в базу данных.

Когда и где Вам требуется вызывать submitAll() зависит от стратегии редактирования таблицы. По умолчанию установлена стратегия QSqlTableModel::OnRowChange, которая указывает, что произведенные изменения будут внесены в базу данных при выборе пользователем другой строки. Другие стратегии это - QSqlTableModel::OnManualSubmit (все изменения кэшируются в модели до вызова submitAll()) и QSqlTableModel::OnFieldChange (где изменения не кэшируются). Они, в основном, полезны, когда QSqlTableModel используется с представлением.

Хотя кажется, что QSqlTableModel::OnFieldChange обещает, что Вам никогда не придется вызывать submitAll(). Есть два нюанса:

  • Без кэширования может снизиться скорость работы.
  • Если вы изменили первичный ключ, то запись может ускользнуть от Вас, пока вы пытаетесь ее заполнить,.

[править] Модель: реляционной SQL таблицы

QSqlRelationalTableModel расширяет QSqlTableModel для предоставления поддержки внешних ключей. Внешний ключ - это связть один-к-одному, установленная между полем одной таблицы и полем первичного ключа другой таблицы. Например, если таблица book имеет поле с названием authorid, которое ссылается на поле id таблицы авторов, вы указываете, что поле authorid является первичным ключем.

center center

Левый скриншот показывает QSqlTableModel в QTableView. Внешние ключи (city и country) не представлены удобочитаемыми значениями. Правый скриншот показывает QSqlRelationalTableModel, в котором внешние ключи представлены удобочитаемыми текстовыми строками.

Следующий отрывок кода демонстрирует настройку QSqlRelationalTableModel:

        model->setTable("employee");
 
        model->setRelation(2, QSqlRelation("city", "id", "name"));
        model->setRelation(3, QSqlRelation("country", "id", "name"));

Более подробную информацию см. в описании QSqlRelationalTableModel.

[править] Отображение данных в таблице-представлении

Классы QSqlQueryModel, QSqlTableModel и QSqlRelationalTableModel могут использоваться в качестве источников данных для классов представлений Qt, таких как QListView, QTableView и QTreeView. На практике, наиболее часто используется QTableView в связи с тем, что результирующая SQL выборка, по существу, представляет собой двумерную структуру данных.

center

В следующем примере создается представление основанное на модели данных SQL:

        QTableView *view = new QTableView;
        view->setModel(model);
        view->show();

Если модель является моделью для чтения-записи (например, QSqlTableModel), то представление позволяет редактировать поля. Вы можете запретить это вызвав

        view->setEditTriggers(QAbstractItemView::NoEditTriggers);

Вы можете использовать одну и ту-же модель в качестве источника данных для нескольких представлений. Если пользователь изменяет данные модели с помощью одного из представлений, другие предсталения немедленно отобразят изменения. Пример Table Model демонстрирует как это работает.

Классы-представления, для обозначения колонок, наверху отображают заголовки. Для изменения текста заголовка, вызовите setHeaderData() модели. Текстом заголовка по умолчанию является наименование поля. Например:

        model->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
        model->setHeaderData(1, Qt::Horizontal, QObject::tr("Name"));
        model->setHeaderData(2, Qt::Horizontal, QObject::tr("City"));
        model->setHeaderData(3, Qt::Horizontal, QObject::tr("Country"));

QTableView также имеет вертикальные заголовки, слева, содержащие номера строк. Если вы программно вставляете строки с помощью QSqlTableModel::insertRows(), новые колонки будут обозначены звездочкой (*) до тех пор, пока они не будут помещены в базу данных с помощью submitAll() или автоматически при переходе пользователя к другой записи (если стратегия редактирования равна QSqlTableModel::OnRowChange).

center

Аналогично, если вы удаляете строки с помощью removeRows(), строки будут отмечены восклицательным знаком (!) пока изменения не будут внесены в базу данных.

Элемены представления отображаются с помощью делегата. Делегат по умолчанию: QItemDelegate, содержит большинство общих типов данных (int, QString, QImage и т.д.). Также делегат отвечает за предоставление виджета-редактора (например, combobox), пользователь начинает редактировать элемент представления. Вы можете создавать свои собственные делегаты наследуя QAbstractItemDelegate или QItemDelegate. Для получения более подробной информации см. Программирование Модель/Представление.

QSqlTableModel оптимизирован для работы с одной таблицей в один момент времени. Если Вам нужна модель для чтения-записи, которая может работать с произвольной результирующей выборкой, вы можете создать подкласс QSqlQueryModel и заново реализовать flags() и setData() для возможности осуществлять чтение-запись. Две следующие функции делают поля 1 и 2 модели SQL запроса редактируемыми:

    Qt::ItemFlags EditableSqlModel::flags(
            const QModelIndex &amp;index) const
    {
        Qt::ItemFlags flags = QSqlQueryModel::flags(index);
        if (index.column() == 1 || index.column() == 2)
            flags |= Qt::ItemIsEditable;
        return flags;
    }
 
    bool EditableSqlModel::setData(const QModelIndex &amp;index, const QVariant &amp;value, int /* role */)
    {
        if (index.column() < 1 || index.column() > 2)
            return false;
 
        QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
        int id = data(primaryKeyIndex).toInt();
 
        clear();
 
        bool ok;
        if (index.column() == 1) {
            ok = setFirstName(id, value.toString());
        } else {
            ok = setLastName(id, value.toString());
        }
        refresh();
        return ok;
    }

Вспомогательная функция setFirstName() определяется следующим образом:

    bool EditableSqlModel::setFirstName(int personId, const QString &amp;firstName)
    {
        QSqlQuery query;
        query.prepare("update person set firstname = ? where id = ?");
        query.addBindValue(firstName);
        query.addBindValue(personId);
        return query.exec();
    }

Функция setLastName() подобна ей. Полный код реализации можно посмотреть в примере Query Model.

Создание подклассов модели делает возможной настройку собственной модели различными способами: вы можете предоставлить подсказки к элементам, изменить цвет фона, отобразить вычисляемые значения, разрешать различным значениям быть отображенными и отредактированными, отдельно обработать нулевые значения и т.д. Для получения более подробной информации см. Программирование Модель/Представление и описание класса QAbstractItemView.

Если все, что Вам требуется - это разрешить внешний ключ для более понятного представления, вы можете использовать QSqlRelationalTableModel. Для получения лучшего результата, вам следует использовать дилегат QSqlRelationalDelegate, который предоставляет для изменения значения внешнего ключа виджет-редактор в виде выпадающего списка.

center

Пример Relational Table Model иллюстрирует использование QSqlRelationalTableModel в совокупности с QSqlRelationalDelegate для представления таблицы с поддержкой внешнего ключа.

[править] Создание информационно-связанных форм

Использование SQL моделей описано выше, содержимое базы данных может быть представлено в других компонентах модель-представление. Для некоторых приложений достаточно, чтобы представить эти данные используя стандартные элемент-ориентированые представления, такие как QTableView. Однако, пользователям приложений, основанных на манипулировании записями, часто требуется пользовательский интерфейс содержащий формы, в котором данные из определенной строки или колонки в таблице базы данных используются, чтобы заполнять виджет-редактор на форме.

Такие информационно-связанные формы могут быть созданы с помощью класса QDataWidgetMapper, общий компонент модель-представление, которого используется, чтобы отобразить данные из модели, в определенный виджет в пользовательском интерфейсе.

QDataWidgetMapper работает с определенной таблицей базы данных, отображая элементы таблицы в базисе row-by-row или column-by-column. В результате, использование QDataWidgetMapper с SQL моделью так же просто, как использование его с любыми другими табличными моделями.

center

Демонстрация Books показывает, как информация может быть представлена для легкого доступа используя QDataWidgetMapper и набор простых виджетов ввода.

[Предыдущая: Модуль QtOpenGL ] [ Модули Qt ] [Следующая: Модуль QtSvg ]


Copyright © 2007 Trolltech Trademarks
Qt 4.3.2