[gelöst]AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

[gelöst]AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von hubblec4 »

Wenn ich einen Datenbankeintrag mache,
wird in einer Spalte, welche mit Autoincrement versehen ist, der wert automatisch um jeweils eins erhöht.
(sinn und zwck des autoincrements).

wie kann ich diesen neuen wert direkt ermitteln? (am besten beim INSERT.)

Ich mache das bis jetzt so:
den neuen Eintrag in die datenbank schreiben und dann direkt einen neuen SQL-Befehl mit COUNT(*), welcher mir dann die zahl des letzten eingefügten Eintrags zurückgibt.

Problem an der sache, wenn ich den Eintrag gemacht habe und bis der neue befehl mit dem COUNT(*) startet, könnte ja ein anderer wieder einen Eintrag gemacht haben und ich erhalte die falsche Zahl.

Wie kommt man an den Autoincrementwert der dann auch ganz sicher zu dem Eintrag passt den man gemacht hat?

LG
hubble
Zuletzt geändert von hubblec4 am Do 28. Aug 2014, 11:05, insgesamt 1-mal geändert.

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von hde »

Das ist von Datenbank zu Datenbank unterschiedlich Schau in die Wilkis der jeweiligen DB

hde

Thomas B.
Beiträge: 90
Registriert: Fr 2. Nov 2007, 13:32
OS, Lazarus, FPC: Win (L 1.0 FPC 2.6.0)
CPU-Target: 32Bit
Wohnort: Ulm

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Thomas B. »

Bei AutoIncrement interessiert normalerweise der Wert beim INSERT nicht. Der Index (Schlüssel) wird erst später z.B. beim Tabellenabgleich gebraucht.

Bei MySQL hilft dir folgender Funktionsinhalt:

Code: Alles auswählen

fSQLQuery.SQL.Clear;
fSQLQuery.SQL.Text := 'SHOW TABLE STATUS WHERE NAME=MeinTabellenName';
fSQLQuery.Open;
fSQLQuery.First;
Result := fSQLQuery.FieldByName('Auto_increment').AsInteger; // Rückgabewert = nächste freie ID
fSQLQuery.Close;
 

Zur Absicherung beim Parallelzugriff mehrerer Clients mit Lock/Unlock arbeiten.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Patito »

Es kommt wie gesagt auf die Datenbank an.

Bei manche Datenbanken gibt es Id-Generatoren.
Manche Datenbanken haben ein sinnvolles 'SELECT @@identity'.
Manche Datenbanken haben eine eher kaputte Version davon (d.h. sobald Trigger im Spiel sind, gibt es Probleme).
Bei manchen Datenbanken gibt es nichts sinnvolles.

Im Notfall verwenden manche Leute GUIDs (soetwas habe ich vor allem im MS-Umfeld gesehen...).

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Michl »

hubblec4 hat geschrieben:Ich mache das bis jetzt so:
den neuen Eintrag in die datenbank schreiben und dann direkt einen neuen SQL-Befehl mit COUNT(*), welcher mir dann die zahl des letzten eingefügten Eintrags zurückgibt.

Das halte ich für problematisch. Was passiert, wenn ein Nutzer mal einen Datensatz löscht?!

Es ist möglicherweise nicht die performanteste Lösung, Du könntest nach einem "Insert" mit einem "Select" genau den eingefügten Wert abfragen und erhälst dabei die automatisch generierte ID zurück (falls keine Dopplungen erlaubt sind).

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Antrepolit »

hubblec4 hat geschrieben:Wenn ich einen Datenbankeintrag mache,
wird in einer Spalte, welche mit Autoincrement versehen ist, der wert automatisch um jeweils eins erhöht.
(sinn und zwck des autoincrements).

wie kann ich diesen neuen wert direkt ermitteln? (am besten beim INSERT.)

Ich mache das bis jetzt so:
den neuen Eintrag in die datenbank schreiben und dann direkt einen neuen SQL-Befehl mit COUNT(*), welcher mir dann die zahl des letzten eingefügten Eintrags zurückgibt.

Problem an der sache, wenn ich den Eintrag gemacht habe und bis der neue befehl mit dem COUNT(*) startet, könnte ja ein anderer wieder einen Eintrag gemacht haben und ich erhalte die falsche Zahl.

Wie kommt man an den Autoincrementwert der dann auch ganz sicher zu dem Eintrag passt den man gemacht hat?

LG
hubble


1. Mache ein SELECT MAX(id) statt COUNT, dann passt das auch.
2. Falls da wirklich zwei Leute zeitgleich Schreiben, solltest du unbedingt mit Transaktionen und Isolation Levels arbeiten um Chaos zu verhindern.
Grüße, Antrepolit

care only if your os is really burning

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von hubblec4 »

ja das mit dem count(*) habe ich dann auch als nicht gut empfunden. (löschen geht so in dem sinne nicht)

das nochmalige abrufen mit dem vergleich der zuletzt eingetragenen daten könnte unter umständen auch nicht gehen, wegen doppelungen.

ich denke das mit MAX(id) ist ausreichend, da jetzt sicher keine flut von einträgen kommen wird.

