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()) { 以下のようにする。        QStringname=query.value(0).toString();intsalary=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 は、 s だけでなく、任意の SQL 文を実行できます。以下の例では、 を使用してテーブルにレコードを挿入しています: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();

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

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.