Delphi-PRAXiS
Seite 5 von 5   « Erste     345   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQL Automatisch zugeteilte Id ermitteln. (https://www.delphipraxis.net/181067-sql-automatisch-zugeteilte-id-ermitteln.html)

Sir Rufo 14. Jul 2014 13:58

AW: SQL Automatisch zugeteilte Id ermitteln.
 
Zitat:

Zitat von supermuckl (Beitrag 1265486)
" jeder Client seine eigene Kennung abrufen kann, ohne die Aktivitäten anderer Clients berücksichtigen oder Sperren setzen bzw. Transaktionen verwenden zu müssen."

ok das war mir neu. danke!

da arbeitet jede DB etwas anderst :)

Hmmm, mir ist jetzt eigentlich nur dieses Verhalten bekannt (MySQL, MSSQL, DB2, Firebird, ...) bzw. man kommt immer an die verbindungsspezifische zuletzt eingefügte ID

arnof 14. Jul 2014 15:03

AW: SQL Automatisch zugeteilte Id ermitteln.
 
Zitat:

Zitat von mkinzler (Beitrag 1265472)
Man könnte auch die Frage lesen, den da steht MySQL!!

Ich benutze zumeist MYSQL via ADO, da geht das in 95% der Fälle, manchmal aber auch nicht (bugs gibt es überall), dann hilft:

SELECT LAST_INSERT_ID()

DeddyH 14. Jul 2014 15:06

AW: SQL Automatisch zugeteilte Id ermitteln.
 
Womit wir dann wieder bei der allerersten Antwort wären :roll:

arnof 14. Jul 2014 16:01

AW: SQL Automatisch zugeteilte Id ermitteln.
 
Zitat:

Zitat von DeddyH (Beitrag 1265503)
Womit wir dann wieder bei der allerersten Antwort wären :roll:

Manchmal ist halt V1.0 besser als alle Updates :lol:

Blup 14. Jul 2014 16:51

AW: SQL Automatisch zugeteilte Id ermitteln.
 
Zitat:

Zitat von Perlsau (Beitrag 1265458)
Zitat:

Zitat von Blup (Beitrag 1265435)
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)

Der Vorgang "Post" umfasst den Transport des aktuellen Datensatzes vom Client zum Server und das Eintragen dieses Satzes in die Datenbank.
Dazu gehört auch die automatische Ausführung aller Trigger.
Die Besonderheit der Before-Trigger ist, man kann die einzutragenden Werte noch ändern (also z.B. ein leeres ID-Feld füllen).
Tritt bei irgendeinem Schritt ein Fehler auf (z.B. auch in einem After-Trigger) wird der Post-Vorgang abgebrochen.
Dabei werden alle Änderungen an Tabellen rückgängig gemacht, die wärend dieses Posts erfolgt sind.
Aber Generatoren können dabei nicht berücksichtigt werden.
Die im Trigger erzeugte ID ist im Fehlerfall ungültig und wird nicht mehr verwendet.
Das kann man sehr leicht nachprüfen.

Zitat:

Zitat von Perlsau (Beitrag 1265458)
Zitat:

Zitat von Blup (Beitrag 1265435)
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.

Die vom IB-Expert automatisch erzeugten Trigger prüfen immer ob das Feld noch den Null-Zustand hat, bevor diese eine neue ID erzeugen.
Die Daten des einzufügenden Datensatzes können auch nur im BeforeTrigger verändert werden.

Zitat:

Zitat von Perlsau (Beitrag 1265458)
Zitat:

Zitat von Blup (Beitrag 1265435)
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.

Hier beist sich die Katze in den Schwanz.
Dazu muss das jeweilige DB-System aber in der Lage sein im Laufe des Post-Vorgangs den Datensatz auf dem Client zu aktualisieren.
Und da gab oder gibt es bei einigen Systemen Schwierigkeiten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:52 Uhr.
Seite 5 von 5   « Erste     345   

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz