Исполнение команд SQL в Qt


Для исполнения команд SQL, после установления соединения, можно использовать класс QSqlQuery. Запросы (команды) оформляются в виде обычной строки, которая передается в конструктор или в метод QSqlQuery::exec(). В случае конструктора, запуск команды будет производиться автоматически, при создании объекта.

Класс QSqlQuery предоставляет возможность навигации. Например, после выполнения запроса SELECT можно перемещаться по собранным данным при помощи методов next(), previous(), first(), last() и seek(). С помощью метода next() мы перемещаемся на следующую строку данных, а вызов метода previous() перемещает нас на предыдущую строку данных. При помощи методов first() и last() можно установить первую и последнюю строку данных соответственно. Метод seek() устанавливает строку данных по указанному целочисленному индексу в его параметре. Количество строк данных можно получить вызовом метода size().

Дополнительные сложности возникают с запросом INSERT. Дело в том, что в запрос нужно внедрять данные. Для достижения этого можно воспользоваться двумя методами: prepare() и bindValue(). В методе prepare() мы задаем шаблон, данные в который подставляются методами bindValue(). Например:


query.prepare("INSERT INTO addressbook (number, name, phone, email) VALUES(:number, :name, :phone, :email);");
query.bindValue (" :number", "1");
query.bindValue(":name", "Piggy");
query.bindValue(":phone", " + 49 631322187");
query.bindValue(":email", "piggy@mega.de");

Также можно воспользоваться, известным из ODBC, вариантом использования безымянных параметров:


query.prepare("INSERT INTO addressbook (number, name, phone, email) VALUES(?, ?, ?, ?);");
query.bindValue("1");
query.bindValue("Piggy");
query.bindValue("+ 49 631322187");
query.bindValue("piggy@mega.de");

В качестве третьего варианта — можно воспользоваться классом QString, в частности методом QString::arg(), с помощью которого можно произвести подстановку значений данных.


int main(int argc, char** argv)
{
    QCoreApplication app(argc, argv);

    if (!createConnection()) {
        return -1;
    }
    
    //Creating of the data base
    QSqlQuery query;
    QString   str  = "CREATE TABLE addressbook ( "
                         "number INTEGER PRIMARY KEY NOT NULL, "
                         "name   VARCHAR(15), "
                         "phone  VARCHAR(12), "
                         "email  VARCHAR(15) "
                     ");";

    if (!query.exec(str)) {
        qDebug() << "Unable to create a table";
    }

    //Adding some information
    QString strF = 
          "INSERT INTO  addressbook (number, name, phone, email) "
          "VALUES(%1, '%2', '%3', '%4');";

    str = strF.arg("1")
              .arg("Piggy")
              .arg("+49 631322187")
              .arg("piggy@mega.de");
    if (!query.exec(str)) {
        qDebug() << "Unable to do insert opeation";
    }

    str = strF.arg("2")
              .arg("Kermit")
              .arg("+49 631322181")
              .arg("kermit@mega.de");
    if (!query.exec(str)) {
        qDebug() << "Unable to do insert operation";
    }

    if (!query.exec("SELECT * FROM addressbook;")) {
        qDebug() << "Unable to execute query - exiting";
        return 1;
    }

    //Reading of the data
    QSqlRecord rec     = query.record();
    int        nNumber = 0;
    QString    strName;
    QString    strPhone;
    QString    strEmail;

    while (query.next()) {
        nNumber  = query.value(rec.indexOf("number")).toInt();
        strName  = query.value(rec.indexOf("name")).toString();
        strPhone = query.value(rec.indexOf("phone")).toString();
        strEmail = query.value(rec.indexOf("email")).toString();
    
        qDebug() << nNumber << " " << strName << ";\t" 
                 << strPhone << ";\t" << strEmail;
    }

    return 0;
}

Программа, приведенная выше, демонстрирует исполнение команд SQL. Производится создание базы, запись данных и их опрос. В результате на консоль будут выведены следующие данные:


1 "Piggy" ;  "+49 631322187" ; "piggy@mega.de" 
2 "Kermit" ; "+49 631322181" ; "kermit@mega.de"

В случае удачного соединения с базой данных с помощью createConnection() создается строка, содержащая команду SQL для создания таблицы. Эта строка передается в метод exec() объекта класса QSqlQuery. Если создать таблицу не удается, то на консоль будет выведено предупреждающее сообщение. Ввиду того, что в таблицу будет внесена не одна строка, в строковой переменной strF при помощи символов спецификации определяется шаблон для команды INSERT. Вызовы методов arg() класса QString подставляют нужные значения используя шаблон.

Затем, когда база данных создана и все данные были внесены в таблицу, выполняется запрос SELECT, помещающий строки и столбцы таблицы в объект query. Вывод значений таблицы на консоль производится в цикле. При первом вызове метода next() этот объект будет указывать на самую первую строку таблицы. Последующие вызовы приведут к перемещению указателя на следующие строки. В том случае, если записей больше нет, метод next() вернет false, что приведет к выходу из цикла. Для получения результата запроса следует вызвать метод QSqlQuery::value(), в котором необходимо передать номер столбца. Для этого мы воспользуемся методом record(). Этот метод возвращает объект класса QSqlRecord, который содержит информацию, относящуюся к запросу SELECT. С его помощью, вызовом метода QSqlRecord::indexOf(), мы получаем индекс столбца.

Метод value() возвращает значения типа QVariant. QVariant — это специальный класс, объекты которого могут содержать в себе значения разных типов. Поэтому, в нашем примере, полученное значение нужно преобразовать к требуемому типу, воспользовавшись методами QVariant::toInt() и QVariant::toString().

Читать далее: Классы SQL-моделей для Интервью