SQLite Verhindern von doppelter Statement Ausführung

Kotelettklopfer

Bekanntes Mitglied
Moin,

mein Java Code beinhaltet auch Statements zur Erstellung sowie Befüllung einer SQL Tabelle.
Um beim erneuten ausführen des Codes die Tabelle nicht doppelt erzeugen zu lassen bzw. in eine Exception zu laufen, gibt es ja das "IF NOT EXIST".
Gibt es sowas auch in der Form für die INSERTS?

Ich möchte verhindern, dass bei jedem Lauf des Codes, die gleichen Datensätze erneut in die DB geschrieben werden..

VD & VG
 
Man kann natürlich Abfragen, ob die Tabellen schon existieren. Wenn man Datenbanken von Hand verwalten will (Und kein Tooling verwenden will, das sich um das Schema kümmert), dann war damals unser Ansatz, in einer Tabelle zu hinterlegen, auf welchem Schema-Stand man ist. (Wir hatten dann einfach eine Tabelle Config in der dann SchemaVersion hinterlegt war.)

Aber ebenso kann man die Metadaten verwenden:

Tooling wäre sowas wie:
 
Schau ich mir an. Danke Euch.
Im Moment hört sich die INSERT ON CONFLICT IGNORE Funktion gut an, wirft mir aber noch Fehler.
Ich tüftle noch dran 🙂

[CODE lang="java" title="SQL Statement"]public void insertData() throws SQLException {
String insertData = "INSERT ON CONFLICT IGNORE INTO " + TABLE_USER + " VALUES "
+ "(NULL, 'Chris', 'Chris@gmail.de', 5678765, 'Germany', DATETIME('now', 'localtime')), "
+ "(NULL, 'Peter', 'Peter@mail.de', 4567876, 'France', DATETIME('now', 'localtime')), "
+ "(NULL, 'Michael', 'Michael@mail.de', 67543, 'Poland', DATETIME('now', 'localtime')), "
+ "(NULL, 'Katja', 'Katja@web.de', 098765, 'Germany', DATETIME('now', 'localtime')), "
+ "(NULL, 'Frank', 'Frank@mail.de', 23456, 'Spain', DATETIME('now', 'localtime')), "
+ "(NULL, 'Betina', 'Betina@gmx.de', 567653, 'Germany', DATETIME('now', 'localtime')), "
+ "(NULL, 'Oliver', 'Oliver@yahoo.de', 0983467, 'China', DATETIME('now', 'localtime')), "
+ "(NULL, 'Mona', 'Mona@mail.de', 678346, 'Germany', DATETIME('now', 'localtime')), "
+ "(NULL, 'Test', 'Test@mail.de', 5647654, 'Germany', DATETIME('now', 'localtime')), "
+ "(NULL, 'Test2', 'Test2@mail.de', 678487, 'Germany', DATETIME('now', 'localtime'))";

executeQuery(insertData);
}

private void executeQuery(String sqlQuery) throws SQLException {

try {
connection = dbConnection.getConnection();
statement = connection.createStatement();
if (statement != null) {
statement.execute(sqlQuery); // execute = ausführen
}
} finally {
statement.close();
connection.close();
}

}[/CODE]
 
Der TE hat für sich eine Lösung gefunden, aber ich möchte dennoch kurz einhaken (@Kotelettklopfer Bitte nicht verwirren lassen!):

Das INSERT IGNORE setzt aber voraus, dass das Insert auch einen Fehler werfen würde. Es verhindert also nicht das erneute Einfügen, so dieses möglich wäre. Sprich: Wenn da auch ein UNIQUE Wert mit eingefügt wird, dann klappt es.

