Estou trabalhando em um programa java que importa um arquivo csv para um banco de dados Postgresql. Algumas linhas nos arquivos csv contêm vírgulas de escape, e vírgulas também são o delimitador. Quando importo esse arquivo com mysql, ele funciona bem, mas com postgresql recebo um erro dizendo que há mais tokens nos dados do que colunas para importá-los ( org.postgresql.util.PSQLException: ERROR: extra data after last expected column
)
Como posso fazer com que COPY importe essas linhas com as vírgulas de escape tratadas como texto em vez de delimitadores?
Meu comando COPY
"COPY temporary_%s (%s) FROM STDIN with csv"
;
E para comparação, a versão mysql funciona
"LOAD DATA LOCAL INFILE ? "
+ "INTO TABLE temporary_%s "
+ "FIELDS TERMINATED BY ',' ENCLOSED BY '\"' "
+ "LINES TERMINATED BY '\n' "
+ "(%s)";
Tenho tentado anexar algo como ESCAPE '\\'
à declaração postgresql, mas não parece ter feito nada. Soluções que vi sugerem envolver cada pedaço de dados entre aspas, mas não tenho controle sobre o conteúdo do arquivo csv, e ele é bem grande (até ~8gb), então prefiro não ter que fazer pré-processamento nele se isso não for necessário.
E o java
BaseConnection physicalConnection =
(BaseConnection) connection.unwrap(Class.forName("org.postgresql.core.BaseConnection"));
CopyManager copyManager = new CopyManager(physicalConnection);
FileReader fileReader = new FileReader(fileName);
copyManager.copyIn(String.format(PROCEDURE_POSTGRES, tableName, columns), fileReader);
E uma linha de dados de amostra com este problema (o \,
)
0.2\,4,000088797e02a729c72ff07bb9c5a84ef27e6b7c,1541592473000,1545585645000,0.3.0,1,NULL,NULL
editar para responder a perguntas: O tipo de dados para essas colunas é charvar(255). O que eu gostaria de ver é as vírgulas sendo inseridas como dados, por exemplo, neste caso, 0.2,4
devem ser os dados na primeira coluna.
Mensagem de erro completa (com nomes apagados para privacidade)
2025-02-04 12:00:40 2025-02-04 17:00:40.374 UTC [89725] STATEMENT: COPY table_name (***, ***, ***, ***, ***, ***, ***, ***, ***) FROM STDIN with csv"
2025-02-04 12:03:48 2025-02-04 17:03:48.733 UTC [89890] ERROR: extra data after last expected column
2025-02-04 12:03:48 2025-02-04 17:03:48.733 UTC [89890] CONTEXT: COPY table_name, line 10: " 0.2\,4,000088797e02a729c72ff07bb9c5a84ef27e6b7c,1541592473000,1..."
também, encontrei uma solução(?) onde não uso CSV
. Não sei por que isso está funcionando, mas está - todas as linhas estão sendo importadas e parecem corretas. Isso pode acabar sendo tudo o que preciso (fazer mais testes)
"COPY temporary_%s (%s) FROM STDIN DELIMITER ','";