Syntaxfehler

Hallo,
ich versuche Datensätze aus einem CSV in eine Tabelle per Kommandozeile zu übertragen. Ich habe diverse Varianten durch, keine will mir gelingen.
Eine Variation meiner Versuche ist diese:

postgres=# \c Buch2019
You are now connected to database "Buch2019" as user "postgres".
Buch2019=# copy umsaetze from \home\u.csv;
Invalid command \home. Try \? for help.
Buch2019-# copy umsaetze from '\home\u.csv';
ERROR:  syntax error at or near "copy"
LINE 2: copy umsaetze from '\home\u.csv';
        ^

Kann mir da jemand den richtigen Weg weisen `?

copy umsaetze from ‘/home/u.csv’;

test=# select * from foo;
test=*# copy foo to '/tmp/foo.csv';
COPY 1000000
test=*# delete from foo;
DELETE 1000000
test=*# copy foo from '/tmp/foo.csv';
COPY 1000000
test=*#

works for me.

Ok, die backslashs sind falsch, das habe ich gerade auch festgestellt.
Kann ich dem Befehl mitteilen, dass die erste Zeile des CSV’s die Feldnamen beinhaltet ?

Die erste Spalte in der TAbelle ist als PK festgelegt mit einem Autoincrement.
Wie bringe ich das dem Copy bei, dass der Wert Kontobezeichnung, nicht in das Feld ID zu schreiben ist.

ERROR:  invalid input syntax for integer: "DE1762050000....
  • Doku lesen
  • CSV HEADER
  • Du kannst angeben, in welche Spalten gelesen werden soll
  • siehe erster Punkt

ja da hast du recht, ich sollte mich da näher einlesen. Meistens nutze ich auch die Doku, um die Dinge nachzulesen.
Manchmal hat man auch ein Brett vorm Kopf -> siehe Backslah anstelle der Slashs.
Manchmal ist es aber auch sehr angenehm Antworten von erfahrenen Usern zu bekommen, das spart oft Zeit und Probierei.

Momentan bin ich soweit:

Buch2019=# copy umsaetze (auftragskonto, buchungstag, valutadatum, buchungstext, verwendungstext, beguenstigter_zahlungspflichtiger, kontonummer, blz, betrag, waehrung,info) from ‘/home/u.csv’ csv header delimiter ‘;’;
ERROR: invalid input syntax for type numeric: “-9,48”

Ich nehme an, dass PostgresSql den Punkt anstelle des KOmmas im Betrag erwartet.
Wie löse ich das ?

als workaround könntest Du eine Tabelle mit ähnlicher Struktur erstellen, aber für diese Spalte TEXT verwenden. Dann machst Du ein

insert into ziel select to_number(…) from import_table;

(jetzt verkürzt, die anderen Spalten natürlich auch). Nachteil: doppelte Arbeit, doppelter Speicherverbrauch.

mühsam ernährt sich das Eichhörnchen.
Ich habe den Datentyp auf “money” umgestellt und dann ging es (fast )…

ERROR: invalid byte sequence for encoding “UTF8”: 0xfc
CONTEXT: COPY umsaetze, line 22
muss ich mal schauen was in line 22 steht :frowning:

Edit: er stört sich am “ü”…

is ja echt ätzend…

Bitte nicht den money Datentyp verwenden. Der hat keine Vorteile aber einen Haufen Nachteile.

https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_money

Aber der Fehler klingt danach, als wäre Deine Datei keine UTF-8 Datei sondern z.B. eine ISO-8859-1 - gibt mal beim COPY Befehl ein anderes Encoding an

Eventuell solltest du das Encoding deiner Eingangsdatei ändern (iconv unter Linux) oder mit set clientencoding auf Datenbankebene anpassen. Das Punktproblem kannst auch mit suchen/ersetzen in einem Editor lösen.

Gibt es denn keine Möglichkeit/Methode ein CSV per Konsole in die Datenbank zu schieben, die sich nicht an Umlauten oder an nicht ISO-konformen Daten (30.12.2019) stört ?

Das mit den Umlauten hängt mit dem Encoding der Datei zusammen und das kannst Du dem COPY Befehl mitteilen.

Für den Umgang mit nicht-standard Datumsformaten gibt es drei Möglichkeiten:

  1. Du änderst ie Datei ab - vermutlich zu aufwändig und deswegen nicht praktikabel (es sei denn Du kannst die Erzeugung der Datei kontrollieren)
  2. Du importierst in eine Zwischentabelle (wird oft als “staging table” bezeichnet) bei der die Spalte z.B. als text definiert ist. Dann verwendest Du einen INSERT … SELECT Befehl der das Datum mit to_date() umwandelt und in die eigentliche Zieltabelle einfügt. Das ist ein sehr übliches Vorgehen.
  3. Du verwendest eine anderes Tool für den Import, bei dem Du das Datumsformat explizit angeben kannst.
  1. Du schreibst einen kleinen Importer z.B.mit Python, der das automatisiert.

zu 1.) müsste ich schauen, ob der Download abänderbar ist. Ist ein Download meiner Umsätze vom Bankkonto. DAs möchte ich in mein Buchhaltungsprogramm was unter Linux bzw. Postgres läuft, importieren und das Buchhaltungsprogramm damit füttern.
zu 2.) ok, dann gibt es wohl keinen direkten Weg
zu 3.) ja, über Access wäre das kein Problem, wollte mich halt ein bißchen in Postgres einarbeiten

Hallo,
danke erstmal für die Hilfe.
Das mit dem Encoding habe ich vorgestern schon mal probiert, bzgl. des Datumsformats. Hat nichts gebracht.
Das Buchhaltungsprogramm erwartet UTF8 (bzw. die Datenbank, die zur Software verwendet wird).
Wie wird in einem CSV festgelegt, welches Coding verwendet wird ?
Wie gesagt, ist einfach ein simpler Download der Umsätze meiner Bank.
@Gisman: mit Python bin ich nicht vertraut.
VBA, MS SQL, etwas php, ganz früher mal Pascal und C, das ist es so in etwa.
Suchen & Ersetzen des “,” durch “.” ist nicht praktikabel, bzw. kann ich da nicht kontrollieren, ob an anderer Stelle falsch korrigiert wird.

Hab jetzt nochmal ein bisschen damit rumgespielt. So wie es aussieht richtet sich COPY nach dem DateStyle parameter.

Wenn die Datei als UTF-8 vorliegt, dann musst Du das beim COPY Befehl mit angegeben.

Das Folgende sollte also klappen:

set datestyle = 'DMY';
copy zieltabelle (spalte1, spalte2, spalte3, ...) from '/home/u.csv' with (format csv, header true, encoding 'UTF-8')

Die Spaltenreihenfolge muss so angegeben werden, wie die Spalten in der Eingabedatei vorhanden sind.

Zumindest bei mir hat das mit einem Datum im Format 21.11.2019 geklappt.

Muss ich ausprobieren. In der Fehlermeldung kam auch als Vorschlag zur Lösung, ich solle den datestyle ändern… konnte aber ad hoc nicht viel damit anfangen, bzw. versuchte dann über die option encoding irgendwas zu reißen.

Bekomme ständig Fehler wegen den blöden Umlauten.

Das mit dem Set Datastyle war goldrichtig !
Datensätze konnte eingelesen werden, allerdings vorher Bereinigen der Umlaute (Suchen&Ersetzen).

Das ist natürlich lästig.