PDA

View Full Version : Embedded SQL (EXEC SQL) und QMHRCVPM



Seiten : [1] 2

dirkus
22-06-07, 11:39
Hallo,

ich beiß mir zur Zeit am RPG-Embedded SQL die Zähne aus... Es funktioniert soweit eigentlich alles, jedoch möchte ich gern die SQL-Meldungen (z. B. SQL0100) aus dem Joblog ins Programm holen, und ggf. dem Benutzer anzeigen. Bisher hat das immer über das API QMHRCVPM geklappt, aber die SQL-Meldungen wollen einfach nicht kommen. Das API schweigt mich an und die RCVM0200-Variable bleibt leer.



*** externe Prozeduren ***
D qmhrcvpm pr extpgm('QMHRCVPM') API-RcvMsg
D msgData like(rcvm0200) Nachrichten-DS
D msgDataLen 10i 0 const Länge
D format 8 const Format
D stack 10 const Aufrufstapel
D stackCounter 10i 0 const Zähler
D msgType 10 const Nachrichten-Art
D msgKey 4 const Nachrichten-Key
D waitTime 10i 0 const Wartezeit
D msgAction 10 const Nachrichten-Aktion
D apiError like(apiErr) Fehler

*** Datenstrukturen ***
D rcvm0200 ds qualified Nachricht
D bytesReturned 10i 0 Bytes returned
D bytesAvail 10i 0 Bytes available
D severity 10i 0 Severity
D msgId 7 Identifier
D msgType 2 Nachrichtentyp
D msgKey 4 MSG-Key
D msgFile 10 MSG-File
D msgFileLib 10 Bibliothek
D msgFileLibU 10 Bibliothek Used
D msgJobName 10 Jobname
D msgUser 10 Benutzer
D msgJobNbr 6 Jobnummer
D msgProgramm 12 Programm
D res1 4
D sndDate 7 Datum gesendet
D sndTime 6 Zeit gesendet
D sndTimeMs 6 0 Mikrosek. gesendet
D sndUser 10 Benutzer gesendet
D res2 1
D ccsidConvTxt 10i 0 CCSID Conv. Text
D ccsidConvData 10i 0 CCSID Conv. Data
D alertOption 9 Alert Option
D ccsidMsgHelp 10i 0 CCSID Message/Help
D ccsidRplData 10i 0 CCSID Repl. Data
D rplDataLenRtn 10i 0 Länge RPL-Data ret.
D rplDataLenAv 10i 0 Länge RPL-Data ava.
D msgLenRtn 10i 0 Länge MSG returned
D msgLenAvail 10i 0 Länge MSG available
D helpLenRtn 10i 0 Länge Hilfe ret.
D helpLenAvail 10i 0 Länge Hilfe avail.
D msgRplMsgHelp 3000 MSG + RPLData + HLP

D apierr ds qualified API-Error
D bytesprov 8b 0 Bytes Provided
D pytesavail 8b 0 Bytes Available
D msgid 7 MSG-Id
...

/free
...
exec sql fetch next from cursorSubf01 into
:recn, :itnr, :text_s;

if sqlcod <> 100;
qmhrcvpm(rcvm0200: %len(rcvm0200): 'RCVM0200': '*': 0:
'*FIRST': ' ': 0: '*SAME': apiErr);
endif;
/end-free

Fuerchau
22-06-07, 16:02
Schau mal per Debugger, ob die Meldung überhaupt an deine Programmebene kommt (bei ILE meist nicht).
Dadurch steht diese allenfalls noch im Joblog, da die Programmebene, an die die Meldung ging, schon verlassen wurde.

Aber warum so kompliziert ?

Alles was du brauchst steht nach jedem SQL in der SQLDA.
SQLCOD kennst du ja schon, der Rest steht analog der MSG-Feld-Beschreibung (QSQLMSG) in SQLERM.

B.Hauser
22-06-07, 19:15
Aus SQL wird keine Nachricht gesendet, sondern (embedded) SQL meldet Fehler oder Warnungen über den SQLCOD/SQLCODE (< 0 = Fehler, 1-99 = Warnungen) oder den SQLSTT/SQLSTATE (Stelle 1-2 = '01' = Warnung, Stelle 1-2 = '02' = nicht gefunden, Stelle 1-2 <> '00', '01', '02' = Fehler).

Wie Baldur sagt, kannst Du Dir die Message-Id aus dem SQLCode zusammenbasteln und den Message-Text aus der Messagefile QSQLMSG ermitteln.

Wenn allerdings Du auf Release V5R3 or höher bist, kannst Du das Ganze viel einfacher haben:
Über das SQL-Statement Get Diagnostics direkt auf den Message-Text zugegriffen werden:



C/Exec SQL
C+ Update ....
C/End-Exec

C/Exec SQL
C+ Get Diagnostics Condition 1 :MsgText = MESSAGE_TEXT
C/End-Exec


Birgitta

Tobse77
23-07-08, 06:26
Guten Morgen,

