Программирование на C++ с использованием библиотеки Qt4


Выполнение SQL-запросов (файл examples-qt/db00/db00.h)


1 #include <QtGui>
2 3 class MyDialog : public QDialog { 4 Q_OBJECT 5 public: 6 MyDialog(QWidget *parent=0);
7 protected: 8 virtual void closeEvent(QCloseEvent *event);
9 private slots: 10 bool start();
11 private: 12 QComboBox *mode; // Режим (драйвер). 13 QLineEdit *host; // Хост. 14 QLineEdit *dbname; // Имя БД. 15 QLineEdit *user; // Пользователь. 16 QLineEdit *password; // Пароль. 17 QTextEdit *scr; // Для вывода сообщений. 18 QPushButton *btnStart; // Кнопка 'Старт'. 19 ;


1 #include <QtGui>
2 #include <QtSql>
3 #include <QtTest/QtTest>
// Для qWait(). 4 5 #include "db00.h" 6 7 MyDialog::MyDialog(QWidget *parent) 8 : QDialog(parent) { 9 QTextCodec *codec = QTextCodec::codecForName("CP1251");
10 QTextCodec::setCodecForTr(codec);
11 QTextCodec::setCodecForCStrings(codec);
12 QTextCodec::setCodecForLocale(codec);
13 14 setWindowFlags(Qt::Window);
15 16 mode = new QComboBox(this);
17 QStringList drivers = QSqlDatabase::drivers();
18 drivers.removeAll("QMYSQL3");
19 drivers.removeAll("QOCI8");
20 drivers.removeAll("QODBC3");
21 drivers.removeAll("QPSQL7");
22 drivers.removeAll("QTDS7");
23 mode->
addItems(drivers);
24 25 host = new QLineEdit(tr("localhost"), this);
26 dbname = new QLineEdit(this);
27 user = new QLineEdit(this);
28 password = new QLineEdit(this);
29 password->
setEchoMode(QLineEdit::Password);
30 31 btnStart = new QPushButton(tr("Старт"), this);
32 33 scr = new QTextEdit(this);
34 scr->
setReadOnly(true);
35 36 QGridLayout *layout = new QGridLayout(this);
37 layout->
addWidget(new QLabel(tr("Режим:"), this), 38 0, 0, Qt::AlignRight);
39 layout->
addWidget(mode, 0, 1, 1, 3);
40 41 layout->
addWidget(new QLabel(tr("Хост:"), this), 42 1, 0, Qt::AlignRight);
43 layout->
addWidget(host, 1, 1);
44 45 layout->
addWidget(new QLabel(tr("База данных:"), this), 46 1, 2, Qt::AlignRight);
47 layout->
addWidget(dbname, 1, 3);
48 49 layout->
addWidget(new QLabel(tr("Пользователь:"), this), 50 2, 0, Qt::AlignRight);
51 layout->
addWidget(user, 2, 1);
52 53 layout->
addWidget(new QLabel(tr("Пароль:"), this), 54 2, 2, Qt::AlignRight);
55 layout->
addWidget(password, 2, 3);
56 57 layout->
addWidget(btnStart, 3, 1, 1, 2);
58 layout->
addWidget(scr, 4, 0, 1, 4);
59 60 layout->
setMargin(6);
61 layout->
setSpacing(5);
62 layout->
setColumnStretch(1, 1);
63 layout->
setColumnStretch(3, 1);
64 layout->
setRowStretch(4, 1);
65 setLayout(layout);
66 67 connect(btnStart, SIGNAL(clicked()), this, SLOT(start()));
68 } 69 70 bool MyDialog::start() { 71 scr->
append(tr("Соединяюсь с базой данных..."));
72 QSqlDatabase db = QSqlDatabase::addDatabase( 73 mode->
currentText() );
74 db.setHostName(host->
text());
75 db.setDatabaseName(dbname->
text());
76 db.setUserName(user->
text());
77 db.setPassword(password->
text());
78 if (db.open()) { 79 mode->
setEnabled(false);
80 host->
setEnabled(false);
81 dbname->
setEnabled(false);
82 user->
setEnabled(false);
83 password->
setEnabled(false);
84 btnStart->
setEnabled(false);
85 scr->
append(tr("Соединение установлено!"));
86 }else{ 87 scr->
append(tr("Не могу соединиться: "));
88 scr->
append(db.lastError().text());
89 return false; 90 } 91 92 QSqlQuery sql = QSqlQuery();
93 //sql.exec(tr("SET NAMES 'cp1251'"));
94 QStringList dbtables = db.tables(QSql::Tables);
95 if (dbtables.contains( tr("employee"), 96 Qt::CaseInsensitive)) { 97 scr->
append( tr( 98 "Таблица \"employee\" уже существует."));
99 sql.exec(tr("DROP TABLE employee"));
100 if ( sql.lastError().type() == QSqlError::NoError ) { 101 scr->
append( tr( 102 "Удалили таблицу \"employee\" "));
103 }else{ 104 scr->
append( tr( 105 "Не могу удалить таблицу \"employee\":"));
106 scr->
append(sql.lastError().text());
107 return false; 108 } 109 } 110 111 sql.exec( tr( 112 "create table employee ( " 113 " id integer PRIMARY KEY, " 114 " name char(30) not null, " 115 " born date null, " 116 " salary numeric(12,2), " 117 " married boolean NULL ) " ) );
118 if ( sql.lastError().type() == QSqlError::NoError ) { 119 scr->
append( tr( 120 "Создали таблицу \"employee\"."));
121 }else{ 122 scr->
append( tr( 123 "Не могу создать таблицу \"employee\":"));
124 scr->
append(sql.lastError().text());
125 return false; 126 } 127 128 if (sql.prepare( tr( 129 "INSERT INTO employee " 130 " VALUES (?, ?, ?, ?, ?)") ) ) { 131 int arr_id[] = {123, 345, 501}; 132 QString arr_name[] = {tr("Винни-Пух"), 133 tr("Ослик Иа"), 134 tr("Поросёнок")}; 135 QDate arr_born[] = {QDate(1971, 12, 31), 136 QDate(1965, 2, 23), 137 QDate(1982, 6, 14)}; 138 float arr_salary[] = {1234.56f, 2345.67f, 871}; 139 int arr_married[] = {1, 0, 0}; 140 141 for (unsigned int i=0; i < 3; i++) { 142 sql.bindValue(0, arr_id[i]);
143 sql.bindValue(1, arr_name[i]);
144 sql.bindValue(2, arr_born[i]);
145 sql.bindValue(3, arr_salary[i]);
146 sql.bindValue(4, arr_married[i]);
147 sql.exec();
148 if ( sql.lastError().type() == QSqlError::NoError ) { 149 scr->
append( tr( 150 "Вставили новую запись."));
151 }else{ 152 scr->
append( tr( 153 "Не могу вставить новую запись:"));
154 scr->
append(sql.lastError().text());
155 return false; 156 } 157 } 158 }else{ 159 scr->
append( tr( 160 "Не могу подготовить запрос:"));
161 scr->
append(sql.lastError().text());
162 return false; 163 } 164 165 sql.exec( tr("SELECT * FROM employee ") );
166 if ( sql.isActive() ) { 167 QSqlRecord rec = sql.record();
168 scr->
append( tr( 169 "В таблице \"employee\" %1 столбцов: ") 170 .arg(rec.count() ) );
171 172 QString fields; 173 for(int j=0; j<rec.count();
j++) 174 fields += rec.fieldName(j) + ", "; 175 176 scr->
append(fields);
177 178 scr->
append( tr( 179 "В таблице \"employee\" %1 записей: ") 180 .arg(sql.size() ) );
181 182 while ( sql.next() ) { 183 int id = sql.value(0).toInt();
184 QString name = sql.value(1).toString();
185 QDate born = sql.value(2).toDate();
186 double salary = sql.value(3).toDouble();
187 bool married = sql.value(4).toBool();
188 scr->
append( tr( 189 "%1\t %2\t %3\t %4\t %5") 190 .arg(id) 191 .arg(name) 192 .arg(born.toString(tr("dd/MM/yyyy"))) 193 .arg(salary) 194 .arg(married) );
195 } 196 }else{ 197 scr->
append( tr( 198 "Не могу получить данные:"));
199 scr->
append(sql.lastError().text());
200 return false; 201 } 202 203 scr->
append( tr( 204 "При закрытии окна соединение с БД будет завершено."));
205 return true; 206 } 207 208 void MyDialog::closeEvent(QCloseEvent *event) { 209 QSqlDatabase db = QSqlDatabase::database();
210 if (db.isOpen()) { 211 db.close();
212 scr->
append("--------------------------");
213 scr->
append(tr("Соединение с базой данных закрыто!"));
214 QTest::qWait(1000);
// Ждать 1 сек. 215 } 216 } 217 218 int main(int argc, char *argv[]) { 219 QApplication app(argc, argv);
220 221 MyDialog *mainWin = new MyDialog();
222 mainWin->
show();
223 return app.exec();
224 }




  • (13) Установили для диалога флаг Qt::Windows, чтобы в заголовке окна появились кнопки сворачивания и восстановления.
  • (15-22) Создали поле со списком и заполнили его названиями всех доступных драйверов SQL, кроме устаревших (17-21).
  • (24-28) Создали однострочные поля для ввода параметров соединения.
  • (30) Кнопка Старт.
  • (32-33) Многострочное поле для вывода сообщений.
  • (35-64) Расположили все элементы с помощью сеточного менеджера размещения.


  • (66) Связали кнопку Старт с функцией start().
  • (69) Функция, выполняемая при нажатии на кнопку.
  • (70) Вывели сообщение.
  • (72-77) Создали соединение с базой данных.
  • (78-83) Если соединение установлено, то менять параметры уже нельзя.
  • (93) При необходимости сообщили серверу кодовую таблицу клиента.
  • (94-95) Выяснили, существует ли в базе данных таблица employee (работники).
  • (98) Если да, то удалили её.
  • (110) Создали новую таблицу.
  • (127-162) Выполнили серию SQL-запросов с параметрами для вставки новых записей в созданную таблицу.
  • (164) Получили все записи таблицы.
  • (166-173) Получили информацию о полях (столбцах).
  • (177-193) Вывели на экран все записи (строки) таблицы.
  • (207) Виртуальная функция closeEvent выполняется при закрытии окна.
  • (209-210) Если соединение с базой данных открыто, то закрываем его.
  • (211-213) Выводим сообщение и ждём секунду перед закрытием окна. Для компиляции проектов, использующих модуль QtTest, в файл проекта *.pro надо добавить строку CONFIG += qtestlib.


  • Перед компиляцией проекта, в котором используется модуль QtSql, надо добавить в pro-файл строку QT += sql.

    Перед выполнением этой программы требуется создать какую-нибудь базу данных: create database db1 character set utf8;

    (вместо utf8 можно использовать кодировки cp1251 или koi8r);
    а перед использованием QODBC -- настроить ODBC-псевдоним.


    Содержание раздела