# ResultSet liefert oracle.sql.TIMESTAMP, aber unbrauchbar



## Rock Lobster (29. Jan 2007)

Hallo,

ich lese eine Datenbank aus, um die Daten in einem XML-File zu speichern und sie später wieder importieren zu können.

Allerdings habe ich Probleme bei Datums-Werten. Und zwar bekomme ich laut ResultSetMetaData den Typ oracle.sql.TIMESTAMP, aber wenn ich dann vom ResultSet getString() aufrufe, bekomme ich einen Datums-String, der nicht korrekt formatiert ist - mit dem Effekt, daß ich keinen neuen oracle.sql.TIMESTAMP damit instanzieren kann (also wenn ich versuche, den String dem Konstruktor zu übergeben).

Hier ein Beispiel für den String, den ich bekomme:

```
2006-12-19.16.29. 8. 144000000
```

Ich kann zwar irgendwie rauslesen, daß es sich um den 2006-12-19 handelt und die Uhrzeit 16:29 und 8,144 Sekunden ist, aber der konstruktor vom TIMESTAMP erwartet folgendes Format:

```
Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
```

Naja, jetzt ist halt die Frage, warum liefert das ResultSet einen String in einem äußerst unglücklichen Format, das ich später nicht wieder weiterverwenden kann?
Als Lösung fällt mir ein, entweder den Typ abzufragen und dementsprechend zu handeln (z.B. ein Date davon getten statt einem String, oder direkt den Long des Timestamps zu getten), aber das würde ich gerne nur als Notlösung in Erwägung ziehen. Mir wäre es lieber, ich würde das auf "sauberem" Wege kriegen, und eigentlich müßte der String mir doch das korrekte Format liefern.

Weiß jemand, an was das liegt? Und gibt es vielleicht eine bessere Lösung, als die von mir vorgeschlagene?


----------



## KSG9|sebastian (29. Jan 2007)

Warum machst du auch ResultSet#getString ? Benutz doch ResultSet#getTimestamp ?

Gruß seb


----------



## Rock Lobster (29. Jan 2007)

Ja klar, das wäre eine Lösung (wie bereits auch erwähnt).

Allerdings will ich nicht extra unterscheiden, mit welchem Wert ich es zu tun habe, sondern ich will jeden Wert als String auslesen, da das ja dann in ein XML-File geschrieben wird. Und es funktioniert ja auch perfekt, nur beim Timestamp kommt er mit so 'nem komischen Format. Dabei wär's mir halt eigentlich lieber, da nicht extra noch den Typ überprüfen zu müssen und je nach dem dann entscheiden, ob ich getString() oder getTimestamp() aufrufen soll.

Ich weiß, codemäßig sind das nur 2 Zeilen, aber irgendwie gefällt mir der Ansatz halt nicht (vor allem halt auch weil es mich einfach nur wundert, wieso getString() in dem Fall so ein ungewöhnliches (und irgendwie falsch aussehendes) Format liefert).


----------



## abollm (29. Jan 2007)

Wenn du schon Oracle nutzt, warum benutzt du nicht gleich die Konvertierfunktion "to_char"?

Damit kannst du die Werte von DATE-Spalten nach Wunsch formiert ausgeben.

Das geht z.B. so:


```
[..]
	static String query = "SELECT a.empno, a.ename, a.job, "
			+ "a.mgr, to_char(a.hiredate, 'DD.MM.YYYY HH24:MM:SS'), a.sal, a.comm, a.deptno  FROM emp a";

	[..]
	// Connect to the database
	Connection conn = DriverManager.getConnection(url, user, passw);

	Statement stmt = conn.createStatement();
	// Query absetzen
	ResultSet rs = stmt.executeQuery(query);
	// Query verarbeiten …
	System.out.println("Ausgabe Datensätze\n");
	while (rs.next()) {
[..]
```

Beachte den String "query" oben!
Im Grunde kannst du mit dieser Methode auch die Parameter für NLS_DATE_LANGUAGE beliebig setzen.


----------



## Rock Lobster (30. Jan 2007)

Naja, ich lese nicht einzelne Werte aus, sondern mache "SELECT *", und zwar aus dem Grund, weil ich die gesamte Tabelle als XML exportieren möchte, unabhängig davon, wie sie aufgebaut ist. Daher habe ich ja dann auch ResultSet - getString() benutzt, weil mir das immer die perfekte String-Repräsentation liefert, egal welcher Datentyp. Nur beim Datum schlägt das leider fehl, und mir ist einfach nicht klar, warum, denn es wird ja tatsächlich ein korrektes Datum geliefert usw, nur das Format paßt halt nicht.


----------



## Guest (30. Jan 2007)

Gäähhn, mir ist langweilig  :wink: 

