Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   LastRowID wie auslesen? (https://www.delphipraxis.net/181577-lastrowid-wie-auslesen.html)

AlexII 26. Aug 2014 20:22

Datenbank: SQLite • Version: 3 • Zugriff über: Lazarus, SQLite3Connection

LastRowID wie auslesen?
 
Hallo,

ich möchte die letzte eingefügte ID auslesen, aber ich scheitere an der Syntax und brauche Hilfe. Hier mein Code:

Delphi-Quellcode:
procedure TForm2.InsertNewJob();
begin
  Form1.SQLQuery1.Close;
  Form1.SQLQuery1.SQL.Text := 'INSERT INTO tbmain VALUES(NULL, :title, :start, :ende, :memo, :fk_category_id, NULL, NULL, :fk_status_id, NULL)';
  Form1.SQLQuery1.ParamByName('title').AsString := TitleEdit.Text;
  Form1.SQLQuery1.ParamByName('start').AsDateTime := StartDateEdit.Date;
  Form1.SQLQuery1.ParamByName('ende').AsDateTime := EndeDateEdit.Date;
  Form1.SQLQuery1.ParamByName('memo').AsString := Memo.Text;
  Form1.SQLQuery1.ParamByName('fk_category_id').AsInteger := Integer(CategoryComboBox.Items.Objects[CategoryComboBox.ItemIndex]);
  Form1.SQLQuery1.ParamByName('fk_status_id').AsInteger := 1;
  Form1.SQLQuery1.ExecSQL;
  Form1.SQLTransaction1.Commit;

  // Letze id auslesen
  Form1.SQLQuery1.Close;
  Form1.SQLQuery1.SQL.Text := 'SELECT last_insert_rowid() FROM tbmain';
  Form1.SQLQuery1.Open;
  showmessage(inttostr(last_insert_rowid())); // funktioniert nicht
end;
Nun an welcher Stelle und vor allem wie lese ich diese aus?

Sir Rufo 26. Aug 2014 20:25

AW: LastRowID wie auslesen?
 
http://www.delphipraxis.net/128882-l...-und-zeos.html

AlexII 26. Aug 2014 21:46

AW: LastRowID wie auslesen?
 
Danke!

himitsu 26. Aug 2014 22:31

AW: LastRowID wie auslesen?
 
Eventuell kennt das SQLQuery1 oder die Connection auch eine LastInsertRowId-Methode.

AlexII 27. Aug 2014 11:07

AW: LastRowID wie auslesen?
 
Zitat:

Zitat von himitsu (Beitrag 1269906)
Eventuell kennt das SQLQuery1 oder die Connection auch eine LastInsertRowId-Methode.

Da finde ich keine... habe das ganze in Lazarus mit ner SQLite DB.

Habe es jetzt wie folgt (siehe // Die letzte ID auslesen) gelöst. Aber die Lösung mit der LastRowID wird wohl mit anderen DBanken nicht funktionieren nehme ich an. Muss da wohl was anderes ausdenken, damit meine Anwendung auch mit MySQL später arbeiten kann.

Delphi-Quellcode:
procedure TForm2.InsertNewJob();
var
  CategoryLastID: Integer;
begin
  Form1.SQLQuery1.Close;
  Form1.SQLQuery1.SQL.Text := 'INSERT INTO tbmain VALUES(NULL, :title, :start, :ende, :memo, :fk_category_id, NULL, NULL, :fk_status_id, NULL)';
  Form1.SQLQuery1.ParamByName('title').AsString := TitleEdit.Text;
  Form1.SQLQuery1.ParamByName('start').AsDateTime := StartDateEdit.Date;
  Form1.SQLQuery1.ParamByName('ende').AsDateTime := EndeDateEdit.Date;
  Form1.SQLQuery1.ParamByName('memo').AsString := Memo.Text;

  // Kategorie nicht vorhanden und ComboBox nicht leer, also erst neue Kategorie in die DB schreiben
  if (CategoryComboBox.ItemIndex = -1) and (CategoryComboBox.Text <> '') and (CategoryComboBox.Items.IndexOf(CategoryComboBox.Text) = -1) then
  begin
    // String manuell reingeschrieben, String sonst in der CB nicht vorhanden
    // Kategorie in die Tabelle tbcategory schreiben
    Form1.SQLQueryCategory.Close;
    Form1.SQLQueryCategory.SQL.Text := 'INSERT INTO tbcategory VALUES(NULL, :category)';
    Form1.SQLQueryCategory.ParamByName('category').AsString := CategoryComboBox.Text;
    Form1.SQLQueryCategory.ExecSQL;
    Form1.SQLTransaction1.Commit;

    // Die letzte ID auslesen
    Form1.SQLQueryCategory.Close;
    Form1.SQLQueryCategory.SQL.Text := 'SELECT last_insert_rowid() as id_tbcategory FROM tbcategory';
    Form1.SQLQueryCategory.Open;
    CategoryLastID := Form1.SQLQueryCategory.FieldByName('id_tbcategory').AsInteger;
    Form1.SQLQuery1.ParamByName('fk_category_id').AsInteger := CategoryLastID;

  end else if (CategoryComboBox.ItemIndex = -1) and (CategoryComboBox.Items.IndexOf(CategoryComboBox.Text) <> -1) then
  begin
    // String manuell reingeschrieben, String in der CB vorhanden
    Form1.SQLQuery1.ParamByName('fk_category_id').AsInteger := Integer(CategoryComboBox.Items.Objects[CategoryComboBox.Items.IndexOf(CategoryComboBox.Text)]);
  end else if CategoryComboBox.ItemIndex <> -1 then
  begin
    // String in der CB ausgewählt
    Form1.SQLQuery1.ParamByName('fk_category_id').AsInteger := Integer(CategoryComboBox.Items.Objects[CategoryComboBox.ItemIndex])
  end;

  Form1.SQLQuery1.ParamByName('fk_status_id').AsInteger := 1;
  Form1.SQLQuery1.ExecSQL;
  Form1.SQLTransaction1.Commit;
end;

Eine andere Frage... wenn ein Feld leer ist, muss ich in die DB ein NULL schreibe, oder reicht es wenn ich das Attribut gar nicht anfasse?

mkinzler 27. Aug 2014 11:13

AW: LastRowID wie auslesen?
 
Bei Parametern muss man vorsichtig sein, möglicherweise wird dann der Feld vom letzten Vorgang genommen. Also besser explizit auf NULL setzen.

AlexII 27. Aug 2014 11:20

AW: LastRowID wie auslesen?
 
Zitat:

Zitat von mkinzler (Beitrag 1269949)
Bei Parametern muss man vorsichtig sein, möglicherweise wird dann der Feld vom letzten Vorgang genommen. Also besser explizit auf NULL setzen.

Ok, sag ma wie mache ich das? Etwa so? Will aber irgendwie nicht so recht...

Delphi-Quellcode:
Form1.SQLQuery1.ParamByName('fk_category_id').AsInteger := nil;

DeddyH 27. Aug 2014 11:23

AW: LastRowID wie auslesen?
 
IIRC:
Delphi-Quellcode:
ParamByName('fk_category_id').Clear;

himitsu 27. Aug 2014 11:28

AW: LastRowID wie auslesen?
 
Oder so
Delphi-Quellcode:
Form1.SQLQuery1.ParamByName('fk_category_id').Value := nil;
, aber Clear ist schon schöner.

Zitat:

Zitat von AlexII (Beitrag 1269950)
Etwa so? Will aber irgendwie nicht so recht...

Irgendwie?
Da steht doch genau in der Fehlermeldung drin, was da nicht geht.

Oder würdest du auch ein
Delphi-Quellcode:
Form1.SQLQuery1.ParamByName('fk_category_id').AsInteger := 'abc';
oder
Delphi-Quellcode:
Form1.SQLQuery1.ParamByName('fk_category_id').AsString := 123;
veruchen?



Eine weitere Frage ist aber auch:
Warum ist der ganze Code in TForm2 drin, obwohl über 50% der Zugriffe auf TForm1 gehen?
Das würde doch wohl eher in eine Methode der TForm1 gehören und die Werte z.B. als Parameter übergeben. :angel2:

AlexII 27. Aug 2014 11:28

AW: LastRowID wie auslesen?
 
Zitat:

Zitat von DeddyH (Beitrag 1269951)
IIRC:
Delphi-Quellcode:
ParamByName('fk_category_id').Clear;

Danke :thumb:

p80286 27. Aug 2014 11:38

AW: LastRowID wie auslesen?
 
[QUOTE=AlexII;1269947]
Delphi-Quellcode:
    Form1.SQLQuery1.ParamByName('fk_category_id').AsInteger := Integer(CategoryComboBox.Items.Objects[CategoryComboBox.ItemIndex])
Das halte ich nicht für optimal. Die möglichen Werte für
Code:
fk_category_id
sollten aus der DB kommen und nicht aus Deinem Programm. Das kann gut gehen, dafür muß aber sicher gestellt werden, daß
Code:
fk_category_id
und
Delphi-Quellcode:
Integer(CategoryComboBox.Items.Objects[CategoryComboBox.ItemIndex])
immer gleich sind (für gleiche zugehörige Inhalte).

Null-Werte würde ich nicht über Parameter, sondern explizit übergeben:
Code:
 'INSERT INTO tbcategory VALUES(NULL, NULL)'
Gruß
K-H

AlexII 27. Aug 2014 12:12

AW: LastRowID wie auslesen?
 
Jah... da muss man sehr aufpassen, aber ich habe alles soweit logisch durchgespielt, es muss gehen. So lade ich die ComboBoxen:

Delphi-Quellcode:
  // Kategorie laden
  Form2.CategoryComboBox.Clear;
  Form2.CategoryComboBox.Items.AddObject(' ', TObject(0));
  SQLQuery1.Close;
  SQLQuery1.SQL.Text := 'SELECT id_tbcategory, category FROM tbcategory';
  SQLQuery1.Open;
  while not SQLQuery1.Eof do
  begin
    Form2.CategoryComboBox.Items.AddObject(SQLQuery1.FieldByName('category').AsString, TObject(SQLQuery1.FieldByName('id_tbcategory').AsInteger));
    SQLQuery1.Next;
  end;
Auch wenn in der ComboBox was gelöscht wird, kommen die IDs nicht durcheinander.

mkinzler 27. Aug 2014 12:57

AW: LastRowID wie auslesen?
 
Zitat:

Null-Werte würde ich nicht über Parameter, sondern explizit übergeben
Oder gleich weglassen
Statt
SQL-Code:
INSERT INTO tabelle VALUES( NULL, :Wert);
SQL-Code:
INSERT INTO tabelle Wert VALUES(:Wert);

DeddyH 27. Aug 2014 13:13

AW: LastRowID wie auslesen?
 
Dann musst Du aber auch die Felder angeben:
Delphi-Quellcode:
INSERT INTO tabelle(Feld1, Feld2) VALUES(:Wert1, :Wert2);

mse1 27. Aug 2014 16:35

AW: LastRowID wie auslesen?
 
Zitat:

Zitat von AlexII (Beitrag 1269947)
Zitat:

Zitat von himitsu (Beitrag 1269906)
Eventuell kennt das SQLQuery1 oder die Connection auch eine LastInsertRowId-Methode.

Da finde ich keine... habe das ganze in Lazarus mit ner SQLite DB.

Die Funktion heisst
Delphi-Quellcode:
TSQLite3Connection.GetInsertID().
Die MSEgui SQLdb Version schreibt die serverseitig generierten Werte übrigens automatisch in die Feldwerte zurück, entweder mittels "LASTINSERTID" für primary keys oder der "RETURNING" clause im SQL statement für beliebige Felder.

UliTs 25. Nov 2020 13:17

AW: LastRowID wie auslesen?
 
Ich habe ein ähnliches Problem, wenn ich mittels Insert / Post einen Datensatz anlege und RowId des neu angelegten Datensatzes bestimmen möchte:
Code:
FDQuery.Insert;
FDQuery.FieldByName( 'Name' ).value := 'Müller';
...
FDQuery.Post;

RowId := FDConnection.ExecSQLScalar( 'select top 1 LastRowId() LastRowId from Personen' );
Da kommt leider immer nur #0#0#0#0... heraus. Was mache ich falsch?

DeddyH 25. Nov 2020 13:20

AW: LastRowID wie auslesen?
 
Das sieht nach FireDAC aus, dann versuch mal:
Delphi-Quellcode:
FDConnection.GetLastAutoGenValue('');

UliTs 25. Nov 2020 20:04

AW: LastRowID wie auslesen?
 
Klappt leider nicht :( . NULL ist der Rückgabewert.

DeddyH 25. Nov 2020 20:14

AW: LastRowID wie auslesen?
 
Hat denn die Tabelle einen Primärschlüssel, der automatisch hochgezählt wird?

UliTs 25. Nov 2020 20:51

AW: LastRowID wie auslesen?
 
Nein, hat sie nicht. Das Problem ist, dass ich die Datenstruktur nicht so einfach ändern kann, da mit einem alten Programm noch mindestens 7 Monate (parallel über den Datenbankserver) darauf zugegriffen werden muß und das alte Programm äußerst empfindlich auf Änderungen in den Tabellen reagiert :shock: . Deshalb auch der Lösungsansatz über LastRowId() (es handelt sich um den Advantage DataBase Server).
Folgendes funktioniert:

Code:
cRowId := FDConnection.ExecSQLScalar(
'insert into TableName( Name ) values( ''Müller'' );'+
'select top 1 LastRowId() LastRowId from TableName' );
Nur ich brauche eine Lösung mittels FDQuery.Insert...FDQuery.Post und anschließend die RowId.
Vielleicht habe ich einen Fehler, wenn FDQuery.Post ausgeführt wird (da passiert noch einiges mehr) und dadurch die RowId nicht mehr verfügbar ist...
Mal sehen, was ich heute Nacht oder morgen noch hinbekomme 8-) .

mkinzler 26. Nov 2020 09:48

AW: LastRowID wie auslesen?
 
Zitat:

Das Problem ist, dass ich die Datenstruktur nicht so einfach ändern kann, da mit einem alten Programm noch mindestens 7 Monate (parallel über den Datenbankserver) darauf zugegriffen werden muß ...
Das sollte grundsätzlich kein Problem sein. Ein weiteres Feld als PK deklarieren und dieses automatisch beim Insert per autoinc oder durch einen Trigger füllen lassen. Das bekommt das Programm dann nicht mit.

joachimd 26. Nov 2020 11:28

AW: LastRowID wie auslesen?
 
Zitat:

Zitat von UliTs (Beitrag 1477978)
(es handelt sich um den Advantage DataBase Server)

Mönsch, sag das doch gleich ... oben steht SQLite!?
Code:
qu.sql.text := 'insert into TableName( Name ) values( ''Müller'' );'+
               'select LastRowId() from system.iota;';
qu.open;
lastid := qu.fields[0].asstring;
qu.close;

UliTs 29. Nov 2020 23:01

AW: LastRowID wie auslesen?
 
Zitat:

Zitat von joachimd (Beitrag 1478003)
Zitat:

Zitat von UliTs (Beitrag 1477978)
(es handelt sich um den Advantage DataBase Server)

Mönsch, sag das doch gleich ...

Hallo Joachim,
Ja, aber Deine Lösung entspricht fast zu 100% der meinigen von Beitrag 20. Ich habe aber Firedac im Einsatz. Dabei benutze ich TDBNavigator in Verbindung mit TFDQuery und TDataSource zum Navigieren. Und wenn der User dabei auf speichern klickt, kann ich erst wieder beim afterPost-Ereignis eingreifen. Oder gibt es noch eine Lösung, wie ich z.B. die "Speicher-Query" anpassen kann?

Viele Grüße

Uli

joachimd 30. Nov 2020 19:52

AW: LastRowID wie auslesen?
 
Hi Uli,
Zitat:

Zitat von UliTs (Beitrag 1478163)
Ja, aber Deine Lösung entspricht fast zu 100% der meinigen von Beitrag 20. Ich habe aber Firedac im Einsatz. Dabei benutze ich TDBNavigator in Verbindung mit TFDQuery und TDataSource zum Navigieren. Und wenn der User dabei auf speichern klickt, kann ich erst wieder beim afterPost-Ereignis eingreifen. Oder gibt es noch eine Lösung, wie ich z.B. die "Speicher-Query" anpassen kann?

Sry, habe ich echt überlesen :(
Ich habe mit FireDAC nicht auf ADS zugegriffen, von daher kann ich die Frage nicht im Allgemeinen beantworten. Du könntest aber evtl eine Ableitung davon machen und den obigen Part hinzufügen. Soweit ich weiß, nutzte Dmitry damals nur pures SQL zum Schreiben der Treiber.

UliTs 1. Dez 2020 10:04

AW: LastRowID wie auslesen?
 
Macht nichts. :-D.

Ich habe leider noch nicht herausgefunden. Wie das TFDQuery.Post programmiert ist. In der Query steht ja "nur" eine select-Anweisung. Aber wie wird die Update oder Insert Anweisung von TDFQuery generiert? Ist der Quellcode dazu offengelegt?


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:23 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 by Thomas Breitkreuz