AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Zitat:
Zitat:
|
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Nochmal an alle, die es in der Hitze der Diskussion nicht mitbekommen haben:
Der Zugriff auf SQLite erfolgt über SQLiteSimpleDelphi-Wrappers von Tim Anderson. Da ist nix mit TDataSet, TDataSource, TDBEdit, TDBComboBox, TDB... |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
So wie ich das lese möchtest Du eine Master Deteil-Kombination eintragen:
1. Masterdatesatz eintragen 2. ID(´s) holen7den 3. Detail-Datensatz mit Referenz (der ID ('s) der Master-Tabelle) speichern. Man kann dafür die SQL-Eingenschaften bei Query-Komponenten nehmen, sind bei Lazarus und Delphi-Versionen mit DB Unterstützung dabei oder das oben aufgeführten Paket. SQLite hat keine Sequences oder Generatoren und daher ist der Ansatz mit Trigger suboptimal, aber SQLite hat zum Ausgleich "AutoIncrement", sodass folgendes geht:
Code:
Master-Tabelle mit Auto-Increment anlegen.
CREATE TABLE COMPANY(
ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, );
Code:
Detail-Tabelle mit Auto-Increment und Referenz-ID-Feld anlegen.
CREATE TABLE Employee(
ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, RID_Company INT NOT NULL, );
Code:
Master Datensatz einfügen, wobei das Auto-Inc-Feld nicht angegeben wird
INSERT INTO COMPANY (NAME )
VALUES ( 'Neptum AG' );
Code:
Letzte Höchste ID holen (geht vielleicht per SQLite-Funktion eleganter... )
Select max(ID ) as MAXID from COMPANY
Code:
Master Datensatz einfügen, wobei Max-ID in einer Variablen übergeben wird.
INSERT INTO Employee (NAME )
VALUES ( 'Kapt´n Nelson', :MAXID ); Das würde ich so als Weg sehen, wobei ich mit meinen VorPostern übereinstimme, dass dies nicht abhängig von einer bestimmten Komponente ist. Grüße in die Runde. |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Ich glaube genau das habe ich gesucht. Danke! :thumb:
Nun muss ich das Praktisch bzw. Syntaktisch richtig umsetzen! |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Ohne Autoinc-Feld klappt das aber besser.
Dann muss man eben den Wert des Primärschlüsselfelds vorher ermitteln und kurz in einer Variablen merken.
SQL-Code:
Das ist besser als hinterher nachzuschauen welchen Datensatz man gerade eben eingefügt hat.
Select max(ID)+1 as NewID from COMPANY
Insbesondere wenn man mal mit einer Multiuserdatenbank arbeitet können Autoinc-Felder zu ganz bösen Fehlern führen. |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Öhm, wie kann ein client-basierter Index in einer Multi-User Umgebung "besser" sein als ein vom Server vergebener AutoInc-Index? Oder soll ich am besten gleich die ganze Tabelle locken wenn ein Client darin Inserted? :shock:
Davon ab habe ich mir schon oft eine vom DBMS direkt unterstütze Rückgabe der ID eines soeben eingefügten Datensatzes gewünscht. Am liebsten in so einer Form von einer DB-Komponente unterstützt:
Delphi-Quellcode:
Das würde zum einen die unhandlichen Abfragen von LastInsertID, sowie die Notwendigkeit alles zugehörige in eine Transaktion zu verpacken sparen.
MyQuery.SQL.Text := 'INSERT INTO foo VALUES (:bar)';
... lastIndex := MyQuery.ExecuteWithResult('indexFieldName'); // Exception wenn das genannte Feld kein AutoInc, oder das Statement kein INSERT ist So eine Methode ließe zudem noch so Nettigkeiten zu wie 'SELECT * FROM foo WHERE bar=:bla', für den Fall dass man genau einen Datensatz als Ergebnis erwartet, und den Wert nur einer Spalte haben will. Exception bei 0 oder >1 Ergebnissen, sowie wenn das gefragte Feld nicht im Ergebnis vorkommt. Spart das Open und den Umweg über die Abbildung auf Fields[]. Ich frage mich fast, warum das sich so nie etabliert hat. |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Zitat:
Aber, man muß wenigstens den "richtigen" Master-Index wieder auslesen, wenn man dazu den Detail-Datensatz anlegen möche.
SQL-Code:
, nach dem Anlegen des Master-Datensatzes, ist da also totaler Mist, da dort natürlich die falsche ID gelesen werden kann, wenn zwischenzeitlich ein anderer User auch da was eingetragen hat.
SELECT Max(ID) FROM Master
Wenn man die IDs im Clienten bestimmt, dann weiß man zwar vor dem Anlegen des Master-Datensatzes, wie dessen ID sein wird und kann sie "sicher" für den Detail-Datensatz nutzen, aber dann muß man womöglich im Clienten extra eine Fehlerbehandlung integrieren, da die Datenbank entsprechend reagiert, wenn zwischen dem
SQL-Code:
und dem
SELECT MAX
SQL-Code:
ein anderer User schneller war und seinen Master-Datensatz anlegete und man nun selber natürlich eine doppelte ID anlegen möchte.
INSERT
LAST_INSERT_ID ist doch Session an die Sessions gebunden? Wenn ja, dann ist es an die eigene Verbindung gebunden und den darüber erstellten Datensatz, womit man dann seine ID bekommt, auch wenn jemand Anderes inzwischen gepostet hat. Einige DBMS kennen sowas wie
SQL-Code:
, was quasi Folgendem entspricht, als "eine" zusammenhängende Abfrage.
INSERT INTO table (id, value) VALUES (:id, :value) RETURNING id
SQL-Code:
SQLite aber anscheinend nicht.
INSERT INTO table (id, value) VALUES (:id, :value);
SELECT LAST_INSERT_ID(); Kennt SQLite eigentlich auch Referenzen? Um gültige Werte der Master-IDs in der Detail-Tabelle sicherzustellen. |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Doku zu SQLite Last Insert Rowid
Ja, das hängt immer an der Session - weil es sonst nutzlos wäre ;) Doku zu SQLite Foreign Key Support |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:33 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