Sobald es um Befehle geht, die mehrfach ausgeführt werden könnten, verhindert dies nicht die Ausführung (Oder sollte ich dies falsch verstanden haben? Habe dazu zur Sicherheit kurz gesucht und z.B. https://www.geeksforgeeks.org/sql-insert-ignore-statement/ gefunden.)

In solchen Fällen hilft nur, die Logik selbst sicher zu stellen. Es muss also irgend eine Information abgelegt werden, die deutlich macht, was gelaufen ist ... Die INSERTs sind ja nicht immer einfache INSERT .... VALUES (...); Befehle sondern verschachtelte Selects (bei Schema-Wechseln. Wobei ich das wohl missverstanden habe - die Anfrage war allgemein und es ging nicht um INSERTs bei einem Schema-Wechsel)
 
Das INSERT IGNORE setzt aber voraus, dass das Insert auch einen Fehler werfen würde. Es verhindert also nicht das erneute Einfügen, so dieses möglich wäre. Sprich: Wenn da auch ein UNIQUE Wert mit eingefügt wird, dann klappt es.
Die Email ist als Unique angelegt im Schema. Also klappt das nur deswegen...

Wobei ich das wohl missverstanden habe - die Anfrage war allgemein und es ging nicht um INSERTs bei einem Schema-Wechsel)
Genau, es ging nur darum, dass die INSERTS nicht doppelt in einer Tabelle ausgeführt werden sollen.

Ich denke mein baldiges Projekt (Haushaltsbuch), macht die IGNORE Funktion an dieser Stelle obsolet, da ich hier die Tabelle mit User eingaben füllen will und nicht mit hart codierten INSERT.....
Das wird spannend xD
 
Als erstes finde ich es ziemlich schlechten Stil eine Tabelle in meiner Application zu erstellen.

Aber wenn du es schon machst, dann brauchst du doch nur testen ob es die Tabelle gibt und wenn ja, dann läßt du den insert einfach weg. Du kannst ja wohl davon ausgehen das wenn er den create table und den insert schon einmal durchlaufen hat er sowohl die Tabelle erstellt als auch die Daten eingefügt hat und wenn nicht dann wenigstens mit einer ordentlichen Exception rausgeflogen ist die du irgendwo bekommen solltest.
 
Es handelt sich hierbei um eine "Übung" aus einem Tutorial. Ich stehe noch ganz am Anfang was Java betrifft.

Wie wäre denn deiner Meinung nach ein "guter Stil" um eine Tabelle zu erstellen?
 
Also bei SQLite ist es so eine Sache. Am saubersten fände ich hier ein Installations-Programm mit auszuliefern das dann die Datenbank erstellt. Aber das ist für Deine Übung sicher erstmal unnötiger Overhead. Wäre dann das Sahnehäubchen zum Schluß
 
