SQL モデル・クラスの使用
QSqlQuery に加えて、Qt はデータベースにアクセスするための 3 つの上位クラスを提供しています。これらのクラスはQSqlQueryModel 、QSqlTableModel 、QSqlRelationalTableModel です。
QSqlQueryModel | 任意の SQL クエリに基づく読み取り専用モデル。 |
QSqlTableModel | 単一のテーブルで動作する読み書きモデル。 |
QSqlRelationalTableModel | 外部キーをサポートするQSqlTableModel サブクラス。 |
これらのクラスはQAbstractTableModel から派生し (QAbstractItemModel からも派生します)、データベースからのデータをQListView やQTableView のような項目ビュー・クラスで簡単に表示できるようにします。これについては、「テーブル・ビューでデータを表示する」のセクションで詳しく説明します。
これらのクラスを使用するもう1つの利点は、コードを他のデータソースに簡単に適応させることができることです。例えば、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 から継承したその他の関数も使用できます。
QSqlQuery オブジェクトを受け取り、その結果セットを操作するsetQuery() オーバーロードもある。これにより、QSqlQuery の機能を使用してクエリを設定することができます(例:プリペアド・クエリ)。
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 は、 に代わる、個々のSQLテーブルを操作し変更するための高レベルな方法です。これは通常、より少ないコードで済み、SQL構文の知識を必要としません。QSqlQuery
テーブルの行を取得するには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();
また、QAbstractItemModel から継承したQSqlTableModel::data() とQSqlTableModel::setData() を使用して、データにアクセスすることもできます。たとえば、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();
以下は、連続する5行を削除する方法である:
model.removeRows(row, 5); model.submitAll();
QSqlTableModel::removeRows() の最初の引数は、削除する最初の行のインデックスです。
レコードの変更が終わったら、必ずQSqlTableModel::submitAll() をコールして、変更がデータベースに書き込まれるようにしなければなりません。
実際に submitAll() をコールする必要があるかどうかは、テーブルのedit strategy に依存します。デフォルトのストラテジーはQSqlTableModel::OnRowChange で、保留中の変更がデータベースに適用されるのは、ユーザが別の行を選択したときです。その他のストラテジは、QSqlTableModel::OnManualSubmit (submitAll()を呼び出すまで、すべての変更がモデルにキャッシュされます) とQSqlTableModel::OnFieldChange (変更はキャッシュされません) です。これらは、QSqlTableModel をビューで使用する場合に便利です。
QSqlTableModel::OnFieldChange は、submitAll()を明示的に呼び出す必要がないという約束を実現しているように見えます。しかし、2つの落とし穴があります:
- キャッシュを使用しないと、パフォーマンスが大幅に低下します。
- プライマリ・キーを変更した場合、そのレコードにデータを入力しようとしている間に、そのレコードがあなたの指をすり抜けてしまうかもしれません。
SQLリレーショナル・テーブル・モデル
QSqlRelationalTableModel は を拡張し、外部キーのサポートを提供します。外部キーとは、あるテーブルのフィールドと別のテーブルの主キー・フィールドを1対1で対応付けるものです。例えば、 テーブルに というフィールドがあり、そのフィールドがauthorテーブルの フィールドを参照する場合、 が外部キーであると言います。QSqlTableModel book
authorid
id
authorid
左のスクリーンショットは、QTableView の中のプレーンなQSqlTableModel を示しています。外部キー(city
とcountry
)は、人間が読める値には解決されません。右のスクリーンショットはQSqlRelationalTableModel を示しており、外部キーは人間が読めるテキスト文字列に解決されています。
以下のコード・スニペットは、QSqlRelationalTableModel がどのように設定されたかを示しています:
model->setTable("employee"); model->setRelation(2, QSqlRelation("city", "id", "name")); model->setRelation(3, QSqlRelation("country", "id", "name"));
詳細はQSqlRelationalTableModel のドキュメントを参照してください。
本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。