Anmelden

View Full Version : emb. SQL und UTF-16



Seiten : [1] 2

tsh1970
03-02-09, 12:32
Hallo zusammen,

Nach Umstellung eines Feldes auf UTF-16 CCSID(1200) habe ich folgendes Problem:
Ich bekomme mittels generierter SqlAnweisung nicht mehr das gewünschte Ergebnis. Sondern es werden alle Datensätze aus der Datei selektiert.

Anbei hänge ich mal den Codeauschnitt.


H CCSID(*UCS2 : 1200)
:
D SqlStatement s 5000C VARYING
D US1 s 80C VARYING
D Search1 s 80C VARYING
D §HK s 1 inz(X'7D') Hochkomma definieren
:
C/exec sql
C+ declare C1 scroll Cursor for S1
C/end-exec
:
C EVAL US1 =%UCS2(' where upper(tititl)') +
C %UCS2(' = ') +
C %UCS2(§HK) + %trim(search1) +
C %UCS2(§HK)
:
Im Debug erhalte ich folgenden Inhalt US1 = where upper(tititl) = 'TOP'
:
/free
SqlStatement
= %UCS2('select * from ')
+ %UCS2(' ') + %UCS2(%trim(§file)) + %UCS2(' ')
+ %ucs2(' ') + %trim(Us1) + %ucs2(' ');
/end-free
:
Im Debug: SQLSTATEMENT = select * from MDPROP03 where upper(tititl) = 'TOP'
:
C/exec sql
C+ prepare S1 from :SqlStatement
C/end-exec
:
C/exec sql
C+ open C1
C/end-exec
:
C/exec sql
C+ FETCH RELATIVE :rows FROM C1 INTO :ds_MDPROP03
C/end-exec
:
:
C/exec sql
C+ close C1
C/end-exec
In der Datei ist das Feld TITITL wie folgt definiert:
TITITL GRAPHIC 60 120 290
ID des codierten Zeichensatzes . . . . . : 1200
UCS2- oder Unicode-Konvertierung . . . . : *CONVERT

Wäre toll wenn jemand eine Lösung dieses Problemes parat hat.

tsh1970
04-02-09, 15:20
Hallo zusammen, ein kleiner Nachtrag.

Hat jemand vielleicht ein Beispiel, für ein SQLRPGLE Programm. Welches Felder die mit CCSID 1200 definiert sind, aus einer Datei liest?

Das "normale" Lesen der Daten mit setll, chain, reade usw mit einem UTF-16 Schlüsselfeld geht ohne Probleme. Nur die Verwendung generischer SQL-Abfragen z.B. für Volltextsuche macht Probleme.

Wäre nett wenn mir jemand weiterhelfen könnt.

Danke
Thorsten

Fuerchau
04-02-09, 17:26
Also ALLE Datensätze kann ich mir fast nicht vorstellen. Da muss der Select irgendwo falsch sein.

Probiere das erst mal mit STRSQL aus.
Ggf. musst du die Felder erst wieder in UCS2 casten:

where upper(cast(feld as graphic(nn) ccsid 13488)) = 'TOP'

Allerdings ist hier das Problem, dass die Konstante 'TOP' nicht UCS2 ist !
Also ist die ggf. auch zu casten.

Das Hauptproblem ist, das der UCS2-SQL-String erst in Job-CCSID konvertiert wird und nicht so als UCS2 verwendet wird.
UCS2-Felder funktionieren nur als Hostvariablen (CLI-Interface) und leider nicht bei dynamischem SQL.

Du kannst dir das mit der %UCS2 für das Statement schenken.

tsh1970
05-02-09, 10:50
Versuche ich unter STRSQL alle mögliche Formen des Cast's wie z.B.:
select * from MDPROP03
where cast(TITITL as graphic(60) ccsid 13488)
= cast('Top' as graphic(60) ccsid 13488)

Erhalte ich immer die Fehlermeldung:
Zeichenumsetzung zwischen CCSID 65535 und CCSID 13488 ungültig.

Folgendes funktioniert unter STRSQL:
select * from MDPROP03 where cast(TITITL as char(20)) = 'Top'
select * from MDPROP03 where UPPER(cast(TITITL as char(60))) = cast('TOP' as char(60))
wäre aber unsinnig da ich eben auch Unicode Zeichen bekomme,die beim Cast auf CHAR "verschluckt" werden.

Führe ich das ganze im Programm aus: Zeigt mir der Debugger
SQLStatement =
select * from MDPROP03 where UPPER(cast(TITITL as char(60))) = cast('TOP' as char(60))

und ich bekomme folgende Fehlermeldung beim Prepare Cursor
SQLCODE: -104, SQLSTATE: 42601, SQLERRMC:<ENDE ANWEISUNG DER> AS
andere Abfragen die ich mit der gleichen Routine zusammenbaue funktionieren korrekt, wenn ich eben kein Graphic Feld abzufragen versuche.

Ich versteh die Welt nicht mehr...

Fuerchau
05-02-09, 11:00
Wichtig ist, dass dein Job nicht mit CCSID 65535 läuft !!!
Wie soll SQL da korrekt umsetzen können ?

BenderD
05-02-09, 11:37
ad CCSID65535:
das bezieht sich auf den Cast des Literals (das hat keine CCSID)
das geht über einen doppelten CAST
CAST(CAST('TOP' as char(60) ccsid 273) as graphic(60) CCSID 13488)

