![]() |
Datenbank: SQLite • Version: 3 • Zugriff über: SQLiteSimpleDelphi-Wrappers von Tim Anderson
Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben werden?
Hallo,
ich komme bei folgendem nicht mehr weiter. Ich möchte in die DB 8 Angaben zu einem Radiosender abspeichern, zwei davon sind Comboboxen mit der Auswahl von Sprache und Kategorie. Nun muss ich schon vor dem Abspeichern wissen welche ID der Sprache und Kategorie ich dem Sender zuweisen soll, wenn diese gerade erst mit allen anderen Angaben erst erstellt werden? Weiß gar nicht wie ich das richtig beschreibe soll... auf jeden Fall ich muss die ersten zwei Werte in die Tabelle speichern, dann die ID dieser Werte holen, und mit anderen Angaben zu dem Sender verknüpft abspeichern. Wie geht das eigentlich? Mit dem Trigger? |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Stichworte Transaction und Last Inserted ID.
|
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
@OrNEC:
Wenn du ComboBoxen zur Auswahl von Sprache und Kategorie einsetzt, ist das im Grunde kontraproduktiv. Verwende doch besser gleich eine TDBLookUpComboBox, verbinde sie entsprechend mit deiner Haupttabelle und der jeweiligen Untertabelle und du hast die ID von Sprache bzw. Kategorie automatisch in der Tabelle. Du kannst dir ja mal als Beispiel das ![]() ![]() |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Zitat:
Aber danke Dir trotzdem! :thumb: |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Zitat:
![]() Wenn du jedoch weiterhin mit obsoleten Mitteln programmieren möchtest – also keine Datasets, kein direkter SQL-Zugriff auf die DB usw. – dann mußt tatsächlich du dir was überlegen, obwohl du im Grunde eigentlich möchtest, das wir hier was für dich überlegen :lol: |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Zitat:
|
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Zitat:
Delphi-Quellcode:
{ "Protokoll"-Rumpfdatensatz generieren }
quSpeichern.SQL.Text := 'Insert Into ..hier steht Dein SQL-Code..'; quSpeichern.ExecSQL; { Den neu erstellten Datensatz finden und die Datensatz ID bestimmen } quSpeichern.SQL.Text := 'Select LAST_INSERT_ID()'; quSpeichern.Active := True; iDatensatz := quSpeichern.Fields[0].AsInteger; |
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Er möchte aber doch keine DB-Komponenten von Delphi verwenden ... :gruebel:
|
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Zitat:
|
AW: Ersten Wert in die DB schreiben und sofort abfragen, bevor andere geschrieben wer
Naja, wenn man mit SQL arbeiten kann, sollte man eher so vorgehen:
Delphi-Quellcode:
oder gleich mit Locate arbeiten:
MyQuery.SQL.Text := 'select * from Tabelle_Sprache where Sprache = ' + QuotedStr(Edit_Sprache.Text);
MyQuery.Open; if MyQuery.RecordCount = 0 then begin // Hier die Insert-Methode einfügen/aufrufen end;
Delphi-Quellcode:
Sonst hat man hinterher unzählige Einträge derselben Sprache in der Tabelle.
If Not MyQuery.Locate('Sprache',Edit_Sprache.Text,[] then ...
Leider hab ich keinen blassen Schimmer, wie der Zugriff über die SQLiteSimpleDelphi-Wrappers von Tim Anderson abläuft und kann daher nur spekulieren. Gibt es in diesem Wrapper die Möglichkeit, SQL einzusetzen? |
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
![]() Ja, das hängt immer an der Session - weil es sonst nutzlos wäre ;) Doku zu SQLite ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:38 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