2010-05-18 10 views
5

Mam skrypt Perl wstawiający dane do PostgreSQL według pliku tekstowego rozdzielanego potokami. Czasami pole ma wartość zerową (zgodnie z oczekiwaniami). Jednak Perl czyni to pole pustym łańcuchem, a instrukcja wstawiania Postgreatora nie powiedzie się.Jak wstawić puste pola z DBD :: Pg Perla?

Oto fragment kodu:


use DBI; 

#Connect to the database. 
$dbh=DBI->connect('dbi:Pg:dbname=mydb','mydb','mydb',{AutoCommit=>1,RaiseError=>1,PrintError=>1}); 

#Prepare an insert. 
$sth=$dbh->prepare("INSERT INTO mytable (field0,field1) SELECT ?,?"); 

while (<>){ 
    #Remove the whitespace 
    chomp; 

    #Parse the fields. 
    @field=split(/\|/,$_); 

    print "$_\n"; 

    #Do the insert. 
    $sth->execute($field[0],$field[1]); 
} 

A jeśli wejście jest:

 
a|1 
b| 
c|3 

EDIT: Za pomocą tego wejścia zamiast.

 
a|1|x 
b||x 
c|3|x 

To się nie uda pod numerem b|.

DBD::Pg::st execute failed: ERROR: invalid input syntax for integer: ""

Po prostu chcę wstawić pustą wartość na pole1. Jakieś pomysły?

EDYCJA: Uprościliśmy dane wejściowe w ostatniej chwili. Stare dane sprawiły, że działało z jakiegoś powodu. Teraz zmieniłem dane wejściowe na coś, co spowoduje awarię programu. Zauważ też, że field1 jest zerowym typem danych całkowitych.

+0

ten kod działa tutaj, Perl 5.10.1, DBD :: Pg 2.15.1 , Postgres 8.4. Dlaczego używasz SELECT? zamiast VALUES (?,?)? – MkV

+0

Należy również użyć ścisłego; używać ostrzeżeń; i popraw swoje deklaracje zmiennych – MkV

+0

O formacie SQL. Prawdziwy kod ma w rzeczywistości kilka złączeń w tym wyborze. – User1

Odpowiedz

4

nie jestem pewien, czy pan przetestowany swojej wklejony kod i dane razem, pracują z Perl 5.10.1, DBD :: Pg 2.15.1 i PostgreSQL 8.4. Powinieneś także używać ścisłych i ostrzeżeń i nie polegać na zakresie pakietów dla zmiennych.

Jeśli zmienisz swój kod i dane, aby użyć co najmniej trzech pól, pozostawiając pusty numer jeden, możesz wywołać błąd z DBD :: Pg. Dodaj linię podobnego do kodu przed wykonaniem przygotowane oświadczenie:

map { $_ eq '' and $_ = undef } @field; 

Aby odwzorować pustych strun w @field do undef

+0

Zajęło to przekształcenie pustych łańcuchów w wartości zerowe. To dziwne, że usunięcie pola w danych wejściowych spowodowało, że pusty ciąg stał się pusty (co najmniej zdaje się, że się wydarzyło). – User1

+0

Foreach będzie o wiele bardziej czytelny tutaj –

+0

Jeśli ciąg znaków kończy się na znakach, które dzielą się, np. "A | 4 |" wtedy ostateczny element tablicy nie zostanie w ogóle zapełniony, a nie przekształcony w pusty ciąg, więc jest to undef, patrz perldoc -f split. – MkV

0

undef zwykle mapuje na NULL. Wygląda na to, że wstawiasz pusty ciąg, który nie jest taki sam jak undef.

+0

testowałeś kod? Tylko z dwoma polami? – MkV

2

Zestaw map DBI undef na NULL. (Zdefiniowanej Ness Perl vs. logiki fałszu jest rzeczywiście bardzo dobre dopasowanie do Trójka logiki SQL.)

Tak w pętli while, wystarczy sprawdzić, czy pole wskazane jest pusty ciąg znaków, a jeśli tak, sprawiają, że undef zamiast:

while (<>){ 
    ... 
    #Parse the fields. 
    @field=split(/\|/,$_); 

    if ($field[1] eq '') { 
     # handle NULLs 
     $field[1] = undef; 
    } 

    #Do the insert. 
    $sth->execute($field[0],$field[1]); 
} 
+0

twoje, jeśli nigdy nie jest prawdziwe, i jeśli użyjesz ścisłego; używać ostrzeżeń; na twoim kodzie pojawia się "Używanie niezainicjowanej wartości $ pole [1] w łańcuchu eq" – MkV

+1

@james, nie jestem pewien co masz na myśli. Działa dobrze, gdy włączone są 'strict' i' ostrzeżenia' oraz warunkowe.'perl -Mstrict -Mrogi -MData :: Dumper -le 'my $ str =" a | b || d "; my @a = split/\ | /, $ str; if ($ a [2] eq "") {$ a [2] = undef; }; print Dumper \ @ a'' – friedo

+0

Działa teraz, ale ponieważ pytanie zostało pierwotnie postawione (i jak odpowiedziałeś), były tylko 2 pola i puste pole było na końcu, zwracając undef dla tego indeksu. – MkV