PDA

View Full Version : SQL: ODP innerhalb eines Moduls löschen?



claudia_669
17-07-12, 12:21
Hallo!

Ich greife mit SQL-Select auf eine Datenbank zu, um ausgewählte Sätze in eine Subfile einzulesen.
Nach dem Close Cursor können die Sätze in der Subfile entsprechend bearbeitet werden (change, delete etc.). Nach jeder Änderung der Daten wird die Subfile mit Hilfe des SQL für die Anzeige wieder neu aufgebaut.

Mein Problem:
Beim ersten Einlesen mit SQL-Statement wird beim Close Cursor folgendes erreicht:

Offener Datenpfad (ODP) gelöscht.
Cursor C1 wurde geschlossen.

Nach einer Änderung eines Datensatzes erscheint nach dem 2. Einlesen und Close Cursor aber:

ODP nicht gelöscht.
Cursor C1 wurde geschlossen.

Wenn ich danach weitere Datenbankzugriffe ausführen möchte, z.b. delete, ist der Satz noch gesperrt.

Durch Umwandeln mit COMMIT *NONE und CLOSQLCSR *ENDMOD wird der ODP sauber nach Beenden des Moduls gelöscht, das hilft mir in diesem Fall aber leider nicht.

Gibt es eine Möglichkeit, ihn INNERHALB meines Moduls zu löschen???

Vielen Dank,
Claudia

B.Hauser
17-07-12, 12:27
Gib mal im Declare Cursor Statement nach dem Select Statement FOR READ ONLY an.

Birgitta

claudia_669
17-07-12, 12:45
Habe ich, ändert leider nichts.
Die Sperre bleibt mit

Sperr-
art Sperre Status
MBR *SHRRD HELD
DATEN *SHRRD HELD

stehen.

ExAzubi
17-07-12, 18:01
Werden die Datensätze über SQL oder mit DELETE / UPDATE gelöscht?
Falls diese ebenfalls mit SQL gelöscht werden, kann es nämlich sein, das das LÖSCH-SQL den Datenpfad offen hält.

claudia_669
18-07-12, 07:29
Nein, per SQL erfolgt nur das Einlesen.

Die Datenbankzugriffe erfolgen getrennt davon und erzeugen auch nicht die Satzsperre :confused:

B.Hauser
18-07-12, 07:56
Wenn SQL nur die Daten einliest (und Du außerdem FOR READ ONLY definiert hast), ist SQL auch nicht für die Satz-Sperren zuständig. Allerdings solltest Du nach den Änderungen den Cursor schließen und erneut öffnen, damit Du auch die aktuellen Daten siehst. (Man kann allerdings auch mit sensitiven Cursorn herumspielen).

Die Sperren erfolgen beim Einlesen vor dem Update oder Delete, oder durch den Delete mit Schlüssel.
Sofern eine Datei in den F-Bestimmungen als Update-Datei definiert wurde, ein Satz eingelesen wurde, bleibt dieser Satz solange gesperrt, solange kein Update erfolgt oder der nächste Satz gelesen wird. (Klassisches RPG ohne Commitment Steuerung).

Wird mit Commitment Steuerung gearbeitet und der Datensatz unter Commit eingelesen, bleibt er solange gesperrt, bis eine Commit oder Rollback-Aktion den Satz freigibt. Die Erweiterung (N) oder ein expliziter UNLOCK sind wirkungslos.

Kann es sein, dass die Inserts, Updates und Deletes unter Commitment Control mit einem höheren Level als *CHG erfolgen und noch nicht freigegeben (Commit oder Rollback) wurden?

Birgitta

claudia_669
18-07-12, 08:27
Damit könnte es zu tun haben.

Mein SQL sieht aus wie folgt:

EXEC SQL Prepare S1 from : mstfSqlStm ;
EXEC SQL Declare C1 Cursor for S1 ;
EXEC SQL Open C1 ;

DoU SqlCod <> 0 ;
EXEC SQL Fetch c1 into : mstfSqlData ;
If SqlCod < 0 ;
Iter ;
Endif ;
If SqlCod = 100 ;
Leave ;
Endif ;
// hier: Fill Subfile ...
Enddo ;

EXEC SQL
Close C1 ;

Aus der Subfile wird danach entsprechend ein Datensatz zur Bearbeitung ausgewählt, z.B. ein Update, das über ein Serviceprogramm erfolgt, in dem die Datei in den F-Bestimmungen so definiert ist:
FDatei UF A E Disk UsrOpn Commit(mblnCmtCtl),
d.h. optional mit Commit-Steuerung.
Dieser Schalter ist in meinem Fall aber auf aus gesetzt und ein Update erfolgt auch auf dem Satz.
Lt. Debugger komme ich aus diesem Serviceprogramm daher OHNE Sperre wieder heraus und erst das dann folgende erneute Einlesen der Subfile per SQL setzt dann die Sperre, die durch das Close nicht mehr aufgehoben wird.

Hast Du hierzu eine Idee, ob da die Ursache liegt?

claudia_669
18-07-12, 08:55
Ohje, mea culpa.

Zwar ist es tatsächlich so, dass bei der ersten Ausführung der ODP wieder gelöscht wird und beim zweiten Mal nicht mehr und das "Satzsperren" (read) stehen bleiben, aber das hat nicht mein Problem verursacht, dass ich danach keine Löschoperation auf dem Satz ausführen konnte, sondern der Fehler lag in der delete-Funktion an sich.

Vielen Dank für die Bemühungen und sorry für die "Fehlanfrage"!

Claudia

andreaspr@aon.at
23-07-12, 12:14
Nur noch zum Verständnis. Der ODP KANN und DARF nicht vom Benutzer/PGM gelöscht werden. Das macht die DB2 von sich aus!

Ein offener ODP setzt auch keine Satzsperren!

Der ODP wird von der DB2 aufgehoben, um Abfragen beschleunigen zu können. Auch wenn der ODP nicht gelöscht wird, werden beim nächsten OPEN dennoch die aktuellen Daten gelesen (auch ohne Sesitive).

Einzig in der QAQQINI kann definiert werden wieviele ODPs maximal pro Job erhalten bleiben dürfen.

lg Andreas