Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Wie kommt man an die ID des eingefügten Eintrages (https://www.delphipraxis.net/208439-wie-kommt-man-die-id-des-eingefuegten-eintrages.html)

kagi3624 29. Jul 2021 09:58

Datenbank: PostgreSQL • Version: 9.1.9 • Zugriff über: TZQuery

Wie kommt man an die ID des eingefügten Eintrages
 
Hallo, mit dem SQL Statement

Code:
INSERT INTO MYTABLE (first, second, last) values (val1, val2, val3) returning ID;
kann ich mir die ID des erzeugten Eintrages ausgeben lassen, zumindest zeigt es der DBeaver sofort an. Wie komme ich über TZQuery von Zeos in Delphi an die ID? Die Komponente ist von 2006, vielleicht kann man es damit garnicht?

tewes 29. Jul 2021 10:01

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Typischerweise (z.B. MySQL):
SELECT LAST_INSERT_ID();

kagi3624 29. Jul 2021 10:10

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von tewes (Beitrag 1492947)
Typischerweise (z.B. MySQL):
SELECT LAST_INSERT_ID();

Aber das ist doch schon in dem insert Statement schon drin mit dem return ID, vielleicht bin ich auch falsch hier in diesem Subforum?

Der schöne Günther 29. Jul 2021 10:11

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Das RETURNING liefert doch ein Ergebnis, genau wie eine SELECT-Query. Bekommst du da nichts zurück?

kagi3624 29. Jul 2021 10:18

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1492949)
Das RETURNING liefert doch ein Ergebnis, genau wie eine SELECT-Query. Bekommst du da nichts zurück?

Also, wenn ich das Statement im Delphi code ausführe mit der TZQuery Komponente, dann bekomme ich den Eintrag auch in die Datenbank, und es gibt auch keine Fehler, ich weiß aber nicht wie ich an die ID des eingefügten Eintrags komme. Ich dachte es ist ja schon irgendwie drin in der Query abgespeichert und ich muss es nur irgendwie abholen. So wenn man normal ein Select statement hat, würde man ja sowas haben:

Code:
i := zQuery.FieldByName('ID').AsInteger;
Hier wird mir aber gesagt, dass so ein Feld nicht existiert nach dem ausführen des Statements.

DeddyH 29. Jul 2021 10:22

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Wie wäre es mal mit etwas mehr Code?

kagi3624 29. Jul 2021 10:26

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von DeddyH (Beitrag 1492951)
Wie wäre es mal mit etwas mehr Code?

Code:
          aQuery.Close;
          aQuery.SQL.Clear;
          aQuery.SQL.Text := 'INSERT INTO MYTABLE (first, second, last) values (:val1, :val2, :val3) returning ID';
          aQuery.ParamByName('val1').AsInteger := 4;
          aQuery.ParamByName('val2').AsString  := 'bla';
          aQuery.ParamByName('val3').AsInteger := 100;
          aQuery.ExecSQL; //bis hier her funktioniert es

          i := aQuery.FieldByName('ID').AsInteger; // Feld nicht gefunden.

DeddyH 29. Jul 2021 10:47

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Versuch mal
Delphi-Quellcode:
aQuery.Open;
statt
Delphi-Quellcode:
aQuery.ExecSQL;

Ron67 29. Jul 2021 11:08

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Ich kenne das so:

letzteId := dmMain.connection.GetLastAutoGenValue('id');

DeddyH 29. Jul 2021 11:13

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Gibt es das unter ZEOS auch? Ich kenne es so nur bei FireDAC.

kagi3624 29. Jul 2021 11:30

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von DeddyH (Beitrag 1492954)
Versuch mal
Delphi-Quellcode:
aQuery.Open;
statt
Delphi-Quellcode:
aQuery.ExecSQL;

THX! Hat funktioniert!

Zitat:

Zitat von DeddyH (Beitrag 1492956)
Gibt es das unter ZEOS auch? Ich kenne es so nur bei FireDAC.

Zumindest bei meiner Komponente ging es nicht.

generic 29. Jul 2021 13:39

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Insert Befehle können mehrere Zeilen anlegen und Trigger dann noch mehr.
Es ist immer dann interessant, wenn LAST_INSERT_ID zum Einsatz kommt.
Zum einen wir ja nur eine ID zurück geliefert, auch wenn mehrere Datensätze eingetragen worden sind,
Zum anderen welche ID die vom Hauptdatensatz oder ggf. die letzte ID welche ein Trigger angelegt hat.

Viele SQLs sind um OUTPUT erweitert worden, so dass ein INSERT auch eine Tabelle zurück geben kann.

In PG wird das mit "RETURNING" erreicht:
https://www.postgresql.org/docs/9.5/sql-insert.html

Sinspin 29. Jul 2021 19:02

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Im Regelfall sollte man sein Insert doch so gestalten können das man danach mit einem Select in der Lage ist seinen Datensatz zu finden.
Zudem kennt man seine DB ja wohl so weit das man weis was beim Insert läuft und wieviele Datensätze erzeugt werden.
LastAutoInc ist zum Beispiel auch in FireDac nicht für alle DB implementiert die angesprochen werden können.

Rollo62 30. Jul 2021 07:17

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von Sinspin (Beitrag 1492980)
... das man danach mit einem Select ... LastAutoInc ...

Wenn das in einem 2-schrittigen Prozess, von aussen, gemacht wird,
dann könnte ja in der (Millisekunde) Zwischenzeit Jemand anderes einen neuen Record angelegt haben.
Dann stimmt dein LastAutoInc oder LastRecord nicht mehr.

DeddyH 30. Jul 2021 07:34

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zumindest MySQL gibt bei last_insert_id() die ID des letzten Datensatzes zurück, der in der aktuellen Verbindung angelegt wurde. In DBMS, die keine Möglichkeit einer RETURNING-Klausel bieten, muss das auch gewährleistet sein, sonst kann man sie ja faktisch nicht gebrauchen.

hstreicher 30. Jul 2021 11:32

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von kagi3624 (Beitrag 1492950)
Zitat:

Zitat von Der schöne Günther (Beitrag 1492949)
Das RETURNING liefert doch ein Ergebnis, genau wie eine SELECT-Query. Bekommst du da nichts zurück?

Code:
i := zQuery.FieldByName('ID').AsInteger;
Hier wird mir aber gesagt, dass so ein Feld nicht existiert nach dem ausführen des Statements.


ja , es wird ja kein Select ausgeführt also keine Ergebnisswerte zum Abfragen geöffnet

bei IbDac UniDac geht das So
Ii := zQuery.ParambyName('RET_ID').AsInteger;

das "RET_" wird von IBDac hinzugefügt

Sinspin 30. Jul 2021 13:38

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von Rollo62 (Beitrag 1492992)
Wenn das in einem 2-schrittigen Prozess, von aussen, gemacht wird,
dann könnte ja in der (Millisekunde) Zwischenzeit Jemand anderes einen neuen Record angelegt haben.
Dann stimmt dein LastAutoInc oder LastRecord nicht mehr.

Sorry. Das ist quatsch.
"von außen machen" : von außerhalb der Transaktion in der man gerade arbeitet wäre es wohl ein bisschen seltsam nach einem autoinc zu fragen.
"LastAutoInc" : ist bei allen DB mit denen ich zu tuen habe Session bezogen, oder kann Session/Active query bezogen abgefragt werden. Bei MSSQL gibt es dafür @@IDENTITY. Was andere DB dafür bereitstellen weis ich nicht. Aber vermutlich ähnliche Lösungen.

Rollo62 30. Jul 2021 14:39

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von Sinspin (Beitrag 1493006)
Zitat:

Zitat von Rollo62 (Beitrag 1492992)
Wenn das in einem 2-schrittigen Prozess, von aussen, gemacht wird,
dann könnte ja in der (Millisekunde) Zwischenzeit Jemand anderes einen neuen Record angelegt haben.
Dann stimmt dein LastAutoInc oder LastRecord nicht mehr.

Sorry. Das ist quatsch.

Gut zu wissen, es hörte sich für mich so an als ob das Jemand vorhätte :stupid:

Sinspin 30. Jul 2021 14:55

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Von außen wird das nix. Es sei denn, man kann sich ganz sicher sein das man den Record auch ohne AutoIncwert noch indentifizieren kann.
Zum Beispiel indem man beim Insert eine GUID in den neuen Record schreibt. Die ist ja (fast) Weltweit eindeutig. Geht also zum identifizieren. Allerdings ist son Ding ne ganz schöne Kanone.
Eine Id für den Nutzer plus eine selber hochgezählte Zahl tut es auch. Es gibt zig Möglichkeiten, man muss nur wollen :lol:

Delphi.Narium 30. Jul 2021 15:17

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zeos kennt auch auch noch TZSequence.

Der Komponente weist man die zu nutzende Datenbanksequenz zu.

Vor dem Insert holt man sich dort den nächsten Wert für die ID und übergibt den dann im Insert mit, so dass die Datenbank nicht die ID vergeben muss und man dann auf die Suche gehen muss, welche ID denn da wohl der eingefügte Satz bekommen haben könnte.

Sind in einem ExecSQL mehrere Inserts enthalten, holt man sich entsprechend viele Wert von der TZSequence und weist die dann in den Insertstatements entsprechend zu (Parameter).

Damit hat man dann weder ein Problem beim Ermitteln der ID für jeden der Datensätze, noch kann jemand anderes "quasi von außerhalb der eigenen Transaktion" die Sequenz für andere Aufgaben weiterzählen, so dass man beim Lesen des letzten Wertes der Sequenz dann ggfls. was falsches bekommen könnte (oder sowasinderart).

Für viele Inserts in einem ExecSQL setzt man bei TZSequence BlockSize auf die Anzahl der Inserts und holt dann den nächsten Wert. Damit sind dann dieser Wert plus die nächsten BlockSize - 1 Werte für einen reserviert und für andere nicht mehr vergebbar. Für z. B. 50 Inserts muss man also die Sequenz nicht 50 mal abfragen, sondern nur einmal mit BlockSize 50 und hat damit die nächsten 50 Ids in aufsteigender Folge für sich reserviert.

jobo 30. Jul 2021 16:24

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Es funktioniert doch!

Zitat:

Zitat von kagi3624 (Beitrag 1492959)
Zitat:

Zitat von DeddyH (Beitrag 1492954)
Versuch mal
Delphi-Quellcode:
aQuery.Open;
statt
Delphi-Quellcode:
aQuery.ExecSQL;

THX! Hat funktioniert!
..

Returning ist genau richtig dafür.

generic 31. Jul 2021 16:33

AW: Wie kommt man an die ID des eingefügten Eintrages
 
Zitat:

Zitat von Sinspin (Beitrag 1493006)
Bei MSSQL gibt es dafür @@IDENTITY. Was andere DB dafür bereitstellen weis ich nicht. Aber vermutlich ähnliche Lösungen.

Da würde ich auch die Finger von lassen. MSSQL hat dazu das OUTPUT Schlüsselwort bei insert, update, delete.
Bei MSSQL hat übrigens noch weitere gefährliche Variable z.B. scope_identity.

Für Datenbanken, welche keine OUTPUT, RETURNING Möglichkeiten haben, könnt ihr immer noch CURSOR einsetzen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:34 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