Seite 1 von 1
SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 20:55
von ErwBer
Hallo,
wie kann ich einen Datensatz aus einer SQlite-Datenbank in eine andere SQLite-Datenbank kopieren?
Ich weiß zwar, wie man in einzelnen Datenbanken Daten einfügt/Daten ausliest, mein Problem liegt jedoch in der "Verbindung" der beiden Datenbanken. Wie können die ausgelesenen Daten von SQlite-DB1 zwischengespeichert werden und dann beim INSERT in SQLite-DB2 verwendet werden?
Vielen Dank
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 20:57
von jerch
@ErwBer:
Mit einer 2. Datenbankverbindung. Wie öffnest Du denn die erste?
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 20:59
von BlackJack
@ErwBer: Wenn Du weisst wie man Daten abfragt und wie man Daten schreibt, dann fehlt mir jetzt die konkrete Frage‽ Die ”Verbindung” zwischen den beiden Datenbanken ist Dein Programm.
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 21:06
von ErwBer
Mit folgendem Code gebe ich z.B. Daten aus:
Code: Alles auswählen
import sqlite3
conn=sqlite3.connect('Messergebnisse.sqlite')
curs=conn.cursor()
for row in curs.execute("SELECT * FROM Messergebnisse WHERE Abgeholt='2'"):
print row
conn.close()
Mein Problem ist jetzt, die mit "SELECT * FROM Messergebnisse WHERE Abgeholt='2'" gewonnenen Daten in eine zweite Datenbank einzufügen.
Kann diese geöffnet werden, bevor die DB1 geschlossen wird? Wie werden die gewonnenen Daten "zwischengespeichert"?
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 21:14
von Sirius3
@ErwBer: Warum sollte man keine zweite Datenbank öffnen können? Und die Daten werden von Dir doch schon in row "zwischengespeichert".
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 21:16
von jerch
ErwBer hat geschrieben:Kann diese geöffnet werden, bevor die DB1 geschlossen wird?
Warum probierst Du das nicht einfach? (Hinweis: ja es geht)
ErwBer hat geschrieben:Wie werden die gewonnenen Daten "zwischengespeichert"?
Hmm, wenn die Frage ernst gemeint ist, antworte ich mal mit einer Gegenfrage: Was glaubst Du, ist `row` in `print row`?
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 21:47
von ErwBer
Hier mal die Datenkopier-Funktion, erklärt mein (Verständnis)Problem vielleicht:
Code: Alles auswählen
#!/usr/bin/env python
import sqlite3
conn=sqlite3.connect('/var/www/Messergebnisse.sqlite')
curs=conn.cursor()
for row in curs.execute("SELECT * FROM Messergebnisse WHERE Abgeholt='2'"):
conn=sqlite3.connect('/var/www/Messergebnisse2.sqlite')
curs=conn.cursor()
curs.execute("INSERT row INTO Messergebnisse")
conn.close()
conn.close()
Der Befehl "INSERT row INTO Messergebnisse" ist mein Problem.
Wie muss er lauten, damit die in "row" zwischengespeicherten Daten in Datenbank2 eingefügt werden?
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 21:58
von Sirius3
@ErwBer: wie soll auf magische Weise row in einem String mit der Variable row verknüpft werden können?
Wie sieht denn ein INSERT Befehl bei SQL aus? Diesem kannst Du dann row als Argument übergeben, wie Du das bei Deinem SELECT auch hättest tun sollen (Stichwort Platzhalter).
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 22:49
von ErwBer
Sieht jetzt so aus, es gibt keine Fehlermeldungen, aber die Daten werden auch nicht übernommen:
Code: Alles auswählen
#!/usr/bin/env python
import sqlite3
conn=sqlite3.connect('/var/www/Messergebnisse.sqlite')
curs=conn.cursor()
for row in curs.execute("SELECT * FROM Messergebnisse WHERE Abgeholt='0'"):
conn=sqlite3.connect('/var/www/Messergebnisse2.sqlite')
curs=conn.cursor()
curs.execute("INSERT INTO Messergebnisse VALUES (?,?,?,?)", row)
conn.close()
conn.close()
Was ist noch beim SELECT-Befehl falsch? Ich vermute da gehört muss da auch was mit (?,?,?,?) hin, weiß aber grad nicht wie genau.
Re: SQlite Datensätze kopieren
Verfasst: Samstag 4. April 2015, 23:07
von BlackJack
@ErwBer: Es fehlt ein `commit()`-Aufruf und Du kannst nicht die selben Namen einfach so wiederverwenden. Du schliesst die zweite Verbindung zweimal und die erste gar nicht.
Re: SQlite Datensätze kopieren
Verfasst: Sonntag 5. April 2015, 13:01
von bfm
@ErwBer: Bei dem jetzigen Code würde ich jetzt mal sagen, das bei jedem row aus select die Datenbank geöffnet, ein Datensatz geschrieben und wieder geschlossen wird.
Neben cursor.execute() gibt es noch cursor.executemany(). Hiermit lässt sich eine Sequenz von Werten in einem Rutsch in die Datenbank schreiben, ohne dass man selber über die Sequenz iteriert werden muss.
Wie wäre es hiermit (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python
import sqlite3
conn=sqlite3.connect('/var/www/Messergebnisse.sqlite')
curs=conn.cursor()
#Ergebnis aus dem select in ergebnis zwischenspeichern
ergebnis = conn.fetchall()
#zur Sicherheit die Verbindung schließen, bevor unter dem gleichen Namen nochmals eine Verbindung zu einer anderen Datenbank geöffnet wird
conn.close()
conn=sqlite3.connect('/var/www/Messergebnisse2.sqlite')
curs=conn.cursor()
#curs.execute() durch curs.executemany() ersetzen, damit man nicht selber über ergebnis iterieren muss
curs.executemany("INSERT INTO Messergebnisse VALUES (?,?,?,?)", ergebnis)
conn.commit()
conn.close()
Re: SQlite Datensätze kopieren
Verfasst: Montag 6. April 2015, 00:43
von BlackJack
In Python sieht das so kurz aus.

In Vala irgendwie länger und umständlicher:
Code: Alles auswählen
using GLib;
static const string SELECT_STRING =
"SELECT * FROM Messergebnisse WHERE Abgeholt=:abgeholt;";
static const string INSERT_TEMPLATE =
"INSERT INTO Messergebnisse (%s) VALUES (%s);";
static inline void print_db_error (string text, Sqlite.Database db)
{
stderr.printf ("%s: %d: %s\n", text, db.errcode (), db.errmsg ());
}
static inline int create_insert_statement (
Sqlite.Statement select_statement,
Sqlite.Database target_db,
out Sqlite.Statement insert_statement
) {
var column_count = select_statement.column_count ();
var column_names = new string[column_count];
var placeholders = new string[column_count];
for (int i = 0; i < column_count; i++) {
column_names[i] = select_statement.column_name (i);
placeholders[i] = "?";
}
var sql = INSERT_TEMPLATE.printf (
string.joinv (",", column_names), string.joinv (",", placeholders)
);
return target_db.prepare_v2 (sql, sql.length, out insert_statement);
}
static inline int copy (
string source_db_name, string target_db_name, int abgeholt_value
) {
Sqlite.Database source_db;
var rc = Sqlite.Database.open_v2 (
source_db_name, out source_db, Sqlite.OPEN_READONLY
);
if (rc != Sqlite.OK) {
print_db_error ("Can't open source database", source_db);
return 1;
}
Sqlite.Statement select_statement;
rc = source_db.prepare_v2 (
SELECT_STRING, SELECT_STRING.length, out select_statement
);
if (rc != Sqlite.OK) {
print_db_error ("Can't prepare select statement", source_db);
return 1;
}
select_statement.bind_int (
select_statement.bind_parameter_index (":abgeholt"), abgeholt_value
);
Sqlite.Database target_db;
rc = Sqlite.Database.open (target_db_name, out target_db);
if (rc != Sqlite.OK) {
print_db_error ("Can't open target database", target_db);
return 1;
}
Sqlite.Statement insert_statement;
rc = create_insert_statement (
select_statement, target_db, out insert_statement
);
if (rc != Sqlite.OK) {
print_db_error ("Can't pepare insert statement", target_db);
return 1;
}
var column_count = select_statement.column_count ();
assert (column_count == insert_statement.bind_parameter_count ());
while (select_statement.step () == Sqlite.ROW) {
for (int i = 0; i < column_count; i++) {
insert_statement.bind_value (
i + 1, select_statement.column_value (i)
);
}
rc = insert_statement.step ();
if (rc != Sqlite.DONE) {
print_db_error("Can't insert data", target_db);
return 1;
}
insert_statement.reset ();
}
select_statement.reset ();
return 0;
}
static int main (string[] args) {
if (args.length != 4) {
print ("Usage %s source_db target_db abgeholt_value\n", args[0]);
return 1;
} else {
return copy(args[1], args[2], int.parse(args[3]));
}
}
Re: SQlite Datensätze kopieren
Verfasst: Montag 6. April 2015, 10:37
von ErwBer
@bfm: Vielen Dank für den Code, leider ergibt sich folgender Fehler:
File "/home/pi/scripts/datenbank.py", line 7, in <module>
ergebnis = conn.fetchall()
AttributeError: 'sqlite3.Connection' object has no attribute 'fetchall'
Ich bin neu in Python und weiß leider nicht, wie ich das Problem beheben kann
Re: SQlite Datensätze kopieren
Verfasst: Montag 6. April 2015, 11:11
von Sirius3
@ErwBer: Deine Code war doch gar nicht mehr so weit von einer Lösung entfernt. Was Du machen mußt ist, die beiden Connections an verschiedene Variablen zu binden, nicht bei jedem Datensatz eine neue aufzumachen und regelmäßig zu commiten.
Re: SQlite Datensätze kopieren
Verfasst: Montag 6. April 2015, 13:52
von ErwBer
Ich habe es jetzt hinbekommen, der Code sieht (mit zusätzlichen UPDATE-Befehlen) jetzt folgendermaßen aus:
Code: Alles auswählen
#!/usr/bin/env python
import sqlite3
#Daten von Datenbank1 auslesen
conn=sqlite3.connect('/var/www/Messergebnisse.sqlite')
curs=conn.cursor()
curs.execute("SELECT * FROM Messergebnisse WHERE Abgeholt=0")
ergebnis = curs.fetchall() #Ergebnis aus dem select in ergebnis zwischenspeichern
conn.commit() #Aenderungen festschreiben
curs.execute("DELETE FROM Messergebnisse WHERE Abgeholt=2")
curs.execute("UPDATE Messergebnisse SET Abgeholt=2 WHERE Abgeholt=1")
curs.execute("UPDATE Messergebnisse SET Abgeholt=1 WHERE Abgeholt=0")
conn.commit() #Aenderungen festschreiben
conn.close() #Verbindung schliessen
#Daten in Datenbank2 eintragen
conn=sqlite3.connect('/var/www/Messergebnisse2.sqlite')
curs=conn.cursor()
curs.executemany("INSERT INTO Messergebnisse VALUES (?,?,?,?)", ergebnis)
conn.commit()
conn.close()
Vielen Dank für alle Tipps und anregenden Fragen!!!
Re: SQlite Datensätze kopieren
Verfasst: Montag 6. April 2015, 14:06
von BlackJack
@ErwBer: Ich würde die Datensätze in der ersten Datenbank ja erst Löschen/Verändern wenn die erfolgreich in der zweiten Datenbank eingetragen wurden. Sonst können Daten verloren gehen wenn das nicht klappt.
Für das UPDATE reicht *ein* Aufruf wenn man die Datenbank den Feldwert ausrechnen lässt: ``UPDATE Messergebnisse SET Abgeholt=Abgeholt + 1``. Wobei das Ändern aller Datensätze sicher nicht besonders effizient ist.
Liegen die Datenbankdateien tatsächlich im Document-Root des Webservers? Das würde ich mir auch überlegen.
Re: SQlite Datensätze kopieren
Verfasst: Montag 6. April 2015, 18:15
von ErwBer
Habs geändert, danke für die Hinweise!