1   2   3   4
Ім'я файлу: Основний розділ.doc
Розширення: doc
Розмір: 1193кб.
Дата: 04.03.2020
скачати

Рисунок 4. Вікно Create Database (створити базу даних)

Серед всіх полів, нас зараз цікавить тільки одне Database File(файл бази даних), сюди вводимо назву файлу БД та шлях до нього. Натискаємо кнопку Ок і наша база даних буде створена:



Рисунок 5. Створено пусту базу даних main

Правда зараз вона пуста і нам необхідно створити в ній всі спроектовані нами таблиці. Для цього на тій же панелі інструментів натискаємо кнопку Create Table(створити таблицю):



Рисунок 6. Кнопка Create Table на панелі інструментів

В робочій області програми з’явиться панель, де і буде проводитися вся робота по створенню таблиці:



Рисунок 7. Панель нової таблиці

У верхній частині , в поле Table Name(ім’я таблиці), потрібно ввести саме ім’я, яке отримує таблиця, а внизу панелі є кнопка Add(додати). Цю кнопку використовуємо для вставлення полів таблиці.

Задавши ім’я, натискаємо кнопку додати поле:



Рисунок 8. Вікно - додати Поле в таблицю

В рядку Name вказується ім’я поля, Type – тут вибираємо необхідний тип поля зі списку допустимих типів, Size – довжина поля, важлива при стрічкових типах даних, Default – значення по замовчуванню, Not Null – це означає, що поле при збереженні в БД, повинне мати якесь значення, PRIMARY KEY – поклавши тут відмітку, ми даємо знати, ще це первинний ключ, AUTOICREMENT – поле буде в якості значення отримувати ціле

число, яке буде з автоприростом. Вводимо всі поля таблиці taxi_driver:



Рисунок 9. Таблицю створено, натискаємо кнопку Застосувати.

Після того як всі необхідні дії з таблицею зроблено, натискаю кнопку Apply(Застосувати) внизу вікна і таблиця створена. Таким же способом створюємо і решту таблиць бази даних, в результаті будемо мати:



Рисунок 10. Створення таблиць БД закінчене

Отже, створено всі 6 таблиць бази даних, які можна почати використовувати.

1.6. Кодування програми.

Підключення в базі даних і виконання Sql-Запитів

Для підключення до бази даних нам треба вказати назву Sql-Драйвера, наприклад:

Qsqldatabase db = Qsqldatabase::adddatabase("QSQLITE", "Mydb1");

Другий необов'язковий параметр дозволяє задати ім'я з'єднання. Потім вказується ім'я сервера, назва бази даних, ім'я користувача й пароль:

db.sethostname("localhost"); // або, наприклад, "my1.server.ru"

db.setdatabasename("mydb1");

db.setusername("root");

db.setpassword("mypassword");

Якщо сервер використовує нестандартний порт, то його нам треба задати також:

db.setport(Номер порту);

У випадку використання QODBC ім'я сервера не потрібно, а замість назви бази даних вказується Odbc-Псевдонім (аліас). Sqlite не підтримує авторизацію користувачів, тому йому потрібно вказати тільки ім'я файлу даних. Визначене ім'я ":memory:" дозволяє розміщати тимчасову базу даних в оперативній пам'яті.

Після того, як усі параметри підключення задані, можна відкрити з'єднання:

bool connected = db.open();

Якщо підключення встановити не вдалося, то довідуємося опис помилки й повідомляємо про це користувача:

if (!connected)

{

Qmessagebox::critical( // Діалог з повідомленням про помилку.

parent, // Батьківський віджет.

Qobject::tr("Database Error"), // Заголовок.

db.lasterror().text()); // Текст повідомлення.

return false; // Повернути ознаку невдалого підключення.

}

Якщо підключення встановлене, то можна виконати Sql-Запит, наприклад:

Qsqlquery query;

query.exec("SELECT id, name, salary FROM empl WHERE salary>=1000");

або

Qsqlquery query("SELECT id, name, salary FROM empl WHERE salary>=1000");

Тут запитуються номери id, імена name і оклади salary усіх працівників з таблиці empl, у яких оклад не нижче 1 000. Якщо при створенні об'єкта Qsqlquery зазначений текст запиту мовою SQL, те цей запит відразу виконується. В обох випадках у запиті можна вказати базу даних Qsqldatabase. Але як правило, програма відкриває тільки одне з'єднання з єдиною базою даних, тому цей параметр ухвалює значення за замовчуванням.

Якщо при виконанні запиту виникла помилка, то метод lasterror() дозволяє вивести на екран її опис:

if ( ! query.isactive() )

QMessageBox::warning( this, tr("Database Error"), query.lasterror().text() );

Інакше можна одержати дані, які сервер повернув як результат:

while ( query.next() )

{

qint64 id = query.value(0).tolonglong();

Qstring name = query.value(1).tostring();

double salary = query.value(2).todouble();

// .......

}

