2017-02-13 6 views
0

私は、ファイルから社会保障番号を読み取り、複数のテーブルにわたって情報を検索し、区切り文字付きのファイルに出力するperlスクリプトを作成しています。私はPERL 5とIBM informixを扱っています。私はそれが問題である私のREGEXであると感じています。PERL:ダッシュで社会保障番号を読み取るための正規表現

DBD :: Informix :: st実行に失敗しました:SQL:-1213:./corylist.pl行61、行461で文字が数値変換処理に失敗しました。 DBD :: Informix :: st fetchrow_array failed:SQL:-400:オープンされていないカーソルに対してフェッチを試みました。 ./corylist.pl line 63、line 461.

誰かが正しい方向に向かって私を微笑んでください。ありがとうございました!

while(<IN>) { 
    $id = $_; 
    chomp $id; 
    $id =~ m/^\d{3}-\d{2}-\d{4}$/; 
    #print "$id\n"; 

$STMT = <<EOF; 
select i.ss_no, 
    i.fullname,    i.firstname,i.lastname,i.addr_line1,i.addr_line2,i.city,i.st,i.zip,r.res_ctry,r.res_cty, 
    i.phone,NVL(aa.phone," ") cell,NVL(a.line1," ") stuemail,NVL(pa.line1," ") peremail 

    from id i, 
    prof r, 
    outer aa_rec a, 
    outer aa_rec aa, 
    outer aa_rec pa 
where i.ss_no = $id 
and  i.id = r.id 
and  i.decsd <> "Y" 
and a.id = i.id and a.aa = "EML" and a.end_date is null 
and pa.id = i.id and pa.aa = "OEML" and pa.end_date is null 
and pa.beg_date = (select max(beg_date) from aa_rec where aa = "OEML" and id=$id and end_date is null) 
and aa.id = i.id and aa.aa = "CELL" and aa.end_date is null 
group by  ss_no,fullname,firstname,lastname,addr_line1,addr_line2,city,st,zip,res_ctry,res_cty,phone,cell,stuemail,peremail 
order by fullname, ss_no 
EOF 

$sth = $db1->prepare($STMT); 
$sth->execute(); 

while (($id,$fullname,$fname,$lname,$addr1,$addr2,$city,$st,$zip,$ctry,$cnty,$phone,$cell,$stuemail,$peremail) = $sth->fetchrow_array()) { 

    $x = $id." | ". $fullname." | "; 
    $x .= $fname." | ".$lname." | ".$addr1." | ".$addr2." | ".$city." | ".$st." | ".$zip." | ".$ctry." | ".$cnty." | "; 
    $x .= $phone." | ".$cell." | ".$stuemail." | ".$peremail." | \n"; 
    print $out_fh $x; 
} 
+0

あなたの正規表現は何かにしかマッチしませんが、あなたは決して行動しません。あなたは代用しないで、あなたは捕まえません。その行は本質的に役に立たない。また、 '$ id'を使用しているSQLでは引用符もありません。代わりにプレースホルダを使用する必要があります。そしてエラーメッセージから、数値フィールドであると言いたいので、ダッシュを取り除く必要があります。 – simbabque

+0

'$ x。= $ fname。" |。$ lname。 "|"。$ addr1。 "|"。$ addr2。 "|"。$ city。 "|" $ st。 " "$ zip。" | ""|" $ cnt "|" | "' $ x。= "$ fname | $ lname | $ addr1 | $ addr2 | $ city | $ st | $ zip | $ ctry | $ cntyと書くことができます| "'? – Borodin

+0

'while'ループのたびに同じステートメントを'準備する 'ことは無駄です。 '$ sth = $ db1-> prepare($ STMT)'はブロック外に移動する必要があります。 – Borodin

答えて

4

あなたの正規表現は問題ありませんが、何もしていません。

$id =~ m/^\d{3}-\d{2}-\d{4}$/; 

$idがパターンと一致する場合、その行は真となります。それは他に何もしません。

A character to numeric conversion process failed

エラーメッセージに、データベースで数値が必要ですが、取得したデータを変換できないというエラーメッセージが表示されます。クエリに$idを使用しているので、それはダッシュでなければなりません。だからあなたのSSNが何らかの並べ替えの整数であると仮定するのは控えています。

エラーメッセージを取り除く最も簡単な方法は、数字以外のものを削除することです。それはダッシュ-を取り除き、他の人々が入力を考えたものを取り除きます。

while (my $id = <IN>) { 
    chomp $id; 
    $id =~ s/\D//g; # remove any non-digits 

    # ... 
} 

ここで挿入することができます。しかし、実際には、適切な引用符なしでSQLに直接変数を書き込むことによってデータを挿入するべきではありません。それはan invitation for SQL injectionです。代わりにplaceholdersを使用してください。あなたはprepare D文をexecuteとき

my $sql = "SELECT * FROM foo WHERE bar=?"; 

は今、あなたは$idに沿って通過します。

my $sth = $dbh->prepare($sql); 
$sth->execute($id); 

あなたはファイルを扱っている場合は、変数のすべてのコピーがかなり高価であるためではなくfetchrow_arrayfetchrow_arrayreffetchrow_hashrefを使用するのは良い考えかもしれません。また、DBIの使用方法の詳細については、this presentationをご覧ください。

実際に社会保障番号を確認するには、SSN::Validateを調べるとよいでしょう。あなたがそれを使用するならば、上で提案されたクリーンアップを行う必要はないようです。

また、Text::CSVを見ると、よりクリーンな方法でCSV出力を作成できます。

関連する問題