¿Cómo copiar desde un archivo CSV a una tabla PostgreSQL con encabezados en un archivo CSV?


Quiero copiar un archivo CSV a una tabla Postgres. Hay alrededor de 100 columnas en esta tabla, así que no quiero reescribirlas si no tengo que hacerlo.

Estoy usando el comando \copy table from 'table.csv' delimiter ',' csv; pero sin una tabla creada obtengo ERROR: relation "table" does not exist. Si agrego una tabla en blanco no recibo ningún error, pero no pasa nada. Probé este comando dos o tres veces y no había salida ni mensajes, pero la tabla no se actualizó cuando la revisé a través de pgAdmin.

¿Hay una manera de importar una tabla con encabezados incluido como estoy tratando de hacer?

4 answers

Esto funcionó. La primera fila tenía nombres de columna.

COPY wheat FROM 'wheat_crop_data.csv' DELIMITER ';' CSV HEADER
 77
Author: G. Cito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-31 12:46:29

Con la biblioteca de Python pandas, puede crear fácilmente nombres de columna e inferir tipos de datos de un archivo 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)

El parámetro if_exists se puede establecer para reemplazar o anexar a una tabla existente, por ejemplo, df.to_sql('pandas_db', engine, if_exists='replace'). Esto también funciona para tipos de archivos de entrada adicionales, docs aquí y aquí.

 23
Author: joelostblom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-09 01:30:52

Alternativa por terminal sin permiso

La documentación de pg en NOTAS say

La ruta se interpretará en relación con el directorio de trabajo del proceso del servidor (normalmente el directorio de datos del clúster), no con el directorio de trabajo del cliente.

Entonces, geralmente, usando psql o cualquier cliente, incluso en un servidor local, tiene problemas ... Y, si usted está expresando comando de COPIA para otros usuarios, por ejemplo. en un README Github, el lector tendrá problema ...

La única forma de expresar ruta relativa con permisos de cliente es usando STDIN ,

Cuando se especifica STDIN o STDOUT, los datos se transmiten a través de la conexión entre el cliente y el servidor.

Como recordado aquí:

psql -h remotehost -d remote_mydb -U myuser -c \
   "copy mytable (column1, column2) from STDIN with delimiter as ','" \
   < ./relative_path/file.csv
 6
Author: Peter Krauss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:15

He estado usando esta función durante un tiempo sin problemas. Solo necesita proporcionar las columnas numéricas que hay en el archivo csv, y tomará los nombres de encabezado de la primera fila y creará la tabla por usted:

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;
 3
Author: mehmet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-25 23:11:36