Oha da ist SQLite wohl deutlich weniger tolerant als mySQL
Die haben einfach eine verschiedene Syntax:
Code:
mysql> insert or ignore into x values (1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'or ignore into x values (1)' at line 1
mysql> insert ignore into x values (1);
Query OK, 1 row affected (0.10 sec)
 
Das ist halt alles kein ANSI SQL. Evtl. wäre ein MERGE Konstrukt eine Alternative, wenn man unabhängig von einer Datenbank sowas abdecken möchte?

Aber ich denke, man bleibt einfach bei einer spezifischen Datenbank und nutzt da die Möglichkeiten. Oder man greift zu entsprechenden Tools, die dann schon richtig mit den Datenbanken umgehen können 🙂
 
Die haben einfach eine verschiedene Syntax:
Code:
mysql> insert or ignore into x values (1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'or ignore into x values (1)' at line 1
mysql> insert ignore into x values (1);
Query OK, 1 row affected (0.10 sec)

Irgendwie schon dämlich das man sich auf solche Kleinigkeiten nicht einigen konnte. Das dürfte einem den letzten Nerv rauben wenn man da mal Portieren möchte.
 
Warum werden meine Themen immer so hochkomplex?? Ich sehe schon das nächste Thema mit 100 Posts und verstehe 20 davon 🙂
Schaue mir Liquibase mal an.
Ich verstehe das so, dass ich Liquibase in mein Projekt einbinde und jeder der meine APP nutzt bekommt die von mir vordefinierte DB automatisch "installiert".
Wenn derjenige dann Daten darin speichern würde, wären diese aber dann im nächstn Start der APP noch existent? Denke die Metadaten werden dann neu abgelegt und daher "weiß" die APP immer den letzten Stand?

Klingt warscheinlich alles sehr Laienhaft, hoffe es ist verständlich und korrekt was ich hier von mir gebe 🙂
 
Die Themen werden nur hochkomplexe wenn du auf Leute wie Brown hörst. Für den gibt es halt kein einfaches programmieren. Da muss man mindestens 20 dicke Frameworks und Tools zusammen stecken und dann wird erst eine für ihn gute Software draus.
Danach hast du zwar nix wirklich selber programmiert, weiß kein bisschen was dein programm Eigentlich so macht aber dafür ist es super clean Code und kann angeblich von jedem dummy gewartet werden…..
 
Wenn du dagegen auf Thallius hörst, kannst du am Ende zwar Code schreiben, hast aber absolut keine Ahnung von Softwareentwicklung und allem, was sich in den letzten 20 Jahren so getan hat – hey, aber immerhin kannst du dann irgendwann sagen, dass du es nach Wochen erfolgreich geschafft hast, deine SQL-Statement von einer zur anderen DB zu migrieren 😉


Ich verstehe das so, dass ich Liquibase in mein Projekt einbinde und jeder der meine APP nutzt bekommt die von mir vordefinierte DB automatisch "installiert".
Wenn derjenige dann Daten darin speichern würde, wären diese aber dann im nächstn Start der APP noch existent? Denke die Metadaten werden dann neu abgelegt und daher "weiß" die APP immer den letzten Stand?
Ja, das sorgt im wesentlichen dafür, dass beim Start das Schema der Datenbank dem entspricht, was du brauchst. Du gibst einfach nur an, dass du Tabelle XY mit Spalte Z und Datentyp A brauchst, und das ganze wird in den Datenbank-spezifischen Dialekt umgesetzte und erstellt. Das ganze ist Versioniert, damit du auch Updates problemlos machen kannst. Für deine Anforderungen ist das eher noch etwas zu viel, ist aber im Gegensatz zum händischen Erstellen für alles größere der "richtig" Weg.


Und zu JOOQ: das ist eine typischere, Datenbank-Dialekt unabhängige DSL für SQL. Dein obiges Beispiel sähe damit ganz grob etwa so aus:
Java:
insertInto(USER)
      .values(null, "Chris", "Chris@gmail.de", 5678765, "Germany", currentDate())
      .onDuplicateKeyIgnore()
Das funktioniert dann mit jeder Datenbank, egal wie die Syntax dafür aussieht oder ob die überhaupt nativen Support für ein wie auch immer geartetes "ignore" bietet.

Braucht etwas Einarbeitungszeit (wobei die mEn wirklich gering ist), jeder der es einmal genutzt hat ist danach aber Fan davon. Macht allerdings nur Sinn, wenn man sowieso schon entsprechendes Tooling nutzt, für's grade Einsteigen in's Programmieren ist das eher zu viel, war auch eigentlich nur eine Antwort auf Kneitzels Ansprechen der entsprechenden Tools 🙂
 
Wird das jetzt wieder eine totel Verdrehte Wahrnehmung von @Thallius? Die Übertreibung mit den "20 großen Frameworks" haben wir ja schon - fehlt nur noch, dass das alles in 5 Minuten selbst programmiert ist ... Und wir springen dann bestimmt auf sowas auch noch an und erläutern, dass die kurz umrissene Lösung eben nicht in 5 Minuten fertig wird und dass die eigentlich nichts kann und Fehler in keiner weise vernünftig behandelt und und und ...

Danach hast du zwar nix wirklich selber programmiert, weiß kein bisschen was dein programm Eigentlich so macht aber dafür ist es super clean Code und kann angeblich von jedem dummy gewartet werden…..
Also dümmer trollen geht kaum. Darauf einzugehen lohnt sich auch nicht - Deine Meinung haben wir in anderen Threads oft genug kopfschüttelnd zur Kenntnis genommen.
 
Leute bitte nicht schon wieder Zoff in meinem Post.. Zieh ich sowas an? Ich versuche doch wenigstens in Foren sowas zu vermeiden 🙂
Da musst Du leider durch. Das solltest Du einfach ignorieren. Die Teile, die sachlich auf Deine Punkte eingehen, sind ja erkennbar.

Sollte es zu sehr abgleiten, dann nutze den Report Link, damit die Off Topic Diskussionen abgespaltet werden.
 

Zurück
Oben