Как связать параметры DBI во время выполнения в Perl?

У меня есть следующий код:

sub run_query { 
    my $name = shift || undef;
    my $sql  = (defined $name ) ? "select * from table where name = ?" :
                                  "select * from table";
    my $sth  = $dbh->prepare("$sql");
    $sth->execute($name);
}

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


person smith    schedule 11.12.2011    source источник
comment
Что-то не так с кодом, который вы предоставили?   -  person TLP    schedule 11.12.2011
comment
если имя не указано и $sth-›execute($name) запускается.   -  person smith    schedule 11.12.2011
comment
мое $имя = сдвиг; # || undef не нужен... Вы не должны заключать в кавычки одиночные переменные, $dbh->prepare($sql)   -  person tadmc    schedule 11.12.2011


Ответы (3)


Из документации DBI по cpan:

Распространенная проблема заключается в том, что фрагмент кода обрабатывает значение, которое может быть либо определено, либо undef (не NULL или NULL) во время выполнения. Простой метод состоит в том, чтобы подготовить соответствующий оператор по мере необходимости и заменить заполнитель для случаев, отличных от NULL:

  $sql_clause = defined $age ? "age = ?" : "age IS NULL";
  $sth = $dbh->prepare(qq{
    SELECT fullname FROM people WHERE $sql_clause
  });
  $sth->execute(defined $age ? $age : ());

Это не совсем относится к вашему вопросу, который, как я предполагаю, заключается в том, что ваше выполнение завершается ошибкой, если вы добавляете аргумент там, где он не ожидается. Итак, последняя строка здесь будет применяться:

  $sth->execute(defined $name ? $name : ());
person TLP    schedule 11.12.2011
comment
Тернарные операторы также работают в контексте списка, поэтому вы можете сказать my ($sql, @args) = defined $name ? ('select ...', $name) : ('select ...'); и $sth->execute(@args);, чтобы сохранить всю условную логику в одном месте. - person mu is too short; 11.12.2011

Вероятно, у вас должно быть два разных сабвуфера, но вы могли бы использовать

sub run_query { 
    my $sql = @_
       ? "select * from table where name = ?"
       : "select * from table";
    my $sth  = $dbh->prepare($sql);
    $sth->execute(@_);
}
person ikegami    schedule 11.12.2011
comment
@smith, обратите внимание, что не предоставлено - это не то же самое, что не определено. Я ответил на фактический вопрос (не предоставлено: @_ ? $name : ()), а TLP и bvr ответили на последний (не определено: defined($name) ? $name : ()). Тем не менее, различие, безусловно, не имеет значения в этом конкретном случае. - person ikegami; 11.12.2011

Вы можете условно опустить параметры, если $name не определено:

$sth->execute(defined $name ? $name : ());
person bvr    schedule 11.12.2011