Das ist so nicht ganz richtig. Auch der BeforeInsert-Trigger der Datenbank wirkt erst, nachdem der Datensatz per Post an den Server übergeben wurde.
Der Generator – und ich schreibe hier wieder ausschließlich über Firebird, auch wenn ich meine, daß es sich hier um eine generelle Verfahrensweise bei allen modernen
DBMS handelt – incrementiert bei BeforeInsert vor dem Posten. In die jeweilige Spalte wird dieser Wert natürlich erst nach dem Posten eingetragen:
This database also maintains a generator named EMP_NO_GEN and a Before Insert trigger named SET_EMP_NO on the EMPLOYEE table, to produce a value for this key whenever a new row is inserted. (Helen Borrie: The Firebird Book)
Wenn die Aktion (insert) nicht abgeschlossen (post) wird (was einem cancel entspricht), setzt der Trigger den einmal erhöhten Generatorwert wieder zurück (rollback):
Work performed by triggers will be rolled back if the transaction that prompted them is rolled back. (Helen Borrie: The Firebird Book)
Es gibt allerdings Komponenten die den Wert solcher Spalten selbst vorab erzeugen.
Dafür muss dann der für diese Spalte zuständigen Generator angegeben werden.
Die Komponente erzeugt die neue ID über eine interne Abfrage und setzt dabei den Generator hoch:
Code:
select GEN_ID(GEN_ZUSATZKLASSE_ID, 1) from RDB$DATABASE
Dann wirkt aber auch der Trigger nicht mehr, da die Spalte bereits belegt ist.
Verwechselst du da nicht was? Die Id-Spalte des neu anzulegenden Datensatzes wird erst nach dem Post belegt. Würden die
DB-Komponenten den Generatorwert von sich aus hochsetzen, würde das bedeuten, daß der Generatorwert immer um 2 erhöht wird, wenn BeforeInsert oder AfterInsert in der
DB gesetzt sind, denn der Trigger wird ja auch ohne entsprechende
DB-Komponenten im Client allein schon durch den Insert-Befehl ausgelöst, z.B. wenn ich ein
SQL-Script mit Insert-Befehlen laufen lasse.
Es ist dagegen fahrlässig, den Generator nur abzufragen ohne den Generatorwert hochzusetzen und sich darauf zu verlassen, dass der Trigger diese ID beim nächsten Post vergibt. Generatoren zählen für alle Transaktion und Datenbankverbindungen. Bis zum eigenen Post kann sich der Generatorwert schon wieder geändert haben und der Trigger vergibt eine andere ID.
Richtig! Für Single-User-Anwendungen spielt das jedoch keine Rolle, bei Multi-User-Anwendungen dagegen schon: Hier sollte man einfach die Id, die nach dem Posten vergeben wurde, aus der jeweiligen Id-Spalte der gerade bearbeiteten Tabelle auslesen. Sollte es irgend eine Spalte in der jeweiligen Systemtabelle geben, die diese LAST_INSERT_IDs protokolliert, besteht dasselbe Problem in einer Multi-User-Umgebung: die letzte eingefügte Id muß nicht zwangsläufig diejenige sein, die der Client eigentlich abrufen möchte – es sei denn, man verwaltet das selbst und hinterlegt in einer weiteren Spalte die entsprechende User-Id.