Strict Standards: Declaration of Walker_Page::start_lvl() should be compatible with Walker::start_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_lvl() should be compatible with Walker::end_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_el() should be compatible with Walker::end_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_PageDropdown::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1244

Strict Standards: Declaration of Walker_Category::start_lvl() should be compatible with Walker::start_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_lvl() should be compatible with Walker::end_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_el() should be compatible with Walker::end_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_CategoryDropdown::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1442

Strict Standards: Redefining already defined constructor for class wpdb in /www/htdocs/v167612/wplog/wp-includes/wp-db.php on line 306

Strict Standards: Redefining already defined constructor for class WP_Object_Cache in /www/htdocs/v167612/wplog/wp-includes/cache.php on line 433
iFool » Autoinkrementierung bei bestehenden DB2/400 Tabellen
Home > AS400, Groovy & Grails > Autoinkrementierung bei bestehenden DB2/400 Tabellen

Autoinkrementierung bei bestehenden DB2/400 Tabellen

Die im “alten Stil” erstellten DB-Tabellen wurden über DDS-Sourcecodebestimmungen beschrieben und anschließend mit CRTPF erstellt. Views (logische Sichten) wurden ebenfalls mit DDS beschrieben und mit CRTLF erstellt.

Heute sollte man Tabellen  mit SQL erstellen und ändern. Wer jedoch eine mit DDS beschriebene Tabelle später um ein Auto-Inkementierungsfeld erweitern möchte hat schlechte Karten: Es existiert kein entsprechendes DDS-Schlüsselwort und ein ALTER-Table der folgenden Art schlägt ebenfalls fehl:

ALTER TABLE AULICH/M$SE009PA ADD COLUMN ID BIGINT NOT NULL GENERATED
 ALWAYS AS IDENTITY
                                                
M$SE009PA in AULICH für Operation ungültig.                        

Die genaue Fehlermeldung lautet SQL7008 M$SE009PA in AULICH für Operation ungültig.   14 - DATALINK-, LOB- oder IDENTITY-Spalte kann einer Nicht-SQL-Tabelle
nicht hinzugefügt werden.                                              

Autoinkrementierung mit DDS-beschriebenen Datenbankdateien geht nicht. Jedenfalls nicht auf normalem Weg! Wer sich damit nicht abfinden kann und die bestehenden Tabellen nicht auf SQL-Tabellen migrieren kann, dem bietet sich ein halbwegs eleganter Ausweg über die Erweiterung der DDS-Tabellenbeschreibung um ein “normales” ID-Feld (numerisch, 18,0) und das Füllen dieses Feldes über ein Triggerprogramm.

So ein Triggerprogramm ist recht schnell geschrieben. Hier einmal ein passendes Beispiel: Triggerprogramm RPGLE Das Programm M$SE001TRG verwendet eine Data-Area M$SE009DTA um über einen Lock-Mechanismus die Eindeutigkeit des Schlüssels gewährleisten zu können. Das Proramm muss anschließend über den folgenden Befehl als BEFORE-INSERT-Trigger mit der Erlaubnis zur Veränderung des Satzpuffers eingetragen werden:

 ADDPFTRG FILE(MYLIB/M$SE001PA)
TRGTIME(*BEFORE) TRGEVENT(*INSERT)
PGM(MYLIB/M$SE001TRG) ALWREPCHG(*YES)

Wie gesagt: Nicht besonders schön, aber es funktioniert sehr gut. Sogar im Zusammenhang mit GRAILS-Anwendungen! Dabei sollte man nur noch folgendes bedenken:

  1. Aus Sicht der Grails-Applikation muss die ID in der  Domänenklasse (static mapping) als id generator: 'assigned' deklariert werden
  2. Da das RDBMS beim insert keine ID an die Applikation zurücksendet muss die Anwendung selbst bestimmen, welche ID gerade über den Trigger vergeben wurde.

Die unter 2. genannte Aufgabe kann man zum beispiel durch eine modifikation des Controllers der Domänen-Klasse erledigen. Beispiel:

def save = {
def dataDictionaryInstance = new DataDictionary(params)
if(!dataDictionaryInstance.hasErrors() && dataDictionaryInstance.save()) {
  // flash.message = "DataDictionary ${dataDictionaryInstance.id} created"
  // redirect(action:show,id:dataDictionaryInstance.id)
  // inserted by TAU starts here —>
  def myDataDictionaries = DataDictionary.listOrderById(max:1, order:”desc”)
  long myID = 0
  if (myDataDictionaries != null && myDataDictionaries.size > 0 )
myID = myDataDictionaries[0].id + 1
    flash.message = “DataDictionary ${myID} created”
    redirect(action:show,id:myID)
  // <— inserted by TAU ends here
  }
  else {
    render(view:’create’,model:[dataDictionaryInstance:dataDictionaryInstance])
  }
}

Einschränkungen der hier vorgestellten Lösung sind mir keine bekannt. Wer seine Tabellen aber zu SQL-Tabellen mit “sauberen” Autoinkrementierungsfeldern migrieren kann sollte das besser machen…

AS400, Groovy & Grails

  1. Bisher keine Kommentare
  1. Bisher keine Trackbacks