danke für die hilfe.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Patito »

hubblec4 hat geschrieben:ja das mit dem count(*) habe ich dann auch als nicht gut empfunden. (löschen geht so in dem sinne nicht)
das nochmalige abrufen mit dem vergleich der zuletzt eingetragenen daten könnte unter umständen auch nicht gehen, wegen doppelungen.
ich denke das mit MAX(id) ist ausreichend, da jetzt sicher keine flut von einträgen kommen wird.

danke für die hilfe.


Sorry, aber Hilfe würde ich das jetzt nicht nennen. Man sollte noch mal deutlich betonen, dass egal, ob Du Max(),
Count() oder einen Zufallswert nimmst, das so im Multi-User-Betrieb nicht funktioniert.

Wenn Du keinen Mechanismus nimmst, der von der Datenbank bereitgestellt wird (Locks, @@identity, Sequence-Generatoren, ...),
zerbröselt Dir das ganze irgendwann.

Benutz einen Mechanismus, der zu deiner Datenbank passt! Und bau keinen Scheiß...

hubblec4
Beiträge: 341
Registriert: Sa 25. Jan 2014, 17:50

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von hubblec4 »

recht hast du auf jedenfall keine frage.

ich habe hier eine MySQL5.1 DB vorliegen. Werde ich mich mal bei denen auf der seite durchwühlen wie das genau zu machen ist.

Antrepolit
Beiträge: 340
Registriert: Di 12. Sep 2006, 08:57
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Kontaktdaten:

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Antrepolit »

hubblec4 hat geschrieben:recht hast du auf jedenfall keine frage.

ich habe hier eine MySQL5.1 DB vorliegen. Werde ich mich mal bei denen auf der seite durchwühlen wie das genau zu machen ist.

Ich hab dir das Stichwort genannt: Isolation Level und READ-COMMITED. Details dazu hier: http://dev.mysql.com/doc/refman/5.1/de/innodb-transaction-isolation.html
Grüße, Antrepolit

care only if your os is really burning

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von mschnell »

hde hat geschrieben:Das ist von Datenbank zu Datenbank unterschiedlich Schau in die Wilkis der jeweiligen DB

Es wäre doch schade, wenn Zeos so etwas allgemein verwendbares nicht vereinheitlichen könnte ...

-Michael

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Patito »

Antrepolit hat geschrieben:
hubblec4 hat geschrieben:recht hast du auf jedenfall keine frage.

ich habe hier eine MySQL5.1 DB vorliegen. Werde ich mich mal bei denen auf der seite durchwühlen wie das genau zu machen ist.

Ich hab dir das Stichwort genannt: Isolation Level und READ-COMMITED. Details dazu hier: http://dev.mysql.com/doc/refman/5.1/de/innodb-transaction-isolation.html


Ich kenne mich mit MySQL nicht aus. Kann sein, dass es funktioniert.
Aber bei einem Isolation Level Read-Commited würde ich jetzt erwarten, dass man verloren hat,
wenn jemand im Zeitraum zwischen Insert und Select Max() ein Dutzend Inserts komplett fertig commitet?!


Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von Patito »

mschnell hat geschrieben:
hde hat geschrieben:Das ist von Datenbank zu Datenbank unterschiedlich Schau in die Wilkis der jeweiligen DB

Es wäre doch schade, wenn Zeos so etwas allgemein verwendbares nicht vereinheitlichen könnte ...


Ein Problem ist, dass das Problem bei verschiedenen Datenbanken mit ganz anderen Mitteln gelöst wird
- Sequenz-Generator
- Autoincrement
- bei manchen Datenbanken stellt man den Key auf GUIDs um

Die beste Lösung ist in jeder Datenbank eine andere und erfordert ggf. Änderungen am Datenbank-Design, sowas kann
eine Client-Library wie Zeos nicht allgemein lösen.

MS-SQL hat z.B. für diese Aufgaben @@IDENTITY, IDENT_CURRENT und SCOPE_IDENTITY, und alle drei funktionieren
nur unter speziellen Bedingungen. Daher habe ich in solchen Datenbanken immer sehr viele GUIDs gesehen...

Bei Datenbanken ist jenseits von "SELECT * FROM Table" Schluß mit der Kompatibilität und spätestens wenn man Inserts
macht ist der Spass mit der Portabilität vorbei.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: AutoIncrement-Wert beim INSERT ermitteln(geht das?)

Beitrag von mse »

mschnell hat geschrieben:
hde hat geschrieben:Das ist von Datenbank zu Datenbank unterschiedlich Schau in die Wilkis der jeweiligen DB

Es wäre doch schade, wenn Zeos so etwas allgemein verwendbares nicht vereinheitlichen könnte ...

MSEgui verwendet "LASTINSERTID" oder die "RETURNING" Option beim SQL-statement um die Feldwerte automatisch aufzufrischen. Soviel ich weiss macht ZEOS das inzwischen auch so. Für FPC SQLdb ist "LASTINSERTID" AFAIK ebenfalls implementiert, möglicherweise ohne automatische Feldwertauffrischung, da bin ich nicht sicher.

Antworten