PDA

View Full Version : SQL-Problem



KM
03-04-07, 14:42
Kann mir jemand sagen warum folgendes Statement nicht funktioniert ?


rs = stmt.executeQuery(
"SELECT ttartn, ttsprs, " +
"CASE " +
"WHEN ttsprs = 'P' THEN " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1153) " +
"WHEN ttsprs = 'G' THEN " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 875) " +
"WHEN ttsprs = 'R' THEN " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1154) " +
"ELSE " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1141) " +
"END " + ...

Hierbei soll je nach Sprachcode der Text in die jeweilige Codepage gecastet werden. Ich erhalte immer den Fehler


SQL error : java.sql.SQLException: [SQL0332] Zeichenumsetzung zwischen CCSID 1154 und CCSID 1153 ungültig.

obwohl ich doch gar nicht zwischen 1154 und 1153 konvertieren will, sondern nur zwischen 65535 und der betreffenden CCSID.

Folgender Code funktioniert:


rs = stmt.executeQuery(
"SELECT ttartn, ttsprs, " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1153), " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 875), " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1154), " +
"CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1141) " +
"FROM ...

wobei ich hier ja immer 3 zusätzliche Felder erhalte und dann erst bei der Verarbeitung des Resultsets das betreffende Textfeld selektiere. Das ist ja nicht sehr effizient und wollte ich eigentlich vermeiden. Aber bei der obigen Variante erhalte ich immer diesen seltsamen Fehler.

Gruß,
KM

Fuerchau
03-04-07, 14:48
Das Problem hier ist, dass das Ergebnisfeld nur genau eine CCSID aufweisen darf.

Da du jedoch verschiedene CCSID's erstellst, muss SQL nun in irgendeine CCSID umwandeln.
Dies ist nunmal die 1. des Case.

Wandle den Case noch mal in eine gemeinsame CCSID um.
In diesem Fall halt UNICODE:

cast(
case-ausdruck
as graphic(60) ccsid 13488)

KM
03-04-07, 15:08
Die Idee hatte ich auch schon. Allerdings hatte ich das mit CCSID 1208 probiert, weil ich hauptsächlich mit UTF-8 arbeite. Dabei habe ich aber bei allen Feldinhalten, wo Sonderzeichen vorkamen, einen "null"-Wert als Ergebnis erhalten. Deshalb hatte ich das mit 13488 erst gar nicht versucht. Jetzt hab ich's doch mal getestet. Und es hat funktioniert. Bei folgendem "triple-cast" erhalte ich das gewünschte Ergebnis:


"SELECT ttartn, ttsprs, " +
"CASE " +
"WHEN ttsprs IN('C', 'P') THEN " +
"CAST(CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1153) AS GRAPHIC (60) CCSID 13488) " +
"WHEN ttsprs = 'G' THEN " +
"CAST(CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 875) AS GRAPHIC (60) CCSID 13488) " +
"WHEN ttsprs = 'R' THEN " +
"CAST(CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1154) AS GRAPHIC (60) CCSID 13488) " +
"ELSE " +
"CAST(CAST(CAST(tttext AS CHARACTER (60) CCSID 65535) AS CHARACTER (60) CCSID 1141) AS GRAPHIC (60) CCSID 13488) " +
"END " ...

Warum geht das mit CCSID 1208 nicht ? Das wäre doch auch eine einheitliche CCSID.

Gruß,
KM

Fuerchau
03-04-07, 16:16
UTF-8 ist ein variabler Zeichensatz (1-4 Byte).
Dadurch wird es schwierig die max. Länge des Ergebnisfeldes festzulegen.

Ich kann zwar ein kurzes 273-Feld in ein langes 1208-Feld kopieren, aber umgekehrt gibts da Schwierigkeiten, da die Ergebnislänge stark vom Inhalt abhängt.

Der "sichere" Umweg ist da immer eine feste Zeichenbreite, eben UNICODE/UCS-2/13488.

PS:
von SBCS nach UTF-8 sollte das Zielfeld 4-Mal so lang sein.