2012-06-22 3 views
0

Немного фона: У меня есть скрипт perl, который выполняет ряд операций внутри цикла.Как мне обойти «Ошибка DBD :: Pg :: st выполнить: ошибка ERROR: подготовленная инструкция уже существует»

Внутри цикла я создаю подготовленное заявление, например, так:

// inside loop 
    my $statement = "select xxxx from zzzzzz where $foobar;"; 
    my $query = $connect->prepare($statement); 
    $query->execute(); 

$ Foobar обновляется новое значение каждый раз, когда цикл завершает, поэтому я хочу, чтобы изменить запрос каждый прогон, однако Я получаю сообщение об ошибке, когда пытаюсь это сделать.

Когда скрипт запускается, я получаю эту ошибку:

DBD::Pg::st execute failed: ERROR: prepared statement "xxxxxxxxxxxxx" already exists at 

Потому что я передаю переменную, которая обновляется каждый раз, запускает цикл, и предполагая, что нужно использовать это подготовленное заявление, как я вокруг этой ошибки?

Спасибо за ваше время.

Edit:

Для будущих людей, имеющих эту проблему, проверить это здесь:

Я пытался получить

my $sth = $dbh->prepare('select interval ?'); 

http://gborg.postgresql.org/pipermail/dbdpg-general/2006-January/001972.html

http://gborg.postgresql.org/pipermail/dbdpg-general/2006-February/002007.html

перечислены некоторые способы обхода: либо отключение серверной стороны готовит через флаг pg_server_prepare, либо используя, например, '? :: interval' вместо 'interval?'

+0

Какие версии * все * (perl, Postgres libs, Postgres server, DBI, DBD :: Pg) вы используете? Это может быть [ошибка в недавнем DBD :: Pg] (http://comments.gmane.org/gmane.comp.bug-tracking.request-tracker.user/65741). – pilcrow

+0

Чтобы быть понятным, «интервал?» проблема - это синтаксическая ошибка *, созданная бэкэндом Pg, когда его попросили подготовить заявление, поведение, которое было введено около 2006 года, когда драйвер DBD представил настоящую подготовку на стороне сервера. Проблема «подготовленное заявление уже существует», которая открыла этот вопрос, имеет другую первопричину. – pilcrow

ответ

4

Переведите подготовленное заявление за пределы цикла. Если у вас есть переменная, которая должна быть передана подготовленному оператору, вы должны использовать маркер ? для передачи переменной в подготовленный оператор. Вот пример:

my $stmt = $dbh->prepare('SELECT * FROM table WHERE id = ?'); 
foreach ... { 

    my $var = <something>; 
    $stmt->execute($var); 
} 

Здесь подготовленный оператор создается один раз, а ? используется для передачи переменных. Когда вы вызываете execute, вы передаете переменную в качестве параметров.

+0

взорвал мой разум, спасибо –

+0

Можно ли сделать то же самое с более чем одной переменной? Например, my $ stmt = $ dbh-> prepare ("SELECT * FROM table WHERE id =? AND name = '?'"); $ stmt-> execute ($ var1, $ var2); ?? –

+1

@BeauBouchard Да, и это именно то, как вы это делаете. '$ var1' будет сопоставляться с' id', а '$ var2' будет соответствовать' name' в вашем примере. – Joel