Accéder aux bases de données avec QtSql

Le module QtSql fournit une API homogène pour accéder à différents SGBDR (Systèmes de Gestion de Bases de Données Relationnelles) : ODBC, PostgreSQL, MySQL, SQLite. Si vous utilisez PySide2, il est intéressant d’utiliser le module QtSql car vous bénéficiez déjà de l’intégration dans Qt et l’interaction avec les différentes bases de données sera identique.

Avertissement

Pour les plates-formes GNU/Linux, le plugin QtSql pour MySQL n’est pas installé par défaut. Vous avez besoin des sources de Qt pour pouvoir le compiler pour votre système. Cf. la documentation officielle :

Déclaration d’une connexion

La classe QSqlDatabase permet de créer un objet représentant une connexion à une base de données. Pour cela, il faut appeler la méthode addDatabase en passant le type de la base de données : "QSQLITE", "QMYSQL", "QPSQL", "QPSQL7", "QODBC".

Déclaration d’une connexion MySQL
db = QSqlDatabase.addDatabase('QMYSQL')
db.setHostName('localhost')
db.setPort(3306)
db.setDatabaseName("mabase")

L’appel à addDatabase permet de créer une nouvelle connexion sur laquelle il est possible de positionner les paramètres nécessaires : hôte, port, nom de la base de données…

Note

Comme second paramètre à la méthode addDatabase, vous pouvez spécifier le nom de la connexion à la base de données dans votre programme. Si vous ne le faites pas, cela signifie que vous déclarez la base de données par défaut pour votre application.

Ouverture d’une connexion

L’ouverture de la connexion à la base de données se fait en appelant la méthode open à laquelle on passe le nom de l’utilisateur et le mot de passe. La méthode retourne True si la connexion a pu être établie

if db.open("login", "motdepase"):
    pass

Attention, si vous voulez gérer correctement l’accès à la base de données, il vous faut fermer la connexion lorsqu’elle n’est plus nécessaire à votre application.

db.close()

Requête avec QSqlQuery

Pour réaliser des requêtes, il faut utiliser la classe QSqlQuery.

Requêtes de modification

Pour des requêtes de modification (INSERT, UPDATE, DELETE, …), il suffit de créer un objet QSqlQuery. À la construction, il est possible de passer l’objet QSqlDatabase représentant la connexion à la base de données. Si la base de données n’est pas précisée, QSqlQuery utilise la connexion par défaut.

query = QSqlQuery("insert into Utilisateur (login) values ('david')")

Ou bien, il suffit d’appeler les méthode exec_ en passant la requête en paramètre

query = QSqlQuery()
query.exec_("insert into Utilisateur (login) values ('david')")

Requêtes de consultation

Pour les requêtes de consultation (SELECT), on utilise la méthode next et la méthode value pour passer à la ligne suivante et récupérer les valeurs des colonnes.

query = QSqlQuery("select login from Utilisateur")
while query.next():
    print(query.value("login"))

Requêtes préparées

Les requêtes préparées permettent de séparer l’exécution des requêtes en trois temps. D’abord la préparation qui permet d’indiquer la structure de la requête, puis l’association de valeur à la requête et enfin l’exécution proprement dite de la requête. Les requêtes préparées autorisent de meilleures performances lorsque l’on désire répéter un grand nombre de fois une requête en ne faisant varier que les valeurs. Elles permettent également d’écrire du code plus robuste en le protégeant de l’injection SQL.

Pour créer une requête préparée, il faut appeler la méthode prepare en passant la requête. Le nom des valeurs commence par deux-points :. La méthode bindValue permet ensuite de spécifier les valeurs à associer à la requête. Enfin, l’appel à exec_ permet l’exécution de la requête.

query = QSqlQuery()
query.prepare("insert into Utilisateur (login) values (:nom)")
query.bindValue(":nom", "david")
query.exec_()

Gestion des erreurs

La gestion des erreurs se fait au travers des objets de type QSqlError. Pour savoir si une connexion à échouer à l’ouverture, vous pouvez appeler la méthode isOpenError et ensuite lastError pour obtenir un objet de type QSqlError.

db.open("login", "motdepasse")
if db.isOpenError():
    error = db.lastError()
    # ...

Les objets de type QSqlQuery disposent également de la méthode lastError pour récupérer la dernière erreur obtenue. Vous pouvez vérifier avec la méthode isValid qu’une erreur s’est produite.

query = QSqlQuery("insert into Utilisateur (login) values ('david')")
if query.lastError().isValid():
    error = query.lastError()
    # ...

Les transactions

Pour les systèmes de base de données qui le supportent, il est possible d’utiliser des transactions. La classe QSqlDatabase fournit les méthodes transaction, commit et rollback pour, respectivement, démarrer une transaction, valider une transaction et annuler une transaction.

db.transaction()
QSqlQuery("insert into Utilisateur (login) values ('david')")
QSqlQuery("insert into Utilisateur (login) values ('éric')")
db.commit()