PDA

View Full Version : SQLCOD = -181 SQLSTATE = '22007'



tarkusch
11-03-13, 12:07
Hallo,

wollte mit Sql einen Sfl befuellen und stosse auf folgenden Fehler:
SQLCOD = -181 SQLSTATE = '22007'
Explanation: Value in date, time, or timestamp string not valid.

Ich hole mir die Daten auf diesem Wege:

D MyDS E DS ExtName(W7KOST)
:
SQLString ='SELECT * FROM W7KOST ';
:
BegSr SQLFetchCsrC1;
Exec SQL
Fetch next from CsrC1 into :MyDs;
EndSr;


Das Feld, was den Fehler verursacht, ist wie folgt definiert:

A W7DAT1 L TEXT('Eingangsdatum')


Wenn ich mit Sql die Datei abfrage:

W7DAT1
10.04.16
10.06.17
10.06.22
10.06.23

Wie muss ich das Feld W7DAT1 behandeln?
Kann ich das ueberhaupt dynamisch mit Sql befuellen?

Dank im Voraus

Gruß

Tarki

Fuerchau
11-03-13, 12:11
Dein Problem ist das Datumsformat.
Wenn du YY.MM.DD liest, muss das Datum zwischen 1940 und 2039 liegen.
Hast du ein anderes Datum (z.B. 01.01.0001) bekommst du beim Lesen eben den Fehler.

Du musst das Datum schon mit *ISO lesen (H-Zeile und SQL-Option).

PS:
Ein dynmisches "select * " birgt das Risiko beim Ändern der Tabelle, dass dein Programm ohne neue Umwandlung auf die Nase fällt.

tarkusch
11-03-13, 12:20
Danke vielmals fuer die absolut rasche Hilfe.

B.Hauser
11-03-13, 12:40
Dein Problem ist das Datumsformat.
Wenn du YY.MM.DD liest, muss das Datum zwischen 1940 und 2039 liegen.
Hast du ein anderes Datum (z.B. 01.01.0001) bekommst du beim Lesen eben den Fehler.

Du musst das Datum schon mit *ISO lesen (H-Zeile und SQL-Option).

PS:
Ein dynmisches "select * " birgt das Risiko beim Ändern der Tabelle, dass dein Programm ohne neue Umwandlung auf die Nase fällt.

Das Problem liegt nicht in den H-Bestimmungen, diese werden von (embedded) SQL bzw. dem SQL Precompiler nicht berücksichtigt. Das Datums-Format muss entweder im Compile-Befehl auf ein Format mit 4-stelligem Jahr oder über ein SET OPTION Statement im Quell-Code gesetzt werden.

Birgitta

Fuerchau
15-03-13, 07:31
@Birgitta
Da muss ich dich leider enttäuschen.
Wenn die H-Bestimmung zur SQL-Option nicht korrespondiert, gibt es zwar keinen SQL-Fehler aber dafür einen RPG-Runtimefehler.

Das Datumformat wird durch den RPG-Compiler auf Feldebene spezifiziert.
Der SQL-Precompiler erstellt SQL-Hilfsvariablen mit dem korrekten Typ aus der Option-Anweisung (*ISO), so dass die SQL-Befehle dann laufen.

Bei der Übertragung von/zu den eigenen Variablen erfolgt dann automatisch eine Konvertierung durch die RPG-Runtime.
Passt nun ein Wert nicht, wird eine RNX-Exception ausgelöst.

Ist die H-Bestimmung z.B. mit *YMD angegeben so wird die Datumsvariable mit 8 Byte statt 10 Byte definiert, so dass eben ein Datum außerhalb der Range einfach nicht passt.

Das selbe gilt auch bei der Kopie aus Dateien mit nicht passendem Datumsformat. Das Datumsformat der Datei wird auf die Variablendefinition übernommen, unabhängig davon, was in den H-Bestimmungen steht.

Fazit:
In den H-Bestimmungen sollte entweder *ISO oder *EUR (10-stelliges Format) definiert werden und wenn überhaupt sollte das Datumsformat in Dateien *ISO oder *EUR sein.

B.Hauser
15-03-13, 08:03
Das ist aber ein klssisches RPG und kein SQL-Problem. Für SQL ist das Datumsformat absolut egal, da es immer mit der internen Repräsentation (Scaliger Nr - 4 Byte Binär) arbeitet.

RPG dagegen konvertiert ein Datum immer in einen alphanumerischen String und konvertiert diesen erst unmittelbar vor dem Update etc. zurück.

Das eigentliche Problem tritt natürlich immer auf, wenn aus einer Datums-Variable mit 4-stelligem Datum Daten in ein Datums-Feld mit 2-stelligem Jahr übertragen werden, deren Werte außerhalb des gültigen Bereichs (vor 01.01.1940 / nach 31.12.2039) liegen.

Die zusätzlichen SQL-Host-Variablen werden mit dem Datums-Format aus dem Compile-Befehl bzw. SET OPTION angelegt. Default-Wert an dieser Stelle ist *JOB (und das Job-Datum ist i.e.R. auf ein Format mit 2-stelligem Jahr eingestellt).

Die RPG-(Host)Variablen beziehen Ihr Datums-Format aus dem Schlüssel-Wort DATFMT, das entweder in den D-Bestimmungen und/oder H-Bestimmungen hinterlegt ist, wobei die Angabe in den D-Bestimmungen den Vorrang hat. Sofern das Schlüssel-Wort DATFMT weder in den D- noch in den H-Bestimmungen wird für die RPG-Variablen das Format *ISO verwendet.

Birgitta

Fuerchau
15-03-13, 10:39
Ich sagte ja nur, H-Bestimmung und SQl-Option müssen korrespondieren.

Einfach zu sagen, die H-Option wäre egal, greift nicht weit genug, da sich das SQL nun mal in einem RPG befindet!
Nur darauf wollte ich hinaus, da sich das Problem im Kontext SQL versus RPG befindet und nicht isoliert betrachtet werden kann.

Ein DATFMT auf einem Table-Field wirkt wie ein Constraint, die interne Speicherform ist dabei vollkommen unerheblich, man bekommt nichts anderes gespeichert (*LOVAL ist dann übrigens 31.12.40!).