ad Unicode:
ja was denn nun, 1200 oder 13488

ad SQL-104:
ungültiger Token => dein Statement ist falsch!

ad %UCS :
cast des SQL Strings ist unnötiger Schnickschnack

ad Cast Arie insgesamt:
wenn das Dateifeld verträglich zu dem Programmfeld deklariert ist, braucht es da keine Konvertierungen.

ad alle Sätze:
schu dir mal deinen SQLCODE nach jedem Statement an, was da wirklich krumm geht

D*B


Versuche ich unter STRSQL alle mögliche Formen des Cast's wie z.B.:
select * from MDPROP03
where cast(TITITL as graphic(60) ccsid 13488)
= cast('Top' as graphic(60) ccsid 13488)

Erhalte ich immer die Fehlermeldung:
Zeichenumsetzung zwischen CCSID 65535 und CCSID 13488 ungültig.

Folgendes funktioniert unter STRSQL:
select * from MDPROP03 where cast(TITITL as char(20)) = 'Top'
select * from MDPROP03 where UPPER(cast(TITITL as char(60))) = cast('TOP' as char(60))
wäre aber unsinnig da ich eben auch Unicode Zeichen bekomme,die beim Cast auf CHAR "verschluckt" werden.

Führe ich das ganze im Programm aus: Zeigt mir der Debugger
SQLStatement =
select * from MDPROP03 where UPPER(cast(TITITL as char(60))) = cast('TOP' as char(60))

und ich bekomme folgende Fehlermeldung beim Prepare Cursor
SQLCODE: -104, SQLSTATE: 42601, SQLERRMC:<ENDE ANWEISUNG DER> AS
andere Abfragen die ich mit der gleichen Routine zusammenbaue funktionieren korrekt, wenn ich eben kein Graphic Feld abzufragen versuche.

Ich versteh die Welt nicht mehr...

tsh1970
05-02-09, 11:47
Okay das ist klar, habe ich im Eifer des Gefechtes schlichtweg übersehen.

Der Job unter dem das Ganze passiert läuft unter der CCSID 1141.

Die CCSID des Feldes ist 1200.

zum SQL-104: wenn ich das SQL aus dem Feld Sql-Statement direkt im SQL eingebe bekomme ich keinen Fehler.

zum %UCS2 bzw. die Arie ;)
Das Feld TITITL hat die CCSID 1200, baue ich mir den SQlStatement String ohne %UCS2 zusammen bekomme ich die Meldung *RNF7421 30 1 Operanden sind mit der Art des Operators nicht kompatibel. Deswegen die %UCS Arie.
Wenn jemand einen anderen Weg kennt bin ich dankbar.

Das mit allen Sätzen könnte ein Folgefehler nach dem FetchCsr sein.

tsh1970
05-02-09, 11:54
Ich denke ich habe die Ursache des Problems gefunden:

Und zwar in der Definition des SQLStatements.
Dieses war als SqlStatement s 5000C VARYING definiert :mad: nach dem ich es auf 5000 Alpha angepasst habe, bekomme ich nun das gewünschte Ergebnis. :confused:

tsh1970
05-02-09, 12:24
Nun noch eine Frage, zum LIKE, CAST und CCSID 1200.

Wenn mein SQL "....where UPPER(cast(TITITL as graphic(60) ccsid 1200)) like cast('%TOP%' as graphic(60) ccsid 1200) " lautet, bekomme ich nur den Titel der genau TOP heißt. Andere Titel in der Tabelle die z.B. "stops" enthalten werden nicht angezeigt.
Meine Vermutung läuft dahin dass das '%' nicht in im Cast sein darf.
Aber wie lautet der String dann? Mit

select * from MDPROP03
where upper(cast(TITITL as graphic(60) ccsid 1200))
like ('%'||cast('TOP' as graphic(60) ccsid 1200)||'%')
SELECT * FROM MDPROP03
WHERE upper(cast(TITITL as graphic(60) ccsid 1200))
like '%' CONCAT cast('TOP' as graphic(60) ccsid 1200)
CONCAT '%'

bekomme ich das gleiche Ergebnis.

BenderD
05-02-09, 12:48
select ... where ... like ?
preparen und anchließend open ... using :myHostVar
sollte da eigentlich funzen, dann fällt die UCS Casterei wieder weg und myHostVar muss dann ein graphic Feld sein.

D*B


Nun noch eine Frage, zum LIKE, CAST und CCSID 1200.

Wenn mein SQL "....where UPPER(cast(TITITL as graphic(60) ccsid 1200)) like cast('%TOP%' as graphic(60) ccsid 1200) " lautet, bekomme ich nur den Titel der genau TOP heißt. Andere Titel in der Tabelle die z.B. "stops" enthalten werden nicht angezeigt.
Meine Vermutung läuft dahin dass das '%' nicht in im Cast sein darf.
Aber wie lautet der String dann? Mit

select * from MDPROP03
where upper(cast(TITITL as graphic(60) ccsid 1200))
like ('%'||cast('TOP' as graphic(60) ccsid 1200)||'%')
SELECT * FROM MDPROP03
WHERE upper(cast(TITITL as graphic(60) ccsid 1200))
like '%' CONCAT cast('TOP' as graphic(60) ccsid 1200)
CONCAT '%'

bekomme ich das gleiche Ergebnis.