Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi ZEOS und Last_Insert nach Insert (https://www.delphipraxis.net/195006-zeos-und-last_insert-nach-insert.html)

Ghostwalker 26. Jan 2018 03:41

Datenbank: SQLite-3 • Version: 3.8.7 • Zugriff über: ZEOS 7.0.2

ZEOS und Last_Insert nach Insert
 
Moinsen,

bin grad einwenig am verzweifeln.

Ich füge mit folgender Methode einen Datensatz in eine Tabelle ein:

Delphi-Quellcode:
  inherited Insert;
  if (fstate = rsNew) then
  begin
    fsql.SQL.Text := 'INSERT INTO actionarea (areaname,areadescr) VALUES(:areaname,:areadescr);';
    fsql.ParamByName('areaname').AsString := fname;
    fsql.ParamByName('areadescr').AsString := fdescr;
    fsql.ExecSQL;
    fsql.Connection.Commit;
    faaid := GetInsertedId;
    findex := faaid;
    fstate := rsNone;
  end;
fsql ist dabei eine TZQuery. :) Um nun den Primärschlüssel (autoincrement) zu ermitteln, hab ich in der
Basisklasse die Methode GetInsertId implementiert:

Delphi-Quellcode:
  result := -1;
  fsql.SQL.Clear;
  fsql.Params.Clear;
  fsql.SQL.Text := 'SELECT last_insert_rowid() as last FROM :table;';
  fsql.Prepare;
  fsql.ParamByName('table').AsString := ftable;
  fsql.Open;
  if not fsql.Eof then
  begin
    fsql.First;
    result := fsql.FieldByName('last').AsInteger;
  end;
  fsql.Close;
end;
ftable ist dabei in Feld, das beim erzeugen der abgeleiteten Instanz entsprechend gesetzt wird.

Problem ist nun, das ich genau beim fsql.open eine Exception "SQL logic error or missing database" bekomme.
Die Datenbankverbindung ist jedoch da, der Datensatz wird auch brav eingefügt. Ich hab auch die Abfrage "last_insert..." manuell ausgeführt (natürlich den entsprechenden Tabellenamen eingefügt). Da funktioniert das ganze wunderbar. Woran kann das noch liegen ?

hoika 26. Jan 2018 05:50

AW: ZEOS und Last_Insert nach Insert
 
Hallo,
lass das Prepare einfach weg und übergib den Tabellennamen ohne Parameter.

DeddyH 26. Jan 2018 06:28

AW: ZEOS und Last_Insert nach Insert
 
AFAIK muss man den Tabellennamen überhaupt nicht angeben. Aus der Doku:
Zitat:

The sqlite3_last_insert_rowid(D) interface usually returns the rowid of the most recent successful INSERT into a rowid table or virtual table on database connection D.

Ghostwalker 26. Jan 2018 06:39

AW: ZEOS und Last_Insert nach Insert
 
ok....jetzt tuts (also ohne Parameter und Tabellenname).:shock:

Aber komisch ists trotzdem, das es im SQLiteStudio und im SQLiteBrowser mit Tabellenname direkt funktioniert.

Fällt wohl in die Kategorie "ok..muss ich jetzt nicht verstehen" :)

Danke euch beiden.

Delphi.Narium 26. Jan 2018 10:19

AW: ZEOS und Last_Insert nach Insert
 
Man kann Tabellennamen nicht per Parameter übergeben!

Dashier geht nicht:
Delphi-Quellcode:
 fsql.SQL.Text := 'SELECT last_insert_rowid() as last FROM :table;';
Per Parameter kann man nur Werte für die Where-Bedingung übergeben, so wie es beim Insert gemacht wurde.

Dashier würde ebenfalls scheitern:
Delphi-Quellcode:
inherited Insert;
  if (fstate = rsNew) then
  begin
    fsql.SQL.Text := 'INSERT INTO :table (areaname,areadescr) VALUES(:areaname,:areadescr);';
    fsql.ParamByName('table').AsString := 'actionarea';
    fsql.ParamByName('areaname').AsString := fname;
    fsql.ParamByName('areadescr').AsString := fdescr;
    fsql.ExecSQL;
    fsql.Connection.Commit;
    faaid := GetInsertedId;
    findex := faaid;
    fstate := rsNone;
  end;
Das Problem ist also nicht die Nutzung des Tabellennamens im Statement überhaupt, sondern die Übergabe des Tabellennamens als Parameter.

Bernhard Geyer 26. Jan 2018 10:49

AW: ZEOS und Last_Insert nach Insert
 
Das ist AsDesigned. Das dürfte bei fast keinem DBMS funktionieren.
Wenn man SQL-Statements parametrisiert verwenden will, führt die Datenbank ein Prepare darauf aus.
Kenn es die beteiligten Tabellen nicht, kann das nicht durchgeführt werden da ja die DB nicht weiß was sie überhaupt machen soll.

hoika 26. Jan 2018 11:02

AW: ZEOS und Last_Insert nach Insert
 
Hallo,
Zitat:

dass es im SQLiteStudio und im SQLiteBrowser mit Tabellenname direkt funktioniert.
Tut es nicht, wird intern abgefangen.

Stevie 26. Jan 2018 14:11

AW: ZEOS und Last_Insert nach Insert
 
Wenn ZEOS/SQLite das unterstützen würde, könnte man das insert und das select last_insert_rowid() direkt in einem Rutsch ausführen.
Das würde auch das Risiko vermindern, dass über die gleiche Connection möglicherweise zwischenzeitlich in weiteres insert passiert und die ID verfälscht.

Zitat:

Zitat von SQLite Dokumentation
If a separate thread performs a new INSERT on the same database connection while the sqlite3_last_insert_rowid() function is running and thus changes the last insert rowid, then the value returned by sqlite3_last_insert_rowid() is unpredictable and might not equal either the old or the new last insert rowid.

Für MySQL hab ich das vor ein paar Monaten mal eingebaut - Link

Ghostwalker 26. Jan 2018 15:33

AW: ZEOS und Last_Insert nach Insert
 
Ok...danke für die Aufklärung :)

Aber wenns so nicht tut, dann spiel ich halt das Spiel mit Bergen und Propheten :)

Über
Code:
SELECT seq FROM sqlite_sequence WHERE (name=:table);
sollte das ganze gehen, denk ich. Da besagte Tabelle(n) über AUTOINCREMENT die ID bauen.

jobo 26. Jan 2018 16:23

AW: ZEOS und Last_Insert nach Insert
 
Zitat:

Zitat von Ghostwalker (Beitrag 1392156)
Über
Code:
SELECT seq FROM sqlite_sequence WHERE (name=:table);
sollte das ganze gehen, denk ich.

Denke nicht, wieder spielt hier der Tabellenname keine Rolle.
Kann es grad nicht ausprobieren, wenn es nicht geht, dann eher so:
Code:
SELECT seq FROM sqlite_sequence ;
P.S.: Die Variante mit der Code Änderung von Stevie ist natürlich top.
Alle die Krücken mit der last insert id sind m.E. immer für Ärger geeignet.
Ausnahme bei Verwendung mit einer Sitzung alleine, also für sqlite je nach Einsatzzweck okay.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:34 Uhr.
Seite 1 von 2  1 2      

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-2025 by Thomas Breitkreuz