Bonjour,
En ce qui concerne la proposition de simplification de wiztricks:
def do_sql(cursor, sql, values=None, tx_mode=False, bulkmode=False):
j'ai déjà essayé, mais ça marche rarement parce qu'une transaction est à appliquer à un "paquet logique" de requêtes et non à une seule, sauf dans les cas très simples. Par exemple dans ton cas, si tu rentres en même temps une nouvelle personne avec une nouvelle adresse, si l'adresse échoue, il ne faut pas que la nouvelle personne puisse être enregistrée (=>rollback): c'est donc l'ensemble qui doit se trouver dans la même transaction. On peut bien sûr enchainer les requêtes dans le même script sql mais ça ne clarifie pas le code.
Avec ta base sans modification (donc sans le "on delete restrict" proposé), j'ai essayé de supprimer l'adresse numéro 9 avec un script Python: il y a bien refus! Voilà mon code d'essai:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import division
# Python 2.7
import sqlite3
#############################################################################
def ouvrebase(basesql, curseur=False):
"""ouvre la base concours.db3 et renvoie la connexion
si curseur est True, renvoie aussi un curseur
"""
try:
cnx = sqlite3.connect(basesql)
cnx.execute("PRAGMA foreign_keys=on;") # active le foreign key
except sqlite3.Error, err:
raise # renvoie l'exception à l'appelant
if curseur:
cur = cnx.cursor()
return cnx, cur
return cnx
#############################################################################
def fermebase(cnx, cur=None):
"""Ferme la base ouverte avec la connexion cnx
si le curseur cur est donné, il est fermé aussi
"""
if cur != None:
cur.close()
cnx.close()
#############################################################################
basesql = u"CarnetAdresse.db"
cnx, cur = ouvrebase(basesql, True)
try:
cur.execute("""DELETE
FROM T_d_Adresse
WHERE id_adresse=9 """)
cnx.commit()
except sqlite3.Error, err:
cnx.rollback()
print u"Erreur", err.args[0]
fermebase(cnx, cur) |
L'exécution de ce code donne l'erreur:
Erreur foreign key constraint failed
Ce qui est le résultat correct. Donc, l'interpréteur Python fait bien son boulot!
Il y a une autre solution qu'il m'arrive d'utiliser: au lieu de laisser l'interdiction de suppression d'adresse par contrainte "foreign key", j'accepte cette suppression d'adresse mais avec la suppression en cascade de tout ce qui dépend d'elle (on delete cascade). Ça peut être dangereux si on se trompe, mais dans certaines applications, c'est extrêmement pratique!
A mon avis: abandonne Idle pour piloter ta base en interactif, et utilise n'importe quelle console non programmée en Python. J'aime bien idle, mais je m'en méfie parce qu'on fait exécuter du Python par du Python, et on ne sait jamais dans quelle mesure le code de Idle interagit avec le code qu'on lui demande d'exécuter. En tout cas, j'ai déjà rencontré des problèmes d'exécution qui n'existaient qu'avec Idle (dans des cas plus complexes il est vrai, genre thread).
Partager