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

JDBC Java Discussion :

Problème INSERT via JDBC


Sujet :

JDBC Java

  1. #1
    Membre actif
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2019
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2019
    Messages : 134
    Points : 209
    Points
    209
    Par défaut Problème INSERT via JDBC
    Bonjour,

    j'effectue plusieurs INSERT et je rencontre un problème de type : java.sql.SQLException: ORA-01722: Nombre non valide

    Voici une ligne qui s'insère correctement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    72,'','','','ID1','-1','750010002','CP','1','-1','','','','','','ID2','','','Agence2','','','0','Reprise','Inactif','0','Nom','Admin Dynamics','','','','','','','','','','','','') SELECT 1 FROM DUAL
    et une autre qui lève une exception :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    73,'37, rue Test,'','','ID1','-1','1','CP','0','-1','','','','','','ID2','','','Agence1','','','8.75','En cours','Actif','1','Nom','Admin Dynamics','','',TO_DATE(SUBSTR('2018-02-20 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),TO_DATE(SUBSTR('2018-02-20 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),TO_DATE(SUBSTR('2006-12-27 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),TO_DATE(SUBSTR('2018-02-19 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),TO_DATE(SUBSTR('2018-02-20 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),TO_DATE(SUBSTR('2009-09-30 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),TO_DATE(SUBSTR('2018-02-20 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),TO_DATE(SUBSTR('2018-02-20 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS'),'',''
    Je fais une requête contenue dans une boucle qui permet de récupérer les données et de les insérer ligne par ligne.
    Requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String insertQuery = "INSERT INTO "+maTable+" ( "+colonneTable+" ) VALUES "+InsertValue+"";
    InsertValue correspond par exemple au ligne cité ci dessus.

    L'erreur obtenue fait référence à un Nombre invalide, '8.75'. Lorsque je remplace le point par une virgule l'erreur n'apparait plus.

    J'ai essayé de changer le "NLS_LANG" du JDBC sous la forme ,. mais l'erreur persiste.

    Y a-t-il une autre soluion que de changer le point par une virgule sinon il faudrait faire après l'INSERT une modification sur la base?

    Merci de votre aide !

  2. #2
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Deux choses :
    1- Il ne faut pas utiliser de Statement pour faire ça mais un PreparedStatement
    Avec un Statement :
    Si tu as des apostrophes dans une chaine, il faut les doubler
    Tu risques des attaques par injection
    etc...

    2- Un nombre n'est pas mis entre apostrophes mais directement
    Dans ton cas, si tu mettais 8.75 plutôt que '8.75', ça fonctionnerait

    Bref, je te suggère de faire quelque chose comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    (En supposant que col1 soit une chaîne de caractère, col2 une Date, col3 un Double)
     
    PreparedStatement pstmtInsert = connection.prepareStatement("insert into MaTable(col1, col2, col3) values(?, ?, ?);
    for (....)
    {
        pstmtInsert.setString(1, maValeurString);
        pstmtInsert.setDate(2, maValeurDate);
        pstmtInsert.setDouble(3, maValeurDouble);
        pstmtInsert.executeUpdate();
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre actif
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2019
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2019
    Messages : 134
    Points : 209
    Points
    209
    Par défaut
    Concernant ta réponse :
    Citation Envoyé par OButterlin Voir le message
    Deux choses :
    Bref, je te suggère de faire quelque chose comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    (En supposant que col1 soit une chaîne de caractère, col2 une Date, col3 un Double)
    PreparedStatement pstmtInsert = connection.prepareStatement("insert into MaTable(col1, col2, col3) values(?, ?, ?);
    for (....)
    {
        pstmtInsert.setString(1, maValeurString);
        pstmtInsert.setDate(2, maValeurDate);
        pstmtInsert.setDouble(3, maValeurDouble);
        pstmtInsert.executeUpdate();
    }
    La colonne 2 d'une table peut très bien être un String alors que sur une autre table ce sera un Double, ça serait compliqué (pour moi ) de mettre en place ce systeme.

    J'ai bien pris note pour le PreparedStatement et le Statement.

    Pour situer un peu le contexte, je créé un flux sur Talend Open Studio. Ce flux doit insérer les données présentent dans des vues dans les tables correspondantes. Actuellement nous avons un flux par table et vue correspondante. J'ai donc créé un flux talend "générique" qui permet de renseigner les différentes variables (Base de données, serveur, user, etc) dans un fichier de context en .CSV. Cependant les tables et les vues correspondantes ne sont pas forcément au même format (ID en plus, colonne non présente sur la vue ou sur la table, etc). Par exemple le format des DATE n'est pas le même, j'ai donc du récupérer toutes les colonnes au format date pour le mettre au même standard. Tu me conseilles donc de faire la même chose que ça mais pour les valeurs numériques ?

  4. #4
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Je n'ai pas tout compris...

    Quelle est la source des données que tu veux insérer dans tes tables ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre actif
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2019
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2019
    Messages : 134
    Points : 209
    Points
    209
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Je n'ai pas tout compris...

    Quelle est la source des données que tu veux insérer dans tes tables ?
    La source est une vue la cible une table, cependant je dois faire faire en sorte que ça fonctionne quelques soientt la vue, la table et leurs structures.

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Est-ce que c'est la structure de ta vue qui détermine la structure de ta table ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre actif
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2019
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2019
    Messages : 134
    Points : 209
    Points
    209
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Est-ce que c'est la structure de ta vue qui détermine la structure de ta table ?
    Non je récupère les données par rapport à la structure de la table, si une colonne est dans la vue et pas dans la table alors je ne peux pas intégrer ces données et si une colonne est dans la table et non dans la vue ... et bien le champs sera vide (comme on peut le voir dans les 2 exemples de lignes dans mon premier commentaire). Je précise que je n'ai pas la main sur la base (je suis un stagiare ) donc pas de modifs possible ...

    EDIT:
    Concernant les Dates c'est normal que tu n'aies pas compris si je ne poste pas ce que j'ai fait .
    Je fais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TO_DATE(SUBSTR('2018-02-20 02:00:00.0' ,1,19), 'YYYY-MM-DD HH:MI:SS')
    lorsque des dates sont renseignées (dans les colonnes au format date) car ils ont trouvé judicieux de ne pas mettre les mêmes formats entre les colonnes Date des Tables et les colonnes Date des Vues ... Donc je récupère via les tables SYS les colonnes format Date afin de les traités spécifiquement pour l'INSERT (cf: TO_DATE(....) ). Je souhaitais trouver une autre solution pour mon problème actuel, sinon je vais faire la même méthode mais avec les colonnes au format Numeric.

  8. #8
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Je te suggère d'utiliser le ResultSetMetaData sur ta vue et ta table et de comparer (via une Map par exemple)
    En gros, tu fais :
    1- Une requête sur ta vue (select * from vue)
    2- Sur le ResultSet en retour, tu appelles la méthode getMetaData() qui te renverra la structure de ta vue (nom de colonne, type, longueur, etc...)
    3- Tu charges une Map avec ces données
    4- Une requête sur ta table
    5- getMetaData()
    6- Tu charges une Map avec ces données

    Tu n'as plus qu'à comparer les 2 et faire les conversions qui vont bien en fonction du type source et type attendu.
    Au moins, la structure de ta table destinatrice est connue, enfin, de ce que j'ai compris...
    Avec le ResultSetMetaData sur la table, tu peux générer le PreparedStatement dynamiquement

    Enfin bref, c'est une piste
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre actif
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2019
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2019
    Messages : 134
    Points : 209
    Points
    209
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Je te suggère d'utiliser le ResultSetMetaData sur ta vue et ta table et de comparer (via une Map par exemple)
    En gros, tu fais :
    1- Une requête sur ta vue (select * from vue)
    2- Sur le ResultSet en retour, tu appelles la méthode getMetaData() qui te renverra la structure de ta vue (nom de colonne, type, longueur, etc...)
    3- Tu charges une Map avec ces données
    4- Une requête sur ta table
    5- getMetaData()
    6- Tu charges une Map avec ces données
    D'accord j'ai fait une autre méthode mais c'est le même principe je vois.
    J'ai fait :
    1. Une requête sur la table SYS qui me permet de récuperer le nom de toutes les colonnes de la table
    2. Une requête qui me permet de récupérer le nom des colonnes de la vue
    3. Une requête qui me permet de récuperer le nom des colonnes au format Date, pareil pour le format Numeric du coup
    4. Je mets par ordre alphabétique mes listes contenant les noms des colonnes table et vue
    5. Avec un retainAll je garde les colonnes communes entre la vue et la table
    6. Ensuite j'enlève les colonnes Numeric et Date de la liste puis je les rajoute afin d'avoir une liste sous la forme ["DataSansTraitement","DataDate","DataNumeric"]
    7. Dans la boucle for j'insère les données sans traitement, puis celle au format Date et enfin au format Numeric


    3- Tu charges une Map avec ces données
    Je ne connais pas du tout le fonctionnement des Map

  10. #10
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Disons que ma méthode est portable alors que la tienne dépend de la DB mais bon, ce n'est pas forcément un problème bien sûr

    Pour le traitement, la conversion d'une donnée source peut se faire de manière générique, quitte à passer par des correspondance source/cible.
    Ceci dit, avec le PreparedStatement, tu as la méthode setObject(idx, value) qui couvre une grande partie des cas, on aurait plutôt des conversions lorsque (par exemple) le fuseau horaire source n'est pas le même que le fuseau horaire cible ou de la transcodification ("01" source correspond à 18 cible...).

    Pour la Map, en gros, c'est un objet qui associe une valeur à une clé (une sorte de dictionnaire).
    Dans le cas qui nous intéresse, je voyais comme clé le nom de la colonne (ou table/colonne) et un objet spécifique pour les propriétés à évaluer (le type, la longueur, le nombre de décimale etc...)
    Ensuite, tu bouclais sur les colonnes cible, tu recherchais par le nom dans la Map, si pas trouvé -> on ne traite pas, sinon, on traite les éventuelles différences nécessitant une conversion.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Membre actif
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2019
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2019
    Messages : 134
    Points : 209
    Points
    209
    Par défaut
    Super merci pour tes explications !

    Je passe en résolu !

  12. #12
    Membre régulier Avatar de abdennour bouaicha
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2009
    Messages
    98
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2009
    Messages : 98
    Points : 112
    Points
    112
    Par défaut
    salut ,
    ma méthode de faire une insertion est comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    insert into table set col1="****" , col2="****",......, coln="***"
    comme ça même si j'ai oublié une colonne à remplir ,ou bien je veux la contourner et la laisser vide le SQLEXCEPTION reste en hibernation et ne déclenche aucun erreur,
    je trouve ça mieux que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    insert into table value (""""""""""""""""")
    avec une table professionnel de trentaine de colonne il nous faudra un ans pour voir si chaque value ("") est dans la bonne place

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème insertion données JDBC
    Par kenda10 dans le forum JDBC
    Réponses: 4
    Dernier message: 18/09/2012, 20h31
  2. [Oracle] Problème d'insertion de ligne via JDBC
    Par nicofromChina dans le forum JDBC
    Réponses: 3
    Dernier message: 17/07/2007, 12h21
  3. Réponses: 9
    Dernier message: 11/06/2007, 16h58
  4. Problème insertion dans bdd access. Via VB express 2005
    Par Frosaf dans le forum Windows Forms
    Réponses: 1
    Dernier message: 08/06/2007, 18h19
  5. Problème de récupération de blob via JDBC
    Par realworld dans le forum Oracle
    Réponses: 2
    Dernier message: 24/01/2007, 10h27

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