이 페이지에서

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() 함수는 현재 레코드의 필드 값을 반환합니다. 필드는 0을 기준으로 한 인덱스로 지정됩니다. ` QSqlQuery::value()`는 ` QVariant`를 반환하며, 이 타입은 ` int`, ` QString`, ` QByteArray`와 같은 다양한 C++ 및 핵심 Qt 데이터 타입을 담을 수 있습니다. 서로 다른 데이터베이스 타입은 자동으로 가장 유사한 Qt 타입으로 매핑됩니다. 코드 예제에서는 ` QVariant::toString()` 및 ` QVariant::toInt()`를 호출하여 `variants`를 ` QString ` 및 ` int`로 변환합니다.

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()를 호출할 수 있습니다. 이는 대규모 결과 집합을 처리할 때 쿼리 속도를 크게 높여주는 간단한 최적화 방법입니다.

레코드 삽입, 업데이트 및 삭제

QSqlQuery SELECT뿐만 아니라 임의의 SQL 문도 실행할 수 있습니다. 다음 예제는 ` `를 사용하여 테이블에 레코드를 삽입합니다: 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는 쿼리를 DBMS로 그대로 전달합니다. 그렇지 않은 경우, Qt는 쿼리를 사전 처리하여 자리 표시자 구문을 시뮬레이션합니다. DBMS에서 최종적으로 실행되는 실제 쿼리는 ` 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();

트랜잭션을 사용하면 복잡한 작업(예: 외래 키 조회 및 레코드 생성)이 원자성을 갖도록 보장하거나, 복잡한 변경 작업을 도중에 취소할 수 있는 수단을 제공할 수 있습니다.

© 2026 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.