SQLite Tabelle während der Laufzeit erzeugen

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
matzespens
Beiträge: 15
Registriert: Di 15. Feb 2022, 08:19

SQLite Tabelle während der Laufzeit erzeugen

Beitrag von matzespens »

Ich versuche mich gerade wieder in das Thema Datenbanken einzuarbeiten und habe mich fürs erste mal für eine SQLite DB entschieden. Zur Datenbankanbindung wollte ich ZEOS nutzen. Leider will es mir nicht gelingen während der Laufzeit eine Tabelle in der DB anzulegen. Das Erstellen der DB funktioniert einwandfrei. Ich habe auch schon versucht zu dem Thema etwas im Netz zu finden, aber ich komme nicht weiter.

Mit folgendem Code erzeuge ich die DB:

Code: Alles auswählen

procedure TForm1.CreateDBClick(Sender: TObject);
begin
  ZConnection1.Connected:=False;
  ZConnection1.Protocol := 'sqlite-3';
  ZConnection1.HostName := Edit1.Text;
  ZConnection1.Properties.Values['CreateNewDatabase [IF NOT EXISTS]']:='Create Database ' + #39 + 'MeineDB.db';
  ZConnection1.Database:='MeineDB.db';
  ZConnection1.Connected:=True;
end;  
Und mit diesem Code versuche ich die Tabelle anzulegen:

Code: Alles auswählen

procedure TForm1.CreateTableClick(Sender: TObject);
begin
  ZConnection1.Connected:=False;
  ZConnection1.Database:='MeineDB.db';
  ZConnection1.Connected:=True;
  ZQuery1.SQL.Text:= Memo4.Text;
  Zquery1.ExecSQL;
  ZQuery1.SQL.Text:= Memo1.Text;
  Zquery1.Open; 
end; 
Meine SQL Anweisung im Memo4 Feld lautet:
CREATE TABLE [IF NOT EXISTS] Astronomie (id INTEGER AUTO_INCREMENT PRIMARY KEY, Katalognummer VARCHAR(40) , Bezeichnung VARCHAR(100));

Im Memo1 steht dann lediglich die Select Abfrage zur Anzeige der Daten:
SELECT * FROM Astronomie;

Beim Klick auf den Button zum Anlegen der Tabelle erhalte ich immer eine SQL Logik Fehlermeldung.

Benutzeravatar
gladio
Beiträge: 167
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von gladio »

was soll die #39 bewirken?

Code: Alles auswählen

ZConnection1.Properties.Values['CreateNewDatabase [IF NOT EXISTS]']:='Create Database ' + #39 + 'MeineDB.db';

matzespens
Beiträge: 15
Registriert: Di 15. Feb 2022, 08:19

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von matzespens »

Das kann natürlich raus.

Funktioniert ja auch so:

Code: Alles auswählen

'Create Database MeineDB.db';
Hatte das erst mal so aus einem anderen Forum übernommen. Die #39 erzeugt glaube ich die Hochkommas.

charlytango
Beiträge: 490
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von charlytango »

matzespens hat geschrieben:
Sa 5. Mär 2022, 14:13
Und mit diesem Code versuche ich die Tabelle anzulegen:

Code: Alles auswählen

procedure TForm1.CreateTableClick(Sender: TObject);
begin
  ZConnection1.Connected:=False;
  ZConnection1.Database:='MeineDB.db';
  ZConnection1.Connected:=True;
  ZQuery1.SQL.Text:= Memo4.Text;
  Zquery1.ExecSQL;
  ZQuery1.SQL.Text:= Memo1.Text;
  Zquery1.Open; 
end; 
Meine SQL Anweisung im Memo4 Feld lautet:
CREATE TABLE [IF NOT EXISTS] Astronomie (id INTEGER AUTO_INCREMENT PRIMARY KEY, Katalognummer VARCHAR(40) , Bezeichnung VARCHAR(100));
Wenn du aus einem Memofeld ein SQL verwendest hast du immer das Problem dass irgend eine Syntax nicht passt. Um genauere Informationen zu bekommen würde ich die Exception der Datenbank abfangen und den Text ZB in einem Memo anzeigen.

