0
votes

Meilleure pratique pour ajouter des données à une base de données PostgreSQL?

J'essaie d'ajouter une quantité statique de données à partir d'un fichier csv dans une base de données postgresql hébergée sur Heroku.

Au départ, je faisais cela par programme dans mon fichier application.py, qui servait le serveur Web avec flask. J'interagis avec la base de données en utilisant SQLalchemy

En gros, j'ai ce bloc de code dans lequel je valide des données dans ma base de données avant de gérer les routes.

for el in books:
   db.execute("INSERT INTO books (isbn, title) VALUES (:isbn, :title)",
             {"isbn": el[0], "title": el[1]})
   db.commit


3 commentaires

Les données du CSV changent-elles un jour?


@AdrianKlaver les données du CSV ne changent jamais. Il ne s'agit que de 5000 entrées dans un format que je sais déjà analyser.


@AdrianKlaver Tov a suggéré quelque chose ci-dessous, mais cela ne contourne toujours pas le fait que je vérifierais CHAQUE fois que je redémarrerais le serveur Web pour voir les changements. Il doit y avoir une meilleure façon de le faire une seule fois? Je ne suis pas sûr cependant.


3 Réponses :


1
votes

Vous écrivez: "Je valide les mêmes données chaque fois que je redémarre mon serveur Web".

Une base de données stocke les données de manière persistante, ce qui signifie que les données restent dans votre base de données (une exception est un in-memory-db , mais même ce type de dbms permet de stocker les données sur disque).

En conséquence, après avoir exécuté votre code n fois, les données devraient y être n fois (en supposant que vous ne supprimez pas également la création de la table à chaque fois).

Vous pouvez facilement vérifier cela, par exemple en comptant les occurrences isbn:

select count(isbn) as c, isbn from books group by isbn order by c desc;

En supposant que dans le csv chaque isbn est unique, toutes les valeurs de comptage doivent être 1 code >, mais dans votre cas c'est plutôt n.

Alors nettoyez votre table et faites l'import une fois. Insérez uniquement les nouvelles données, mettez à jour uniquement les données existantes et modifiées.


2 commentaires

Alors, j'ai juste besoin de faire une simple vérification pour cet ID de livres avant d'essayer de l'insérer à nouveau dans la base de données? Je pense que vous avez raison sur les données qui s'y trouvent n fois, c'est ce que je voulais dire.


Oui, si vous souhaitez vérifier si un livre est déjà dans le tableau, vous pouvez vérifier l'ISBN avant de l'insérer.



1
votes

J'ai réalisé que parce que les données ne changent pas, je pouvais simplement utiliser la commande COPY de sql.

Après avoir lancé la ligne de commande avec psql DATABASE_URL , j'ai pu TRUNCATE la table pour supprimer tout ce qu'elle contient, puis je l'ai fait:

\ copy books (column_name_1, column_name_2, ...) from 'path / to / csv' delimiter ',' csv header;

le délimiteur est la manière dont les valeurs de votre champ sont séparées dans l'en-tête csv et l'option d'en-tête csv indique à sql la répartition du fichier csv. Dans mon cas, l'en-tête csv était la première ligne, que sql ignore avec l'option d'en-tête csv, cela ressemblait à ceci:

isbn,titre, auteur, année

Merci à tous ceux qui ont répondu.


0 commentaires

0
votes

Si les données du CSV ne changent jamais, \ copiez-les dans la base de données une fois en dehors de l'application, puis déposez le code qui le fait au démarrage. Si vous prévoyez qu'il pourrait y avoir des changements dans le futur, ayez du code que vous pouvez déclencher à l'intérieur de l'application (dans la section admin si cela existe) ou à l'extérieur. Ce que fait ce code dépendrait de ce que seraient les changements. Si les modifications consistent simplement à ajouter ou à supprimer des entrées complètes, vous pouvez vous en sortir avec quelque chose comme (pseudo code):

CREATE TEMP table data_staging(fields to match CSV);
\copy data_staging FROM  csv_file
--INSERT new items
INSERT INTO books() SELECT * from data_staging AS ds  LEFT JOIN books ON ds.isbn = books.isbn WHERE books.isbn IS NULL;
--If you want to DELETE
INSERT INTO books() SELECT * FROM books LEFT JOIN  data_staging AS ds    ON books.isbn = ds.isbn WHERE ds.isbn IS NULL;

La mise à jour des lignes nécessiterait plus de travail car vous auriez besoin de parcourir les enregistrements et voir s'il y a des changements entre ceux de la table de préparation et de la table des livres.


0 commentaires