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]과 같지 않을 것입니다. $ repeating은 0으로 설정되고 루프는 끝납니다. 그게 내가 생각하는거야. – prgrm

+0

나는 프로그램 밖에서 의미했다. 데이터베이스에 올바른 테이블이 있고이 테이블에 결과를 반환하는 데 적합한 데이터가 포함되어 있는지 확인하십시오. – AntonH

답변

2

이름이 존재하지 않으면 다시 행을 가져 오지 않는 것이 문제입니다. 해결 방법은 행을 가져 왔는지 확인하는 것입니다. 그렇지 않으면 파일 이름이 사용되지 않습니다. BTW, 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++; 
    } 

편집 :이 작업을해야합니다. 드라이버를 요청하면 모든 드라이버에서 똑같이 작동해야합니다.

두 경쟁 스크립트가 동시에 실행되는 경우 경합 조건에 영향을 받기 쉽습니다. 즉, 둘 다 동일한 "사용되지 않은"파일 이름을 선택할 수도 있습니다 . 그것을 피하기 위해 어떤 종류의 잠금 장치를 사용하고 있는지 확인하십시오.

+0

'$ sth-> rows'는'SELECT' 문에 대해 의미가 있다고 보장되지 않습니다. 'if ($ sth-> rows == 0) {$ 반복 = 0; }'with'last 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