```
public final class ResultSetReader {
   private static final Format dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm");
   private ResultSet resultSet;
   private Map<Integer,Integer> fieldMap;

   public ResultSetReader(ResultSet resultSet) throws SQLException {
      this.resultSet = resultSet;
      ResultSetMetaData metaData = resultSet.getMetaData();
      Map<String,Integer> fieldMap = new HashMap<String,Integer>(metaData.getColumnCount()+1, 1.0f);
      for(int i=1, n=metaData.getColumnCount(); i<=n; i++)
         fieldMap.put(i, metaData.getColumnType(i));
   }

   public boolean next() {
      return resultSet.next();
   }

   public int getColumnCount() {
      return fieldMap.size();
   }

   public String getStringValue(int index) throws SQLException {
      assert index >= 1 && index <= fieldMap.size() : "Field index out of range ("+index+")";
      Integer valueType = fieldMap.get(index);
      String result = null;
      if(Types.TIMESTAMP != valueType.intValue()) {
         String stringValue = resultSet.getString(index);
         if(!resultSet.wasNull())
            result = stringValue;
      }
      else {
         Timestamp timestampValue = resultSet.getTimestamp(index);
         if(!resultSet.wasNull())
            result = dateFormat.format(timestampValue);
      }
      return result;
   }
}
```
Anwendung
	
	
	
	





```
...
ResultSet resultSet = null;
try {
   ...
   ResultSetReader reader = new ResultSetReader(resultSet);

   int columnCount = reader.getColumnCount();
   while(reader.next()) {
      for(int i=1; i<=columnCount; i++) {
         String stringValue = reader.getStringValue(i);
         ...
      }
   }
}
finally {
   if(null != resultSet)
      resultSet.close();
   ...
}
```


----------



## Guest (30. Jan 2007)

Kleine Korrektur
	
	
	
	





```
Map<Integer,Integer> fieldMap = new HashMap<Integer,Integer>(metaData.getColumnCount()+1, 1.0f);
```


----------



## abollm (30. Jan 2007)

Rock Lobster hat gesagt.:
			
		

> Naja, ich lese nicht einzelne Werte aus, sondern mache "SELECT *", und zwar aus dem Grund, weil ich die gesamte Tabelle als XML exportieren möchte, unabhängig davon, wie sie aufgebaut ist. Daher habe ich ja dann auch ResultSet - getString() benutzt, weil mir das immer die perfekte String-Repräsentation liefert, egal welcher Datentyp. Nur beim Datum schlägt das leider fehl, und mir ist einfach nicht klar, warum, denn es wird ja tatsächlich ein korrektes Datum geliefert usw, nur das Format paßt halt nicht.



Welche Oracle-Version hast du auf deinem DB-Server am laufen?

Ab Oracle 10.1 kannst du beispielsweise die erweiterten XML-Möglichkeiten des Oracle-RDBMS bequem nutzen.


----------



## abollm (30. Jan 2007)

Rock Lobster hat gesagt.:
			
		

> Naja, ich lese nicht einzelne Werte aus, sondern mache "SELECT *", und zwar aus dem Grund, weil ich die gesamte Tabelle als XML exportieren möchte, unabhängig davon, wie sie aufgebaut ist. Daher habe ich ja dann auch ResultSet - getString() benutzt, weil mir das immer die perfekte String-Repräsentation liefert, egal welcher Datentyp. Nur beim Datum schlägt das leider fehl, und mir ist einfach nicht klar, warum, denn es wird ja tatsächlich ein korrektes Datum geliefert usw, nur das Format paßt halt nicht.



Na ja, mir ist zwar nicht langweilig, aber hier einmal ein motivierendes Beispiel, das ab Oracle 9i lauffähig ist. Es basiert auf den installierten XSU-Klassen. Das dürfte dein Problem vollständig lösen.

```
package ora.xml;

import java.sql.*;
import oracle.xml.sql.query.*;

public class XMLOracleSample
{

  // Hier geht es los ...
  public static void main(String args[]) throws SQLException
  {

    String tabName = "emp";
    String user = "scott/tiger";

    DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

    // Initialisiere JDBC-Verbindung (mit native Oracle-Treiber OCI
    Connection conn = 
      DriverManager.getConnection("jdbc:oracle:oci8:"+user+"@allfatst");

    // Erzeuge SQL-Statement und führe es aus, um ResultSet zu erhalten
    Statement stmt = conn.createStatement();
    ResultSet rset = stmt.executeQuery("select * from "+tabName );
    
    // Initialisiere OracleXMLQuery; Hinweis: Man kann auch die SQL-Query anstatt
    // ResultSet übergeben
    OracleXMLQuery qry =  new OracleXMLQuery(conn,rset);
    
    // Datumsformat für Datenfelder setzen
    qry.setDateFormat("dd.MM.yyyy HH:mm:ss");

    // XML-Dokument im String-Format
    String xmlString = qry.getXMLString();
    
    // Ausgabe auf Konsole
    System.out.println("XML-Ausgabe:\n"+xmlString); 
  }
```

Merke: Oracle bietet allein mit den gelieferten Bordmitteln eine erhebliche Menge an Möglichkeiten für die Verarbeitung von XML-Daten!

Hth


----------



## Rock Lobster (31. Jan 2007)

Okay, danke für eure Antworten!

Mir persönlich gefällt die Version mit dem "ResultSetReader" besser, naja da hätt ich eigentlich auch selbst draufkommen können 

Die andere Möglichkeit ist natürlich auch gut, aber ich will eigentlich nicht allzu speziell auf den Typ der Datenbank eingehen. Natürlich glaube ich nicht, daß wir irgendwann von Oracle (9i) auf was anderes umstellen, aber irgendwie möchte ich den Code halt relativ unabhängig halten, und im Moment kann ich ihn halt für jede Datenbank einsetzen, die ich will.

Werde es jetzt also wohl so wie in Möglichkeit 1 handhaben.


----------

