CSV Import via COPY FROM geht bei Nullvalue "\N" nicht

Hallo zusammen,

ich habe mir eine kleine Testtabelle erstellt, anhand derer ich euch mein CSV-Import Problem zeigen möchte. Die Tabelle besteht aus 2 Spalten: zum Einen eine Autoinkrementspalte und zum Anderen eine Spalte vom Typ “publish year”, wobei es sich dabei um eine varchar(100)-Spalte mit entsprechendem Constraint handelt (Die Jahreszahl muss aus 4 Zahlen bestehen). Im Gegensatz zur “ID” Spalte, kann die “value”-Spalte NULL Werte enthalten.

  1. Zunächst also mal die Tabelle (kann man bei sich direkt “nachkochen”)
CREATE DOMAIN publish_year AS VARCHAR (100) CONSTRAINT publish_year_format CHECK
  (VALUE SIMILAR TO '[0-9][0-9][0-9][0-9]');
COMMENT ON DOMAIN publish_year IS 'Year of publication...';

CREATE TABLE mytable
(
  "ID" serial NOT NULL,
  "value" publish_year,
  CONSTRAINT pk_mytable PRIMARY KEY ("ID")
)
WITH (
  OIDS=FALSE
);
ALTER TABLE mytable OWNER TO postgres;
  1. Es soll folgende CSV zum Test importiert werden:
"id","value"
1,"\N"
2, "2010"
  1. Abschließend soll der eigentliche CSV-Import via “Copy x FROM y” ausgeführt werden.
    Dem Copy-Befehl gebe ich mit, dass …
    a) … es sich um eine CSV-Datei handelt
    b) … die Datei eine Headerzeile hat
    c) … die Nullwerte als \N dargestellt werden
COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS E'\N';

Problem:
Es kommt immer folgende Fehlermeldung. Wenn ich die Spalte “value” ganz normal ohne Constraint definiere, nämlich einfach nur als varchar(100), so geht der Importbefehl erfolgreich durch. Postgres erkennt offenbar an dieser Stelle nicht, dass mit “\N” ein Nullwert gemeint ist.

[WARNING  ] COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS E'\N'
            ERROR:  value for domain publish_year violates check constraint "publish_year_format"
            CONTEXT:  COPY mytable, line 2, column value: "\N"

Evtl. hat von euch ja jmd. eine Idee oder hat schonmal sowas ähnliches gehabt. Ich bin für jede Hilfe dankbar.

Wenn ich den Import via phpPGAdmin mache und eben dort den Import aufrufe, so klappt dieser auch.
phpPGAdmin scheint da also auch einen anderen “Copy from”-Befehl anzuwenden…ich weiß leider nicht, welcher das ist :frowning:

Grüße

PS: Ich weiß, dass das Beispiel sehr konstruiert erscheint, aber das liegt daran, dass ich meine eigentliche Tabelle auf das Wesentliche reduziert habe um eben den entsprechenden Fall für euch reproduzieren zu können. Dass man für das Ablegen von Jahreszahlen einen Integer nehmen sollte, weiß ich natürlich … :slight_smile:

Warum in aller Welt verwndest Du für eine Spalte, die ganz offensichtlich INT-Werte enthalten soll, einen varchar(100)?

Okay:

test=# create table bla (n text);
CREATE TABLE
test=*# copy bla from stdin;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> \N
>> '\N'
>> "\N"
>> \.
test=*# select * from bla;
  n
-----

 'N'
 "N"
(3 rows)

Du siehst Deinen fehler?


Andreas

Hallo,

Da ich diese Nachfrage erwartet hatte, habe ich das direkt bei Threaderstellung im “PS” am Ende reingeschrieben. Das hast Du wohl leider überlesen.
Mir ist klar, dass man das normalerweise nicht so macht, aber für das Beispiel war es notwendig einen constraint auf der “value”-Spalte zu erstellen und da muss man eben eine regex als constraint hinterlegen.
Das hat aber mit dem eigentlichen Import-Problem nichts zu tun. Sorry für die Verwirrung.

Leider nein. Deinem Beispiel nach würde ja die Angabe von \N die korrekte Wahl sein, um Postgres dies entsprechend als Null-Wert zu verklickern. Das hatte ich ja bereits versucht und meinen Copy-From Befehl entsprechend gestaltet:

COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS E'\N';

Liefert leider: "Error: value for domain publish_year violates check constraint “publish_year_format”

Folgende Varianten gehen auch nicht (ist mir klar warum; nur der Form halber):

COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS '\N';  --error: nonstandard use of escape in a string literal
COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS E"\N"; --error: syntax error at or near "E"
COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS \N; --error: syntax error at or near "\"

Nochmal etwas konkreter:

1.) Meine CSV-Datei gehorcht der Standardnorm, d.h. der “\N”-Eintrag in der value Spalte ist korrekt, da die Spalte als varchar definiert ist und alle varchar/text-Spalten werden in einem validen CSV mit doppelten Anführungszeichen escaped.
2.) Wenn ich die Datei via phpPGAdmin importiere, klappt der Import ohne Probleme, d.h. Postgres versteht meine CSV, wenn man sie mit dem richtigen Befehl importiert (ich kenne diesen “richtigen” Befehl leider nicht)
3.) Wenn ich meine Spalte ganz normal als varchar definiere (also ohne den constraint), so klappt der import mit folgendem Befehl wunderbar:

COPY mytable FROM '/tmp/testdata.csv' CSV HEADER NULL AS E'\N';

Mir leuchtet aber nach wie vor nicht ein, wo da das Problem liegen könnte?