Как я могу проверить, вернет ли запрос к базе данных результаты?

StackOverflow https://stackoverflow.com/questions/290133

  •  08-07-2019
  •  | 
  •  

Вопрос

Наш веб-сайт использует Perl, чтобы предоставить нашим сотрудникам отдела кадров простой механизм размещения вакансий на нашем веб-сайте.Он был разработан третьей стороной, но они уже давно вышли на связь, и, к сожалению, у нас нет собственных навыков работы с Perl.Вот что происходит, когда маркетологи обходят свою внутреннюю ИТ-команду!

Мне нужно внести простое изменение в это приложение.В настоящее время на странице вакансий указано "В настоящее время у нас есть следующие вакансии:", независимо от того, есть ли какие-либо вакансии!Поэтому мы хотим изменить его таким образом, чтобы эта строка отображалась только в соответствующее время.

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

Ниже приведено начало процедуры, в которой перечислены вакансии.

sub list {
  require HTTP::Date;
  import HTTP::Date;

  my $date = [split /\s+/, HTTP::Date::time2iso(time())]->[0];

  my $dbh = DBI->connect($dsn, $user, $password)
    || die "cannot connect to $database: $!\n";

  my $sql = <<EOSQL;
SELECT * FROM $table where expiry >= '$date' order by expiry
EOSQL

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


  while (my $ref = $sth->fetchrow_hashref()) {
    my $temp  = $template;
    $temp     =~ s#__TITLE__#$ref->{'title'}#;

    my $job_spec = $ref->{'job_spec'};

...etc...

Ключевой линией является while (my $ref = $sth->fetchrow_hashref()) {.Я полагаю, что это означает "пока я могу найти другую вакансию из возвращенного набора записей ...".Если я помещу свою инструкцию print перед этой строкой, она всегда будет отображаться;после этой строки и это должно было повторяться для каждой вакансии.

Как мне определить, что есть какие-то вакансии для отображения, без преждевременного перемещения по возвращенному набору записей?

Я всегда мог скопировать код в цикл while и поместить его в инструкцию if() (предшествующую циклу while), которая также будет включать мою инструкцию print.Но я бы предпочел просто использовать более простой подход If any records then print "We currently have.." line.К сожалению, у меня нет ключа к кодированию даже этой простой строки.

Видите, я же говорил вам, что это тривиальная проблема, даже учитывая мое неуклюжее объяснение!

ТИА

Крис

Это было полезно?

Решение

Действительно простым способом было бы:

$sth->execute();

my $first = 1;
while (my $ref = $sth->fetchrow_hashref()) {
    if( $first ) {
        print "We currently have the following vacancies:\n";
        $first = 0;
    }
    my $temp  = $template;
    ...
}
if( $first ) {
    print "No vacancies found\n";
}

Другие советы

Если вы используете Mysql, метод "rows" работает просто отлично:

$sth->execute();

if($sth->rows) {
  print "We have data!\n";
}

while(my $ref = $sth->fetchrow_hashref()) {
...
}

Этот метод и некоторые предостережения подробно задокументированы в "perldoc DBI".Всегда начинайте с "perldoc".

Это вопрос не столько Perl, сколько базы данных, и нет хорошего способа узнать, сколько результатов у вас есть, пока вы их не получите.Здесь у вас есть два варианта:

  1. Выполните запрос, который выполняет "select count(*)", чтобы увидеть, сколько существует строк, а затем другой запрос, чтобы получить фактические строки или
  2. Выполните запрос и сохраните результаты в хэше, затем подсчитайте, сколько записей у вас есть в хэше, а затем просмотрите хэш и распечатайте результаты.

Например, навскидку с моей головы:

my @results = ();
while (my $ref = $sth->fetchrow_hashref()) {
   push @results, $ref;
}

if ($#results == 0) {
  ... no results
} else {
  foreach $ref (@results) {
    my $temp = $template;
    ....
 }

Поскольку все хотят оптимизировать повторные тесты на предмет того, был ли заголовок напечатан в решении Грэма, я представляю это небольшое изменение:

$sth->execute();

my $ref = $sth->fetchrow_hashref();
if ($ref) {
  print "We currently have the following vacancies:\n";
  while ($ref) {
    my $temp  = $template;
    ...
    $ref = $sth->fetchrow_hashref();
  }
} else {
    print "No vacancies found\n";
}

Поскольку ваш запрос представляет собой ВЫБЕРИТЕ, вы не можете воспользоваться строки или значения, возвращаемого выполнить сама по себе.

Однако вы можете предварительно подсчитать, сколько строк (т.е.вакансии) ваш запрос будет выбран путем добавления другого запроса...что- то вроде этого:

# Retrieve how many vacancies are currently offered:
my $query = "SELECT COUNT(*) AS rows FROM $table WHERE expiry >= ?";
$sth = $dbh->prepare($query);
$sth->execute($date);
$numVacancies = $numinfo->fetchrow_arrayref()->[0];

# Debug:
print "Number of vacancies: " . $numVacancies . "\n";

if ( $numVacancies == 0 ) { # no vacancy found...
    print "No vacancies found!\n";
}
else { # at least a vacancy has been found...
    print "We currently have the following vacancies:\n";

    # Retrieve the vacancies:
    my $sql = "SELECT * FROM $table where expiry >= '$date' ORDER BY expiry";
    my $sth = $dbh->prepare($sql);
    $sth->execute();

    ...
}

Или, аналогично, вместо "приготовиться" и "выполнить" запрос, а затем используйте "fetchrow_array" (выборка), вы можете сделать все за один вызов, используя selectrow_array выбираем_array:

# Retrieve how many vacancies are currently offered:
my $query = "SELECT COUNT(*) AS rows FROM $table WHERE expiry >= ?"; 
my $numVacancies = $dbh->selectrow_array($query, undef, $date);

# Debug:
print "Number of vacancies: " . $numVacancies . "\n";

И то же самое также верно для выделение_arrayref:

# Retrieve how many vacancies are currently offered:
my $query = "SELECT COUNT(*) AS rows FROM $table WHERE expiry >= ?";
my $numVacancies = $dbh->selectall_arrayref($query, {Slice => {}}, $date);

# Debug:
print "Number of vacancies: " . @$numVacancies[0]->{rows} . "\n";

Однако, если вы используете selectrow_array выбираем_array или выделение_arrayref, вы также можете получить количество вакансий непосредственно из результата исходного запроса:

# Retrieve the vacancies:
my $sql = "SELECT * FROM $table where expiry >= ? ORDER BY expiry";
my $vacancies = $dbh->selectall_arrayref($sql, {Slice => {}}, $date);

# Debug:
print "Number of vacancies: " . scalar @{$vacancies} . "\n";

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

my $output = '';

а затем внутри цикла измените любую инструкцию print, чтобы она выглядела следующим образом:

$output .= "whatever we would have printed";

затем, после цикла:

if ($output eq '')
{
  print 'We have no vacancies.';
}
else
{
  print "We currently have the following vacancies:\n" . $output;
}

Просто добавьте еще один запрос..что- то вроде этого:

# count the vacancies    
$numinfo = $dbh->prepare("SELECT COUNT(*) FROM $table WHERE EXPIRY >= ?");
$numinfo->execute($date);
$count = $numinfo->fetchrow_arrayref()->[0];

# print a message
my $msg = '';
if   ($count == 0) $msg = 'We do not have any vacancies right now';
else               $msg = 'We have the following vacancies';
print($msg);
use Lingua::EN::Inflect 'PL';

$sth->execute();
my $results = $sth->fetchall_arrayref( {}, $max_rows );

if (@$results) {
    print "We currently have the following ", PL("vacancy",scalar @$results), ":\n";

    for my $ref (@$results) {
        ...
    }
}

Говорит perldoc DBI:

 For a non-"SELECT" statement, "execute" returns the number of rows
 affected, if known. If no rows were affected, then "execute"
 returns "0E0", which Perl will treat as 0 but will regard as true.

Итак, ответ заключается в проверке возвращаемого значения $sth->execute():

 my $returnval = $sth->execute;
 if (defined $returnval && $returnval == 0) {
     carp "Query executed successfully but returned nothing";
     return;
 }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top