2015-01-29 5 views
0

나는 매우 이상한 결과를 얻고 있습니다. 나는 행을 postgresql 데이터베이스 테이블에 존재하는지 확인하고 첫 번째 루프에서 실제 값을 얻는 지 확인하려고합니다. 루프의 두 번째 반복과 거기에있는 모든 반복에서 undef를 얻습니다. 왜? 내가하지 말아야 할 일이 있습니까? 나는 준비를 사용하지 않기 때문에 마무리 등을하지 않아도됩니다.Perl DBI Postgresql : 거기에있는 데이터에 대해 undef를 반환합니다.

어떤 통찰력이라도이 문제를 디버그하는데 크게 도움이 될 것입니다.

죄송합니다. 지금은 코드가 너무 심해요. 나는 디버깅 사냥을하고 꽤 못생긴 것들을 만들었습니다.

추악한 샘플 출력에 대해서도 죄송합니다. stackoverflow 함께 잘 형식을 지정하는 방법을 모르겠습니다.

샘플 출력에서 ​​"이름 선택"출력물을 사용하지 마십시오. 첫 번째 반환 이후의 모든 반복은 undef를 반환합니다. 해당 SQL 호출이 파일의 끝을 향하고 있습니다.

#!/usr/bin/perl 

use LWP::Simple;    # From CPAN 
use JSON qw(decode_json);  # From CPAN 
use JSON::Parse 'parse_json'; 
use Data::Dumper;    # Perl core module 
use HTML::TreeBuilder 5 -weak; 
use Mojo::DOM; 
use DBI; 
use String::Util qw(trim); 
use strict;      # Good practice 
use warnings;     # Good practice 

my $initialize = 0; 
my $debug = 1; 

&main; 

sub main { 
    my $dbh = connect2db(); 

    unless(defined($dbh)) { 
     exit 1; 
    } 


    my $trendsurl; 

    my $sth = $dbh->prepare("SELECT company_name from companies where active=1"); 
    $sth->execute; 
    while(my $company = $sth->fetchrow_hashref()) { 
     #print Dumper($company)."\n"; 

     my $sth2 = $dbh->prepare("SELECT url from crawlers where company_name='$$company{'company_name'}' "); 
     $sth2->execute; 
     while(my $url = $sth2->fetchrow_hashref()) { 
      #print " NOW ON URL $$url{'url'} ##########\n"; 
      $trendsurl = $$url{'url'}; 
      chomp($trendsurl); 
      $trendsurl = trim($trendsurl); 
      print "URL: ".$trendsurl."\n"; 

      my $json = get($trendsurl); 
      die "Could not get $trendsurl!" unless defined $json; 

      my $parsed_json = parse_json($json); 
      my $items = $parsed_json->{'sections'}[0]->{'items'}; 

      foreach my $item_hash (@$items) { 
       #print Dumper($item_hash)."\n"; 
       my $category = $item_hash->{'name'}; 
       print "Lip Product Category: $category\n"; 

       foreach my $item (@{ $item_hash->{'items'} }) { 
        print Dumper($item)."\n"; 

        my $selectSQL = "select name from crawler_url where url='http://www.maccosmetics.com$item->{'uri'}' "; 

        print $selectSQL."\n" if($debug); 

        my ($productCount) = $dbh->selectrow_array($selectSQL); 

        my $date = localtime; 
        chomp($productCount); 
        trim($productCount); 
        chomp($item->{'name'}); 
        trim($item->{'name'}); 

        print "Select Name: '$productCount'\n"; 
        print "Item Name: '$item->{'name'}'\n"; 
        print "Do they equal: ", index($productCount, $item->{'name'}), " \n"; 

        print Dumper($productCount); 

        if(index($productCount, $item->{'name'}) == -1) { 
         my $insertSQL = "insert into crawler_url (first_seen,url,name,category,last_checked) values ('$date','http://www.maccosmetics.com$item->{'uri'}','$item->{'name'}','$category','$date') "; 
         print $insertSQL."\n" if($debug); 
         my $retVal = $dbh->do($insertSQL); 

         $insertSQL = "insert into urls (company_name,url) values ('$$company{'company_name'}','http://www.maccosmetics.com$item->{'uri'}') "; 
         print $insertSQL."\n" if($debug); 
         $retVal = $dbh->do($insertSQL); 
        } 
        else { 
         #We have seen this before 
         my $updateSQL = "update crawler_url SET (url,name,category,last_checked) = ('http://www.maccosmetics.com$item->{'uri'}','$item->{'name'}','$category','$date')"; 
         print $updateSQL."\n" if($debug); 
         my $retVal = $dbh->do($updateSQL); 
        } 
       } 
      } 
     } 
    } 
} 

