![]() |
AW: Automatiach erstellte Syntax
Zitat:
SQL-Code:
select * from table1;
delete from table2 where id=12345; update table4 set wert=1234 where id=6789; Zitat:
Zitat:
![]() Gruß K-H Edith: Zitat:
|
AW: Automatiach erstellte Syntax
Zitat:
Und wenn man nun Delphi Componenten nutzt, die gewisse Datenbank-Features als Attribute anbieten, Transaktionseinstellungen, i18 settings usw, dann dürfte klar sein, dass es Probleme gibt, wenn man in einem Script oder auch nur einer einzelnen SQL Query widersprechende Anweisungen absetzt. |
AW: Automatiach erstellte Syntax
Hi zusammen
Ich hab das mal so umgesetzt:
Delphi-Quellcode:
Wie gesagt: Beim 2. ExecSQL krachte es. Hmm, ich bin mir jetzt nicht mehr sicher, aber ich glaube mich an ein Tut zu erinnern, dass nach jeder Create-Anweisung ein ExecSQL durchführte. Der Grund könnte sein: Durch meine Aufteilung der einzelnen TableCreate-Statements und deren wiederzusammenführung in einem einzelnen SQLString hab ich wohl Leerzeichen zwischen den einzelnnen Anmweisungen entfernt, so dass da nun Konstrukte vorhanden sind wie
procedure TDMLSQLite.ContentmasterDBCreate;
var SQLString: String; begin try DMLSQLite.FDSQLiteConnection.Connected := false; FDSQLiteConnection.ExecSQL('ATTACH "M:\SQLite-DB Corner\ContentMasterData\ContentMasterData.sqlite" AS ContentMasterData'); // DMLSQLite.FDSQLiteConnection.Params.Values['Database']:='"M:\SQLite-DB Corner\ContentMasterData\ContentMasterData.sqlite"'; // War obige Zeile nicht auskommentiert: Unbekannte Datenbank. Danach liefen alle Createanweisungen durch. Beim nächsten ExecCSQL krachte es DMLSQLite.FDSQLiteConnection.Params.Values['FailIfMissing']:='False'; DMLSQLite.FDSQLiteConnection.Params.Values['PRAGMA foreign_keys']:='ON'; SQLiteTestMain.LBxPathlist.Items.AddStrings(FDSQLiteConnection.Params); DMLSQLite.FDSQLiteConnection.Connected := true; DMLSQLite.FDSQLiteConnection.GetInfoReport(SQLiteTestMain.Memo1.Lines); SQLString := ''; SQLString := Createbilddescribetabelle; SQLString := SQLString + Createbilddescribetabelle_has_HtmlTabell; SQLString := SQLString + Createbildtabelle; SQLString := SQLString + CreateCSSTabelle; SQLString := SQLString + Creategalerietabelle; SQLString := SQLString + CreateHTMLTable; SQLString := SQLString + CreateJavascriptTable; SQLString := SQLString + Createkategorien_tabelle; SQLString := SQLString + Createkategorien_tabelle_has_bildDescribeTabelle; SQLString := SQLString + CreateMenueTabelle; SQLString := SQLString + CreateSubMenue2Table; SQLString := SQLString + CreateSubmenuetabelle; DMLSQLite.FDSQLiteConnection.ExecSQL(SQLString); except on E: EDatabaseError do ShowMessage('Exception raised with message' + E.Message); end; end; Zitat:
Zitat:
Gruss Delbor |
AW: Automatiach erstellte Syntax
Bei Deinem 2. ExecSQL führst Du irgendwas aus, was aus mehreren Strings zusammengesetzt ist.
Da uns der Inhalt nicht bekannt ist, ist es annähernd unmöglich, hier irgendwie brauchbare Hilfestellung zu geben. Normalerweise kann ExecSQL (wie oben schon angemerkt) nur ein Statement, also z. B. das Create von einer Tabelle, ein einzelnes Insert, ein einzelnes Update ..., aber keine Abfolge von mehr oder weniger Statments: Sprich: (höchstwahrscheinlich) keine Scripte. Zitat:
Wenn die Anzahl der " beim Zusammenbau des SQLString aus einer Vielzahl weiterer Strings nicht so ganz zusammen passt, kann das zu diversen Fehlern führen, die man anhand der Fehlermeldung allein niemals finden und beheben kann. Dann werden da mehrere String hintereinander gehängt, ist jeder ein vollständiges Statement, bei dem auch sichergestellt ist, dass es mit ; endet? Meine Regel ist: Ein Statement ein ExecSQL (auch dann, wenn ich es anders lösen könnte). Dadurch weiß ich im Fehlerfalle immer, welches Statement den Fehler auslöste und muss nicht ggfls. tausende von Zeilen durchsuchen, um irgendwo einen Fehler zu finden. Möchte man z. B. im Zusammenhang mit einer Firebird-Datenbank mehrere Statements als Script per ExecSQL ausführen, muss man es in dieser Art machen:
SQL-Code:
Andernfalls erntet man bestenfalls nur 'ne Fehlermeldung.
EXECUTE BLOCK AS BEGIN
Statement_1; ... Statement_n; END Ob SQLite sowas unterstützt, weiß ich nicht. |
AW: Automatiach erstellte Syntax
Liste der Anhänge anzeigen (Anzahl: 1)
Hi zusammen
Der Abruch erfolgt gleich im erstem Statementt: (Hier das 2.)
Delphi-Quellcode:
Wie man hier sieht, habe ich im unteren Statement in der 1. Zeile die doppelten Anführungszeichen entfernt. Allerdings erst vor einemm zweiten Durchlauf. Die Fehlermeldung lautete zwar gleich, aber der Datenbankname endete diesmal mit einem Hochkomma.
function TDMLSQLite.Createkategorien_tabelle:String;
var SQLString: String; begin SQLString := 'CREATE TABLE "ContentMasterData"."kategorien_tabelle"('+ '"Kath_ID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("Kath_ID">=0),'+ '"Kategorie" VARCHAR(120) NOT NULL);'; Result := SQLString; end; function TDMLSQLite.Createbilddescribetabelle :String; var SQLString: String; begin SQLString := 'CREATE TABLE ContentMasterData.bilddescribetabelle('+ '"BilddesribeID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("BilddesribeID">=0),'+ '"bildtabelle_idBild" INTEGER NOT NULL CHECK("bildtabelle_idBild">=0),'+ '"bildkatID" INTEGER NOT NULL CHECK("bildkatID">=0),'+ '"bildname" VARCHAR(45),"Dateipfad" VARCHAR(250),"bildbeschreibung" VARCHAR(800),'+ '"bildlegende" VARCHAR(300),"Author" VARCHAR(250),'+ 'CONSTRAINT "fk_bilddescribetabelle_bildtabelle1" '+ 'FOREIGN KEY("bildtabelle_idBild")'+ 'REFERENCES "bildtabelle"("idBild"));'+ 'CREATE INDEX "ContentMasterData"."bilddescribetabelle.fk_bilddescribetabelle_bildtabelle1_idx" ON"bilddescribetabelle" ("bildtabelle_idBild");'; Result := SQLString; end; Zitat:
Delphi-Quellcode:
Und die Fehlermeldung, als der Index erzeug werden sollte:
SQLString := 'CREATE TABLE "bilddescribetabelle"('+
'"BilddesribeID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("BilddesribeID">=0),'+ '"bildtabelle_idBild" INTEGER NOT NULL CHECK("bildtabelle_idBild">=0),'+ '"bildkatID" INTEGER NOT NULL CHECK("bildkatID">=0),'+ '"bildname" VARCHAR(45),"Dateipfad" VARCHAR(250),"bildbeschreibung" VARCHAR(800),'+ '"bildlegende" VARCHAR(300),"Author" VARCHAR(250),'+ 'CONSTRAINT "fk_bilddescribetabelle_bildtabelle1" '+ 'FOREIGN KEY("bildtabelle_idBild")'+ 'REFERENCES "bildtabelle"("idBild"));'+ 'CREATE INDEX "ContentMasterData"."bilddescribetabelle.fk_bilddescribetabelle_bildtabelle1_idx" ON"bilddescribetabelle" ("bildtabelle_idBild");'; Result := SQLString; end; Zitat:
Ja, ich denk, dann werd' ich mal... Gruss Delbor |
AW: Automatiach erstellte Syntax
Je nach Datenbank muss ein Name eindeutig sein, es darf also keine Tabelle mit dem Namen bilddescribetabelle und gleichzeitig einen Index mit dem Namen bilddescribetabelle geben.
Auch dürfen die Namen, je nach Datenbank, nur eine bestimmte Länge haben (häufig 30 Zeichen). Funktioniert statt:
SQL-Code:
'CREATE INDEX "ContentMasterData"."bilddescribetabelle.fk_bilddescribetabelle_bildtabelle1_idx" ON "bilddescribetabelle" ("bildtabelle_idBild");';
eventuell dieses hier:
SQL-Code:
'CREATE INDEX "ContentMasterData"."fk_bilddescribetabelle_bildtabelle1_idx" ON "bilddescribetabelle" ("bildtabelle_idBild");';
Muss in den Tabellennamen immer auch noch tabelle drinstehen? Wenn nein, lass das weg, dann werden die Namen deutlich kürzer oder wenn Du bei Fremdschlüsseln ein fk_ davorstellst und beim Index ein _idx hinten anhängst, dann lass Tabellennamen mit t_ beginnen, Views können dann mal mit v_ beginnen ... Sind die Unmengen von " bei SQLite tatsächlich bei der Angabe der Bezeichner erforderlich? Je nach Datenbank benötigt man das, wenn man die Bezeichner zwingend casesensitiv haben will, ohne die " wäre Groß-/Kleinschreibung dann egal. Aber das scheint nicht einheitlich zu sein. Bei den Änderungen ist mir durchaus klar, dass sie dann nicht zur die Scripte betreffen, sondern sich auch durch die von Dir schon erstellte Applikation ziehen. Der Änderungsaufwand könnten dann auch einen unüberschaubaren Rattenschwanz nach sich ziehen. Da wären dann erstmal Aufwand und Nutzen abzuwägen. |
AW: Automatiach erstellte Syntax
Hi nahpeds
Zitat:
Zitat:
Zitat:
Zitat:
So, wies nun ausieht, muss, bzw. darf ich die Datenbank in den einzelnen Statements gar nicht mehr anführen. Und was das mit den diversen Hochkommas auf sich hat, wird sich zeigen. Die Dinger sind möglicherweise bei Namen, die Leerzeichen enthalten (ich glaub, das steht auch irgendwo hier) zwingen, bei Namen andreseits aber nicht störend.
Delphi-Quellcode:
Das wurde anstandslos ausgeführt.
'CREATE TABLE "bilddescribetabelle"('+
Gruss Delbor |
AW: Automatiach erstellte Syntax
Zitat:
Irgendwie gibst Du Dich doch sehr beratungsresistent. Wenn Du Deine DB nicht abräumst vor einem 2. Versuch, muss es wohl knallen, beim erneuten Anlegen eines bereits bestehenden Objekts. Wenn Du trotz mehrfacher Hinweise mehrere Statements in einen Aufruf packst, was soll man da noch raten? 2 Statements werden über ; getrennt. |
AW: Automatiach erstellte Syntax
SQL-Statments enden (für gewöhnlich) mit einem Semikolon, das ist der Trenner. Ein Leerzeichen zwischen mehreren Statements ist (technisch) nicht erforderlich. Zur besseren Lesbarkeit gilt bei mir: Ein Statemnt, eine Zeile. Muss ein Statement auf mehrere Zeilen verteilt werden, dann kommt auch noch eine Leerzeile dazwischen.
Technisch kann man alles weglassen, was zur besseren Lesbarkeit führt, kann also z. B. ein Script von 10 MB durchaus als Einzeiler schreiben. Kann man, muss man aber nicht. Auch wenn es mehr Aufwand ist, mache ich sowas
Delphi-Quellcode:
lieber eher so:
function TDMLSQLite.Createbilddescribetabelle :String;
var SQLString: String; begin SQLString := 'CREATE TABLE ContentMasterData.bilddescribetabelle('+ '"BilddesribeID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("BilddesribeID">=0),'+ '"bildtabelle_idBild" INTEGER NOT NULL CHECK("bildtabelle_idBild">=0),'+ '"bildkatID" INTEGER NOT NULL CHECK("bildkatID">=0),'+ '"bildname" VARCHAR(45),"Dateipfad" VARCHAR(250),"bildbeschreibung" VARCHAR(800),'+ '"bildlegende" VARCHAR(300),"Author" VARCHAR(250),'+ 'CONSTRAINT "fk_bilddescribetabelle_bildtabelle1" '+ 'FOREIGN KEY("bildtabelle_idBild")'+ 'REFERENCES "bildtabelle"("idBild"));'+ 'CREATE INDEX "ContentMasterData"."bilddescribetabelle.fk_bilddescribetabelle_bildtabelle1_idx" ON"bilddescribetabelle" ("bildtabelle_idBild");'; Result := SQLString; end;
Delphi-Quellcode:
Und das geht nur, wenn man mehrere Statements bei SQLite mit ExecSQL ausführen kann, sonst musst Du dadraus mehrere Funktionen machen, eine für's Create Table und eine für Create Index.
function TDMLSQLite.Createbilddescribetabelle :String;
var sl: TStringList; begin sl := TStringList.Create; sl.Add('CREATE TABLE ContentMasterData.bilddescribetabelle'); sl.Add('('); sl.Add(' "BilddesribeID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL '); sl.Add(' CHECK("BilddesribeID" >= 0),'); sl.Add(' "bildtabelle_idBild" INTEGER NOT NULL CHECK("bildtabelle_idBild" >= 0),'); sl.Add(' "bildkatID" INTEGER NOT NULL CHECK("bildkatID" >= 0),'); sl.Add(' "bildname" VARCHAR(45),'); sl.Add(' "Dateipfad" VARCHAR(250),'); sl.Add(' "bildbeschreibung" VARCHAR(800),'); sl.Add(' "bildlegende" VARCHAR(300),'); sl.Add(' "Author" VARCHAR(250),'); sl.Add(' CONSTRAINT "fk_bilddescribetabelle_bildtabelle1" '); sl.Add(' FOREIGN KEY("bildtabelle_idBild")'); sl.Add(' REFERENCES "bildtabelle"("idBild")'); sl.Add(');'); sl.Add('CREATE INDEX "ContentMasterData"."bilddescribetabelle.fk_bilddescribetabelle_bildtabelle1_idx"'); sl.Add(' ON "bilddescribetabelle" ("bildtabelle_idBild");'); Result := sl.Text; sl.Free; end; Also eher sowas:
Delphi-Quellcode:
Bitte prüfe als Erstes: Kann man bei SQLite mehrere SQL in einem ExecSQL ausführen?
function TDMLSQLite.Create_BilddescribeTabelle :String;
var sl: TStringList; begin sl := TStringList.Create; sl.Add('CREATE TABLE ContentMasterData.bilddescribetabelle'); sl.Add('('); sl.Add(' "BilddesribeID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL '); sl.Add(' CHECK("BilddesribeID" >= 0),'); sl.Add(' "bildtabelle_idBild" INTEGER NOT NULL CHECK("bildtabelle_idBild" >= 0),'); sl.Add(' "bildkatID" INTEGER NOT NULL CHECK("bildkatID" >= 0),'); sl.Add(' "bildname" VARCHAR(45),'); sl.Add(' "Dateipfad" VARCHAR(250),'); sl.Add(' "bildbeschreibung" VARCHAR(800),'); sl.Add(' "bildlegende" VARCHAR(300),'); sl.Add(' "Author" VARCHAR(250),'); sl.Add(' CONSTRAINT "fk_bilddescribetabelle_bildtabelle1" '); sl.Add(' FOREIGN KEY("bildtabelle_idBild")'); sl.Add(' REFERENCES "bildtabelle"("idBild")'); sl.Add(');'); Result := sl.Text; sl.Free; end; function TDMLSQLite.Create_fk_bilddescribetabelle_bildtabelle1_idx :String; var sl: TStringList; begin sl := TStringList.Create; sl.Add('CREATE INDEX "ContentMasterData"."bilddescribetabelle.fk_bilddescribetabelle_bildtabelle1_idx"'); sl.Add(' ON "bilddescribetabelle" ("bildtabelle_idBild");'); Result := sl.Text; sl.Free; end; Wenn nein, dann baue zuerst entsprechende Funktionen, je Statement eine. Also pro SQL darf es nur ein ; geben. |
AW: Automatiach erstellte Syntax
Hi nahpeds
Zitat:
Zitat:
Zitat:
Und so kommt irgendwann mal der Punkt, wo ich sagen muss: Jetzt lass ich das mal so und arbeite am eigentlichen Programm weiter. Ich hab auch grad gesehen: die Doppelten Hochkommas wurdenso von Workbench exportiert. Das scheint mal so,als ob sich da nicht viel machen lässt... Gruss Delbor PS: Mal etwas mehr oftopic: In den MySQL Workbench-Einstellungen sind die FK-Namensregelung so definiert: fk_%stable%_%dtable%, für Spaltennamen so: %table%_%column%. Da seh ich eigentlich keinen grossen Spielraum, wenn man sprechende Namen verwenden will... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:19 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