2016-02-29 3 views
4

Я очень новичок в Perl, я пытаюсь преодолеть начальную кривую обучения.Подготовленный SQL-оператор в Perl

У меня есть следующий SQL заявление:

 SELECT 
      node_id 
     FROM 
      pagenodes 
     INNER JOIN 
      pageproducts 
     ON 
      pagenodes.node_id = pageproducts.nodeid 
     INNER JOIN 
      products 
     ON 
      pageproducts.prodid = products.prodid 
     WHERE 
      products.prodid = ? 
     LIMIT 1 

Как вы можете видеть это имеет LIMIT 1 комплект в запросе, я пытаюсь выполнить этот запрос из сценария Perl и установить результат в переменная.

До сих пор у меня есть следующие:

my $sql = 
    'SELECT 
     node_id 
    FROM 
     pagenodes 
    INNER JOIN 
     pageproducts 
    ON 
     pagenodes.node_id = pageproducts.nodeid 
    INNER JOIN 
     products 
    ON 
     pageproducts.prodid = products.prodid 
    WHERE 
     products.prodid = ? 
    LIMIT 1'; 

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

Мой вопрос, как я могу передать в $prod_id как WHERE В параметре, и как я могу установить результат переменной. Спасибо

ответ

9

Вы уже довольно далеко. Замечательно, что у вас уже есть the placeholders (?). Все, что вам нужно сделать, это передать параметр as an argument to execute. Он автоматически заполнит их в заполнителях, в том порядке, в котором они появятся в вашем запросе.

use strict; 
use warnings; 
use DBI; 

my $dbh = DBI->connect('dsn goes here', 'user', 'password') or die $DBI::errstr; 

# stuff happens ... 

my $prod_id = 1337; # or whatever 

my $sql = 
    'SELECT 
     node_id 
    FROM 
     pagenodes 
    INNER JOIN 
     pageproducts 
    ON 
     pagenodes.node_id = pageproducts.nodeid 
    INNER JOIN 
     products 
    ON 
     pageproducts.prodid = products.prodid 
    WHERE 
     products.prodid = ? 
    LIMIT 1'; 

my $sth = $dbh->prepare($sql); 
$sth->execute($prod_id);  # no `my` here! 

LIMIT в этом случае не имеет значения. Он также будет работать в цикле.

Обратите внимание, что у вас есть my перед линией execute. Это неправильный синтаксис. my используется для , объявляет переменных, но в этой строке вы вызываете метод только для уже существующего объекта дескриптора. Возвращаемое значение для метода execute, но обычно не назначается переменной. Если возвращаемое значение истинно, execute был успешным. Если это ложь, что-то пошло не так. Вы также можете использовать or до check for errors.

$sth->execute or die $dbh->errstr; 

Теперь, чтобы получить одно значение из базы данных, вы можете use fetchrow_array in list context.

(my $node_id) = $sth->fetchrow_array; 

Это даст вам единственный node_id, один раз.


Если вы намерены получить только одно значение и вызывать только один раз, вы также можете сохранить несколько строк кода и use selectrow_array instead.

(my $node_id) = $dbh->selectrow_array('SELECT node_id FROM foo WHERE prodid=? LIMIT 1', undef, $prod_id); 

Опять же, контекст список имеет важное значение, потому что fetchrow_array и selectrow_array возвратных списков, а не ссылки на массив. Без () вокруг левой стороны он назначил количество результатов (из-за скалярного контекста).

Если, однако, вы хотите сделать все это в цикле для совокупности значений, это выглядит несколько иначе. В этом случае сделайте свою подготовку вне цикла и только execute и fetchrow_array (или любой другой метод fetchrow_*) внутри цикла. Это сделает его значительно быстрее.

my $sth = $dbh->prepare($sql); 
foreach my $prod_id (@prod_ids) { 
    $sth->execute($prod_id); 
    (my $node_id) = $sth->fetchrow_array; 
    print "$node_id\n"; 
} 
+1

Может также проверить [прекрасные слайды презентации Тим Банс на передовой DBI в OSCON] (http://www.slideshare.net/Tim.Bunce/dbi-advanced-tutorial-2007). – simbabque

+0

Спасибо за это.Я, кажется, вытаскиваю ошибку: «Глобальный символ« $ dbh »требует явного имени пакета« Я просто смотрю на это. –

+0

@ Liam загрузил DBI и вообще подключился к базе данных? – simbabque

Смежные вопросы