Есть ли привязка параметров SQL для массивов?
Существует ли стандартный способ привязки массивов (скаляров) в SQL-запросе? Я хочу привязать к предложению IN
, например:
SELECT * FROM junk WHERE junk.id IN (?);
Я использую Perl::DBI
, который принуждает параметры к скалярам, поэтому я получаю бесполезные запросы, например:
SELECT * FROM junk WHERE junk.id IN ('ARRAY(0xdeadbeef)');
Разъяснение: Я помещаю запрос в свой собственный файл .sql
, поэтому строка уже сформирована. В тех случаях, когда в ответах упоминается динамическое создание строки запроса, я бы, скорее всего, выполнил поиск и заменил.
Изменить: Этот вопрос является своего рода дубликатом Параметрирование предложения SQL IN?. Первоначально я думал, что он должен быть закрыт как таковой, но похоже, что он накапливает какую-то хорошую Perl-специфическую информацию.
Ответы
Ответ 1
Вы указываете "это SQL для запроса с одним параметром" - это не будет работать, если вам нужно много параметров. Конечно, это боль. Еще два варианта того, что было предложено:
1) Используйте DBI- > quote вместо держателей мест.
my $sql = "select foo from bar where baz in ("
. join(",", map { $dbh->quote($_) } @bazs)
. ")";
my $data = $dbh->selectall_arrayref($sql);
2) Используйте ORM, чтобы сделать этот материал низкого уровня для вас. DBIx:: Class или Rose:: DB:: Object, например.
Ответ 2
Если вам не нравится карта, вы можете использовать оператор "x":
my $params = join ', ' => ('?') x @foo;
my $sql = "SELECT * FROM table WHERE id IN ($params)";
my $sth = $dbh->prepare( $sql );
$sth->execute( @foo );
Скобки нужны вокруг '?' потому что это означает, что x 'находится в контексте списка.
Прочтите "perldoc perlop" и найдите "Binary" x "для получения дополнительной информации (в разделе" Мультипликативные операторы ").
Ответ 3
Я делаю что-то вроде:
my $dbh = DBI->connect( ... );
my @vals= ( 1,2,3,4,5 );
my $sql = 'SELECT * FROM table WHERE id IN (' . join( ',', map { '?' } @vals ) . ')';
my $sth = $dbh->prepare( $sql );
$sth->execute( @vals );
Ответ 4
И еще один способ создания SQL - использовать что-то вроде SQL:: Abstract....
use SQL::Abstract;
my $sql = SQL::Abstract->new;
my $values = [ 1..3 ];
my $query = $sql->select( 'table', '*', { id => { -in => $values } } );
say $query; # => SELECT * FROM table WHERE ( id IN ( ?, ?, ? ) )
Ответ 5
С обычным DBI
вам нужно будет построить SQL самостоятельно, как было предложено выше. DBIx::Simple (обертка для DBI
) делает это для вас автоматически, используя '??' Обозначения:
$db->query("select * from foo where bar in (??)", @values);
Ответ 6
В python я всегда делал что-то вроде:
query = 'select * from junk where junk.id in ('
for id in junkids:
query = query + '?,'
query = query + ')'
cursor.execute(query, junkids)
... который по существу строит запрос с одним '?' для каждого элемента списка.
(и если там есть другие параметры, вам нужно убедиться, что вы правильно выполняете строки при выполнении запроса)
[edit], чтобы сделать код более понятным для людей, не относящихся к python. Есть ошибка, когда запрос будет иметь дополнительную запятую после последнего?, Из которой я уйду, потому что исправление будет просто облако общей идеи]
Ответ 7
Я использую DBIx:: DWIW. Он содержит функцию, называемую InList(). Это создаст ту часть SQL, которая необходима для списка. Однако это работает только в том случае, если у вас есть все ваши SQL в программе, а не снаружи в отдельном файле.
Ответ 8
Используйте
SELECT * FROM junk WHERE junk.id = ANY (?);
вместо