Importer un fichier CSV dans une base de données

Des propositions de code sont données ci-dessous pour réaliser le projet suivant. Normalement il suffit de les copier-coller, puis de les adapter à la situation choisie avant de les exécuter.

  1. Choisir un ficher CSV de taille conséquente, à partir de data.gouv.fr ou autre...
  2. Analyser et décrire son contenu.
  3. Créer la structure de la base de données en SQL.
  4. Importer les données avec SQLite3 à partir du fichier CSV.
    Le fichier ".db" devra porter un nom de forme "monNom-monTheme.db". A ramener sur une clé USB.
  5. Proposer des requêtes d'exploitation de ce fichier, et les résultats obtenus.

Le code proposé par Mathis :


import csv

# on import le csv avec la bibliothèque 'csv'
# le résultat est sous forme d'un itérable, une liste de ligne
result = []
with open('titanicCSV.csv') as csvfile :
    reader = csv.reader(csvfile, delimiter = ';')
    for row in reader :
        result.append(row)

# on ouvre le fichier SQL

f = open('titanic.sql', "w")

for row in result[1:]:
    requete = "INSERT INTO titanic VALUES(" # on rédige la requete
    requete += row[0] + ","
    requete += row[1] + ","
    requete += '"' + row[2] + '"' + ","
    requete += row[3] + ","
    requete += row[4] + ","
    requete += row[5]
    requete += "); \n"
    f.write(requete) # on enregistre la requete

f.close()


Voici le code proposé par Gaël, Paul et Louis.


import csv, sqlite3

with open('titanicCSV.csv', "r") as fichier :
    tableau = csv.DictReader(fichier, delimiter = ";")
    to_db = [ ( int(i['classe']) , int(i['survie']) , i['nom'] , int(i['sexe']) , int(i['age']) , int(i['tarif']) ) for i in tableau]
                    
conn = sqlite3.connect('titanic.db')

curseur = conn.cursor()

conn.executemany("INSERT INTO titanic VALUES(?,?,?,?,?,?)", to_db)

conn.commit()

conn.close()


Voici le code proposé par M. Deslandes.


import csv, sqlite3


def supprime_symbole(chaine, carac):
    retour = ""
    for lettre in chaine :
        if lettre != carac :
            retour += lettre
    return retour


def supprime_espace_debut_fin(chaine):
    if chaine == "" :
        return chaine
    lettre = chaine[0]
    while lettre == " " :
        chaine = chaine[1:]
        if chaine == "" :
            return chaine
        lettre = chaine[0]
    if chaine == "" :
        return chaine
    lettre = chaine[-1]
    while lettre == " ":
        chaine = chaine[:-1]
        if chaine == "" :
            return chaine
        lettre = chaine[-1]
    return chaine


def validation(valeur, genre):
    valeur = supprime_espace_debut_fin(valeur)
    if valeur == "":
        return 'NULL'
    if genre == 'int' or genre == 'float' : # si le type est numérique, on le laisse tel quel
        return valeur
    else :
        return "'" + supprime_symbole(valeur, "'") + "'"  # sinon on vire les apostrophes et renvoie la valeur avec
    

def CSV_to_DATABASE(source, separateur, nomBase, nomTable, champs):
    fichier = open(source) # le fichier source, au format CSV
    entete = champs
    data = csv.DictReader(fichier, delimiter = separateur)
    listeChamps = '' # on crée la liste des champs
    for elem in champs :
        listeChamps = listeChamps + elem + ','
    listeChamps = listeChamps[:-1] # on enlève la dernière virgule ajoutée
    conn = sqlite3.connect(nomBase)
    curseur = conn.cursor()
    # ici on peut si besoin vider la base...
    for ligne in data :
        listeValeurs = ""   #  on initialise la liste des valeurs
        for champ in champs : 
            val = ligne[champ]  # on récupère les valeurs de chaque champ voulu
            val = validation(val, champs[champ])  # on fait valider la valeur selon son type
            listeValeurs = listeValeurs + str(val) + ','
        listeValeurs = listeValeurs[:-1]  # on enlève la virgule
        sql = "INSERT INTO " + nomTable + " ( " + listeChamps + " )  VALUES ( " + listeValeurs + " ) ; \n"
        conn.execute(sql)
    conn.commit()
    conn.close()
    fichier.close()
      
    
# un petit test du programme...

dico = {"classe" : "int", "survie" : "int" , "nom" : "str", "sexe" : "int", "age" : "int", "tarif" : "float"}

CSV_to_DATABASE("titanicCSV.csv", ";" , "titanic.db", "titanic", dico )


def CSV_to_SQL(source, separateur, destination, nomTable, champs):
    # on récupère les paramètres
    fichier = open(source) # le fichier source, au format CSV
    export = open(destination, "w") # le fichier de sortie, au format SQL
    entete = champs
    data = csv.DictReader(fichier, delimiter = separateur)
    # rappel : c'est un itérable, une liste de dictionnaire.
    # on crée la str ( champ1, champ2, champ3...)
    listeChamps = ''
    for elem in champs :
        listeChamps = listeChamps + elem + ','
    listeChamps = listeChamps[:-1] # on enlève la dernière virgule ajoutée
    # print(listeChamps) # pour voie la liste des champs
    # on parcourt les data et pour chaque on fait la liste des valeurs
    for ligne in data :
        listeValeurs = ""   #  on initialise la liste des valeurs
        for champ in champs : 
            val = ligne[champ]  # on récupère les valeurs de chaque champ voulu
            val = validation(val, champs[champ])  # on fait valider la valeur selon son type
            listeValeurs = listeValeurs + str(val) + ','
        listeValeurs = listeValeurs[:-1] 
        # print(listeValeurs) # pour voir la liste des valeurs
        sql = "INSERT INTO " + nomTable + " ( " + listeChamps + " )  VALUES ( " + listeValeurs + " ) ; \n"
        # print(sql) # pour voir la requete
        export.write(sql)
    fichier.close()
    export.close()
        
    



# un petit test du programme...

dico = {"classe" : "int", "survie" : "int" , "nom" : "str", "sexe" : "int", "age" : "int", "tarif" : "float"}

CSV_to_SQL("titanicCSV.csv", ";" , "titanicINSERT.sql", "titanic", dico )