![]() |
Datenbank: MySQL • Version: 5 • Zugriff über: k. A.
SQL Automatisch zugeteilte Id ermitteln.
Hallo,
Ich möchte ein Programm machen das etwas in eine SQL Datenbank schreibt. Der Datensatz bekommt automatisch von der Datenbank eine id zugeteilt. Nun möchte ich diese Id meinen Programm irgendwie mitteilen. Jedoch weiß ich nicht wie ich das machen soll. - ich kann nicht einfach den letzten eingetragenen Datensatz auslesen, da es möglich ist, dass ein anderes Programm etwas in der Zwischenzeit in die Datenbank - Tabelle Schreibt. Wie soll / kann ich dies realisieren? Lg Simon |
AW: SQL Automatisch zugeteilte Id ermitteln.
Die meisten Datenbanken haben dafür eine Funktion wie
![]() |
AW: SQL Automatisch zugeteilte Id ermitteln.
@Bladefire:
Gleich nach dem Posten bzw. Insert ist der bearbeitete bzw. gerade eingefügte Record der aktuelle Datensatz. Da kannst du doch einfach abfragen, welcher Wert in deinem Id-Feld steht:
Delphi-Quellcode:
Zur Anzeige in der Statusbar mache ich das in den meisten DB-Anwendungen sogar grundsätzlich, und zwar mittels des Ereignisses AfterScroll. Dort wird dann die Id ausgelesen und ein Ereignis generiert, das meien Statusbar aktualisiert.
AktuelleId := MyDataset.FieldByName('IdFeld').asInteger;
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Das funktioniert 100 % zuverlässig, zumindest meiner Erfahrung nach, ich kenne das gar nicht anders, und zwar bei allen DBMS, die ich jemals in Verwendung hatte, als da wären:
Firebird, MsSQL, MySQL, ProstGreSQL, MsAccess. Wäre dem nicht so, wären DBMS nicht wirklich einsatzfähig. Ob DBMS vor 20 Jahren unzuverlässig waren, kann ich nicht beurteilen, hatte damals noch nichts damit am Hut. Und wenn du's nicht glaubst, probier's doch einfach mal aus, wirst schon sehen (sollte man sowieso immer machen, wenn man Ratschläge aus Foren erhält). |
AW: SQL Automatisch zugeteilte Id ermitteln.
Ob das so funktioniert, hängt nicht vom RDBMS ab, sondern vom Provider (Zeus, ADO, dbExpress, DAC) und da gab es -zumindest bei ADO- früher wirklich Probleme bzw. hat das nicht funktioniert. Früher. Jetzt ist das alles kein Problem mehr. Man muss nur sicherstellen, das der Provider erkennt, das es sich um ein AutoInc-Feld handelt bzw. das persistente Feld entsprechend deklarieren. Firebird z.B. kennt keinen AutoInc-Datentypen. Da erstellt man einen Generator und stellt im Provider das Feld entsprechend ein.
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Mit all den von dir genannten DB-Komponenten funktioniert genau das: Wenn ich einen neuen Datensatz in eine Datensatz-Menge einfüge, bleibt dieser Datensatz der aktuelle, solange ich keinen anderen Datensatz einfüge oder anwähle. Das hat nichts mit Auto-Inc-Feldern zu tun. Im Übrigen gibt es Zeus nicht, das heißt Zeos.
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Ach, Zeos, genau. Ich wollte dir nach widersprechen, sondern nur darauf hinweisen, das es Sache des Providers ist, sich um die Aktualisierung von Daten zu kümmern. Ähnliches gilt ja auch für einen Zeitstempel, der vom Server gesetzt wird, weil man z.B. in einer Spalte den Zeitpunkt der letzten Änderung haben will, und da ist es sinnvoll, die Serverzeit zu setzen (per Trigger). Nun muss aber dieser Wert wieder zum Client...
Und das es der aktuelle Datensatzzeiger ist, liegt daran, das der aktuelle Record eingefügt/aktualisiert wird, wenn ein Post stattfindet. Und das findet bei einem Recordwechsel statt (dann ist der eben noch aktuelle DS zwar nicht mehr aktuell, aber ich weiss ja, was Du meinst), oder man ruft explizit Post auf. Es gibt ja auch den Modus, das man die Änderungen erst lokal durchführt (für beliebig viele Records) und dann die Änderungen in einem Abwasch zum Server schickt. Dann gibt es ja keinen 'aktuellen' Datensatzzeiger. bzw. gibt es einen, aber es werden auch andere Records aktualisiert. Wie ist denn die ID-Spalte bei einer Verbindung zu Firebird deklariert, damit sie nach einem INSERT weiß, welche ID vom RDBMS vergeben wurde? |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Code:
Willst du AutoInc-Funktionalität, erstellst du dir einen BeforeInsert- oder AfterInsert-Trigger, der einen Generator aufruft, von dem er sich den neuen Wert holt und in die Id-Spalte einträgt. IbExpert erledigt das automatisch, wenn man beim Erstellen der Tabelle die AutoInc-Checkbox aktiviert.
ID_ZUSATZKLASSE INTEGER NOT NULL
ALTER TABLE ZUSATZKLASSE ADD CONSTRAINT PK_ZUSATZKLASSE PRIMARY KEY (ID_ZUSATZKLASSE); Vom Client aus kannst du dann – bei BeforeInsert – die Id-Spalte bereits vor dem Posten auslesen. Hast du AfterInsert eingestellt, mußt du dir mit dem Auslesen des aktuellen Generatorwertes behelfen:
Code:
... wobei der zweite Parameter den Increment-Wert darstellt.
select GEN_ID(GEN_ZUSATZKLASSE_ID,0) from RDB$DATABASE
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Firebird kennt (IIRC ab der Version 2.0) eine RETURNING-Klausel, die genau für solche Zwecke gedacht ist, siehe z.B.
![]() |
AW: SQL Automatisch zugeteilte Id ermitteln.
Klar, wenn man via SQL-Befehlen direkte Inserts absetzt. Arbeitest du jedoch mit einer Datenmenge (Query), mittels derer du einen neuen Datensatz anzulegen gedenkst, nützt dir die Returning-Klausel nichts, denn Query.Append ist eine Procedure.
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Ich muss mein Deutsch verbessern: Was ich meine, ist etwas wie die Property 'AutoGenerateValue' in einem TIntegerField. Normalerweise erzeugt der Provider einen Befehl, à la:
Code:
Der weiß doch nicht, das ID ein AutoInc-Feld ist. Erst wenn ich die o.g. Property entsprechend setze, wird der Befehl anders gerendert:
INSERT INTO Foo (ID,Value) VALUES (0,'Bar')
Code:
ADO kann die 'AutoGenerateValue' selbst richtig setzen, weil ja aus der Schemainformation (zumindest im SQL-Server) hervorgeht, das ID eine IDENTITY-Spalte ist. Nur, woran erkennt der Provider nun, das das Feld 'ID' bei Firebird eine Art AutoInc-Feld ist? Er wird ja wohl kaum die Trigger parsen...
INSERT INTO Foo (Value) VALUES ('Bar') RETURNING ID
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Wenn deine Datenbank AutoInc in irgend einer Form unterstützt (bei Firebird z.B. über AfterInsert- bzw. BeforeInsert-Trigger und entsprechendem Generator) benötigst du keine clientseitige Initialisierung dieser Funktionalität, denn der Trigger löst automatisch beim Insert aus, und zwar völlig unabhängig vom Provider oder dem Sender des SQL-Befehhls.
Unterstützt dein DBMS das nicht, bieten einige DB-Komponenten die Möglichkeit, das via Client zu erledigen. Die entsprechenden Einstellungen zu wählen ist Aufgabe des Entwicklers. Der Provider muß nicht "wissen", ob es sich um ein "AutoInc-Feld" handelt. Und ja: Kommuniziert man über Sachgebiete, die exakte Darstellungen erfordern (wie beispielsweise Mathematik oder eben auch eine Programmiersprache wie Pascal), ist es nicht wirklich zielführend, weiterhin die gewohnte Umgangssprache einzusetzen. Ohne ausreichende Kenntnis der Fachbegriffe und ihrer Bedeutung versagt man dann regelmäßig beim Versuch, Sachverhalte korrekt darzustellen. |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Delphi-Quellcode:
bzw. den DataType
TAutoIncField
Delphi-Quellcode:
. Der Provider muss das nur passend zum Server umsetzen. Nicht alle können bzw. machen das. DbExpress hat da so seine Problemchen während FireDAC das ganz gut hinkriegt.
ftAutoInc
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Ist schon klar. Nur ganz so automatisch, wie Perlsau das gesagt hat, scheint es dann doch nicht zu gehen. Die Felder muss man dann ggf. manuell anpassen.
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Das RETURNING von FireBird wird ihm be der Verwendung von MySQL wenig bringen. In diesem Fall würde ich mich auch nicht darauf verlassen, dass der Datensatzzeiger nach dem Insert aauf dem richtigen Datensatz steht, sondern wie in der 1. Antwort beschrieben die saubere Variante wählen.
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Das RETURNING hatte ich erwähnt, als von Firebird die Rede war. Weshalb man unter MySQL LAST_INSERT_ID verwenden sollte, ist in dem verlinkten Artikel aus der ersten Antwort erschöpfend beschrieben.
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Wenn deine Datenbank AutoInc in irgend einer Form unterstützt (bei Firebird z.B. über AfterInsert- bzw. BeforeInsert-Trigger und entsprechendem Generator) benötigst du keine clientseitige Initialisierung dieser Funktionalität, denn der Trigger löst automatisch beim Insert aus, und zwar völlig unabhängig vom Provider oder dem Sender des SQL-Befehhls. Automatisch bedeutet hier nicht halbautomatisch, sondern in der Tat ganz automatisch ohne weiteres Zutun. Um jedoch auf einen tatsächlichen Fall, bei dem es nicht wie erwartet ganz automatisch funktioniert, eingehen zu können, wäre es hilfreich, wenn du ein wenig mehr dazu verraten würdest. Ich habe diesen Fall mit den von mir genannten DBMS in vielen Jahren der Datenbankanwendungsentwicklung noch kein einziges Mal erlebt, nicht mal ansaztweise, weder mit Ado, IbDac, dbExpress, FibPlus, Zeos oder UIB. Mit anderen Worten: Meine Ids wurden bislang immer verläßlich erzeugt. Nachtrag: Wenn irgendwelche obsolte DBMS hier Fehlverhalten zeigten, sollten sie nicht mehr eingesetzt werden. Insbesondere der Einsatz der völlig veralteten Borland Database Engine sollte, will man zukunftsfähige und zuverlässige DB-Anwendungen entwickeln, unbedingt vermieden werden. |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
MSEgui z.B. macht dies automatisch für das primary key Feld via "last insert id" wenn die DB es unterstützt. Für andere DB's muss entweder "tsequencelink" verwendet werden oder das Feld-flag "of_refreshinsert" und eventuell "of_refreshupdate" gesetzt werden, welche die "returning" Option im SQL-Kommando aktivieren. |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Zitat:
Wann ist der "richtige Moment"? Zitat:
![]() Bis jetzt hat hier noch keiner eine Situation beschrieben, in der die Zuverlässigkeit der Erzeugung einer Id nicht gewährleistet wäre. Ich lese immer nur Andeutungen und "von früher". Übrigens: Weder Hände noch andere Extremitäten sollte man ins Feuer legen, auch nicht, um irgend etwas zu beweisen. Ich bin nicht dafür haftbar zu machen, wenn irgend jemand eine Konstruktion zusammenbastelt, die irgendwelche fehlerhafte PK-Ids liefert oder anzeigt. Ich hatte damit wie bereits erähnt noch niemals auch nur das geringste Problem. Da gibt's im Zusammenhang mit Datenbank-Anwendungen ganz andere Dinge, die problematisch sein können. |
AW: SQL Automatisch zugeteilte Id ermitteln.
Das es bisher und jetzt funktioniert ist aber keine Garantie, dass es auch in der Zukunft so funktioniert. Deshaln würde ich den dokumentierten Weg über die vom DBMS bereitgestellten Funktionen gehen.
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Abseits des eigentlichen MySql-Themas:
Zitat:
Auch der BeforeInsert-Trigger der Datenbank wirkt erst, nachdem der Datensatz per Post an den Server übergeben wurde. 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:
Dann wirkt aber auch der Trigger nicht mehr, da die Spalte bereits belegt ist.
select GEN_ID(GEN_ZUSATZKLASSE_ID, 1) from RDB$DATABASE
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. |
AW: SQL Automatisch zugeteilte Id ermitteln.
ich hab das problem letztens in postgres so gelöst:
transaction auf query ausführen "id des eingefügten records auslesen" query dahinter transaction zu damit kommt direkt die neue id als resultset zurück |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
![]() Zitat:
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Das kann nicht sein!:mrgreen: Gruß K-H |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
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) Zitat:
Zitat:
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
aber es gibt halt den weg - und ob der sicher ist, hängt von der implementation der transaktion ab (transaktionsisolation) begin; insert into test(name) values ('something'); select CURVAL('test_id_seq'); commit; und auch den weg (postgresql native) über "returning" INSERT INTO t2 (eid, ...) VALUES (...) RETURNING eid; ob es das bei anderen DBs gibt, weiß ich nicht |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Zitat:
![]() |
AW: SQL Automatisch zugeteilte Id ermitteln.
@supermuckl
Eine Funktion "CURVAL" dürfte es nicht durchgehend auf allen DBMS geben. Allerdings hatte ich Deinen ersten Beitrag dazu eher so verstanden:
Code:
Der Schlüssel muss dann natürlich eindeutig sein.
INSERT INTO table(f1, f2) VALUES(<Schlüsselwert>, 'Blabla');
SELECT <autoincrementfield> FROM table WHERE f1=<Schlüsselwert> Das dürfte innerhalb einer Transaktion in jedem DBMS funktionieren, könnte bei manchen (je nach Konfiguration) aber zum Rollback führen, wenn zwei User "gleichzeitig" diese Transaktion durchführen. |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Code:
Wenn das Feld "table.f1" das Primary Key Feld ist, ergibt sich das Problem, dass man den Autonkrementwert nicht kennt, und daher logischerweise auch kein
SELECT <autoincrementfield> FROM table WHERE f1=<Schlüsselwert>
Code:
durchführen kann. Denn <Schlüsselwert> ist bei Autoinkrement-Feldern nicht bekannt (wenn der Wert über einen BEFORE INSERT Trigger unter Verwendung eines Firebird-Generators erzeugt wurde, hat der Client nach Ausführung des INSERT keinen Zugriff auf den soeben erzeugten <Schlüsselwert>).
SELECT f1 FROM table WHERE f1=<Schlüsselwert>
|
AW: SQL Automatisch zugeteilte Id ermitteln.
der TE könnte ja mal erzählen, was für eine DB er einsetzt.
//edit da stehts :D mysql.. |
AW: SQL Automatisch zugeteilte Id ermitteln.
Man könnte auch die Frage lesen, den da steht MySQL!!
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Die ganze Diskussion ist doch eigentlich unsinnig, denn
Das Thema geht eigentlich um Punkt (2) und der ist irgendwie nicht Thema der Diskussion ... Sollte also der Provider es nicht schaffen die von MySQL (das ist das RDBMS dieses Themas) generierte ID zu liefern, dann geht man eben den folgenden Weg:
SQL-Code:
CREATE TABLE `foo` (
`foo_id` int NOT NULL AUTO_INCREMENT , `foo_value` varchar(50) NOT NULL , PRIMARY KEY (`foo_id`) );
Delphi-Quellcode:
LQuery.SQL.Text := 'INSERT INTO foo (foo_value) VALUES (:foo_value); SELECT LAST_INSERT_ID() Foo_ID;';
LQuery.ParamByName('foo_value').Value := 'bar'; LQuery.Open; LId := LQuery.FieldByName('Foo_ID').Value; |
AW: SQL Automatisch zugeteilte Id ermitteln.
richtig!
aber genau das
Code:
muss in einer multiuser DB in einer transaktion aufgerufen werden, soweit ich das richtig sehe
LQuery.SQL.Text := 'INSERT INTO foo (foo_value) VALUES (:foo_value); SELECT LAST_INSERT_ID() Foo_ID;';
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Eher 3) Ob man davon ausgehen kann, das der Datensatzzeiger im DataSet auf dem neuen Datensatz steht
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
http://dev.mysql.com/doc/refman/5.1/de/information-functions.html
|
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
Zitat:
f1 soll nicht primary Key sein, sondern lediglich eindeutiger Schlüssel. |
AW: SQL Automatisch zugeteilte Id ermitteln.
Zitat:
|
AW: SQL Automatisch zugeteilte Id ermitteln.
" 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 :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:16 Uhr. |
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