IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Firebird Discussion :

Problème insertion de données utilisant le résultat d'une autre insertion


Sujet :

SQL Firebird

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8
    Points : 31
    Points
    31
    Par défaut Problème insertion de données utilisant le résultat d'une autre insertion
    Bonjour!

    J'ai hésité quant au forum où poster, mais je pense que j'ai besoin des lumières des afficionados de Firebird.
    Je rencontre un petit... enfin non, un gros problème dans le développement d'une application utilisant Firebird (2.1).

    Mon souci : insérer des données en chaine dans la base de données. La "requête suivante" doit utiliser l'identifiant inséré par la requête précédente, etc.

    Voici un code très simplifié de ce que je cherche à faire (je développe en C++ avec Qt mais c'est compréhensible pour la plupart des développeurs).
    Le souci, à l'issue de l'exécution de ce code, c'est que les données n'ont été insérées que dans la première table, les deux suivantes ne sont pas touchées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    QSqlQuery query;
            query.exec("INSERT INTO parking (idparking) VALUES (null) 
                             RETURNING idparking;");
            query.next();
            QString idParking = query.value(0).toString();
            // affiche : "2" (par exemple)
            qDebug() << "idParking " << idParking;
     
            query.exec("INSERT INTO voiture (idvoiture, fk_idparking) 
                             VALUES (null, "+ idParking +") RETURNING idvoiture;");
            query.next();
            QString idVoiture = query.value(0).toString();
            // affiche : "16" (par exemple)
            qDebug() << "idVoiture " << idVoiture; 
     
            query.exec("INSERT INTO option(idoption, fk_idvoiture) 
                             VALUES (null, "+idVoiture+") RETURNING idoption;");
            query.next();
            // affiche : ""
            qDebug() << "idOption " << query.value(0).toString();
    Et j'obtiens comme message d'erreur :
    QSqlQuery::value: not positioned on a valid record

    Si je place un point d'arrêt juste avant la troisième requête, je peux constater que ma table "parking" a été modifiée, mais ma table "voiture", elle, n'a pas été modifiée. Donc la seconde requête est effectuée et me renvoie un résultat... mais il n'est pas inscrit dans la base de données!

    Je suppose que mon souci vient du fonctionnement interne de Firebird, mais... j'y comprend rien.
    Si quelqu'un pouvait m'expliquer ce qui se trame là, et mieux encore m'expliquer la marche à suivre je lui en serait très reconnaissant !
    Je voudrais pouvoir placer toutes mes requêtes au sein d'une transaction...

    Merci.

  2. #2
    Membre expert

    Homme Profil pro
    Consultant spécialité Firebird
    Inscrit en
    Mai 2002
    Messages
    2 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Consultant spécialité Firebird
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 342
    Points : 3 712
    Points
    3 712
    Par défaut
    c'est ton code qui est étrange
    c'est quoi ces "query.next();"

    par ailleurs tu dis :
    Je voudrais pouvoir placer toutes mes requêtes au sein d'une transaction...
    mais nul part tu annonces le début et la fin de ta transaction
    Philippe Makowski
    IBPhoenix - Firebird
    Membre de l'April

  3. #3
    Membre expert

    Homme Profil pro
    Consultant spécialité Firebird
    Inscrit en
    Mai 2002
    Messages
    2 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Consultant spécialité Firebird
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 342
    Points : 3 712
    Points
    3 712
    Par défaut
    voilà en python :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import kinterbasdb as k; k.init(type_conv=300)
    from kinterbasdb import services
     
    def createCon(db,login,mypassword):
        connect = k.connect(host='127.0.0.1', database=db,
            user=login, password=mypassword, charset='UTF8'
          )
        return connect
    def main():
    	print 'connection'
    	mydb = createCon('C:/bla/bla.fdb','SYSDBA','masterke')
    	# optionel explicit start transaction
    	mydb.begin()
    	curmydb = mydb.cursor()
    	curmydb.execute("INSERT INTO PARKING (IDPARKING) VALUES (NULL) RETURNING IDPARKING")
    	for row in curmydb:
    		vidparking = row[0]
    	print 'valeur idparking : %d' % (vidparking,)	
    	curmydb.execute("INSERT INTO VOITURE (IDVOITURE,IDPARKING) VALUES (NULL,%d)" % (vidparking,))	   
    	mydb.commit()
    	curmydb.execute("SELECT IDVOITURE,IDPARKING FROM VOITURE")
    	print curmydb.fetchall()
    	mydb.close()
     
    if __name__ == '__main__':
        main()
    et le résultat exécuté deux fois:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    C:\bla>python bla.py
    connection
    valeur idparking : 4
    [(3, 4)]
     
    C:\bla>python bla.py
    connection
    valeur idparking : 5
    [(3, 4), (4, 5)]
    Philippe Makowski
    IBPhoenix - Firebird
    Membre de l'April

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8
    Points : 31
    Points
    31
    Par défaut
    Merci de t'intéresser à mon pépin

    Citation Envoyé par makowski Voir le message
    c'est ton code qui est étrange
    c'est quoi ces "query.next();"
    J'ai réécrit un exemple bidon où j'ai viré tout ce qui ne concerne pas mon problème. J'aurai dû le commenter
    Voilà :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    // la connexion a été établie avant dans le code
     
    // déclaration de la requête
            QSqlQuery query;
    // exécution de la requête
            query.exec("INSERT INTO parking (idparking) VALUES (null) RETURNING idparking;");
    // navigation dans le resultset jusqu'à l'enregistrement suivant 
    // (le premier, en fait car le curseur se trouve au départ sur le résultat -1)
            query.next();
    // je récupère la valeur
            QString idParking = query.value(0).toString();
    // affichage la valeur dans la console
            qDebug() << "idParking " << idParking;
    // et je refait ça pour les deux requêtes qui suivent...

    Citation Envoyé par makowski Voir le message
    par ailleurs tu dis :
    mais nul part tu annonces le début et la fin de ta transaction
    Parce que cela ne change rien au résultat, peu importe :
    - que je débute la transaction au tout début de mon code pour la terminer tout à la fin après la troisième requête,
    - ou alors que chaque requête soit elle-même effectuée à l'intérieur d'une transaction (j'ai voulu tester ça après avoir lu ton code, en voyant un commit() après exécution de la requête).

    Au sujet de ton exemple : est-ce que tu voudrais bien essayer avec une troisième requête qui utilise l'identifiant renvoyé par la seconde requête?
    Parce que, dans mon exemple les deux première tables (parking et voiture) sont correctement peuplées, c'est la dernière (option) qui reste désespérément vide...

  5. #5
    Membre expert

    Homme Profil pro
    Consultant spécialité Firebird
    Inscrit en
    Mai 2002
    Messages
    2 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Consultant spécialité Firebird
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 342
    Points : 3 712
    Points
    3 712
    Par défaut
    Citation Envoyé par Zarkenciel Voir le message
    - ou alors que chaque requête soit elle-même effectuée à l'intérieur d'une transaction (j'ai voulu tester ça après avoir lu ton code, en voyant un commit() après exécution de la requête).
    mon commit est fait après les deux requetes, les deux requetes sont exécutée dans la même transaction

    et ok, je vais ajouter une troisième table
    Philippe Makowski
    IBPhoenix - Firebird
    Membre de l'April

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8
    Points : 31
    Points
    31
    Par défaut
    Merci

  7. #7
    Membre expert

    Homme Profil pro
    Consultant spécialité Firebird
    Inscrit en
    Mai 2002
    Messages
    2 342
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France

    Informations professionnelles :
    Activité : Consultant spécialité Firebird
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 342
    Points : 3 712
    Points
    3 712
    Par défaut
    voilà :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    C:\bench\bla>python bla.py
    connection
    debut transaction
    insertion dans parking
    valeur idparking : 10
    insertion dans voiture
    valeur idvoiture : 13
    insertion dans option
    valeur vidoption : 14
    commit
    SELECT IDVOITURE,IDPARKING FROM VOITURE
    [(13, 10)]
    SELECT IDOPTION,IDVOITURE FROM OPTION
    [(14, 13)]
    et le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    	print 'connection'
    	mydb = createCon('C:/bench/bla/bla.fdb','SYSDBA','masterke')
    	curmydb = mydb.cursor()
    	# on vide les tables
    	curmydb.execute("DELETE FROM PARKING")
    	mydb.commit()	
    	print 'debut transaction'
    	# optionel explicit start transaction
    	mydb.begin()
    	print 'insertion dans parking'
    	curmydb.execute("INSERT INTO PARKING (IDPARKING) VALUES (NULL) RETURNING IDPARKING")
    	for row in curmydb:
    		vidparking = row[0]
    	print 'valeur idparking : %d' % (vidparking,)	
    	print 'insertion dans voiture'
    	curmydb.execute("INSERT INTO VOITURE (IDVOITURE,IDPARKING) VALUES (NULL,%d) RETURNING IDVOITURE" % (vidparking,))	   
    	for row in curmydb:
    		vidvoiture = row[0]
    	print 'valeur idvoiture : %d' % (vidvoiture,)	
    	print 'insertion dans option'
    	curmydb.execute("INSERT INTO OPTION (IDOPTION,IDVOITURE) VALUES (NULL,%d) RETURNING IDOPTION" % (vidvoiture,))	   
    	for row in curmydb:
    		vidoption = row[0]
    	print 'valeur vidoption : %d' % (vidoption,)	
    	print 'commit'
    	mydb.commit()
    	print 'SELECT IDVOITURE,IDPARKING FROM VOITURE'
    	curmydb.execute("SELECT IDVOITURE,IDPARKING FROM VOITURE")
    	print curmydb.fetchall()
    	print 'SELECT IDOPTION,IDVOITURE FROM OPTION'
    	curmydb.execute("SELECT IDOPTION,IDVOITURE FROM OPTION")
    	print curmydb.fetchall()
    	mydb.close()
    donc le problème est clairement dans ton code
    là j'ai reproduit ce que tu annonce faire dans ton premier post
    avec seulement en plus des débuts de transaction et des commit explicites
    revois ton code.
    il y a qq chose que tu ne fais pas correctement, et semble t il pas comme tu le décris

    autre chose à vérifier, ta table option, elle a bien un trigger on insert actif pour affecter la valeur de idoption ?
    Philippe Makowski
    IBPhoenix - Firebird
    Membre de l'April

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8
    Points : 31
    Points
    31
    Par défaut
    Bon, à force de faire des tests dans tous les sens, j'ai fini par m'embrouiller.

    En relisant attentivement les messages d'erreur SQL, j'ai finalement compris que c'était le nom de ma table "option" qui ne plaisait pas. Allez comprendre pourquoi je l'ai renommée en "lesoptions" et maintenant mon bout de code marche nickel.

    J'aimerai bien comprendre le pourquoi du comment, mais je ne pense pas y arriver.

    Ne me reste plus qu'à retourner dans mon application, là où l'erreur a surgi et chercher à comprendre, à nouveau, l'erreur générée - là je n'ai pas de table nommée "option", donc la vérité est ailleurs.

    Merci infiniment pour ton aide et désolé du dérangement.
    Peut-être à bientôt, je sens que l'erreur d'origine va encore me donner bien du fil à retordre !

Discussions similaires

  1. Réponses: 2
    Dernier message: 24/11/2012, 13h51
  2. UPDATE utilisant le résultat d'une autre requete
    Par haltabush dans le forum Requêtes
    Réponses: 2
    Dernier message: 29/07/2008, 16h12
  3. requetes utilisant le résultat d'une autre
    Par babou54 dans le forum ASP
    Réponses: 3
    Dernier message: 20/12/2007, 05h14
  4. Utilisation du résultat d'une requête
    Par Manu14400 dans le forum Access
    Réponses: 1
    Dernier message: 15/10/2005, 13h01
  5. Réponses: 4
    Dernier message: 05/04/2005, 18h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo