Tabellen aus CSV Dateien in SQLite Datenbanken importieren

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
BlackJack

@ThoSchoo: Der `os.getcwd()`-Aufruf ist hier sowieso überflüssig.

Das Programm würde ja nun sämtliche Felder in der Datenbank vom Typ TEXT anlegen. Und Constraints wie NOT NULL oder PRIMARY KEY gehen auf diese Art und Weise ja auch nicht.

Warum gibt es in der Datei überhaupt Zeilen mit der falschen Länge?

Statt *in* der Schleife ständig zu prüfen ob man die erste Zeile vor sich hat oder nicht, würde man die erste Zeilen einfach *vor* der Schleife mit `next()` vom Reader-Objekt abfragen.

Das ganze ist mittlerweile komplex genug um es sinnvoll auf Funktionen aufzuteilen.

Bei der Gelegenheit kann man dann auch gleich das Hauptprogramm in eine Funktion stecken (üblicherweise `main()` genannt) und auf Modulebene damit dann keinen Code mehr haben der nicht Konstanten, Funktionen, oder Klassen definiert.
ThoSchoo
User
Beiträge: 20
Registriert: Freitag 8. Januar 2016, 12:54

@cofi

wenn ich es so schreibe :

Code: Alles auswählen

csvfile in glob.glob(os.getcwd(""), "*.csv"):
gibt er mir das :

Code: Alles auswählen

 for csvfile in glob.glob(os.getcwd(""), "*.csv"):
TypeError: getcwd() takes no arguments (1 given)
ThoSchoo
User
Beiträge: 20
Registriert: Freitag 8. Januar 2016, 12:54

@BlackJack

mit dem `os.getcwd()` will ich ja mein Arbeitsverzeichnis aufrufen in mein die Dateien vorhanden sind
Wie gelange ich denn sonst in das Verzeichnis? :|

Es dürfte eigentlich keine Daten mit einer falschen länge geben
BlackJack

@ThoSchoo: Die Fehlermeldung ist doch ziemlich deutlich. Die Funktion erwartet keine Argumente, Du übergibst aber ein Argument. Lass das sein.

Zum aktuellen Arbeitsverzeichnis muss man nicht gelangen, da ist man bereits. Das ist ja gerade die Bedeutung von „aktuellem Arbeitsverzeichnis“, das von dort aus alle relativen Pfadangaben gesucht werden.

Wenn es keine Zeilen mit falscher Anzahl von Feldern geben kann, warum ist dann eine Prüfung darauf im Programm?
ThoSchoo
User
Beiträge: 20
Registriert: Freitag 8. Januar 2016, 12:54

So funktioniert es :

Code: Alles auswählen

import csv
import sqlite3
import os
import glob



db = ("Mockupdata")
con = sqlite3.connect(db)
cur = con.cursor()

# traverse the directory and process each .csv file
for csvfile in glob.glob( "*.csv"):
    # remove the path and extension and use what's left as a table name
    tablename = os.path.splitext(os.path.basename(csvfile))[0]

    with open(csvfile, "rb") as inputfile:
        reader = csv.reader(inputfile, delimiter = ";")
 
        header = True
        for row in reader:
            if header:
                # gather column names from the first row of the csv
                header = False
 
                sql = "DROP TABLE IF EXISTS %s" % tablename
                cur.execute(sql)
                sql = "CREATE TABLE %s (%s)" % (tablename,
                          ", ".join([ "%s text" % column for column in row ]))
                cur.execute(sql)
                       
                insertsql = "INSERT INTO %s VALUES (%s)" % (tablename,
                            ", ".join([ "?" for column in row ]))
 
                rowlen = len(row)
 
        con.commit()
 
cur.close()
con.close()
allerdings ist es so alles in TEXT

wie könnte ich das denn umschrieben damit es den jeweiligen DatenTypen erkennt ?
Zuletzt geändert von Anonymous am Dienstag 12. Januar 2016, 20:01, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@ThoSchoo: In einen DB-Entwurf gehört ja noch mehr als der Tabellenname und die Spaltennamen und -typen, das lässt sich nicht so einfach in einer CSV-Kopfzeile abbilden. Dementsprechend würde ich das dort auch nicht speichern oder von dort ermitteln wollen. Üblicherweise verwendet man SQL für das Schema oder ein ORM und lässt sich von dem die Tabellen erstellen. SQLAlchemy erwähnte ich ja schon mal…
ThoSchoo
User
Beiträge: 20
Registriert: Freitag 8. Januar 2016, 12:54

Uff ja .. In SQLAlchemy müsste ich mir mal einlesen ..
Hab es nun allerdings nun zunächst mal ehr primitiv gelöst.
Nun bekomme ich allerdings bei einer Zeile ein Problem ..

Code: Alles auswählen

con = sqlite3.connect("Mockup_Data.db")
cur = con.cursor()
cur.execute( "DROP TABLE IF EXISTS tbl_Supplier_Class")
cur.execute("CREATE TABLE tbl_Supplier_Class (Supplier_Class_ID INTEGER, Supplier_Class_Name TEXT, Share REAL, Avg_DPO INTEGER, Saisonality_Factor REAL, Invoice_Share REAL);")

with open('tbl_Supplier_Class.csv', "rb") as input_file:
        reader = csv.DictReader(input_file, delimiter = ";")
        to_db = [(i["Supplier_Class_ID"], i["Supplier_Class_Name"], i["Share"], i["Avg_DPO"], i["Saisonality_Factor"], i["Invoice_Share"]) for i in reader]

cur.executemany("Insert into tbl_Supplier_Class (Supplier_Class_ID, Supplier_Class_Name, Share, Avg_DPO, Saisonality_Factor, Invoice_Share) Values (?, ?, ?, ?, ?, ?);", to_db)
con.commit()
Da wird mir nun das hier als Fehler gegeben und ich versteh beim besten Willen nicht warum :D

Code: Alles auswählen

    to_db = [(i["Supplier_Class_ID"], i["Supplier_Class_Name"], i["Share"], i["Avg_DPO"], i["Saisonality_Factor"], i["Invoice_Share"]) for i in reader]
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/csv.py", line 107, in next
    self.fieldnames
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/csv.py", line 90, in fieldnames
    self._fieldnames = self.reader.next()
_csv.Error: new-line character seen in unquoted field - do you need to open the file in universal-newline mode?
Die Datei sieht so aus :

Code: Alles auswählen

Supplier_Class_ID;Supplier_Class_Name;Share;Avg_DPO;Saisonality_Factor;Invoice_Share
1;A;0,1;90;0,15;0.5
2;B;0,35;60;0,05;0.3
3;C;0,55;30;0,01;0.2
Zuletzt geändert von Anonymous am Mittwoch 13. Januar 2016, 19:45, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@ThoSchoo: Die Fehlermeldung enthält ja eine Frage. Die was mit `open()` und „universal-newline mode“ zu tun hat. Man könnte ja mal in der Dokumentation von `open()` nachlesen ob da vielleicht etwas über einen solchen Modus steht. ;-)
ThoSchoo
User
Beiträge: 20
Registriert: Freitag 8. Januar 2016, 12:54

Danke @BlackJack

Nun steht ich leider vor dem nächsten Problem und sitze seit Stunden davor und finde den Fehler einfach nicht

Code: Alles auswählen

con = sqlite3.connect("Mockup_Data.db")
cur = con.cursor()
cur.execute( "DROP TABLE IF EXISTS tbl_Material_Class")
cur.execute("CREATE TABLE tbl_Material_Class (Material_Class_ID INTEGER, Share REAL, Mean_Price REAL, Deviation_Price REAL, Mean_Ordersize INTEGER);")

with open('tbl_Material_Class.csv', "rb") as input_file:
        reader = csv.DictReader(input_file, delimiter = ";")
        to_db = [(i["Material_Class_ID"], i["Share"], i["Mean_Price"], i["Deviation_Price"], i["Mean_Ordersize"]) for i in reader]

cur.executemany("Insert into tbl_LGORT (Material_Class_ID, Share, Mean_Price, Deviation_Price, Mean_Ordersize) Values (?, ?, ?, ?, ?);", to_db)
con.commit()
und er gibt mir nur einen Keyerror aus

Code: Alles auswählen

   to_db = [(i["Material_Class_ID"], i["Share"], i["Mean_Price"], i["Deviation_Price"], i["Mean_Ordersize"]) for i in reader]
KeyError: 'Mean_Ordersize'
Das ist die dazugehörige Tabelle:

Code: Alles auswählen

Material_Class_ID;Share;Mean_Price;Deviation_Price; Mean_Ordersize
1;0,4;5;0,5;500
2;0,2;60;3;200
3;0,15;150;10;100
4;0,15;300;20;50
5;0,1;500;100;10
Zuletzt geändert von Anonymous am Freitag 22. Januar 2016, 15:07, insgesamt 2-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@ThoSchoo:

Code: Alles auswählen

In [1]: ' Mean_Ordersize' == 'Mean_Ordersize'
Out[1]: False
ThoSchoo
User
Beiträge: 20
Registriert: Freitag 8. Januar 2016, 12:54

@BlackJack
Ich versteh allerdings nicht warum :K
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@ThoSchoo: dann solltest Du die Definition von Gleichheit nachlesen. Auch Leerraum ist signifikant.
ThoSchoo
User
Beiträge: 20
Registriert: Freitag 8. Januar 2016, 12:54

Ja ich hab es gefunden .. Beim erstellen der CSV ist eine Leerzeile gewesen ;)
Trotzdem Danke !!
Antworten