Insérer un champ clob dans Oracle

Résolu
cs_polux31 Messages postés 3 Date d'inscription lundi 11 juin 2007 Statut Membre Dernière intervention 13 avril 2011 - 7 avril 2011 à 14:51
cs_polux31 Messages postés 3 Date d'inscription lundi 11 juin 2007 Statut Membre Dernière intervention 13 avril 2011 - 13 avril 2011 à 09:15
Bonjour,

Je rencontre un problème lors d'un INSERT d'un champ Clob dans une base Oracle 10g.

Je dois parser un fichier XML et passer à la base le contenu d'une balise qui contient du texte. La taille de ce texte dépasse les 4000 caractères. Jusque là pas de problème, tout fonctionne.

J'ai donc créé une table avec un champ Clob.

Voilà mon code :
public void insertNote(int id, String mTexte){		

String query = "INSERT INTO TABLE_CLOB (ID, CLOB_NOTETEXT) VALUES ('" + id + "', '" + mTexte + "')";


OracleConnection oc = new OracleConnection();
cnx = oc.connexionBD();

//
System.out.println(query);
//

try {

Statement s = cnx.createStatement();

s.executeUpdate(query);

s.close();

oc.closeBD();

}
catch (SQLException excep){
oc.closeBD();
excep.printStackTrace();
}


}


Et voilà ce que j'obtiens dans la console :
java.sql.SQLException: ORA-00917: missing comma

at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
at oracle.jdbc.ttc7.TTIoer.processError(TTIoer.java:289)
at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:573)
at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1891)
at oracle.jdbc.ttc7.TTC7Protocol.parseExecuteFetch(TTC7Protocol.java:1093)
at oracle.jdbc.driver.OracleStatement.executeNonQuery(OracleStatement.java:2047)
at oracle.jdbc.driver.OracleStatement.doExecuteOther(OracleStatement.java:1940)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2709)
at oracle.jdbc.driver.OracleStatement.executeUpdate(OracleStatement.java:796)
at QuerySQL.insertQueryNote(QuerySQL.java:75)
at ParseNote.ParseNoteXML(ParseNote.java:63)
at SearchNodeCandidat.SearchCandidat(SearchNodeCandidat.java:63)
at SearchNodeCandidat.OpenDocXML(SearchNodeCandidat.java:24)
at Main.main(Main.java:14)


Quelqu'un a-t-il une piste ?

Merci pour l'intérêt que vous porterez à mon blème.

4 réponses

HFanny Messages postés 699 Date d'inscription mercredi 19 février 2003 Statut Membre Dernière intervention 13 mai 2011 20
7 avril 2011 à 22:58
Quelle est la valeur de "query" lors du System.out.println ?
As-tu essayé d'exécuter ce résultat directement en base de données ? Il est possible que mTexte contienne une apostrophe qui casserait l'instruction SQL.

Essaie de modifier ton code en utilisant un PreparedStatement (plus "safe" que de créer la requête soi-même dans un object String) :

//pas besoin d'apostrophes, juste un point d'interrogation pour chaque valeur qu'on veut passer
String query = "INSERT INTO TABLE_CLOB (ID, CLOB_NOTETEXT) VALUES (?, ?)";
//On initialise le PreparedStatement
PreparedStatement s = cnx.prepareStatement(query);
//En fonction du type du champ, on utilise setInt, setString, setDate ...
s.setInt(1, id);
s.setString(2, mTexte);
s.executeUpdate();
s.close();


Fanny
3
cs_polux31 Messages postés 3 Date d'inscription lundi 11 juin 2007 Statut Membre Dernière intervention 13 avril 2011
13 avril 2011 à 09:15
Bonjour,

Encore merci à toi pour ton aide. Effectivement en utilisant le lien que tu m'as indiqué, j'ai pu résoudre mon problème.

J'ai pris l'exemple d'un insert de fichier dans un clob. J'ai donc créé un fichier temporaire avec le texte à insérer que j'efface une fois la requête effectuée:

import java.io.*;
import java.sql.*;
import oracle.jdbc.*;
import oracle.sql.*;


public void insertQueryCV(String candid, String profileid) throws IOException, SQLException{

/** Insertion d'un cv dans la table profile_CV_Clob
    @candid = identifiant du candidat
    @profileid = identifiant du profil du candidat pour une offre
**/

OracleConnection oc = new OracleConnection();
cnx = oc.connexionBD();

try{

//initialize connection variable to connect to your database...
Statement stmt = cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
stmt.executeUpdate("INSERT INTO PROFILE_CV_CLOB (PROFILEID, RESUME_CV_CLOB) VALUES('" + profileid + "',EMPTY_CLOB())");

String query="SELECT RESUME_CV_CLOB FROM PROFILE_CV_CLOB WHERE PROFILEID = '" + profileid + "' for update";
//
System.out.println(query);
//
cnx.setAutoCommit(false);
ResultSet resultset = stmt.executeQuery(query);


if(resultset.next()){
CLOB clobnew = ((OracleResultSet) resultset).getCLOB("RESUME_CV_CLOB");
PrintWriter pw = new PrintWriter(clobnew.getCharacterOutputStream() );
BufferedReader br = new BufferedReader (new FileReader( new File("C:\\temp\"tmpClob.txt") ) );
String  lineIn = null;
while( ( lineIn = br.readLine() ) != null )
      pw.println( lineIn );
      pw.close();
      br.close();
}

stmt.executeUpdate("Update PROFILE_CV_CLOB SET CANDID '" + candid + "' WHERE PROFILEID '" + profileid + "'");
cnx.setAutoCommit(true);
cnx.commit();

}
catch (SQLException excep){
oc.closeBD();
excep.printStackTrace();
}

}


En espérant que ça aide également d'autres néophytes comme moi.
3
cs_polux31 Messages postés 3 Date d'inscription lundi 11 juin 2007 Statut Membre Dernière intervention 13 avril 2011
8 avril 2011 à 09:57
Bonjour,

Tout d'abord merci pour ce précieux conseil qui a partiellement réglé le problème.

Oui, j'avais vérifié le contenu de query et également le passage de la requête directement dans la base. Je me doutais bien que je n'employais pas la bonne méthode dans mon code.

J'ai donc une nouvelle exception qui se lève :

java.sql.SQLException: La taille des données est supérieure à la taille max. pour ce type: 9029
...


Le champ de la base est pourtant bien de type CLOB qui devrait pouvoir contenir 4Go.

Est-ce un problème Java ou Oracle ?

Merci encore.
0
HFanny Messages postés 699 Date d'inscription mercredi 19 février 2003 Statut Membre Dernière intervention 13 mai 2011 20
8 avril 2011 à 20:45
J'avoue n'avoir jamais eu besoin d'exécuter ce genre de requête et n'ai donc jamais rencontré cette erreur.
En faisant quelques recherches rapidement, il semblerait qu'il faudrait d'abord ajouter un contenu Clob vide, et ensuite récupérer l'objet pour le mettre à jour :

SELECT clob_notetexte FROM table_clob WHERE id = ? FOR UPDATE


Voici l'exemple que j'ai trouvé (en anglais) ici.

Citation :
The main point: Unlike with other JDBC drivers, the one from Oracle doesn't support using Reader and InputStream as parameters of an INSERT. Instead, you must SELECT the CLOB column FOR UPDATE and then write into the ResultSet

En tout cas, il semblerait qu'en utilisant "thin", un setString() ne peut pas fonctionner pour plus de 4000 caractères.

Fanny
0
Rejoignez-nous