habe diese Funktion Get Diagnostics eben mal ausprobiert, jedoch leider mit mäßigem Erfolg.

Get Diagnostics 1 :SQLMSG = MESSAGE_TEXT; <- hier meckert bereits SEU die 1 an und behauptet, dass das Token 1 ungültig sei. Der Compiler meldet das Gleiche und wandelt nicht um.
Wir haben hier V5R4 und erfüllen somit also die OS-Voraussetzungen.

Weiß jemand, was ich falsch mache??

JIM
23-07-08, 06:43
Guten Morgen,

versuche es mal ohne die 1.

DB2 Universal Database (http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0005647.htm)

Tobse77
23-07-08, 07:21
Guten Morgen Jim,

habe ich auch schon versucht, aber dann meckert SEU das Token MESSAGE_TEXT an. Hab inzwischen gemerkt, dass ich lediglich auf die Funktionen der Rubrik statement-information-item fehlerfrei zugreifen kann. Auf connection-informationen-item und condition-information-item klappt es nicht.

Wofür steht diese ominöse 1 eigentlich??

JIM
23-07-08, 07:26
Hallo Tobse77,

wofür die steht weiß ich nicht.

Da ich zur Zeit viel mit SQL mache, habe ich das Thema mit Interesse verfolgt und den mir (unter vielen anderen) unbekannten Befehl GET DIAGNOSTICS ausprobiert. Nach einem FETCH habe ich den Befehl mit

GET DIAGNOSTICS :rpgvar = ROW_COUNT

ausprobiert und im Debugger gesehen, dass als Wert eine 1 in rpgvar steht - wie es nach dem Lesen EINES Satzes zu erwarten war.

Hast Du mal die Befehlssyntax in meinem Link oben angeschaut? Ich habe hier übrigens auch V5R4.

B.Hauser
23-07-08, 07:27
Sorry, ich hatte das Wörtchen "Condition" in meinem Beispiel vergessen. Das kommt davon wenn man irgendwas aus dem Kopf tippt ohne Zugriff auf eine Maschine.

@JIM
SQL ist nicht SQL (trotz Standard) und DB2 ist auch nicht DB2!
Die DB2s für Linunx, Unix, Windows und z-Series funktionieren in einigen Bereichen anders als die DB2 UDB for i, einfach deshalb, weil die DB2 UDB for i direkt im Betriebssystem integriert ist.

So können z.B. beim GET DIAGNOSTICS auf der AS/400 (oder wie auch immer) wesentlich mehr Informationen ausgegeben werden und für Condition-Informationen schreibt man auch CONDITION (was ich im obigen Beispiel vergessen hatte) und nicht EXCEPTION!

Aus diesem Grund ist es besser, sich die SQL Referenz für die DB2 UDB for i zur Brust zu nehmen.
Hier ist der Link zu GET DIAGNOSTICS auf der AS/400:
Get Diagnostics (http://publib.boulder.ibm.com/infocenter/systems/scope/i5os/index.jsp?topic=/db2/rbafzgetdiag.htm&tocNode=int_218514)

Die 1 ist im embedded SQL einfach eine beliebige Zahl (oder auch Variable), die für die Syntax bei Condition Informationen erforderlich ist.
Birgitta

Tobse77
23-07-08, 08:08
Guten Morgen Birgitta,

vielen Dank für die prompte und hilfreiche Antwort - wie gewohnt ;-)

Die Befehlsreferenz zu GET DIAGNOSTICS habe ich mir zwar schon angeschaut, aber die richtige Syntax hat sich mir daraus nicht erschlossen.

Mein Statement sieht nun folgendermaßen aus:
Get current Diagnostics CONDITION 1 :SQLMSG = MESSAGE_TEXT;

Und das Beste ist: ES FUNKTIONIERT AUCH NOCH!!! :-)

Habe zuvor mittels API QMHRTVM den SQL-Code aus QSQLMSG ausgelesen, was gegenüber der Get Diagnostics-Funktion natürlich viel umständlicher ist und dazu auch bei z. B. SQL0100 nur die Meldung "Zeile für &1 nicht gefunden" zurückgemeldet hat. Nun bekomme ich folgerichtig "Zeile für INSERT nicht gefunden"

Vielen Dank nochmals!!

B.Hauser
23-07-08, 08:30
Habe zuvor mittels API QMHRTVM den SQL-Code aus QSQLMSG ausgelesen, was gegenüber der Get Diagnostics-Funktion natürlich viel umständlicher ist und dazu auch bei z. B. SQL0100 nur die Meldung "Zeile für &1 nicht gefunden" zurückgemeldet hat. Nun bekomme ich folgerichtig "Zeile für INSERT nicht gefunden"

Mit QMHRTVM bzw. RtvMsg wäre das auch gegangen, man muss lediglich wissen, dass die variablen Message-Texte (MSGDTA) im Feld SQLERM in der SQLCA hinterlegt sind.

Birgitta