Метод Qsqlquery::next() переводить курсор на черговий запис результуючого набору даних або повертає false, якщо досягнуться його кінець. Метод value(номер_стовпця) повертає значення типу Qvariant, яке треба перетворити до потрібного типу за допомогою методів Qvariant::toint, Qvariant::tolonglong, Qvariant::tostring, Qvariant::todouble, Qvariant::todate, Qvariant::todatetime і т.д. Крім next(), для навігації по набору даних можна використовувати методи first(), last(), previous(), seek(int index, bool relative=false). Для збільшення швидкодії набір даних нам краще зробити односпрямованим, викликавши метод Qsqlquery::setforwardonly(true) до виконання запиту, після цього можна використовувати тільки next().

Метод Qsqlquery::size() повертає число записів, отриманих у результаті виконання запиту SELECT (-1, якщо була помилка або якщо драйвер даної СУБД не підтримує цю функцію). При виконанні Sql-Запитів INSERT, UPDATE або DELETE замість size() нам треба використовувати метод Qsqlquery::numrowsaffected(). Щоб довідатися, чи виникла помилка при останньому виконанні запиту, використовується метод Qsqlquery::lasterror(). Аналогічний метод має й клас Qsqldatabase. В обох випадках вертається екземпляр класу Qsqlerror. Тип помилки можна з'ясувати, викликавши метод Qsqlerror::type(). Можливі типи помилок: Qsqlerror::Noerror (помилок не було), Qsqlerror::Connectionerror (помилка з'єднання), Qsqlerror::Statementerror (синтаксична помилка в Sql-Запиті), Qsqlerror::Transactionerror (помилка транзакції) і Qsqlerror::Unknownerror (невідома помилка).

Нам потрібно виконати велику кількість однотипних Sql-операторів, то ефективніше використовувати запит з параметрами:

Qsqlquery query;

query.prepare("INSERT INTO empl (id, name, salary) "

"VALUES (:id, :name, :salary)");

for (int i=0; i
query.bindvalue(":id", arr_id[i]);

query.bindvalue(":name", arr_name[i]);

query.bindvalue(":salary", arr_salary[i]);

query.exec();

}

або, що ж саме (тільки параметри безіменні):

Qsqlquery query;

query.prepare("INSERT INTO empl (id, name, salary) "

"VALUES (?, ?, ?)");

for (int i=0; i
{

query.addbindvalue(arr_id[i]);

query.addbindvalue(arr_name[i]);

query.addbindvalue(arr_salary[i]);

query.exec();

}

Тут виконується вставка N записів, дані беруться з масивів arr_id, arr_name і arr_salary. Якщо ж СУБД підтримує механізм транзакцій, то для початку нової транзакції використовується метод

bool Qsqldatabase::transaction()

для її підтвердження треба викликати

bool Qsqldatabase::commit()

а для скасування:

bool Qsqldatabase::rollback()

Якщо СУБД не підтримує транзакцій, то виклики transaction, commit і rollback нічого не роблять. За допомогою методу Qsqldriver::hasfeature() можна довідатися, чи підтримується даним драйвером і СУБД та або інша функція, у тому числі й транзакції:

Qsqldriver *driver = Qsqldatabase::database().driver();

if (driver->hasfeature(Qsqldriver::Transactions))

.......

Кожне з'єднання з базою даних може мати тільки одну активну транзакцію. Якщо цього недостатньо, завжди можна відкрити ще кілька з'єднань із тою же базою даних. Посилання на з'єднання з базою даних можна одержати, викликавши функцію Qsqldatabase::database(connectionname). Необов'язковий параметр connectionname - це ім'я з'єднання, яке було задано при його створенні за допомогою Qsqldatabase::adddatabase().

По закінченню роботи з базою даних з'єднання треба закрити: Qsqldatabase::close(). Потім можна або відкрити його знову за допомогою методу open(), або вилучити зі списку з'єднань, викликавши статичний метод Qsqldatabase::removedatabase(connectionname).

У лістингах наведений приклад програми, що працює з базою даних.

Лістинг. Виконання Sql-Запитів

1 #include

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 ;


Лістинг. Виконання Sql-Запитів

1 #include

2 #include

3 #include // Для 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("Створили таблицю \"employee\"."));

121 }else{

122 scr->append( tr("Не можу створити таблицю \"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("Вставили новий запис."));

151 }else{

152 scr->append( tr("Не можу вставити новий запис:"));

154 scr->append(sql.lasterror().text());

155 return false;

156 }

157 }

158 }else{

159 scr->append( tr(Не можу підготувати запит:"));

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("У таблиці \"employee\" %1 стовпців: ")

170.arg(rec.count() ) );

171

172 Qstring fields;

173 for(int j=0; j
174 fields += rec.fieldname(j) + ", ";

175

176 scr->append(fields);

177

178 scr->append( tr("У таблиці \"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("Не можу одержати дані:"));

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 }

Для компіляції проектів, що використовують модуль Qttest, у файл проекту *.pro треба додати рядок CONFIG += qtestlib.

Перед компіляцією проекту, у якому використовується модуль Qtsql, треба додати в pro-файл рядок QT += sql.

Перед виконанням цієї програми потрібно створити базу даних:

create database db1 character set utf8;

( замість utf8 можна використовувати кодування cp1251 або koi8r);

1   2   3   4

скачати

© Усі права захищені
написати до нас