2010-12-14 60 views
1

Je dois utiliser JDBC pour écrire dans une base de données (hibernate/ibatis n'est pas une option) et ma base de données est Oracle 11g.JDBC: se plaint d'un signe invalide mais semble correct

Je crée la requête suivante: insert into user(user_id, username, age, creation_ts) values(seq_userid.NEXTVAL, 'Jack', 19,TO_TIMESTAMP('14/12/2010 15/09/46', 'DD/MM/RR HH24/MI/SS'));

Cependant, mon statetement.execeuteUpdate(above sql). génère une exception de signe non valide. Mais quand j'effectue la requête dans l'écureuil, il se commet très bien. Est-ce que quelqu'un sait pourquoi cela se produit?


Edit: 
user table: 
id: number : not null 
username varchar2(30) not null 
age number(10) not null 
creation_ts timestamp not null 

Error: 
ORA-00911: invalid character 

Java snippet: 
try 
     {  
      DriverManager.registerDriver (new oracle.jdbc.OracleDriver()); 
      String url = "privatized"; 
      Connection conn = DriverManager.getConnection(url, "username", "password"); 

      Statement st = conn.createStatement(); 

      Format formatter = new SimpleDateFormat(dateTimeFormatString); 
      String formattedDate = formatter.format(Calendar.getInstance(TimeZone.getDefault()).getTime()); 

      StringBuilder insertQuery = new StringBuilder("insert into user(user_id, username, age, creation_ts) values(seq_userid.NEXTVAL,"); 
       insertQuery.append(username); 
       insertQuery.append(","); 
      insertQuery.append(age); 
      insertQuery.append(",TO_TIMESTAMP('"); 
      insertQuery.append(formattedDate); 
      insertQuery.append("', 'DD/MM/RR HH24/MI/SS'));"); 
      System.err.println(insertQuery.toString()); 
      st.executeUpdate(insertQuery.toString()); 

      conn.close(); 
     } catch (SQLException ex){ 
      System.err.println(ex.getMessage()); 
      System.err.println(ex.getCause().toString()); 
      ex.printStackTrace(); 
      System.out.println("========================================="); 
     } catch(Exception ex) { 
      System.err.println(ex.getMessage()); 
     } 
+0

Il serait utile de voir la spécification de la table en question. L'extrait de code Java pourrait aussi être utile. – Jules

+0

At-il une exception Oracle? – HamoriZ

+0

Qu'est-ce qu'une exception de signe non valide? Pourriez-vous coller la trace d'erreur/pile? –

Répondre

2

Comme je l'ai mis dans un commentaire ci-dessus, le problème pourrait être dû au point-virgule supplémentaire à la fin de votre Instruction SQL voir ce article

Vous pouvez également regarder PreparedStatments pour vous faciliter la vie. Voici une traduction approximative de votre code ci-dessus. J'ai laissé quelques parties, et il y a des erreurs les plus probables.

String query = "insert into user(user_id, username, age, creation_ts) values(?,?,?,?)"; 
PreparedStatement pstmt = conn.prepareStatement(query); 
... //fill in all your parameters 
pstmt.setTimestamp(4, new Timestamp(System.currentTimeMillis())); 
... //execute here 
+1

Soupir, en effet la même erreur que cet utilisateur. Des heures de débogage sur quelque chose d'aussi stupide. Et je n'ai rien lu à ce sujet dans la documentation ... Parfois les bonnes habbits tournent mal ... – jack

+0

Je suis passé par la même chose il y a 2 mois, et j'ai trouvé ce lien alors. Erreur facile à faire. – Sean

+0

Et merci pour l'indice setTimeStamp. Cela efface en effet quelques lignes du code et améliore considérablement la lisibilité. – jack

0
TO_TIMESTAMP('14/12/2010 15/09/46', 'DD/MM/RR HH24/MI/SS') 

Vous envoyez un an à 4 chiffres, mais la chaîne de format définit une année à 2 chiffres (pas siècle)

pour cette solution:

insertQuery.append("', 'DD/MM/RRRR HH24/MI/SS'));"); 
+0

Juste essayé et il ne l'a pas résolu, merci pour la suggestion cependant. – jack

0

Êtes-vous sûr que la valeur de la variable username est 'Jack' et non Jack? (l'erreur ORA-00911 ne ressemble pas à une erreur de format de date typique).

En outre, vous devriez en apprendre davantage sur PreparedStatement. Ils sont plus efficaces, plus faciles à lire et à déboguer et ne sont pas sensibles à l'injection SQL.

Mon java est un peu rouillé, mais cela ressemblerait à quelque chose comme ça avec un PreparedStatement:

String query = "insert into user(user_id, username, age, creation_ts) values " 
       + "(seq_userid.NEXTVAL, ?, ?, ?)"; 

Statement st = conn.prepareStatement(query); 

st.setString(1, username); 
st.setInt(2, age); 
st.setTimestamp(3, new java.sql.Timestamp(
          Calendar.getInstance(
          TimeZone.getDefault()).getTimeMillis())); 

st.executeUpdate(insertQuery.toString()); 

De cette façon, vous n'avez pas besoin de convertir une date à une chaîne pour l'obtenir reconverti par la DB. En outre, vous pouvez trouver la déclaration plus facile à lire et vous ne devrez jamais vous soucier de l'utilisateur nommant leur compte with a ' (single-quote) :)

+0

Bonjour Vincent, je suis certain qu'il se résout à jack. J'ai imprimé la déclaration sql et c'est ce que j'ai obtenu comme résultat. Et je vais donner un coup d'oeil aux PreparedStatements. En toute honnêteté, je n'utilise pas souvent JDBC. Je suis plus familier avec hibernate/Ibates où je peux juste définir les valeurs. – jack

+0

@jack: comme [Sean] (http://stackoverflow.com/questions/4440022/jdbc-complains-about-invalid-sign-but-seems-fine/4440482#4440482) a souligné que cela ne ressemble pas à un erreur de format de date. PreparedStatement est définitivement le chemin à parcourir, j'espère que vous aurez un coup d'oeil :) (J'ai mis à jour ma réponse avec un exemple) –

+0

Je le ferai certainement. En toute honnêteté, je les avais oubliés. Trop hiberner. – jack