# Preparedstatement SQL-string auslesen



## michaelarban2 (17. Aug 2007)

hi,

ich benutze preparedstatments, um sql-befehle an eine Oracle-DB zu schicken.

Beispiel

String sql = ... blabla ...  (select * from meinetabelle where name = ? )

PreparedStatement pstmt = conn.prepareStatement(sql) 

pstmt.setString(1, "Otto"); 
... blabla blabla ...


Nun will ich nach dem ausführen den ganzen übermittelten sql-befehl select * from meinetabelle where name = "Otto" wieder haben.

pstmt.toString() funktioniert nicht, sondern leifert eine speicheradresse.

gibt es so was wie pstmt.getSQLbefehl() ?

danke


----------



## Guest (17. Aug 2007)

Schau dir das hier an: http://www.elvyx.com


----------



## tuxedo (17. Aug 2007)

Krasses Tool, aber ich glaub das ist etwas "zu groß" für sein Vorhaben... ;-)

Allerdings gibts laut PreparedStatement-Interface da keine Methode um an das dran zu kommen: 
http://java.sun.com/j2se/1.4.2/docs/api/java/sql/PreparedStatement.html

Über das Statement-Interface oder das ResultSet scheint man auch nicht dran zu kommen. 

Korrigiert mich bitte jemand wenn ich stuss erzähle ...

- Alex


----------



## Kim Stebel (17. Aug 2007)

Debugger anwerfen, die privaten Attribute des preparedStatement angucken...insbesondere parameterValues und staticSQL. Die sind notfalls auch per Reflection zu bekommen... Ist natürlich alles nicht für den Produktiveinsatz gedacht. Wozu brauchst du das überhaupt?


----------



## Guest (20. Aug 2007)

hi,

ich will nur wissen, welchen SQL-String das Prepared-statememt ausführt.

Komischweise ging es, wenn ich als Datenbank MySQL verwende; liegt es vielleicht an dem jeweiligen treiber??

bye


----------



## tuxedo (20. Aug 2007)

Öhm, bist du dir sicher dass es mit MySQL ging? JDBC unterstützt das AFAIk nämlich nicht. Auch der MySQL Connector/J nicht. 
Und die MySQL-Datenbank hat, soweit ich weiß, auch keine Technik das Statement zu rekonstruieren, da das ganze ja DB-Intern gehandhabt wird (die DB bekommt auch nur das Satement mit Platzhaltern und dann einzeln die Parameter).  

wozu brauchst du die Funktion denn?

- Alex


----------



## Guest (20. Aug 2007)

ich brauche das ganze zu Logging-zwecken; ich will nämlich rekonstruieren, welchen SQL-Fehl durch das Prepared-statemtn an die DB geshickt worden ist.


hmmm, es muss doch einen weg geben, das zu erreichen.


----------



## SlaterB (20. Aug 2007)

zu welchem Zeitpunkt denn?
erstmal kannst du einfach beim Erzeugen des PS loggen, wenn du den String und die Parameter übergibst,

zweitens kannst du dir diese Daten immer für das letzte PS merken und dann im Fehlerfall im Nachhinein ausgeben,

drittens verwende eine eigene Klasse anstelle des PS und speichere dort die Daten in einer Exemplarvariablen
(nicht viel anders als zweitens, nur eine Frage der Organisation/ Nebenläufigkeit)


----------



## Guest (20. Aug 2007)

Ich habe 100e von Preparedstatements, die jeweils andere parameter erwarten; 

der Zeitpunkt wann ein sql-Anweisung an das PS übegeben wird ist doch egal, oder? 
kurz vor oder nach dem ps.execute(), will ich folgendes für Loging-zwecke:

loggeInEineDatei(ps.getMeinSQLString())


----------



## SlaterB (20. Aug 2007)

eben andersrum:

PS createPS(connection, String sql) {
   loggeInEineDatei(sql)
  return connection.createPS(sql); 
}


----------



## tuxedo (20. Aug 2007)

Das hatte ich auch schon vorgeschlagen. Aber scheinbar prallt das einfach an ihm ab. Mit dem Kopf durch Stahlbeton is halt leider nicht möglich. Außer man kommst vom Planet Krypton ... ;-)


----------



## Guest (20. Aug 2007)

Den vollständigen SQL-String habe ich doch zu keinem zeitpunkt ,

also
String sql =select * from meinetabelle where name = ? 

--> den sql-string kann ich hier nicht loggen, weil noch unvollständig.


PreparedStatement pstmt = conn.prepareStatement(sql) 

pstmt.setString(1, "Otto"); --> erst hier ist der sql-string vollständig, oder?


----------



## SlaterB (20. Aug 2007)

wenn du die Parameter möchtest, dann musst du diese eben auch loggen,
entweder nach dem gleichen Verfahren wie oben in einzelnen Log-Aufrufen,
oder eben Strings zusammenbauen,
wie gesagt mit eigenem Objekt pro PS oder einer Bearbeiter-Klasse, die für das aktuelle PS erst alle Teile merkt und am Ende ausgibt


----------



## tuxedo (20. Aug 2007)

Anonymous hat gesagt.:
			
		

> Den vollständigen SQL-String habe ich doch zu keinem zeitpunkt ,


Und genau so siehts bei der DB auch aus... Der Treiber übermittelt auch keinen vollständigen SQL-String. Sondern alles einzeln:

- Also das PS
- Dann die einzelnen Argumente



> pstmt.setString(1, "Otto"); --> erst hier ist der sql-string vollständig, oder?



Falsch. Die Argumente werden auch in SQL-Statements umgewandelt. Hast du dir mal angesehen wie sowas in SQL ausschaut?


```
PREPARE getuser FROM 'SELECT id, username FROM `account` WHERE username = ? AND gmlevel = ?';
SET @username = 'alex';
SET @gmlevel = '3';
EXECUTE getuser USING @username, @gmlevel;
DEALLOCATE PREPARE getuser;
```

Erst beim "execute" baut die Datenbank INTERN alles zusammen. 

Die DB bekommt also auch nie ein komplettes, ausgefülltes Statement. 
Wenn du das Statement "komplett" haben willst, dann musst du dir da halt selbst was basteln. SlaterB hat's ja auch schon erklärt.

- Alex


----------

