2010-05-18 13 views
5

Tôi có một tập lệnh chèn Perl vào Postgres theo một tệp văn bản được phân tách bằng đường ống. Đôi khi, một trường là null (như mong đợi). Tuy nhiên, Perl làm cho trường này thành một chuỗi rỗng và câu lệnh chèn Postgres không thành công.Làm cách nào để chèn các trường rỗng bằng DBD :: Pg của Perl?

Dưới đây là một đoạn mã:


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]); 
} 

Và nếu đầu vào là:

 
a|1 
b| 
c|3 

EDIT: Sử dụng đầu vào này để thay thế.

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

Nó sẽ thất bại tại b|.

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

Tôi chỉ muốn chèn null vào trường1 để thay thế. Bất kỳ ý tưởng?

EDIT: Tôi đã đơn giản hóa đầu vào ở phút cuối cùng. Các đầu vào cũ thực sự làm cho nó hoạt động vì một lý do nào đó. Vì vậy, bây giờ tôi đã thay đổi đầu vào thành một cái gì đó mà sẽ làm cho chương trình thất bại. Cũng lưu ý rằng field1 là một kiểu dữ liệu số nguyên nullable.

+0

Mã này làm việc ở đây, Perl 5.10.1, DBD :: Thạc 2.15.1 , Postgres 8.4. Ngoài ra tại sao bạn sử dụng SELECT?,? thay vì VALUES (?,?)? – MkV

+0

Ngoài ra, hãy sử dụng nghiêm ngặt; sử dụng cảnh báo; và sửa các khai báo biến của bạn – MkV

+0

Giới thiệu về định dạng SQL .. mã thực sự thực sự có một số phép nối trên lựa chọn đó. – User1

Trả lời

4

tôi không chắc chắn bạn đã kiểm tra liệu mã và dữ liệu dán lại với nhau, họ làm việc với Perl 5.10.1, DBD :: Thạc 2.15.1 và Postgres 8.4. Ngoài ra, bạn nên sử dụng nghiêm ngặt và cảnh báo và không dựa vào phạm vi gói cho các biến của bạn.

Nếu bạn thay đổi mã và dữ liệu của mình để sử dụng ba hoặc nhiều trường, để trống một trường không có thiết bị đầu cuối, bạn có thể kích hoạt lỗi từ DBD :: Pg. Thêm một dòng như thế này để mã của bạn trước khi thực hiện báo cáo kết quả chuẩn bị:

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

Để ánh xạ chuỗi rỗng trong @field để undef

+0

Đó là chăm sóc chuyển đổi các chuỗi rỗng để nulls. Đó là lẻ rằng việc loại bỏ một trường trong đầu vào gây ra chuỗi rỗng để trở thành một null (ít nhất là những gì dường như đã xảy ra). – User1

+0

foreach sẽ dễ đọc hơn ở đây –

+0

Nếu chuỗi kết thúc bằng các ký tự bạn đang chia nhỏ, như 'a | 4 |' sau đó phần tử mảng cuối cùng không được điền đầy đủ, không được biến thành một chuỗi rỗng, do đó, nó là undef, xem phân chia perldoc -f. – MkV

0

undef thường ánh xạ tới NULL. Có vẻ như bạn đang chèn chuỗi trống không giống như undef.

+0

bạn đã kiểm tra mã? Chỉ với hai trường? – MkV

2

Gói DBI bản đồ undef đến NULL. (Perl của định nghĩa-Ness vs Logic sự sai lầm thực sự là một sự phù hợp khá tốt cho logic trinary SQL của.)

Vì vậy, trong while vòng lặp của bạn, chỉ cần kiểm tra nếu trường chỉ định là một chuỗi rỗng, và nếu như vậy, làm cho nó undef thay vì:

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

nếu bạn không bao giờ đúng, và nếu bạn sử dụng nghiêm ngặt; sử dụng cảnh báo; trên mã của bạn, bạn nhận được 'Sử dụng giá trị uninitialized $ trường [1] trong chuỗi eq' – MkV

+1

@ james, tôi không chắc chắn những gì bạn có ý nghĩa. Nó hoạt động tốt với 'strict' và' warningnings' được bật và thành công có điều kiện.'perl -Mstrict -Mwarnings -MData :: Dumper -le 'my $ str =" a | b || d "; @a = split/\ | /, $ str; if ($ a [2] eq "") {$ a [2] = undef; }; in Dumper \ @ a'' – friedo

+0

Nó hoạt động ngay bây giờ, nhưng khi câu hỏi ban đầu được đặt ra (và khi bạn trả lời nó), chỉ có 2 trường và trường trống ở cuối, trả về undef cho chỉ mục đó. – MkV

Các vấn đề liên quan