sqlite neue Tabelle in Datenbank erzeugen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

Wenn ich eine Tabelle in der existierenden Datenbank laender.db erstellen möchte, erhalte ich mit folgendem Code eine Fehlermeldung:

Code: Alles auswählen

connection = sqlite3.connect('laender.db')

cursor = connection.cursor()


cursor.execute('''CREATE TABLE armutsgefahr 
                 (land TEXT, jahr INT, quote REAL)''')
Traceback (most recent call last):

File "<ipython-input-142-4e9e05a0f639>", line 2, in <module>
(land TEXT, jahr INT, quote REAL)''')

OperationalError: unable to open database file



woran liegt das ???
Zuletzt geändert von Anonymous am Samstag 10. Januar 2015, 13:15, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@Padidem: Ein Rechteproblem vielleicht. Oder ein anderer Prozess hat die Datenbank gerade offen und hat seine Transaktion noch nicht abgeschlossen/commited.

Edit: Warum ist das Land eine Textspalte? Sollte das nicht ein Fremdschlüssel auf eine Tabelle mit den Ländern sein? Hast Du aus der letzten Aufgabe nicht bereits so eine Tabelle?
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

@ BlackJack: Danke für den Tipp...leider ist die Datei nirgendwo anders geöffnet es müsste demnach mit dem Schreibzugriff zusammenhängen...gibt es eine Möglichkeit diesen zu umgehen bzw. auf eine andere Art eine neue Tabelle in laender.db einzufügen?
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

die genaue Aufgabenstellung lautet:

Erzeugen sie eine neue Tabelle in laender.db, mit dem Namen "armutsgefahr" und drei Spalten ('land', 'jahr', 'quote'). Befüllen sie die Tabelle mit den entsprechenden Daten aus armutsgefahr.txt.
BlackJack

@Padidem: Wenn man einen Schreibschutz irgendwie umgehen könnte, dann wäre es ja kein Schutz. :-) Und um eine Tabelle in eine Datenbankdatei schreiben zu können muss man die nötigen Rechte besitzen um in die Datei schreiben zu können.

Bezüglich der Aufgabenstellung: Dann muss man wohl hoffen das ihr im Stoff noch nicht bei Beziehungen zwischen Tabellen und Fremdschlüsseln wart und das das deshalb eine redundante Spalte hat und kein guter DB-Entwurf ist. Und auch wenn Land + Jahr als Primärschlüssel wäre, würden viele eine künstliche ID hinzufügen.
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

@ BlackJack: Danke für deine Antwort...

Also das mit dem PRIMARY KEY und FOREIGN KEY hatten wir schon angeschnitten im Seminar aber inwiefern könnte ich dies auf die Aufgabe anwenden.. :K
Sie müsste doch irgendwie zu lösen sein und ich verstehe nicht, warum Python die Datenbank laender.db nicht öffnet.
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

@Padidem: Wahrscheichnlich startest Du Dein Pythonprogramm in einem Verzeichnis, auf das Du keine Schreibrechte hast und nicht dort wo laender.db liegt.

Wie sieht denn Dein bisheriges Datenbankdesign aus? Welche Anfragen willst Du auf die Daten loslassen?
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

also die Mastertabelle gibt folgendes aus:

Code: Alles auswählen

[(u'table',
u'laender_info',
u'laender_info',
2,
u'CREATE TABLE laender_info (\n [index] INTEGER,\n [land] TEXT,\n [kuerzel] TEXT,\n [hauptstadt] TEXT,\n [beitrittsdatum] INTEGER,\n [regierungschef] TEXT,\n [regierungspartei] TEXT,\n [stimmgewicht] INTEGER,\n [flaeche] INTEGER,\n [einwohner_mio] REAL,\n [einwohner_km2] INTEGER,\n [auslaender] REAL,\n [sprachen] TEXT\n )'),
(u'table',
u'migrationshintergrund_2013',
u'migrationshintergrund_2013',
5,
u'CREATE TABLE migrationshintergrund_2013 (\n [index] INTEGER,\n [land] TEXT,\n [insgesamt] INTEGER,\n [ohne_mh] INTEGER,\n [mit_mh] INTEGER\n )')]
hier soll nun mit CREATE TABLE eine neue Tabelle "armutsgefahr" mit den oben genannten 3 Spalten und folgenden Daten aus der txt.Datei eingefügt werden:

Code: Alles auswählen

Bundesland      2005    2006    2007    2008    2009    2010    2011    2012    2013
    Deutschland     14.7    14.0    14.3    14.4    14.6    14.5    15.0    15.0    15.5
    Altes Bundesgebiet ohne Berlin  13.2    12.7    12.9    13.1    13.3    13.3    13.8    13.9    14.4
    Neue Bundeslaender mit Berlin   20.4    19.2    19.5    19.5    19.5    19.0    19.4    19.6    19.8
    Baden-Wuerttemberg      10.6    10.1    10.0    10.2    10.9    11.0    11.1    11.1    11.4
    Bayern  11.4    10.9    11.0    10.8    11.1    10.8    11.1    11.0    11.3
    Berlin  19.7    17.0    17.5    18.7    19.0    19.2    20.6    20.8    21.4
    Brandenburg     19.2    18.9    17.5    16.8    16.7    16.3    16.8    18.1    17.7
    Bremen  22.3    20.4    19.1    22.2    20.1    21.1    22.0    22.9    24.6
    Hamburg 15.7    14.3    14.1    13.1    14.0    13.3    14.7    14.8    16.9
    Hessen  12.7    12.0    12.0    12.7    12.4    12.1    12.8    13.3    13.7
    Mecklenburg-Vorpommern  24.1    22.9    24.3    24.0    23.1    22.4    22.1    22.8    23.6
    Niedersachsen   15.5    15.3    15.5    15.8    15.3    15.3    15.5    15.7    16.1
    Nordrhein-Westfalen     14.4    13.9    14.6    14.7    15.2    15.4    16.4    16.3    17.1
    Rheinland-Pfalz 14.2    13.2    13.5    14.5    14.2    14.8    15.1    14.6    15.4
    Saarland        15.5    16.0    16.8    15.8    16.0    14.3    15.2    15.4    17.1
    Sachsen 19.2    18.5    19.6    19.0    19.5    19.4    19.5    18.8    18.8
    Sachsen-Anhalt  22.4    21.6    21.5    22.1    21.8    19.8    20.6    21.1    20.9
    Schleswig-Holstein      13.3    12.0    12.5    13.1    14.0    13.8    13.6    13.8    14.0
    Thueringen      19.9    19.0    18.9    18.5    18.1    17.6    16.7    16.8    18.0
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

@Padidem: das ist doch kein Datenbankdesign. Mit den Spaltennamen allein, kann man nichts anfangen, manche Namen sind ja noch einigermaßen aussagekräftig, aber gerade bei statistischen Daten ist ja Exaktheit essentiell. Migrationshintergrund insgesamt? Was soll das sein? Fläche als INTEGER?
Dann sind da viele redundante Daten: Einwohner pro km² kann man aus Einwohner und Fläche jederzeit berechnen. Aus Einwohner mit und ohne Migrationshintergrund kann man die Gesamtzahl der Einwohner berechnen, und warum ist die dann sowohl in der Länder-Info-Tabelle als auch in der Migrationshintergrundtabelle?
Dann der schlimmste Design-Fehler, den man wirklich nie machen darf: Daten in den Tabellennamen integrieren: migrationshintergrund_2013! Die Jahreszahl ist ein Datum, das in die Tabelle gehört und nicht in den Namen.
Zu guter Letzt fehlen noch die Relationen zwischen den Tabellen.
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

das ist allerdings die Datengrundlage (laender.db und armutsgefahr.txt) , die uns der Dozent für die Aufgaben zur Verfügung gestellt hat. Ich glaube hier geht es daher eher weniger um die Aussagekraft und die Sinnhaftigkeit der Tabellen als vielmehr zu lernen mit den grundlegenden SQL Befehlen umgehen zu können.
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

@Padidem: man kann auch versuchen, mit Hilfe eines Telefonbuchs Lesen zu lernen. Besser geht das aber auf jeden Fall, wenn man einfache sinnvolle Sätze dazu nimmt. Wenn die Tabellen wirklich so von Deinem Dozenten kommen, richte ihm schöne Grüße von mir aus und frage ihn, was er mal gelernt hat. Das ist so, als ob ein Fahrlehrer in der ersten Stunde seinen Schüler über rote Ampeln und falsch durch Einbahnstraßen schickt, weil er sagt, er muß ja erst mal Fahren lernen.
Das hilft Dir zwar jetzt auch nicht weiter, aber Du solltest wenigstens wissen, dass das, was Du da lernen sollst, nichts mit Datenbanken zu tun hat.
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

ok...das ist gut möglich aber gibt es davon abgesehen keinen angemessenen Lösungsvorschlag, denn die Aufgaben müssen ja irgendwie gelöst werden können :)
BlackJack

@Padidem: Müssen sie nicht wirklich denn die Aufgabe nach den Spaltennamen und Typen der Tabellen in der DB aus dem anderem Thema ist zumindest für Anfänger IMHO nicht wirklich sinnvoll lösbar. Insbesondere nicht wenn es hauptsächlich um das Benutzen von Datenbanken geht. Die Informationen sind in SQLite nicht einfach abfragbar sondern man muss SQL parsen oder eine externe Bibliothek verwenden die letztendlich die Aufgabe löst.

Und zum jetzigen akuten Problem kann man nicht wirklich mehr sagen als: Beseitige die Probleme die dazu führen das nicht in die Datei geschrieben werden kann. Das ist mit ziemlicher Sicherheit etwas ausserhalb von Python als solches. Das wird irgendein Rechteproblem auf Betriebs- oder Dateisystemebene sein, oder das doch irgendein anderer Prozess da die Finger auf der Datei hat. Ein eigenes Programm, eine interaktive sqlite3-Shell, ein grafisches Programm mit dem man auf die DB zugreifen kann, ein Virenscanner, irgendwie so etwas.
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

@ BlackJack: also ich konnte die Datenbank nun endlich öffnen...war im falschen Verzeichnis :)
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

konnte jetzt mit CREATE TABLE diese Tabelle erzeugen....könntest du mir dabei helfen, wie ich nun die Daten aus der txt Datei in die Spalten aufnehmen kann?

Danke :)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich hatte Dir doch schon in einem anderen Thread das ``csv``-Modul für das Parsen der Daten und den ``INSERT``-Befehl von SQL genannt. Wo hakt es denn da jetzt noch? :K

Kleiner Tipp noch: Man probiert Queries nicht über ein Python-Script aus! Man nutzt dafür eine gute SQL-Shell. Für SQLite kann ich Dir ein Fireforx Plugin "SQLite Manager" empfehlen. Wenn Du Linux nutzt, dann ist der Sqliteman exzellent.
Alternativ natürlich sonst noch die CLI-Shell.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

wie verbinde ich den INSERT Befehl mit dem csv Modul?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Auf Seiten der DB-API 2.0 gibt es die Methode executemany. Damit kannst Du effizient viele Datensätze auf einmal in die DB pumpen. Wie in der Doku beschrieben, musst Du ein Iterable mit den Daten übergeben. Dieses liefert Dir das ``csv``-Modul... es sollte also nicht so schwierig sein, das zu realisieren ;-)

(Am besten erstellst Du *zwei* Funktionen! Eine liefert Dir die Daten aus der CSV-Datei und die andere fführt die ``executemany``-Methode aus und bekommt als Parameter ein Iterable übergeben. Auf diese Weise kannst Du jede Funktion *unabhängig* voneinander für sich testen, bevor Du sie dann im Hauptprogramm kombinierst)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Padidem
User
Beiträge: 63
Registriert: Donnerstag 8. Januar 2015, 14:52

ist das in etwa dieses Iterable?

Code: Alles auswählen

with open('armutsgefahr.txt', 'rb') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
    for row in spamreader:
        print ', '.join(row)
sry übrigens falls ich so langsam nerve aber bin grad komplett durcheinander
Zuletzt geändert von Hyperion am Sonntag 11. Januar 2015, 15:37, insgesamt 1-mal geändert.
Grund: Code in Python-Code Tags gesetzt
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Bitte formatiere doch Dein Code-Schnipsel mit den dafür vorgesehen Tags! Auch das wurde Dir jetzt schon mehrfach gesagt. So kann man das doch gar nicht sauber lesen, weil die Einrückungen verloren gehen...

In dem Schnipsel ist der Name ``spamreader`` an ein Iterable gebunden (das erkennst Du einfach daran, dass Du eine ``for``-Schleife einsetzen kannst ;-) )
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten