Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi id des soeben angelegten Datensatzes? (https://www.delphipraxis.net/202601-id-des-soeben-angelegten-datensatzes.html)

SearchBot 21. Nov 2019 16:01

Datenbank: MS-SQL • Version: Express2014 • Zugriff über: ADO

id des soeben angelegten Datensatzes?
 
Hallo,

ich arbeite mich gerade in die Wissenschaft der Datenbanken ein. Ich habe hier Microsoft SQL Server Express Edition (64-bit, Version 12.0.6108 SP3) zur Verfügung, Datenbank erstellte/beobachte ich mit dem Microsoft SQL Server Management Studio.

:!: Ich versuche seit Tagen die id des soeben erfolgreich mit Insert angelegtem Datensatz auszulesen.

Die OH ist leider unverständlich für mich, aus verschiedenen Foren habe ich allerlei erfolglos versucht (ich sollte "allerlei" vielleicht beschreiben, da es aber zu nichts führte... :roll: ). Ich las, daß nach dem Insert der Zeiger auf dem Datensatz stünde - ja das ist fein, aber ich weiß trotzdem nicht, wie ich dann daraus die automatisch erstellte id ermittle (ADOQuery.recNo sagt 1 aber das ist nicht der Wert von id)!?

Wenn das Projekt fertig ist, werden ca. 10 Clients mitunter gleichzeitig Datensätze anlegen - folglich sollte ich nicht einfach die zuletzt generiert id auslesen, sondern diejenige, die ich gerade selbst generiert habe. Ich habe gelesen, daß die Datensätze clientbezogen angelegt werden und deshalb nichts durcheinander kommen kann - aber trotzdem kann ich ja nicht einfach fragen, welches ist die letzte id, denn die könnte ja 1 µs nach meiner id angelegt worden sein und bekomme dann die falsche id-Nummer... (bin mir da nicht sicher)

Mit einem nachfolgenden
Delphi-Quellcode:
db.ADOQuery.SQL.Text:='SELECT max(id) FROM tabelle';
und ExecSQL bzw. Open weiß ich aber nicht, wie/wo ich das Ergebnis lesen kann...

Für Euch sind das bestimmt Basics :oops: ich lerne das aber erst :|

Vereinfacht dargestellt mache ich so das Insert (das auch funktioniert):
Delphi-Quellcode:
   db.ADOQuery.paramCheck:=true;
   db.ADOQuery.SQL.Text:='INSERT into Tabelle (foo1,foo2,foo3) '+
                         'Values (:foo1,:foo2,:foo3) ';

   db.ADOQuery.Parameters.ParamByName('foo1').Value:=s;
   db.ADOQuery.Parameters.ParamByName('foo2').Value:=strtoint(copy(s,3,2));
   db.ADOQuery.Parameters.ParamByName('foo3').Value:=strtoint(copy(s,1,2));

   db.ADOQuery.ExecSQL;
Danach versuchte ich es zunächst mit
Delphi-Quellcode:
   idstring:=db.ADOQuery['id'];
Die Fehlermeldung sagt aber nur "Das Feld 'id' wurde nicht gefunden" - ist aber sehr wohl in der Tabelle vorhanden als primary key.

Sowas wie
Delphi-Quellcode:
RETURN id
in die SQL-Anfrage zu notieren, bringt mir einen anderen Fehler ein und geht auch nicht.

:?: Ich vermute aber, ich muss nach dem ExecSQL noch was dazuschreiben...?
Delphi-Quellcode:
SELECT max(id) FROM tabelle
hilft mir auch nicht, weiß nicht wie ich das Ergebnis lese...

Oder wird in der ADOQuery-Komponente etwas automatisch aktualisiert, woraus ich die id ganz einfach auslesen kann?
Ich brauche die id, um diesen Datensatz in weiteren Datensätzen anderer Tabellen zu verknüpfen.

Ich habe auch noch ADOCommand, ADOTable, ADODataset, ADOConnection und Datasource zur Verfügung, die ich aber ohne Komponenten erst zu Laufzeit initialisiere und "verdrahte".
Gibt es vielleicht nach dem ExecSQL auch dort irgendwo eine Wertaktualisierung??

Was kann ich tun oder wie geht es bitte?

KodeZwerg 21. Nov 2019 16:17

AW: id des soeben angelegten Datensatzes?
 
Da SQL ein riesiges Thema ist, antworte ich in Form einer bereits diskutierten Variante: Stackoverflow Link

Da steht Dein Thema aus vielen Gesichtspunkten beantwortet :-)

Grüße

hoika 21. Nov 2019 16:24

AW: id des soeben angelegten Datensatzes?
 
Hallo,
Zitat:

SELECT max(id) FROM tabelle hilft mir auch nicht, weiß nicht wie ich das Ergebnis lese...
Geht schon mit
Query.Open;
Id:= Query.Fields[0].AsInteger


Aber ob das wirklich dein Eintrag ist, oder der des Nachbarn, der kurz nach dir etwas eingetragen hat ...
Ich gehe immer über Sequenzen, lasse mir also vor dem Insert eine neue Nummer geben.

BeiMS-SQL kannst du das Feld auch mit dem Feldtyp Identity angeben.
Den Wert bekommst Du hiermit:
https://stackoverflow.com/questions/...f-inserted-row

jobo 21. Nov 2019 16:57

AW: id des soeben angelegten Datensatzes?
 
Ich glaube der Standard könnte die RETRUN Anweisung sein, die solche ID zurückliefert.
Bei ms sql gibt es jedenfalls dafür die OUTPUT Clause.
Bedeutet, ein Insert liefert seine neue ID selbst zurück (sofern es entsprechend mit OUTPUT Clause formuliert ist)

EmWieMichael 21. Nov 2019 17:33

AW: id des soeben angelegten Datensatzes?
 
Ich mach das so...

Delphi-Quellcode:
Query.SQL.Add('INSERT INTO TABELLE ... VALUES ...');
Query.SQL.Add('SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]');
Query.Open;
if (Query.RecordCount = 1) then
 begin
   RecID:=Query.Fields.FieldByName('SCOPE_IDENTITY').AsString;
   ...
 end;

Redeemer 21. Nov 2019 23:53

AW: id des soeben angelegten Datensatzes?
 
Die Lösung von EmWieMichael ist mMn die korrekte, so mache ich das auch.

Der Fehler vom TE kommt daher, dass es in der Query
Code:
SELECT max(id) FROM tabelle
keinen Spaltennamen id gibt, er aber versucht, darauf zuzugreifen. Ist aber wie gesagt auch der falsche Ansatz, denn genau dafür gibt es IDENTITY. Beachte, dass man Identitätsfelder nicht selbst schreiben kann. Kennt man von MySQL anders.

EmWieMichael 22. Nov 2019 07:40

AW: id des soeben angelegten Datensatzes?
 
Zitat:

Zitat von Redeemer (Beitrag 1451737)
...
Beachte, dass man Identitätsfelder nicht selbst schreiben kann. Kennt man von MySQL anders.


Doch, geht auch mit MSSQL; die DB wäre für mich sonst auch unbrauchbar:
Delphi-Quellcode:
Query.SQL.Add('SET IDENTITY_INSERT TABELLE ON');
Query.SQL.Add('INSERT INTO TABELLE ... VALUES ...');
Query.SQL.Add('SET IDENTITY_INSERT TABELLE OFF');
Query.ExecSQL;
Result:=(Query.RowsAffected = 1);

SearchBot 22. Nov 2019 14:16

erledigt: id des soeben angelegten Datensatzes?
 
:thumb: Dankeschön an alle, die Empfehlung von EmWieMichael trifft es genau.
:kiss:


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