Delphi-PRAXiS
Seite 6 von 8   « Erste     456 78      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   ID nicht gefunden nach last_insert_rowid() (https://www.delphipraxis.net/192717-id-nicht-gefunden-nach-last_insert_rowid.html)

Aviator 15. Mai 2017 21:33

AW: ID nicht gefunden nach last_insert_rowid()
 
Zitat:

Zitat von nahpets (Beitrag 1371502)
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.

:thumb:

jobo 16. Mai 2017 00:02

AW: ID nicht gefunden nach last_insert_rowid()
 
Zitat:

Zitat von EdAdvokat (Beitrag 1371457)
jobo, Du schreibst
Zitat:

Allerdings sind wir in diesem Thread bei SQLite und das ist keine klassische Mehrbenutzerumgebung.
Folglich müsste hier die LastInsertRowID ausreichen und funktionieren.
LAST_INSERT_ROWID () funktionierte jedoch nicht. Lediglich mit dem SQL-Statement
Delphi-Quellcode:
qMain.SQL.Text := 'SELECT ID FROM KONTAKTE ORDER BY ID DESC LIMIT 1';
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.

Ja, hab ich verstanden, dass es nicht funktioniert.

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. > http://www.w3resource.com/sqlite/cor...sert_rowid.php

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)

nahpets 16. Mai 2017 01:02

AW: ID nicht gefunden nach last_insert_rowid()
 
Zitat:

Zitat von jobo
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)

Die Idee finde ich gut, ist letztlich nix anderes als bei Oracle.

SQL-Code:
select LAST_INSERT_ROWID() from dual


Die Tabelle könnte dann ungefähr so aussehen:
SQL-Code:
create table dual (dummy Char(1));
insert into dual (dummy) values ('X');
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.

jobo 16. Mai 2017 06:27

AW: ID nicht gefunden nach last_insert_rowid()
 
Zitat:

Zitat von nahpets (Beitrag 1371542)
Die Tabelle könnte dann ungefähr so aussehen:

Ja, man sollte aber sicherheitshalber- wenn es über einen Test hinaus geht und man das ernsthaft einsetzen will- noch ein paar brauchbare Constraints draufpacken, sodass weder versehentlich
- ein Datensatz eingefügt
- noch gelöscht werden kann

Selbstverständlich nachdem eben genau ein Datensatz drin ist.

himitsu 16. Mai 2017 07:34

AW: ID nicht gefunden nach last_insert_rowid()
 
Zitat:

Zitat von nahpets (Beitrag 1371542)
SQL-Code:
select LAST_INSERT_ROWID() from dual

Wieso das FROM?

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.

nahpets 16. Mai 2017 09:29

AW: ID nicht gefunden nach last_insert_rowid()
 
@himitsu

from weil dann egal welche Datenbank.

Bei SQLite geht auch ein
Delphi-Quellcode:
select funktion
Bei manchen anderen Datenbanken auch, bei Oracle nicht, bei FireBird auch nicht.

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.

jobo 16. Mai 2017 09:46

AW: ID nicht gefunden nach last_insert_rowid()
 
Zitat:

Zitat von himitsu (Beitrag 1371552)
Zitat:

Zitat von nahpets (Beitrag 1371542)
SQL-Code:
select LAST_INSERT_ROWID() from dual

Wieso das FROM?

Lies nochmal ...

Ja, es ist ein großes Durcheinander mit vielen Vorschlägen.
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?

EdAdvokat 16. Mai 2017 15:32

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:
qMain.SQL.Text:='select last_insert_rowid() FROM KONTAKTE';
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.
Einsetzen von
Delphi-Quellcode:
SELECT CAST(last_insert_rowid() AS INTEGER) AS ID
gleiche Exception.
Den Hinweis von jobo
Zitat:

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. )
verstehe ich nicht, denn ich bin immer davon ausgegangen, dass die Funktion mit der jeweiligen Tabelle korespondiert. Ist wohl doch nicht so und was bewirkt die Funktion denn dann ohne Beachtung der Tabelle im Programm? Entschuldigt bitte meine naive Frage, doch ich bin da noch nicht dahinter gestiegen. Es ist doch eine einige Tabelle und kein multiuser-Programm, in das von verschiedenen Usern Eingaben vorgenommen werden - sehe ich da was völlig falsch?
Wenn das Prog. gewünscht wird, stelle ich es ein.

nahpets 16. Mai 2017 16:06

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:
SELECT last_insert_rowid() AS ID
macht, dann führ' es doch im DBBrowser aus.

Ebenso gilt das hierfür: Wie sieht das Ergebnis im DBBrowser aus?
Delphi-Quellcode:
select last_insert_rowid() FROM KONTAKTE
Was passiert, wenn Du nur einen Datensatz in der Tabelle KONTAKTE hast, und was passiert, wenn Du mehrere Datensätze in der Tabelle hast?

jobo 16. Mai 2017 16:08

AW: ID nicht gefunden nach last_insert_rowid()
 
Zitat:

Zitat von EdAdvokat (Beitrag 1371630)
.. verstehe ich nicht, denn ich bin immer davon ausgegangen, dass die Funktion mit der jeweiligen Tabelle korespondiert. Ist wohl doch nicht so und was bewirkt die Funktion denn dann ohne Beachtung der Tabelle im Programm? Entschuldigt bitte meine naive Frage, doch ich bin da noch nicht dahinter gestiegen. Es ist doch eine einige Tabelle und kein multiuser-Programm, in das von verschiedenen Usern Eingaben vorgenommen werden - sehe ich da was völlig falsch?
Wenn das Prog. gewünscht wird, stelle ich es ein.

Mach doch mal einen kleinen Versuch und setze folgendes Statement ab, am besten in einem Tool in dem man mehrere Sätze als Ergebnis erhält:
[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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:36 Uhr.
Seite 6 von 8   « Erste     456 78      

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