PDA

View Full Version : SQL Update



Joe
19-08-03, 22:36
Hallo Forum.

Ein Bild sagt mehr als tausend Worte...
deshalb etwas Code:

D File E DS ExtName(Datei)
D UFile E DS Extname(Datei) Prefix(U)

C *Entry Plist
C Parm File
C Parm UFile

C select
C when Fld01 <> UFld01
C eval Fld01 = UFld01
C when Fld02 <> UFld02
C eval Fld02 = UFld02
C when Fld03 <> UFld03
C eval Fld03 = UFld03
C* usw.
C endsl
C if file <> UFile
C update Datei
C endif



Dieses "Program" wird aus einer DDS
generiert und als "Server-Program" für Datei-Updates eingesetzt.
Der Update erfolgt nur für die tatsächlich geänderten Felder
aus der Datei-Datenstruktur UFile.
(Natürlich fehlt da einiges an Code- aber ich hoffe, das wesentliche kommt rüber.)
Und Jetzt die Frage an *ALL:
Wie kann ich den Select/Update entsprechend dem obigen Beispiel mit Embedded SQL erledigen?
Geht das überhaupt?

Gruss Joe

Fuerchau
20-08-03, 09:00
Wenn ich mir den Code so betrachte ist das so falsch wie nur irgend möglich !!

Was passiert denn eigentlich wenn mehr als 1 Feld geändert wird ?
=> Es wird nur das 1. geänderte Feld in die Datei geschrieben !!

Warum ?

Ein SELECT entspricht einem IF ... ELSE IF ... ELSE IF ... ENDIF ENDIF

Und wozu soll das dann gut sein ?

Ausserdem muss man zu RPG folgendes wissen:
Die DB400 arbeitet mit einem internen Dateipuffer, der von RPG pro Feld mit einem MOVE gefüllt wird bevor die EA-Operation stattfindet. Deshalb optimiert der Compiler auf Grund der Verwendung von Feldern.
Werden Felder nicht verwendet, findet auch keine Übertragung statt, weder beim Lesen noch beim Schreiben.

Der Update ändert nun ALLE Felder automatisch mit, so dass eigentlich die Abfrage ob sich was geändert hat müssig ist.

Und nun zu embedded SQL:

Der Update sieht hierzu ganz simpel aus, da (wie oben angemerkt) kein Performance-Gewinn entsteht wenn jedes Feld einzeln geändert wird.

UPDATE MYFILE SET F1=:UF1, F2=:UF2 ...
WHERE KEY1=:UKEY1 and KEY2=:UKEY2 ...

Auch hier ist es wenig sinnvoll den Update zu zerlegen, da sonst für jedes Feld ein einzelner Update erforderlch wäre.
Auch hierzu sei zu bemerken, dass SQL intern nicht anders arbeitet als RPG: Satz lesen, Felder übertragen, Satz updaten.

Joe
20-08-03, 22:28
Hallo Herr Fuerchau.

Ich muss Ihnen absolut Recht geben, mein Beispiel ging total daneben. Natürlich kein Select(when) sondern if...
Und ausserdem waren die DS falsch definiert.
Deshalb hier die überarbeitete Version.

Sinn und Zweck: Für jede Datei soll ein zentrales "GET", "UPDATE", "INSERT", "DELETE" -Programm verwendet werden.

+++++++++++++++++++++++++++++++++++++++++++
Irgend ein Verarbeitungsprogramm

D PARMA E DS EXTNAME(Datei) Prefix(A)
D PARMN E DS EXTNAME(Datei)

C* füllen Keyfelder in "PARMA"
C CALL "GET"
C PARM PARMA
C Move PARMA PARMN
C* Verarbeitung z.B. Bildschirmausgabe von "PARMN"
C* Ändern von Felder(n) in "PARMN"
C* Aufrufen UPDATE-Programm
C CALL "UPD"
C PARM PARMA
C PARM PARMN

++++++++++++++++++++++++++++++++++++++++++++++
Programm "UPD"
++++++++++++++++++++++++++++++++++++++++++++++
FDatei UF E K DISK
D PARMA E DS EXTNAME(Datei) Prefix(A)
D PARMN E DS EXTNAME(Datei) Prefix(N)
C *ENTRY PLIST
C PARM PARMA
C PARM PARMN
C If PARMN <> PARMA
C Key Chain Datei
C* jetzt stehen Fld01,Fld02... zur Verfügung
C If NFLD01 <> AFld01
C eval Fld01 = NFld01
C endif
C If NFLD02 <> AFld02
C eval Fld02 = NFld02
C endif
C update Datei
C endif

++++++++++++++++++++++++++++++++++++++++++++++
Programm "GET"
++++++++++++++++++++++++++++++++++++++++++++++
FDatei IF E K DISK
D PARMA E DS EXTNAME(Datei)
C *ENTRY PLIST
C PARM PARMA
C Key Chain Datei ***Keyfelder werden in PARMA übergeben
C Return

++++++++++++++++++++++++++++++++++++++++++++++

Soviel zum Programmcode.
Der funktioniert übrigens und ist täglich im Einsatz.

Gruss Joe


Hallo *ALL.
Ich weiss dass dieses Forum kein RPG-Seminar ist wie bei anderen Beiträgen schon mehrmals angemerkt wurde.
Ich möchte nur erfahren, ob SQL die Möglichkeit bietet, innerhalb
eines Update Feldbedingungen abzufragen um nur bestimmte
Felder zu verändern.

Gruss Joe

BenderD
21-08-03, 10:51
Hey Joe,

um es mit Jimi Hendrix zu sagen, ich würde bei solchen Zugriffsprogrammen dringend zu einem ILE Serviceprogramm mit exportierten Prozeduren für update, delete und insert raten. Für die Datenbank Operationen kann man dann Record Level Access oder SQL verwenden, das gibt sich bei den Satzoperationen wenig.
Interessant wird es bei Mengen orientierten Operationen (zum füllen eines Subfiles z.B.) da ist SQL weit im Vorteil und wesentlich flexibler, insbesondere bei der Verwendung von dynamic SQL.

Dieter Bender

Fuerchau
21-08-03, 12:06
@Dieter Urlaub schon vorbei ?

@Joe

Ich muss noch mal auf meinen obigen Beitrag hinweisen.

Sehr viel schneller ist das ganze, wenn man die ganzen If's einfach wegläßt und mit einer Mehrfachstruktur arbeitet (OCCURS 2) und ohne Prefix.

Warum ?

Vor dem Chain auf OCCURS 2 umschalten, RPG füllt automatisch alle Felder, die aber nicht verwendet werden.
Auf OCCURS 1 zurückschalten und den Update durchführen.

Anstelle von OCCURS kann man ja auch die gesamte Struktur übertragen.
Ein Zeitvorteil ist Ihre Methode nicht, da ja sowieso ein Update des gesamten Immage stattfindet.

Wie entgehst du der Gefahr des konkurierenden Updates ?!?!

Zwischen dem CALL GET und CALL UPD kann ja einige Zeit liegen.
Also müsstest du das aktuelle Immage (CHAIN) mit dem vorher gelesenen Immage (aus GET) vergleichen und nur wenn dieses noch gleich ist, deinen Update durchführen, ansonsten brauchst du eine Fehlerbehandlung, von wegen "Daten zwischenzeitlich geändert" oder so.

Und nun nochmal zu SQL:

Natürlich kannst du mittels CASE Abfragen durchführen, aber um es RPG-Like zu gestalten musst du auf jeden Fall einen SELECT vorher durchführen (analog CHAIN) um überhaupt vergleichen zu können.

Übrigens: Ohne CMTCTL wirst du Probleme mit konkurierenden Updates erhalten, wenn du den Datensatz beim Lesen nicht sperrst (SELECT .... FOR UPDATE ............... UPDATE CURRENT OF )

B.Hauser
21-08-03, 13:23
Hallo Joe,

ich nehme an, dass beim GET z.Z. eine Input Datei eingelesen wird und beim Update dann die entsprechende Update Datei.

Bei dem Update-Programm soll nur dann ein Feld fortgeschrieben werden, wenn sich die Feldwerte zwischen 1. Lesen und Fortschreiben geändet haben.
Anderenfalls könnten zwischenzeitliche Änderungen überschrieben werden.

Soweit so klar!

Ich würde vorerst noch abraten das Ganze mit SQL zu machen, da der Zugriff für einen einzelnen Datensatz mit SQL länger dauert.
Müssen mehrere Sätze eingelesen werden (z.B. Füllen einer Subfile) ist SQL die bessere Wahl.

Im Prinzip kannst Du im SQL-genauso verfahren wie im RPG:
1. Cursor für den SELECT definieren
2. Cursor öffnen
3. Den Satz mit FETCH einlesen
2. Die Felder wie gehabt mit RPG prüfen und die Host-Variablen, die upgedated werden sollen umladen
3. Update des eingelesenen Satzes mit
UPDATE FILE SET Feld1 = :UpdFeld1, .... FOR CURRENT OF CursorName

Für die Update-Routine über RPG würde ich ausserdem nicht den Schlüssel sondern die Relative Satz-Nr. übergeben.
Damit wird sicher gestellt, dass genau der richtige Satz verarbeitet wird.
(Bei SQL dauert das zu lange. Da kein Index über die relative Satz-Nr. erstellt werden kann, wird die komplette Datei verarbeitet)

Weiterhin würde ich unabhängig ob mit SQL oder RPG gearbeitet wird ein Service-Programm (kein Programm) erstellen und aufrufen.
Der Aufruf ist schneller!
Ausserdem würde ich beim Service-Programm eine feste Activierungs-Gruppe (z.B. Aktivierungs-Gruppe=Service-Programm-Name) angeben, so dass das Service-Programm nicht für jedes Programm, das es aufruft aktiviert werden muss.

Birgitta

Fuerchau
21-08-03, 14:12
@Birgitta

Bei "UPDATE ... CURRENT OF .." wird genau 1 Satz geändert, da ja der aktuelle Cursor verwedet wird.

Bei "UPDATE ... WHERE ..." hast du natürlich Recht, wenn keine UNIQUE-Bedingung angegeben ist. Ausserdem bleibt hier noch das Problem der Satzsperre.

Joe
21-08-03, 22:54
Hallo und danke für die interessanten Beiträge.

Mit scheint, ich bleib erst mal bei meinen RPG-Programmen
und sammel ausreichend Know-How für die Umstellung auf SQL.

Den konkurrierende Satzupdate habe ich durch nicht erwähnte
Update-Zähler im Datensatz gelöst: Satz lesen und beim Chain
vor dem update prüfen, ob der Zähler inzwischen geändert
wurde. Klappt ausgezeichnet.

Also Dieter, Micky würde sagen: No Satisfaction! :-))

Gruss
Joe