2017-12-14 13 views
0

私はこのコードを書いています。存在しないものが見つかるまで名前を確認し続けなければなりません。PerlはwhileループでSQL文を実行しません

while ($repeating == 1) { 
      $new_name = $i . "_" . $file; 
      my $sql= "SELECT file_name FROM PDFdocument WHERE user_id = '$id' AND file_name = '$new_name' "; 
      my $sth = $dbh->prepare($sql); 
      $sth->execute(); 
      while (my @row = $sth->fetchrow_array) { 
        //never enters here 
       if ($new_name ne $row[0]) { 

        $repeating = 0; 

       } 
      } 
      $i++; 
     } 

それはこの繰り返しループ内で立ち往生ので、それは、第二whileループに入ることはありません。なぜそれがうまくいかないのか分からない。私は以前にいくつかの他のSQL文を実行し、それらはすべて動作します。これは動作しない唯一のものです。

助けが必要ですか?

+0

クエリが実際にデータを返すと確信していますか? (ちょうど確かめて...) – AntonH

+0

@AntonHもしデータが返らなければ、$ new_nameは$ row [0]と等しくないでしょう。$ repeatは0に設定され、ループは終了します。それは私が思うものです... – prgrm

+0

私はプログラムの外を意味しました。データベースに適切なテーブルがあり、このクエリが結果を返すための正しいデータがテーブルに含まれていることを確認してください。 – AntonH

答えて

2

名前が存在しない場合は、行を返さないという問題があります。解決策は、行を取得するかどうかを確認することです。そうでなければ、ファイル名は使用されません。ところで、DBIがデータベースに送信したものをエスケープさせてください。 @ikegamiコメントで述べたように、$sth->rowsの動作はドライバに依存するので、SELECT文を扱うときには(もthe DBI docs参照の異なるデータベースエンジンに異なる値を返す場合があります:

while ($repeating == 1) { 
     $new_name = $i . "_" . $file; 
     # the question marks are placeholders 
     my $sql= "SELECT file_name FROM PDFdocument WHERE user_id = ? AND file_name = ? "; 
     my $sth = $dbh->prepare($sql); 
     # filling the placeholders while executing 
     $sth->execute($id, $new_name); 
     if(!$sth->fetch) { 
     # no rows found? this name must be fresh 
       $repeating = 0; 
     } 
     $i++; 
    } 

編集を:これは動作するはずです。

これは競合状態の影響を受けやすいことに注意してください。つまり、2つのスクリプトが同時に実行された場合、両方が同じ「未使用」ファイル名を選択する可能性がありますそれを避けるために何らかの種類のロック機構を使用していることを確認してください。

+0

'$ sth-> rows'は' SELECT'文では意味がありません。 'if($ sth-> rows == 0){$ repeating = 0; } ''最後にif!$ sth-> fetch; $ sth-> finish; ' – ikegami

2

最終的に$iが見つかると、$sth->fetchrow_arrayは空のリストを返しますので、は0を返します。したがって、ループは入力されません。


解決策1:

my $new_name; 
for (my $i=1; ; ++$i) { 
    $new_name = $i . "_" . $file; 
    $dbh->selectrow_arrayref(
     "SELECT 1 FROM `PDFdocument` WHERE `user_id` = ? AND `file_name` = ?", 
     undef, 
     $id, $new_name, 
    ) 
     and last; 
} 

解決策2:


注プレースホルダの使用。 SQLステートメントを作成するバグのある方法は、攻撃ではなく誤動作を起こす可能性があります。

+0

私はすべての質問に対してこれを行いましたが、注射攻撃のリスクはありませんでした。ユーザー入力はありません。ありがとう。 – prgrm

+1

ユーザー入力がないという事実は、バグがないことを意味するものではありません。実際には、文字列に特殊文字が決して含まれないようにする必要があります。常にプレースホルダを使用するのではなく(実際には物事をより読みやすくする)代わりに、そのことを確認する余分な作業(そしてそれが変更される危険性がある)はなぜですか? – ikegami

関連する問題