Повторное использование? На DBI готовят - PullRequest
8 голосов
/ 05 июля 2010

Есть ли способ повторно использовать?, Используемые в операторе подготовки DBI.Рассмотрим следующий код:


$sth=$dbh->prepare("INSERT INTO mytable(a,b,c) SELECT ?,B(?),C(?)");
$sth->execute($a,$a,$a);

Было бы очень неплохо вместо этого использовать что-то вроде этого:


#I'm making this up as something I hope exists
$sth=$dbh->prepare("INSERT INTO mytable(a,b,c) SELECT ?,B(?:1),C(?:1)");
$sth->execute($a);

Обратите внимание, что на выполнение передается только один $a вместо трех,Есть ли способ сделать это в реальной жизни?

Ответы [ 4 ]

7 голосов
/ 06 июля 2010

Это зависит от вашего DBD.Например, используя DBD :: Pg с заполнителями в стиле $1 или DBD :: Oracle с именованными заполнителями и bind_param, вы можете делать именно то, что вам нравится.Но с использованием универсального стиля ? заполнителей, который работает в масштабе DBI, это невозможно.

4 голосов
/ 05 июля 2010

Если вы используете библиотеку для создания своих операторов SQL, например, SQL :: Abstract или полноценного ORM, например DBIx :: Class , у вас не будетбеспокоиться о таких вещах.

В качестве альтернативы вы можете сделать что-то похожее всего с помощью нескольких строк кода:

my $sql = 'INSERT INTO ...blah blah... VALUES (' . (join(', ', ('?') x scalar(@insert_elements))) . ')';
3 голосов
/ 06 июля 2010

@ hobbs ' ответ правильно - заполнители DBI по умолчанию не могут этого сделать.@ Ether ответ правильно - абстракция SQL может сделать это без проблем.

Однако обычно требуется связать каждое отдельное параметризованное значение только один раз .В вашем примере использование скалярной производной таблицы делает предоставленное пользователем значение доступным по имени для остальной части запроса:

my $sth = $dbh->prepare(<<'__eosql');
    INSERT INTO mytable(a,b,c)
                SELECT x, B(x), C(x) FROM (SELECT ? AS x) subq
                              -- Subquery may vary from DB to DB:
                              --    "FROM (SELECT ? AS x FROM DUAL) subq"
                              --    "FROM (SELECT ? FROM rdb$database) subq(x)"
                              --    "FROM (VALUES (?)) subq(x)"
                              -- etc.
__eosql

for $v (@values) {
    $sth->execute($v);
}

Обычно это постепенно становится более "эффективным по проводам", чемальтернатива, поскольку предоставленный пользователем параметр обычно передается только один раз вместо N раз.

0 голосов
/ 16 июня 2016

Вы можете установить переменные SQL в одном операторе SQL, а затем использовать эту переменную несколько раз в следующем запросе.

$dbh->do('set @reusable = ?', undef, $perl_var);
$dbh->select_arrayref('select * from table where cola = @reusable or colb = @reusable');

Нет дублированных переменных, и вы по-прежнему получаете безопасность параметризованных запросов.

...