Für SQL-Befehle die keine Ergebnisse liefern würde ich Zquery1.ExecSQL; verwenden und nur für solche die Ergebnisse liefern Zquery1.Open. (vor dem ändern des SQL Statements mache ich immer sicherheitshalber ein Zquery1.Close;

Wenn ich SQL Statements teste benutze ich immer www.heidisql.com.
Das bietet mehrere Möglichkeiten. Zur Erstellung/Änderung von Tabellen einfach die entsprechenden Einträge machen. Das nötige SQL-Statement wird protokolliert und man kann es einfach rauskopieren und weiterverwenden. Damit ist die Syntax schonmal korrekt.

Benutzeravatar
gladio
Beiträge: 167
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von gladio »

Die eckigen Klammern in der Erzeugung der Tabelle müssen weg.

Code: Alles auswählen

  ZConnection1.Connected:=False;
  ZConnection1.Protocol := 'sqlite-3';
  ZConnection1.LibraryLocation:=ExtractFilePath(Application.ExeName);
  ZConnection1.Properties.Values['CreateNewDatabase [IF NOT EXISTS]']:='Create Database MeineDB.db';
  ZConnection1.Database:=ExtractFilePath(Application.ExeName)+'MeineDB.db';
  ZConnection1.Connected:=True;
  .....
  ZQuery1.SQL.Text:= 'CREATE TABLE IF NOT EXISTS Astronomie (id INTEGER AUTO_INCREMENT PRIMARY KEY, Katalognummer VARCHAR(40) , Bezeichnung VARCHAR(100));';
  Zquery1.ExecSQL;
  ...
  ZQuery1.SQL.Clear;
  ZQuery1.SQL.Text:= 'select * from Astronomie';
  Zquery1.Open;
Du solltest der ZConnection noch mitteilen, wo die SQLite.dll zu finden ist (LibraryLocation:=) und den Pfad zu deiner Datenbank.
Für SQL-Befehle die keine Ergebnisse liefern würde ich Zquery1.ExecSQL; verwenden und nur für solche die Ergebnisse liefern Zquery1.Open. (vor dem ändern des SQL Statements mache ich immer sicherheitshalber ein Zquery1.Close;
ExecSQL ist in diesem Fall richtig.

matzespens
Beiträge: 15
Registriert: Di 15. Feb 2022, 08:19

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von matzespens »

Das Programm HeidiSQL kannte ich noch nicht. Danke für den Tipp.

Habe es installiert und dann mal den Create Table Befehl aus meinem Programmcode getestet. Auch hier habe ich eine Meldung über fehlerhafte Syntax bekommen.

Jetzt weiß ich, dass es am [IF NOT EXISTS] lag.

Wenn das aber nicht funktioniert wie kann ich das vorher prüfen? Mache ich dann einfach eine Abfrage über SQL und werte das aus?

Benutzeravatar
gladio
Beiträge: 167
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von gladio »

In HeidiSQL oder anderen Datenbank-Adminprogrammen sollte es einen SQL-Editor zur direkten Eingabe von SQL-Statements geben.
Die zeigen auch an, wo eventuell ein Fehler ist.
Es ist auch sicher irgendwo angezeigt, wie die SQL-Struktur der angelegten Tabellen ist. Wird meistens mit DDL bezeichnet.

matzespens
Beiträge: 15
Registriert: Di 15. Feb 2022, 08:19

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von matzespens »

gladio hat geschrieben:
Sa 5. Mär 2022, 18:57
Die eckigen Klammern in der Erzeugung der Tabelle müssen weg.

Code: Alles auswählen

  ZConnection1.Connected:=False;
  ZConnection1.Protocol := 'sqlite-3';
  ZConnection1.LibraryLocation:=ExtractFilePath(Application.ExeName);
  ZConnection1.Properties.Values['CreateNewDatabase [IF NOT EXISTS]']:='Create Database MeineDB.db';
  ZConnection1.Database:=ExtractFilePath(Application.ExeName)+'MeineDB.db';
  ZConnection1.Connected:=True;
  .....
  ZQuery1.SQL.Text:= 'CREATE TABLE IF NOT EXISTS Astronomie (id INTEGER AUTO_INCREMENT PRIMARY KEY, Katalognummer VARCHAR(40) , Bezeichnung VARCHAR(100));';
  Zquery1.ExecSQL;
  ...
  ZQuery1.SQL.Clear;
  ZQuery1.SQL.Text:= 'select * from Astronomie';
  Zquery1.Open;
Du solltest der ZConnection noch mitteilen, wo die SQLite.dll zu finden ist (LibraryLocation:=) und den Pfad zu deiner Datenbank.
Für SQL-Befehle die keine Ergebnisse liefern würde ich Zquery1.ExecSQL; verwenden und nur für solche die Ergebnisse liefern Zquery1.Open. (vor dem ändern des SQL Statements mache ich immer sicherheitshalber ein Zquery1.Close;
ExecSQL ist in diesem Fall richtig.
Die eckigen Klammern waren das Problem. Jetzt funktioniert es. Danke.

charlytango
Beiträge: 490
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von charlytango »

matzespens hat geschrieben:
Sa 5. Mär 2022, 18:58
Wenn das aber nicht funktioniert wie kann ich das vorher prüfen? Mache ich dann einfach eine Abfrage über SQL und werte das aus?
Meines Wissens (und ich bin da bei weitem keine absolute Instanz) gibt es keine direkte Möglichkeit die Gültigkeit eines SQL-Statements nur syntaktisch zu prüfen. Bzw ggfs genaue Fehlermeldungen zu bekommen. Das wird zwar bei jeder SQL-Anweisung vom DB-Parser gemacht, aber ich kenne keine Möglichkeit nur den Parser zu benutzen.

Die Anweisung EXPLAIN dient "nur" dazu den internen Ablaufplan einzusehen. ZB ob die richtigen Indizes benutzt werden etc.

Ich würde eine eventuelle Exception abfangen und auswerten bzw loggen

Code: Alles auswählen

//zuerst die Anzeige unterbinden falls es ein SELECT ist
ZQuery1.DisableControls;
try
  ZQuery1.Open;
except
  on E: Exception do 
    showmessage('Unit: ' + UnitName + LineEnding +
                           'File: ' + {$I %FILE%} + LineEnding +
                           'Methodname: ' +  {$I %CURRENTROUTINE%} + LineEnding +
                           'Linenumber: ' + {$I %LINE%} + LineEnding + LineEnding+
                           E.Message);
    //dann einen definierten Zustand herstellen
    exit;
end;
//Anzeige wieder einschalten
ZQuery1.EnableControls;
HeidiSQL scheint das im übrigen genauso zu machen.

Socke
Lazarusforum e. V.
Beiträge: 3054
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von Socke »

charlytango hat geschrieben:
So 6. Mär 2022, 10:51
matzespens hat geschrieben:
Sa 5. Mär 2022, 18:58
Wenn das aber nicht funktioniert wie kann ich das vorher prüfen? Mache ich dann einfach eine Abfrage über SQL und werte das aus?
Meines Wissens (und ich bin da bei weitem keine absolute Instanz) gibt es keine direkte Möglichkeit die Gültigkeit eines SQL-Statements nur syntaktisch zu prüfen. Bzw ggfs genaue Fehlermeldungen zu bekommen. Das wird zwar bei jeder SQL-Anweisung vom DB-Parser gemacht, aber ich kenne keine Möglichkeit nur den Parser zu benutzen.
Dafür kann man prepared Statementes nutzen. Ob und wie das in ZEOS geht, kann ich aber nicht sagen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

matzespens
Beiträge: 15
Registriert: Di 15. Feb 2022, 08:19

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von matzespens »

Die Prüfung ob die Tabelle schon existiert funktioniert ja. Das Problem waren lediglich die eckigen Klammer bei IF NOT EXISTS.

Code: Alles auswählen

 ZQuery1.SQL.Text:= 'CREATE TABLE IF NOT EXISTS Astronomie (id INTEGER AUTO_INCREMENT PRIMARY KEY, Katalognummer VARCHAR(40) , Bezeichnung VARCHAR(100));';
So funktioniert die Überprüfung.

charlytango
Beiträge: 490
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von charlytango »

Socke hat geschrieben:
Mo 7. Mär 2022, 08:55
Dafür kann man prepared Statementes nutzen. Ob und wie das in ZEOS geht, kann ich aber nicht sagen.
In diesem einen Fall ja. Also wenn es um Statements geht die Tabellen erstellen zB. Was sich dann ja auch ad absurdum führt weil die Tabellen schon in der SQLite Datei existieren könnten.

Nur war der Anwendungsfall eine leere Datei zu erstellen und darin eine Tabelle.
Zudem wurden dazu (vielleicht nur als Demo) Memofelder benutzt. IMHO nutzen da prepered Statements nichts, denn alles muss on the fly erzeugt und abgearbeitet werden.

Klar kann man sich selber einen SQL Parser schreiben oder die Syntax (automatisiert) über mehrere Onlinedienste checken lassen - was ich aber für einen Overkill halte.

Ich kenne keine Methode mittels Zugriffs-DLL ein SQL Statement syntaktisch zu prüfen ohne es auch durchzuführen und ggfs Fehlermeldungen auszuwerten

charlytango
Beiträge: 490
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz 2.0 fixes FPC 3.2 fixes
CPU-Target: Win 32Bit, 64bit
Wohnort: Wien

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von charlytango »

Socke hat geschrieben:
Mo 7. Mär 2022, 08:55
Dafür kann man prepared Statementes nutzen. Ob und wie das in ZEOS geht, kann ich aber nicht sagen.
In diesem einen Fall ja. Also wenn es um Statements geht die Tabellen erstellen zB. Was sich dann ja auch ad absurdum führt weil die Tabellen schon in der SQLite Datei existieren könnten.
Theoretisch könnte man wohl mit sqlite ein extra int sqlite3_prepare machen das jedes Statement im voraus prüft. IMHO: Kanonen auf Spatzen.

Nur war der Anwendungsfall eine leere Datei zu erstellen und darin eine Tabelle.
Zudem wurden dazu (vielleicht nur als Demo) Memofelder benutzt. IMHO nutzen da prepered Statements nichts, denn alles muss on the fly erzeugt und abgearbeitet werden.

Klar kann man sich selber einen SQL Parser schreiben oder die Syntax (automatisiert) über mehrere Onlinedienste checken lassen - was ich aber für einen Overkill halte.

Ich kenne keine effiziente Methode mittels Zugriffs-DLL ein SQL Statement syntaktisch zu prüfen ohne es auch durchzuführen und ggfs Fehlermeldungen auszuwerten
Zuletzt geändert von charlytango am Mi 9. Mär 2022, 18:17, insgesamt 1-mal geändert.

Socke
Lazarusforum e. V.
Beiträge: 3054
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: SQLite Tabelle während der Laufzeit erzeugen

Beitrag von Socke »

charlytango hat geschrieben:
Mo 7. Mär 2022, 10:51
Nur war der Anwendungsfall eine leere Datei zu erstellen und darin eine Tabelle.
Zudem wurden dazu (vielleicht nur als Demo) Memofelder benutzt. IMHO nutzen da prepered Statements nichts, denn alles muss on the fly erzeugt und abgearbeitet werden.
Wenn du die SQL-Statements direkt ausführen willst, braucht es tatsächlich keine prepared Statements um die Syntax zu prüfen. Da brauchst du nur eine saubere Fehlerbehandlung.
charlytango hat geschrieben:
Mo 7. Mär 2022, 10:51
Ich kenne keine Methode mittels Zugriffs-DLL ein SQL Statement syntaktisch zu prüfen ohne es auch durchzuführen und ggfs Fehlermeldungen auszuwerten
Keine der mir bekannten Datenbanken bietet eine Funktion ausschließlich für die Syntaxprüfung an. Bei SQLite3 kann mandie Funktion sqlite3_prepare_v2 nutzen. Dabei wird nicht nur die Syntax geprüft sondern auch ggf. der Zugriffsplan berechnet.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten