Working with Databases/ro

From Qt Wiki
Jump to navigation Jump to search
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

Lucrul cu baze de date

Generalități

Bazele de date sunt o parte integrantă chiar și pentru cele mai simple aplicații moderne. Deși mulți asociază bazele de date cu site-urile web, ele sunt folosite și pentru aplicații desktop. Qt permite stocarea datelor folosind baze de date. Qt oferă un modul pentru baze de date relaționale numit QtSql. SQL este limbajul folosit pentru manipularea unor baze de date relaționale. Folosind SQL putem comunica între diferite baze de date și aplicație propriu-zis.

Modului QtSql oferă drivere pentru a comunica cu diferite API-uri de baze de date. De vreme ce API-ul modulului QtSql este independent de API-ul bazelor de date, tot codul care ține de lucrul cu baze de date este conținut de aceste drivere. O multitudine de drivere sunt oferite împreună cu Qt, iar altele pot fi adăugate.

Următorul tabel conține o listă cu driverele incluse în Qt. Datorită unor incompatibilități cu licența GPL, nu toate driverele sunt oferite împreună cu versiunile open-source ale lui Qt.

https://lh6.googleusercontent.com/-1gywxJ7snT8/TiMY9j9wdGI/AAAAAAAAAOY/cxd2E5sxaRo/drivere%20SQL.JPG Driverele disponibile pentru a comunica cu API-uri de baze de date

Driverul pentru SQLite este mai bine pus punct și este disponibil pentru toate platformele. Driverele pentru Oracle, PostreSQL,MySQL și ODBC sunt adresate în special pentru Windows și Linux.

Conectarea la baze de date

Pentru a accesa o bază de date cu un obiect QSqlQuery sau QSqlQueryModel trebuie ca mai întâi să stabilim și să deschidem niște conexiuni cu niște baze de date. Conexiunile se identifică prin numele conexiunii ci nu numele bazei de date. Pot exista mai multe conexiuni la aceeași bază de date. QSqlDatabase oferă suport pentru conceptul de conexiune implicită, care este o conexiune fără nume. Atunci când apelăm funcţii ale unor obiecte QSqlQuery sau QSqlQueryModel fără să specificăm un nume de conexiune, se va utiliza conexiunea implicită. Crearea unor conexiuni implicite este recomandată atunci când aplicaţia necesită doar o singură conexiune la o bază de date.

Există o diferenţă între a crea o conexiune şi a o deschide. Crearea unei conexiuni presupune crearea unei instanţe a clasei QSqlDatabase . Conexiunea nu este utilizabilă până când nu este deschisă. Următorul cod ne arată cum putem crea o conexiune, iar mai apoi cum putem să o deschidem:

 myDb = QSqlDatabase::addDatabase("QODBC", "MyDbConnectionName");
 myDb.setDatabaseName(
 "Driver={Microsoft Access Driver (*.mdb)};FIL={MS Access};DBQ=myDb.mdb");
 if (myDb.open() == false) {
 QMessageBox::critical(0,"Critical Error!",
 "Could not connect to myDb.mdb."
 + myDb.lastError().text());
 }

În cazul de mai sus am creat o conexiune cu ajutorul driverului QODBC cu numele MyDbConnectionName. Mai apoi setăm numele bazei de date. De reținut că numele bazei de date este diferit de numele conexiunii. Baza de date pe care o deschidem în acest caz este o bază de date Access. După ce am setat un nume pentru baza de date urmează să încercăm să deschidem baza de date. Daca acest lucru nu a fost posibil vom afișa un mesaj de eroare prin care să semnalăm eroare întâmpinată.

Executarea unor interogări SQL

Clasa QSqlQuery oferă o interfață pentru executarea unor interogări SQL și navigare prin setul de rezultate al interogării. Clasele QSqlQueryModel și QSqlTableModel oferă un suport de un nivel mai înalt pentru accesarea unei baze de date.

Pentru a executa un query SQL putem crea un obiect de tip QSqlQuery iar mai apoi apelăm metoda bool exec(QString &query;) precum în următorul exemplu :

 QSqlQuery query(QSqlDatabase::database("MyDbConnectionName"));
 query.exec("SELECT ID FROM PROFILE ORDER BY ID ASC");

Constructorul obiectului QSqlQuery primește ca argument conexiunea la baza de date care va fi folosită. Dacă nu am fi specificat-o s-ar fi folosit conexiunea implicită.

QSqlQuery ne permite să accesăm rezultate doar pe rând. După ce executăm metoda exec(), pointerul intern al lui QSqlQuery este localizat cu o poziție în urmă față de prima înregistrare. Pentru a avansa în setul de rezultate trebuie să apelăm metoda bool next(). În exemplul următor se iterează peste rezultatele unei interogări :

 while (query.next()) {
 id = query.value(0).toInt();
 if (id == free_id) {free_id++;
 } else {return free_id;}
 }

Funcția QVariant value(int index) const returnează valoară câmpului cu indexul specificat din înregistrarea curentă. Numerotarea indexurilor câmpurilor începe de la zero. El returnează această valoare ca un QVariant, un tip de date care poate păstra diverse tipuri precum int, QString sau QByteArray. În cazul din codul de mai sus folosim funcția int toInt(bool* ok=0)const pentru a converti această valoare într-un int.

Dar putem itera atât înainte cât și înapoi folosind : next(), previous(), first(), last() și seek(). Indexul înregistrării curente este returnat de funcțiaint at() const, iar numărul total de înregistrări din setul de rezultate se obține apelând funcția int size() const.

Pentru a deternina dacă un anumit driver posedă o anumită trăsătură apelăm funcția bool QSqlDriver::hasFeature(). Dacă iterăm printr-un set de rezultate folosind doar next() și seek() este recomandat să folosim funcția QSqlQuery::setForwardOnly(true) înainte de a apela exec(). Aceasta este o optimizare simplă prin care mărim viteza unor interogări mai ales în cazul în care lucrăm cu seturi mari de rezultate.

QSqlQuery poate executa orice tip de interogare SQL, nu doar SELECT-uri. Dacă dorim să inserăm mai multe valori deodată, este mai eficient să separăm interogarea de valorile ce urmează să le inserăm. Acest lucru poate fi făcut prin intermediul unor substituenți. Qt oferă suport pentru două tipuri de substituenți :

  • substituenți cu nume și
  • substituenți poziționali.

Un exemplu în care se folosesc substituenți cu nume poate fi văzut în următoarea secvență de cod :

 QSqlQuery query(QSqlDatabase::database("MyDbConnectionName"));
 query.prepare("INSERT INTO PROFILE"
 " (Id,Name)"
 " VALUES (:Id,:Name)");
 query.bindValue(":Id", profile->getId());
 query.bindValue(":Name", profile->getName());
 query.exec();

Utilizarea unui model SQL

Pe lângă QSqlQuery, Qt oferă clase de nivel înalt pentru accesarea bazelor de date. Aceste clase sunt:

Aceste clase ușurează prezentarea datelor dintr-o bază de date într-o vizualizare de prezentare a datelor precum QListView sau QTableView.

  • QSqlQueryModel oferă un model care poate fi doar citit bazat pe o interogare SQL. Un exemplu de folosire îl aveți mai jos :
 myModel = new QSqlQueryModel(this);
 myModel->setQuery("SELECT * FROM PROFILE",
 QSqlDatabase::database("MyDbConnectionName"));
  • QSqlTableModel oferă un model editabil pentru un singur tabel dintr-o bază de date. Nu presupune cunostințe de sintaxă SQL. Tabelul se selectează prin apelul funcției void setTable(const QString& tableName). Mai apoi putem apela la filtre sau sorta după o anumită coloană precum în exemplul următor :
 QSqlTableModel model;
 model.setTable("PROFILE");
 model.setFilter("Age > 50");
 model.setSort(2, Qt::DescendingOrder);
 model.select();

QSqlRelationalTableModel oferă suport pentru chei externe. O cheie externă este o relație de unu la unu între un câmp dintr-un tabel la cheia primară a unui alt tabel. De exemplu daca tabelul book are un câmp numit authorid care indifică câmpul id de al tabelului author, spunem că authorid este o cheie externă.