sub connect2db { 
    return DBI->connect("dbi:Pg:dbname=xxxxxx", "xxxxx", "XXXXXX"); 
} 

샘플 출력 :이 라인을

my $selectSQL = "select name from crawler_url where url='http://www.maccosmetics.com$item->{'uri'}' "; 

펄 코드이다

URL: http://www.maccosmetics.com/includes/panel_nav/catalog.js?CATEGORY_ID=CAT163&LOCALE=en_US 

Lip Product Category: Lipstick 

$VAR1 = { 
    'uri' => '/product/shaded/168/310/Products/Lips/Lipstick/Lipstick/index.tmpl', 
    'description' => 'Colour plus texture for the lips. Stands out on the runway...', 
    'name' => 'Lipstick', 
    'thumbnail' => '/images/products/56x56/M300.jpg', 
    'header' => '/images/pnav/product/headers/pnav_M300_200x12_off.gif', 
    'id' => 'CAT168PROD310' 
}; 

select name from crawler_url where url='http://www.maccosmetics.com/product/shaded/168/310/Products/Lips/Lipstick/Lipstick/index.tmpl' 

Select Name: 'Lipstick                              ' 

Item Name: 'Lipstick' 


Do they equal: -1 

$VAR1 = 'Lipstick                              '; 
update crawler_url SET (url,name,category,last_checked) = ('http://www.maccosmetics.com/product/shaded/168/310/Products/Lips/Lipstick/Lipstick/index.tmpl','Lipstick','Lipstick','Wed Jan 28 21:15:40 2015') 

$VAR1 = { 
     'id' => 'CAT168PROD34492', 
     'thumbnail' => '/images/products/56x56/MX5G8N.jpg', 
     'header' => '/images/pnav/product/headers/pnav_MX5G8N_200x12_off.gif', 
     'description' => "Miley Cyrus\x{2019}s shade of VIVA GLAM Lipstick. Her super-sexy hot...", 
     'name' => 'VIVA GLAM Miley Cyrus Lipstick', 
     'uri' => '/product/shaded/168/34492/Products/Lips/Lipstick/VIVA-GLAM-Miley-Cyrus-Lipstick/index.tmpl' 
    }; 

select name from crawler_url where url='http://www.maccosmetics.com/product/shaded/168/34492/Products/Lips/Lipstick/VIVA-GLAM-Miley-Cyrus-Lipstick/index.tmpl' 

Select Name: '' 

Item Name: 'VIVA GLAM Miley Cyrus Lipstick' 


Do they equal: 0 

$VAR1 = undef; 

insert into crawler_url (first_seen,url,name,category,last_checked) values ('Wed Jan 28 21:15:40 2015','http://www.maccosmetics.com/product/shaded/168/34492/Products/Lips/Lipstick/VIVA-GLAM-Miley-Cyrus-Lipstick/index.tmpl','VIVA GLAM Miley Cyrus Lipstick','Lipstick','Wed Jan 28 21:15:40 2015') 

insert into urls (company_name,url) values ('MAC                ','http://www.maccosmetics.com/product/shaded/168/34492/Products/Lips/Lipstick/VIVA-GLAM-Miley-Cyrus-Lipstick/index.tmpl') 

$VAR1 = { 
     'uri' => '/product/shaded/168/34798/Products/Lips/Lipstick/Isabel-and-Ruben-Toledo-Lipstick/index.tmpl', 
     'description' => 'Formulated to shade, define and showcase the lips in a rouge-y...', 
     'name' => 'Isabel and Ruben Toledo Lipstick ', 
     'header' => '/images/pnav/product/headers/pnav_MWWE1T_200x12_off.gif', 
     'thumbnail' => '/images/products/56x56/MWWE1T.jpg', 
     'id' => 'CAT168PROD34798' 
    }; 

select name from crawler_url where url='http://www.maccosmetics.com/product/shaded/168/34798/Products/Lips/Lipstick/Isabel-and-Ruben-Toledo-Lipstick/index.tmpl' 

Select Name: '' 


Item Name: 'Isabel and Ruben Toledo Lipstick ' 

Do they equal: 0 

$VAR1 = undef; 

insert into crawler_url (first_seen,url,name,category,last_checked) values ('Wed Jan 28 21:15:40 2015','http://www.maccosmetics.com/product/shaded/168/34798/Products/Lips/Lipstick/Isabel-and-Ruben-Toledo-Lipstick/index.tmpl','Isabel and Ruben Toledo Lipstick ','Lipstick','Wed Jan 28 21:15:40 2015') 

insert into urls (company_name,url) values ('MAC                ','http://www.maccosmetics.com/product/shaded/168/34798/Products/Lips/Lipstick/Isabel-and-Ruben-Toledo-Lipstick/index.tmpl') 

업데이트 : 나는 $dbh->do 호출하기 전에 next을 넣었을 때 내가 기대하는 결과를 얻을 수 . 그래서 그것은 $dbh->do($insertSQL) 또는 $dbh->do($updateSQL)과 관련이 있습니다. 제 2 인터뷰에서 $dbh->selectrow_array($selectSQL)을 다시 사용하기 전에 다른 전화를해야할까요? 그렇다면 왜?

+0

예. 2 개의 문장이 있으면 문제가되지 않습니다. 저는 다른 작은 프로그램에서이 프로그램을 사용해 본 적이 없으며 전혀 문제가 없었습니다. 나는 그것이 트랜잭션, 특히 삽입이나 업데이트와 관련이 있다고 생각하고있다. 기본적으로 문서별로 AutoCommit 플래그가 활성화되어 있으므로'do' 함수 후에 커밋을 호출 할 필요가 없습니다. 어쩌면 내가 여기 DBI, DBD :: Pg 및 posgresql 관계에서 누락되었습니다. –

+0

동일한 테이블에서 활성 커서로 업데이트하거나 삽입 할 때 어떤 일이 발생하는지 잘 모르겠습니다. 또한 당신은 * 정말로 정말로 * [bind parameters] (https://metacpan.org/pod/DBI#Placeholders-and-Bind-Values)를 사용하거나 SQL 주입 공격을해야합니다. – Schwern

+0

DBI의 과거 사용법에 따라 업데이트 및 삽입하는 것이 좋다고 생각합니다. 바인딩 매개 변수에 대한 팁 주셔서 감사합니다. 나는 지금부터 이것을 사용하기 위해 모든 SQL 호출을 변경할 것이다. SQL 인젝션에 대한 위키 페이지는 놀랍게도 매우 철저했습니다. http://en.m.wikipedia.org/wiki/SQL_injection –

답변

-1

정말 $ sth2-> finish()를 추가해야합니다. inner while 루프의 끝에서 $ sth-> finish(); 바깥 쪽 while 루프 후에. 내부 루프에서 완료를 수행하지 않으면 첫 번째 반복이 작동하지만 모든 후속 반복이 발생하지 않을 수 있습니다.

stash에서 마무리 작업을 수행하지 않는 것이 좋지만, 중첩 된 페치가없는 경우 일반적으로 벗어날 수 있습니다. 상응하는 완료없이 페칭을 중첩하면 설명하는 정확한 문제가 발생합니다.

+2

일반적으로 명령문 핸들은 변수가 범위를 벗어나거나 다시 할당되기 때문에 자동으로 종료됩니다. '$ sth2'는 루프가 반복 될 때마다 끝날 것입니다. '$ sth'는'main'의 끝에서 끝날 것입니다. – Schwern

+0

@Schwern 이것은 어떻게 문장에 영향을 줍니까? DBI와 DBD :: Pg의 문서에 따라'do' 함수는 준비와 실행 만하고 완료는하지 않습니다. 마무리는'할 '과 함축되어 있습니까? http://search.cpan.org/dist/DBD-Pg/Pg.pm#do –

+0

@ Nick.D'do'는 완료 할 커서가 없으며 단지 명령문을 실행하고 얼마나 많은 행이 실행되었는지 알려줍니다. 'selectall_ *'가 끝나면 (명시 적으로 또는 내부 명령문 핸들이 범위를 벗어남으로써) 종료됩니다. 기본적으로 [전화를받을 때만 전화가 오면) 모든 데이터를 가져 오지 않을 것이며 B) 핸들이 곧 삭제되지 않을 것이라는 것을 알고 있습니다.] (https://metacpan.org/pod/DBI#finish). 'prepare_cached'를 사용하면 좀 더 복잡해 지지만, 활성 핸들을 재사용하면 경고합니다. – Schwern