![]() |
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Aber um ganz sicher zu gehn, baust du dir einfach eine Form mit Memo, DB-Grid und je einem Sendeknopf für Execute/Open auf, mit den Komponenten, die du verwendest. (oder es gibt eine Test-/Demo-App des Komponentenherstellers) Da kannst du dann mit einer "vergleichbaren" Umgebung testen, wie in deinem Programm vorkommt und bemerkst auch schon beim Testen Sonderprobleme bezüglich deiner Umgebung. |
AW: ID nicht gefunden nach last_insert_rowid()
dazu habe ich den DBBrowser für SQL installiert und mit SQLite-DB-Tabellen experimentiert gem. Tutorials SQL. Damit habe ich auch die hier verwendeten SQL-Statements nachvollzogen, leider erst nach Finden der Lösung. Nichts destotrotz kann man ja weiter experimentieren und üben.
|
AW: ID nicht gefunden nach last_insert_rowid()
Der DBBrowser verhält sich wie der DBBrowser.
Ein selbst mit Delphi geschriebenes Programm, verhält sich wie alle selbst mit Delphi geschriebenen Programme. Der DBBrowser muss sich weder so wie ein Programm, dass Zeos nutzt verhalten, noch wie ein Programm des DBExpress nutzt. Du wirst sicherlich eine große Übereinstimmung erhalten, aber nicht zwingend eine unbegrenzte Portierbarkeit. In einem selbst geschriebenen Programm kannst Du genau sehen, wie sich ein selbst geschriebenes Programm in einer bestimmten Situation verhalten wird. Mit dem DBBrowser erfährst Du nur, dass es mit dem DBBrowser funktioniert und kannst mutmaßen, dass es höchstwahrscheinlich mit 'nem Eigenbau auch so funktionieren wird. Da Du aber gerade gemerkt hast, dass Du mit Zeos und DBExpress nicht zwingend ein gleiches Verhalten erwarten kannst, ist himitsus Vorschlag, was eigenes zu bauen, garnicht mal so verkehrt. Und da es Dir ja in erster Linie ums lernen geht, wäre ein eigener DBBowser ja sicherlich nicht unbedingt das ungeeignetste Projekt. Oder anders: Damit kannst Du genau die Unterschiede herausarbeiten und erfahren, wie Du sinnvollerweise vorgehst, um eben von den Unterschieden der Zugriffkomponenten wegzukommen. |
AW: ID nicht gefunden nach last_insert_rowid()
Die absolute Sicherheit gibt die Abfrage "SELECT MAX(ID) FROM ..." aber nun mal gar nicht in einer Multi-User-Umgebung mit hochfrequenten Eingaben.
Wer sagt denn, dass er seine ID des INSERT's bekommt und nicht die letzte eingefügte (und damit maximale) ID eines anderen Users? Da es in diesem Beispiel ja auch nicht über eine Transaktion geht funktioniert es so nicht zu 100%. Genau dafür haben DB-Systeme wie Firebird die RETURNING_VALUE im INSERT-Statement. |
AW: ID nicht gefunden nach last_insert_rowid()
Da kann ich nur voll zustimmen.
Allerdings sind wir in diesem Thread bei SQLite und das ist keine klassische Mehrbenutzerumgebung. Folglich müsste hier die LastInsertRowID ausreichen und funktionieren. Ich hätte nichts dagegen wenn SQLite RETURNING unterstützt, einfach aus Komforgründen. |
AW: ID nicht gefunden nach last_insert_rowid()
Alternativ kann man die ID eben auch selber füllen, vor abschicken des Posts die Sequenz abfragen, also im AfterInsert oder spätestens BeforePost(wenn NULL) holen und eintragen, so hat man da schon die richtige ID.
|
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
|
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Der Aufwand für so ein Programm ist nicht zu unterschätzen. Ich würde mal behaupten, dass so ein Programm zum Lernen auch nicht zielführend ist da viel zu aufwendig. |
AW: ID nicht gefunden nach last_insert_rowid()
jobo, Du schreibst
Zitat:
Delphi-Quellcode:
kam ich ohne Fehlermeldung weiter. Mit den Zeos-Komp. klappte es auf Anhieb mit LAST_INSERT_ROWID (). Leider gibt es bei dbExpress nicht die Einstellmöglichkeiten der Zeos-Komp.
qMain.SQL.Text := 'SELECT ID FROM KONTAKTE ORDER BY ID DESC LIMIT 1';
|
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Hatte eher an ein TMemo, ein TDBGrid, 'ne TDataSource, 'nen TDBNavigator gedacht. Für die Datenbankverbindung wird einmal Zeos genutzt und einmal DBExpress. (Und wer will nimmt auch noch die ADO-Komponenten, die sich auch wieder anders verhalten.) Durch ändern der Querykomponente des DataSet von TDataSource kann man dann zwischen den unterschiedlichen Datenbankkomponeten hin- und herschalten. Mir ging es eher darum ein Programm zu schreiben, das die vorhandenen Datenbankkomponenten nutzt und nicht ein Programm, das vollständig ohne die zu Delphi gehörenden Datenbankkomponenten auskommt. Dass man sowas "nicht mal eben" schreiben kann, ist vollkommen klar. |
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
|
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Also meine Sicht nochmal (ich hab keine Möglichkeit, es zu testen): Die Funktion last_insert_rowid() ist der "SQLite" Weg, diesen Wert zu bekommen. Dass es bei DB Express nicht funktioniert, ist vielleicht so, wir suchen nach workarounds. Aber zu Klarstellung: Die Funktion in der Form "select last_insert_rowid() from <tabelle>" ergibt für mich keinen Sinn, weil sie unabhängig von der Tabelle arbeitet und etwas/einen Wert zurückliefert, den es nicht pro Zeile gibt. ( Schön das sie mit zeos so funktioniert. ) Sinn ergäbe m.E. eine Abfrage "select last_insert_rowid();" Ende. Die Funktion liefert einen konstanten Wert, auch wenn in der Tabelle Millionen Datensätze stehen. siehe z.B. > ![]() Wenn nun hier vorgeschlagen wird, mit Sequenzen zu arbeiten, dann ist das bezogen auf SQLite schwierig. M.E. müsste es erst selbst implementiert / nachgebaut werden. SQLite bietet zwar "Sequenzen" im weitesten Sinne, aber eben nur eine einzige feste Implementierung in Form von Autoincrement. Die angesprochene "Returning Clause" dient in "großen Datenbanken", den Wert einer (oder mehr) beliebigen, eingefügten Spalte aus dem Insert zurückzuliefern. Das kann ein Wert aus einem Autoincrement sein, aus einer selbst angelegten Sequenz oder anderes. Hilft Dir in SQLite nicht, gibt's nicht. Mein Zitat gilt lediglich der Tatsache, dass ein light weight, single User System wie SQLite per Definition mit dem last_insert_rowid() Konstrukt auskommen kann und kein RETURNING unterstützen muss. Das gilt zumindest solange, wie es tatsächlich als Single User System eingesetzt wird. Ich kann mir eigentlich nicht vorstellen, dass die DBExpress Komponenten das nicht können, aber Du kannst folgendes ausprobieren: lege eine Hilfstabelle mit einem Datensatz an. Eine Spalte reicht, Typ egal.Vielleicht klappt damit dann der DBExpress Aufruf: "Select last_insert_rowid() from Hilfstabelle_mit_einem_Datensatz" (Natürlich nach mindestens einem Insert, und zwar egal in welche andere Tabelle) |
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
SQL-Code:
select LAST_INSERT_ROWID() from dual
Die Tabelle könnte dann ungefähr so aussehen:
SQL-Code:
Könnte man bei FireBird und Co. eigentlich auch machen, dann muss man da nicht immer nach einer passenden Alternative suchen und kann derartige Statements datenbankunabhängig nutzen.
create table dual (dummy Char(1));
insert into dual (dummy) values ('X'); |
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
- ein Datensatz eingefügt - noch gelöscht werden kann Selbstverständlich nachdem eben genau ein Datensatz drin ist. |
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Lies nochmal die vielen vorhergegehen Posts.
SQL-Code:
SELECT CAST(last_insert_rowid() AS INTEGER) AS ID
Da es ja in der DB keine Probleme gibt, aber bei unterschiedlichen Zugriffskomponenten, würde ich es nochmal mit einem CAST probieren, falls es einen "komischen" Typ zurück gibt, denn dbExpress einfach nur nicht mag. |
AW: ID nicht gefunden nach last_insert_rowid()
@himitsu
from weil dann egal welche Datenbank. Bei SQLite geht auch ein
Delphi-Quellcode:
Bei manchen anderen Datenbanken auch, bei Oracle nicht, bei FireBird auch nicht.
select funktion
Oracle kennt die Tabelle dual. Bei FireBird kann man dann RDB$Database nehmen, weil da immer ein Datensatz drin ist. Meine Idee war halt, nach Jobos Anregung, analog zu Oracle einfach "überall" eine Tabelle dual anzulegen. Damit wären dann SQLs zwischen Datenbanken portierbar und müssten nicht, abhängig von der Datenbank, gegen die ein Programm läuft, angepasst werden. Und da ich für gewöhnlich Software schreibe, bei der zur Entwicklungszeit die Zieldatenbank noch unbekannt ist, bzw. die Software datenbankunabhängig sein muss, halte ich das jetzt nicht unbedingt für eine so schlechte Idee. |
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Die "Erfindung" einer Eindatensatztabelle soll ja nur eine Krücke sein, um die DB Express Komponenten zu überlisten und zur klaglosen Arbeit zu bewegen. Ja, so ist das bei Oracle üblich. So machen es viele Oracle nach / analog (um kompatibler zu werden) Ja, eine solche Tabelle gibt es bei Firebird bereits wie von nahpets geschrieben, hatte ich verdrängt. Nein, ich bin mir nicht sicher, dass die DB-Express Kompos auf die Art überredet werden müssen, aber der Test dauert 1 Minute. Ja, vielleicht ist es nur ein Typproblem, hab den Faden verloren, welche Fehlermeldungen gab es? |
AW: ID nicht gefunden nach last_insert_rowid()
Hallo, war leider unterwegs und kann erst jetzt in die weitergeführte Diskussion einsteigen. Wenn gewünscht, würde ich das Prog. einstellen, damit es von Euch ggf. nachvollzogen werden kann. Es ist ja nur ein kleines Übungsprogramm für mich.
Habe eine völlig neue Tabelle Kontakte mit den gleichen Spalten erstellt und mit einem Datensatz gefüllt. Dann
Delphi-Quellcode:
eingefügt und neben dem ersten Datensatz nach Aufruf des Prog. einen neuen DS eingefügt. Es kommt erneut die bekannte Exception, dass er die ID nicht finden kann.
qMain.SQL.Text:='select last_insert_rowid() FROM KONTAKTE';
Einsetzen von
Delphi-Quellcode:
gleiche Exception.
SELECT CAST(last_insert_rowid() AS INTEGER) AS ID
Den Hinweis von jobo Zitat:
Wenn das Prog. gewünscht wird, stelle ich es ein. |
AW: ID nicht gefunden nach last_insert_rowid()
Häng' bitte den vollständigen Quelltext an.
Momentan bin ich nicht mehr in der Lage nachzuvollziehen, was denn hier jetzt in welcher Kombination wie gemacht wurde und wobei genau jetzt ein Fehler auftritt und wann nicht. Du hast doch 'nen DBBrowser installiert. Wenn Du wissen willst, was dashier
Delphi-Quellcode:
macht, dann führ' es doch im DBBrowser aus.
SELECT last_insert_rowid() AS ID
Ebenso gilt das hierfür: Wie sieht das Ergebnis im DBBrowser aus?
Delphi-Quellcode:
Was passiert, wenn Du nur einen Datensatz in der Tabelle KONTAKTE hast, und was passiert, wenn Du mehrere Datensätze in der Tabelle hast?
select last_insert_rowid() FROM KONTAKTE
|
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
[code]Select 1 from KONTAKTE;[code] Aber überleg vor dem Drücken auf "Feuer" mal, was Du für ein Ergebnis erwartest. Last_insert_rowid() verhält sich (hoffentlich) genauso wie die "1". Last_insert_rowid() ist scheinbar eine Funktion ohne Abhängigkeiten. In den Klammern wo gewöhnlich Parameter einer Funktion stehen steht nichts. Vergleichbar mit einer Funktion date() oder so, sie liefert die Zeit, ohne irgendwelche Abhängigkeiten. [am Rande: Wenn Du Dir die Doku (mal wirklich) anschaust, wirst Du feststellen, dass es doch einen Parameter für die Funktion gibt, "D" für Database. Braucht hier für das Verständnis nicht zu interessieren] Also: Ob "Select 1 from <meineTabelle>" oder "Select Last_Insert_RowID() from <meinTabelle>" Das Result ist nichts anderes als das an jeden Datensatz einmal der Rückgabewert 1 oder eben die letzte RowID geklebt wird. Wenn Du Tabellen mit Tausenden Datensätzen hast, ist leicht vorstellbar, dass es ziemliche Ressourcenverschwendung ist, für eine Zahl tausende Datensätze "abzuarbeiten". In der Realität ist es vielleicht nicht ganz so schlimm, weil von dem mglw. riesigen Ergbnis meist nur der erste Datensatz verwendet wird. Im Umkehrschluss reicht also das einmalige Abfragen der letzten ROWID, wie es schon mehrfach beschrieben wurde, indem entweder gar kein ..from meinetabelle.. verwendet wird oder wenn doch- für DB Express- dann bitte eine mit nur einem Datensatz. Ich vermute ich könnte noch viel schreiben, probier es einfach, schau dir die Ergebnisse an. Das sagt mehr als tausend Worte. Die letzte RowID wird nur in einer Instanz verwaltet und gilt für alle Tabellen in der "Datenbank" (sprich sqlite datei) "gleichzeitig". Denn es kann immer nur eine geben! Jenachem in welcher Tabelle zuletzt ein Datensatz eingefügt wurde, findest Du dessen RowID bei der Abfrage von Last_insert_rowid. |
AW: ID nicht gefunden nach last_insert_rowid()
Liste der Anhänge anzeigen (Anzahl: 1)
anbei das Programm mit der jungfräulichen Datenbank und der Tabelle KONTAKTE mit nur einem Datensatz.(bitte ggf. diese Datei sichern vor erster Probe)
Eigentlich war ich mit der funktionierenden Lösung ganz glücklich, sofern es kein Fehler wäre diese zu verwenden. Ich betone nochmals, ich will anhand dieses Programms lernen und möglichst nichts falsches lernen. Hoffentlich ist das was ich da geschrieben habe wirklich dafür geeignet. Leider muss ich mir das alles so zusammenklauben, denn so wirkliche Beispiele, anhand der ich prüfen könnte, ob ich richtig liege gibt es wohl nicht. Da bin ich daher sehr sehr dankbar, dass es hier im Forum Hilfe und Unterstützung gab und gibt. Ich habe ein Edit für die Eingabe von SQL-Statements an die bewußte Stelle eingefügt. Somit kann unabhängig von welcher Delphiversion auch immer das Problem nachvollzogen werden. Wenn beim Überfliegen des Prg. noch andere Ecken und Kanten auffallen, wäre ich für Hinweise dankbar und bereite mich schon auf einiges vor.... Bitte berücksichtigt, dass ich noch lerne und leider wenig wirklich geeignete Tutorials zu dem Thema gefunden habe. Nochmals ich habe nur auf die fortgeschriebene Diskussion geantwortet und die darin genannten Lösungsansätze probiert. Wenn es mit der funktionierenden Lösung ok ist, dann soll es so sein. Danke |
AW: ID nicht gefunden nach last_insert_rowid()
Liste der Anhänge anzeigen (Anzahl: 1)
Hallöle...:P
Ach Jungs...soviele Beiträge und ein Blick in die Dataset DefList hätte genügt. :P @EdAdvokat: Der der Debugger hilft dir solche Probleme zu analysieren. :thumb: Ich weiß das das nur zum Testen ist...aber die Logik dahinter verstehe icht nicht. :?
Delphi-Quellcode:
PS: Im SQL select last_insert_rowid() muß die Klammer angegeben werden!
procedure TMainFRM.btnuebernehmenClick(Sender: TObject);
var currentID: string; sqlstring: string; begin qMain.SQL.Clear; // da du mit SQL.Text arbeitest ist die Zeile überflüssig qMain.Params.Clear; // da du mit SQL.Text arbeitest ist die Zeile überflüssig sqlstring:=edtsqlstring.text; if flag then begin // currentID zuweisen currentID:=lv.Selected.Caption; // SQL mit Parametern qMain.SQL.Text:='UPDATE KONTAKTE SET NAME= :NAM, VORNAME= :VNA, GEB= :GEB, STRASSE= :STR, Nr= :NR, PLZ= :PLZ, ORT= :ORT, TEL= :TEL, EMAIL= :EMA, BEMERKUNG= :BEM WHERE ID=:CID'; qMain.ParamByName('CID').AsString:=currentID; qMain.ParamByName('NAM').AsString:=edtName.Text; qMain.ParamByName('VNA').AsString:=edtVorname.Text; qMain.ParamByName('GEB').AsString:=edtGeb.Text; qMain.ParamByName('STR').AsString:=edtStrasse.Text; qMain.ParamByName('Nr').AsString:=edtNr.Text; qMain.ParamByName('PLZ').AsString:=edtPLZ.Text; qMain.ParamByName('ORT').AsString:=edtOrt.Text; qMain.ParamByName('TEL').AsString:=edtTel.Text; qMain.ParamByName('EMA').AsString:=edtemail.text; qMain.ParamByName('BEM').AsString:=edtBemerkung.Text; // Ausführen des Update qMain.ExecSQL; // Listview neu einlesen refreshItems(currentID,edtName.Text,edtVorname.Text,edtGeb.Text,edtStrasse.Text,edtNr.Text,edtPLZ.Text,edtOrt.Text,edtTel.Text,edtemail.Text,edtBemerkung.Text); // Listview wieder leeren... Hä? :-) lv.Items.Clear; // Datenbank verbinden... Hä? :-) Die Verbindung wird im FormCreate gemacht. :-) Connect; end |
AW: ID nicht gefunden nach last_insert_rowid()
Bei 'nem
Delphi-Quellcode:
erwarte ich, dass die Ergebnisspalte ID heißt und nicht Column0.
SELECT last_insert_rowid() AS ID
|
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Ich tippe darauf das das mit der Funktion zusammenhängt. Auch die Klammern müssen sein. |
AW: ID nicht gefunden nach last_insert_rowid()
Ja, da der Quelltext aber erst seit ca. 'ner Stunde vorliegt, hat uns das gestern nicht so viel geholfen ;-)
|
AW: ID nicht gefunden nach last_insert_rowid()
Na und? Die muss doch trotzdem den Alias als Spaltennamen zurückgeben. Ich mache das BTW immer mit
![]() |
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
Oder es sind die Komponenten...:gruebel: Verstehe das wer will. :P Nachtrag: Zitat:
|
AW: ID nicht gefunden nach last_insert_rowid()
Den Fehler gibt es unter Zeos nicht.
Daher meine Behauptung: DBExpress ist für diese Aufgabe wohl nicht erste Wahl. |
AW: ID nicht gefunden nach last_insert_rowid()
Ich kann noch immer nicht erkennen, wo ich welche Klammer vergessen habe.
Das grundsätzliche Vorgehen, um mit SQLite eine DB-Anwendung zu schreiben habe ich mir von einem Youtube-Video von Andreas Hiller abgeschaut und da war immer die Rede von qMain.SQL.Clear; qMain.Params.Clear; usw. Danke Haentschmann ich werde das ganze nochmals überarbeiten. Das connect an der bewußten Stelle hat mir so richtig auch nicht gefallen, doch es war eine Lösung für die Darstellung nur des aktuell bearbeiteten Datensatzes ohne die anderen DS. Nach Bearbeiten wurde nur der bearbeitete DS danach dargestellt und die vorheriigen nicht mehr. Das refresh half auch nicht. Leider kann ich euren aha-Aufschrei nicht nachvollziehen. Was konkret habe ich falsch gemacht??? Ich habe nochmals nachgesehen und festgestellt, dass ich sowohl im Zeos-Komp. Programm als auch im dbExpress-Programm stets geschrieben habe: qMain.SQL.Text:='SELECT LAST_INSERT_ROWID() AS ID FROM KONTAKTE'; |
AW: ID nicht gefunden nach last_insert_rowid()
Es geht nicht darum, ob Du was falsch gemacht hast oder nicht, sondern darum ob es mit DBExpress geht oder nicht.
Der Fehler, der von Deine Exe geworfen wird, ist logisch nicht nachvollziehbar. Wenn man in 'nem SQL einen Alias für 'nen Spaltennamen angibt, also
Delphi-Quellcode:
schreibt, dann muss im Ergebnis die
select Funktion() as Spalte from Tabelle
Delphi-Quellcode:
funktionieren.
qMain.FieldByName('SPALTE').AsString
Wenn man in Deinem Programm also
Delphi-Quellcode:
eingibt, dann muss es im Ergebnis die Spalte ID geben, also
SELECT last_insert_rowid() AS ID
Delphi-Quellcode:
verfügbar sein.
qMain.FieldByName('ID').AsString
Dem ist aber nicht so. Das sieht für mich jetzt erstmal nach 'nem Fehler bei DBExpress aus, zumal das Ganze mit den Zeos-Komponenten ja funktioniert. Und dass die SQLite-Datenbank bei identischen Statements aber unterschiedlichen Komponenten unterschiedliche Ergebnisse liefert, halte ich für eher unwahrscheinlich. |
AW: ID nicht gefunden nach last_insert_rowid()
Du hast nichts falsch gemacht. :P Das mit der Klammer war nur ein Hinweis. :wink:
|
AW: ID nicht gefunden nach last_insert_rowid()
da fällt mir ein Stein vom Herzen. Ich dachte, ich liege wieder mal sowas von falsch. Wenn auch das Zeos-Prg. erforderlich sein sollte, bitte anmahnen. Es unterscheidet sich lediglich hinsichtlich des connect.
Alles andere ist identisch, natürlich ohne last_insert_rowId()... Es war wirklich nicht meine Absicht, Euch aufdringlich mit dem Problem zu belästigen, doch es scheint wohl was faul zu sein im Staate Delphi... |
AW: ID nicht gefunden nach last_insert_rowid()
Ist denn FireDAC bei der Professional nicht dabei? Falls doch, würde ich doch lieber das benutzen.
|
AW: ID nicht gefunden nach last_insert_rowid()
Liste der Anhänge anzeigen (Anzahl: 2)
Ich habe das mal in meinem eigenen SQLite Manager ausgeführt den ich gerade programmiere. Einmal mit Alias und einmal ohne. Ich steuere die Datenbank direkt über die SQLite3.dll an. Ohne Umweg über Zeos oder sonstige Fremdkomponenten. Folgendes kommt bei mir erwartungsgemäß dabei rum:
Anhang 47345 Anhang 47346 Hier noch ein Zitat von der SQLite Homepage: Zitat:
Zusätzliche Informationen gibt es dann noch hier: ![]() |
AW: ID nicht gefunden nach last_insert_rowid()
doch das ist dabei und ich könnte es damit auch mal versuchen. Braucht ein Zeitchen.
|
AW: ID nicht gefunden nach last_insert_rowid()
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:51 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-2025 by Thomas Breitkreuz