Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Von INSERT generierte Daten erfassen (https://www.delphipraxis.net/138324-von-insert-generierte-daten-erfassen.html)

WorstNightmare 7. Aug 2009 13:42

Datenbank: MySQL • Version: 5 • Zugriff über: ZeosLib 7

Von INSERT generierte Daten erfassen
 
Hallo,

mein Programm führt einen INSERT-Befehl in einer MySQL5 Datenbank mittels ZeosLib durch. Dabei werden, neben den Daten die eingetragen werden, auch zufällige IDs von der Datenbank erzeugt.

In Java kann man so darauf zugreifen (ps ist ein PreparedStatement):
Code:
    ResultSet rs = ps.getGeneratedKeys();
    int uniqueid;
    if (rs.next()) {
         uniqueid = rs.getInt(1);
    } else {
         throw new DatabaseException("Inserting failed.");
    }
Gibt es sowas wie GetGeneratedKeys auch in ZeosLib?

Mein Delphi-Code sieht bisher so aus:
Delphi-Quellcode:
  with Q.DbcStatement do
    for i := -1 to 5 do
    begin
      SetInt(3, Integer(FInventory[i].InvType));
      for Item in FInventory[i] do
      begin
        SetInt(1, FID);
        SetInt(2, Item.ID);
        SetInt(4, Item.Position);
        SetInt(5, 1);  // xxx
        SetString(6, '');  // xxx
        SetNull(7, stTimestamp); // xxx
        SetInt(8, 0);  // xxx
        SetInt(9, 0);  // xxx

        ExecuteUpdatePrepared;

        // hier möchte ich gerne abfragen, welche ID jetzt zugewiesen wurde
      end;
    end;
Es werden zwar IDs eingetragen, diese können jedoch durchaus mehrmals vorkommen, sind also nicht eindeutig sodass ich die andere ID einfach per SELECT-Abfrage herausfinden könnte.

anse 7. Aug 2009 15:57

Re: Von INSERT generierte Daten erfassen
 
Du kannst die letzte auto_increment ID durch ein zweites SELECT abfragen:
SQL-Code:
SELECT LAST_INSERT_ID()

anse 7. Aug 2009 17:20

Re: Von INSERT generierte Daten erfassen
 
Merkwürdig, dass das in Zeos gar nicht als Funktion zur Verfügung steht. Zumal es in der ZPlainMySqlDriver.pas eine
Delphi-Quellcode:
TZMySQL5PlainDriver.getLastInsertID (Handle: PZMySQLConnect): Int64;
gibt, die genau das gleiche liefert wie der o.s. SELECT query, nur eben ohne SQL Abfrage. Dieses TZMySQL5PlainDriver wird aber scheinbar nicht nach "außen" verfügbar gemacht.

WorstNightmare 7. Aug 2009 18:48

Re: Von INSERT generierte Daten erfassen
 
Funktioniert das auch wenn ~10 Insert Anfragen zur selben Zeit (Threads) durchgeführt werden oder kommt es dann zu falschen Ergebnissen?

mkinzler 7. Aug 2009 18:50

Re: Von INSERT generierte Daten erfassen
 
das funktioniert auch dann, weil die Funktion den letzen Wert der Verbindung zurückgibt.

WorstNightmare 7. Aug 2009 18:56

Re: Von INSERT generierte Daten erfassen
 
Zitat:

Zitat von mkinzler
das funktioniert auch dann, weil die Funktion den letzen Wert der Verbindung zurückgibt.

Alle Threads nutzen die selbe Verbindung (falls du dachtest sie würden alle eine erstellen). Wäre es besser die alle mit einer separaten Verbindung zu bestücken? Wenn es hoch kommt können bis zu 300 Clients verbunden sein, ich dachte da würde es sich Ressourcen-technisch nicht so gut machen so viele ZConnections zu haben.

mkinzler 7. Aug 2009 18:59

Re: Von INSERT generierte Daten erfassen
 
Bei der Verwendung der VCL sollte man immer eigene Verbindungen wählen, das die bisher nicht threadsicher ist.

WorstNightmare 7. Aug 2009 20:32

Re: Von INSERT generierte Daten erfassen
 
So, hab jetzt nen bisschen umgestellt und so. Danke für eure Antworten! :dp:
LAST_INSERT_ID() funktioniert einwandfrei.

anse 7. Aug 2009 23:27

Re: Von INSERT generierte Daten erfassen
 
Ein Thread kann immer nur exakt einen Query zur gleichen Zeit ausführen, auch wenn wir auf Gigahertz-Multi-Tasking-Systemen arbeiten. Ergo ist die LAST_INSERT_ID() an die DB Connection gebunden. Auch wenn das sehr schnell geht ist es immer noch eine Stapelverarbeitung. Wenn du mit Threads mehrere Verbindungen aufbaust hast du auch mehrere TZConnection Objekte und du mußt über diese die LAST_INSERT_ID() abfragen.

anse 7. Aug 2009 23:31

Re: Von INSERT generierte Daten erfassen
 
Sorry hab überlesen dass du für mehrere Query-Threads dieselbe Verbindung benutzt - hört sich merkwürdig an, funktioniert das ohne Abstürze und sonstige Sonderfälle?

Jedenfalls wird das Abfragen der LAST_INSERT_ID() damit zum Glücksspiel - die kann bei gleichem Timing die ID eines anderen Threads zurückliefern, in so einem Fall, dend der Server arbeitet die Queries nun mal thread-los ab, wenn du eine einzige Verbindung benutzt:

1. Thread A: INSERT
2. Thread A: SELECT LAST_INSERT_ID()
** Alles ok, phew.. **
3. Thread B: INSERT
4. Thread C: INSERT
5. Thread B: SELECT LAST_INSERT_ID()
6. Thread C: SELECT LAST_INSERT_ID()
** Böses durcheinander **

Besser wäre es für jede Query eine eigene Verbindung aufzubauen. Hört sich verschwenderisch an, und eigentlich braucht man daß bei INSERTs nicht, weil das eh schnell genug ist. Außerdem ist die relevante Tabelle eh gelockt für die Zeit des INSERTs was multi-Thread-INSERTs unterm Strich dann doch wieder eins nach dem anderen abarbeitet. Also, Empfehlung: Keine Threads für INSERTs verwenden, hat keinen Vorteil, macht deinen Code nur komplizierter.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:17 Uhr.

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