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:
- Aus Sicht der Grails-Applikation muss die ID in der  Domänenklasse (static mapping) als
id generator: 'assigned'
deklariert werden - 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…