View Full Version : Externe Dateien in Cobol
puddschini
26-02-08, 13:00
Hallo,
dringend Hilfe benötigt.
Ich bin ein Host-Cobol-Programmierer und tummel mich seit kurzem auf der AS400 herum, einer völlig fremden Welt für mich. Wie kann ich meinem Programm klarmachen, daß es eine extern beschriebene physische Datei benutzen soll (bisher immer nur interne Definitionen). Wichtig dabei ist das korrekte Handling von Nullfields und VARCHAR-Feldern. ein BeispielCode wäre hilfreich.
Vielen Dank im voraus.
Ich würdde dir da folgende Handbücher empfehlen:
WebSphere Development Studio: ILE COBOL Programmer's Guide
WebSphere Development Studio: ILE COBOL Reference
Finden kannst du die PDF's hier:
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/pdf_table/table/launcher.htm
puddschini
18-03-08, 16:49
Hallo,
In einem Cobol-Pgm verwende ich Strukturen, die mittels eines RPG-Programmes und embedded-SQL generiert wurden.
Dies beschreibt eine phys. Datei mit zwei logischen Sichten. In jeder dieser Beschreibungen gibt es z.B. ein Feld KTSTAT, das einmal KTSTAT OF KTOSTML1 und einmal als KTSTAT OF KTOSTML2 angesprochen wird. Dieses Feld ist jeweils Schlüsselfeld neben zwei bzw. drei anderen.
Der compiler mault beide Fälle an, aber zuerst ein Auszug aus dem Coding:
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT KTOSTM1 ASSIGN TO DATABASE-KTOSTML1-ALWNULL
ORGANIZATION IS INDEXED
ACCESS IS DYNAMIC
RECORD KEY IS KTSTAT OF KTOSTML1
FILE STATUS IS KTO-STAT1.
SELECT KTOSTM2 ASSIGN TO DATABASE-KTOSTML2-ALWNULL
ORGANIZATION IS INDEXED
ACCESS IS DYNAMIC
RECORD KEY IS KTSTAT OF KTOSTML2
FILE STATUS IS KTO-STAT2.
DATA DIVISION.
FILE SECTION.
FD KTOSTM1.
01 KTO-SATZ1.
COPY DDS-ALL-FORMATS OF KTOSTML1.
FD KTOSTM2.
01 KTO-SATZ2.
COPY DDS-ALL-FORMATS OF KTOSTML2.
WORKING-STORAGE SECTION.
01 KTOSTML1-NKM.
COPY DDS-ALL-FORMATS OF KTOSTML1 WITH NULL-KEY-MAP.
01 KTOSTML1-NM.
COPY DDS-ALL-FORMATS OF KTOSTML1 WITH NULL-MAP.
01 KTOSTML2-NKM.
COPY DDS-ALL-FORMATS OF KTOSTML2 WITH NULL-KEY-MAP.
01 KTOSTML2-NM.
COPY DDS-ALL-FORMATS OF KTOSTML2 WITH NULL-MAP.
PROCEDURE DIVISION.
START KTOSTM2
KEY NOT < KTSTAT IN KTOSTML2
NULL-KEY-MAP IS KTOSTML2-NKM
INVALID KEY SET KTOS2 TO TRUE
END-START.
IF KTOS2
PERFORM U800-FEHLER-IN-KONPF
END-IF.
READ KTOSTM2 NEXT RECORD
NULL-KEY-MAP IS KTOSTML2-NKM
NULL-MAP IS KTOSTML2-NM
AT END SET KTOR2 TO TRUE
END-READ.
Nachricht . . . : 'KTSTAT OF KTOSTML2' nicht als Name definiert.
Anweisung oder Klausel ignoriert.
Desweiteren:
Nachricht . . . : KEY RECORD fehlt für Datei 'KTOSTM1'.
Nachricht . . . : KEY RECORD fehlt für Datei 'KTOSTM2'.
Ganz unverständlich für mich diese Meldungen:
Nachricht . . . : Die Länge des Bezeichners 'BNKSTML1-NKM' in Phrase
NULL-KEY-MAP in Byte ist nicht gleich 0. Phrase akzeptiert.
Oder diese meldung:
Nachricht . . . : Datenname 'KTSTAT OF KTO-SATZ1' als Schlüsselname
in Anweisung START für Datei 'KTOSTM1' ungültig. Anweisung ignoriert.
Vielleicht gibt es ja eine einfache Lösung zu dem Problem. Danke im voraus.
Zur Bennennung:
Name of Struktur-Name !
KTOSTML2 ist der externe Name und nicht dein Struktur-Name.
Beim Zugriff auf extern beschriebene Dateien ist "externally-described key" erforderlich, sowohl in der Select-Klausel als auch in der Start-Anweisung.
Die Schlüsselfelder sind vor dem Zugriff im FD-Puffer zu füllen.
Begründung:
COBOL unterstützt bei Index-Zugriffen nur zusammenhängende Schlüsselfelder im Satzpuffer.
Da DDS-Dateien aber mehrere Schlüsselfelder über den Puffer verteilt haben können, ist die Sonderform "externally-described key" erforderlich.
puddschini
19-03-08, 09:50
Hallo und guten Morgen,
der Hinweis war super.
Beim Open erhalte ich den file-status 95, (unvollständige Informationen). Was muß ich hier noch tun?
Inzwischen habe ich "with duplicates" eingebaut. Der Status beim Öffnen ist jetzt ok, aber beim Start erhalt ich 23 und beim folgelesen 46. Meine Idee ist, zu einem bestimmenten Mandanten eine höchste lfdNr zu ermitteln. Ich plante, den größten Wert in lfdNr zu vergeben und dann mit Prior einen Satz zurückzulesen. Das klappt wohl nicht so recht.
Mein Coding sieht nun so aus:
FILE-CONTROL.
SELECT KTOSTM1 ASSIGN TO DATABASE-KTOSTML1-ALWNULL
ORGANIZATION IS INDEXED
ACCESS IS DYNAMIC
RECORD KEY IS EXTERNALLY-DESCRIBED-KEY
WITH DUPLICATES
FILE STATUS IS KTO-STAT1.
DATA DIVISION.
FILE SECTION.
FD KTOSTM1.
01 KTO-SATZ1.
COPY DDS-ALL-FORMATS OF KTOSTML1.
WORKING-STORAGE SECTION.
* external key
01 K1-KEY.
05 K1-KTSTAT PIC X VALUE SPACE.
05 K1-KTMAND PIC 9(4) COMP-3 VALUE ZEROES.
05 K1-KTKVER PIC 9(8) COMP-3 VALUE ZEROES.
PROCEDURE DIVISION USING TAB-KVER.
OPEN I-O KTOSTM1.
* Index-Felder belegen
MOVE SPACE TO K1-KTSTAT KTO-STAT1
MOVE T-MAND(I-T) TO K1-KTMAND
MOVE 99999999 TO K1-KTKVER
START KTOSTM1
KEY NOT < K1-KEY
NULL-KEY-MAP IS KTOSTML1-NKM
INVALID KEY SET KTOS1 TO TRUE
END-START.
READ KTOSTM1 PRIOR RECORD
NULL-KEY-MAP IS KTOSTML1-NKM
NULL-MAP IS KTOSTML1-NM
AT END SET KTOR1 TO TRUE
END-READ.
Schau dir genau den Key an.
Vor dem Mandant gibts noch den Status.
Bist du sicher, dass nach dem Prior noch der richtige Mandant und Status im Puffer steht ?
puddschini
19-03-08, 12:12
Deine Antwort macht mich unsicher. Aber ich habe kein Bsp gefunden, in dem zw. Start und read prior(next) der Key neu belegt wird. Nebenbei, der Start bringt immer noch einen Status 23. Ansonsten habe ich keine Lösung.
Nach einem Test vor wenigen Minuten sehe ich die Keys beide gleich gefüllt, den in der FD-Stufe und den in der WorkStor. Nun bin ich ratlos.
Sieh' mal in der Umwandlungsliste nach. Vermutlich wurde da der Fehler LNC0635 (Angegebene Schlüssel entsprechen nicht den extern beschriebenen Schlüsseln der Datei ...) ausgegeben.
Du mußt die Schlüsselfelder mit Vorzeichen definieren (PIC S9(nnn)), damit sie den Feldern der Datei entsprechen. Außerdem müssen beim START anscheinend die Felder einzeln angegeben werden (jeweils durch Komma getrennt), oder du gibst EXTERNALLY-DESCRIBED-KEY als Schlüssel an.
puddschini
19-03-08, 17:26
Danke für den Tip, kann ich aber erst wieder am Dienstag testen, wollte aber nur schnell noch reagieren. Frohe Feiertage.
Habe gestern Abend noch über Deinen Vorschlag nachgedacht. Das Vorzeichen hat keine Auswirkungen, und die Felder müssen auch nicht einzeln angegeben werden. Mit SQL und einem select max(lfdnr) from x/y where mand = 5 (z.B.) erhalte ich die höchste lfdNr dieses Mandanten. Wenn ich nun diesen Wert anstatt 8x eine 9 eingebe, findet der START die richtige Position und liefert genau den Satz zurück, der read prior geht dann auch ganz brav einen Satz zurück. Das geht wunderschön. Es geht nur nicht, wenn man das Feld mit 9en belegt (um den höchsten Wert darzustellen), um den letzten Satz zu lesen. Das liefert den Status 23 (Satz nicht gefunden) beim START und der read prior liefert den filestatus 46 (read beyond end-of-file). Mir fehlt in Cobol der Befehl (oder eine Möglichkeit) wie in RPG oder der funktioniert wie die max-Funktion bei SQL. Lese ich mit LAST, so erhalte ich den allerletzten Satz in der Datei, der aber zu keinem der Mandanten passen müßte.
Hallo,
fülle einfach die Schlüsselfelder direkt im FD-Satz und mache den Start mit:
start ktostm1
key is not < externally-described-key
invalid continue
end-start.
Das vielleicht unerwartete "continue" deswegen, weil auch beim Start-Versuch hinter dem allerhöchsten Key-Wert der Pointer für das "read prior" richtig gesetzt ist.