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 を呼び出すと、結果セットに 1 レコードずつアクセスできる。 () の呼び出し後、 の内部ポインタは、最初のレコードの 1 つexec QSqlQuery前の位置にある。最初のレコードに進むには () を1回呼び、他のレコードにアクセスするには () を繰り返し呼び、 を返すまで呼び続けなければならない。以下は、すべてのレコードを順番に繰り返し処理する典型的なループである: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() は、intQStringQByteArray など、さまざまな C++ およびコア Qt データ型を保持できる型であるQVariant を返します。異なるデータベース・タイプは、Qtの最も近い等価物に自動的にマッピングされます。コード・スニペットでは、QVariant::toString() とQVariant::toInt() を呼び出し、バリアントをQStringint に変換しています。

Qtがサポートするデータベースで使用するための推奨型の概要については、この表を参照してください。

データセット内を移動するには、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 SELECT以下の例では、 を使用してテーブルにレコードを挿入しています:INSERT

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

同時に多くのレコードを挿入したい場合、クエリと実際に挿入される値を分離した方が効率的なことが多い。これにはプレースホルダを使用します。Qtは、名前付きバインディングと位置バインディングの2つのプレースホルダー構文をサポートしています。以下は名前付きバインディングの例です:

    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 はクエリを DBMS に転送します。そうでない場合、Qt はクエリを前処理することでプレースホルダ構文をシミュレートします。DBMS によって実行される実際のクエリは、QSqlQuery::executedQuery() として利用できます。

複数のレコードを挿入する場合、QSqlQuery::prepare() を一度だけ呼び出す必要があります。その後、bindValue ()またはaddBindValue ()の後に、exec ()を必要な回数だけ呼び出します。

パフォーマンスだけでなく、プレースホルダの利点の1つは、特殊文字のエスケープを気にすることなく、任意の値を簡単に指定できることである。

レコードの更新は、テーブルへの挿入と同様である:

    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) は真を返します。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();

トランザクションは、複雑な操作がアトミックであることを保証したり(例えば、外部キーを検索してレコードを作成する)、複雑な変更を途中でキャンセルする手段を提供するために使用することができます。

本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。