Je veux copier un fichier CSV dans une table Postgres. Il y a environ 100 colonnes dans cette table, donc je ne veux pas les réécrire si ce n’est pas nécessaire.
J'utilise la commande \copy table from 'table.csv' delimiter ',' csv;
mais sans table créée, je reçois ERROR: relation "table" does not exist
. Si j'ajoute un tableau vide, je ne reçois aucune erreur, mais rien ne se passe. J'ai essayé cette commande deux ou trois fois et il n'y avait aucune sortie ni message, mais la table n'était pas mise à jour lorsque je l'ai vérifiée via PGAdmin.
Est-il possible d'importer un tableau avec des en-têtes inclus, comme ce que j'essaie de faire?
Cela a fonctionné. La première ligne contenait des noms de colonnes.
COPY wheat FROM 'wheat_crop_data.csv' DELIMITER ';' CSV HEADER
Avec la bibliothèque Python pandas
, vous pouvez facilement créer des noms de colonne et déduire des types de données à partir d'un fichier csv.
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('postgresql://user:pass@localhost/db_name')
df = pd.read_csv('/path/to/csv_file')
df.to_sql('pandas_db', engine)
Le paramètre if_exists
peut être défini pour remplacer ou ajouter à une table existante, par exemple. df.to_sql('pandas_db', engine, if_exists='replace')
. Cela fonctionne également pour d'autres types de fichiers d'entrée, docs here et here .
La documentation de pg sur NOTES Say
Le chemin sera interprété par rapport au répertoire de travail du processus serveur (normalement le répertoire de données du cluster), pas au répertoire de travail du client.
Donc, généralement, en utilisant psql
ou un client, même sur un serveur local, vous avez des problèmes ... Et, si vous exprimez la commande COPY pour d'autres utilisateurs, par exemple. dans un fichier README de Github, le lecteur aura des problèmes ...
Le seul moyen d’exprimer chemin relatif avec des autorisations client consiste à utiliser STDIN,
Lorsque STDIN ou STDOUT est spécifié, les données sont transmises via la connexion entre le client et le serveur.
comme rappelée ici :
psql -h remotehost -d remote_mydb -U myuser -c \
"copy mytable (column1, column2) from STDIN with delimiter as ','" \
< ./relative_path/file.csv
J'utilise cette fonction depuis un moment sans aucun problème. Vous devez simplement fournir le nombre de colonnes présentes dans le fichier csv. Les noms des en-têtes de la première ligne seront créés et le tableau créé pour vous:
create or replace function data.load_csv_file
(
target_table text, -- name of the table that will be created
csv_file_path text,
col_count integer
)
returns void
as $$
declare
iter integer; -- dummy integer to iterate columns with
col text; -- to keep column names in each iteration
col_first text; -- first column name, e.g., top left corner on a csv file or spreadsheet
begin
set schema 'data';
create table temp_table ();
-- add just enough number of columns
for iter in 1..col_count
loop
execute format ('alter table temp_table add column col_%s text;', iter);
end loop;
-- copy the data from csv file
execute format ('copy temp_table from %L with delimiter '','' quote ''"'' csv ', csv_file_path);
iter := 1;
col_first := (select col_1
from temp_table
limit 1);
-- update the column names based on the first row which has the column names
for col in execute format ('select unnest(string_to_array(trim(temp_table::text, ''()''), '','')) from temp_table where col_1 = %L', col_first)
loop
execute format ('alter table temp_table rename column col_%s to %s', iter, col);
iter := iter + 1;
end loop;
-- delete the columns row // using quote_ident or %I does not work here!?
execute format ('delete from temp_table where %s = %L', col_first, col_first);
-- change the temp table name to the name given as parameter, if not blank
if length (target_table) > 0 then
execute format ('alter table temp_table rename to %I', target_table);
end if;
end;
$$ language plpgsql;