Comment puis-je vérifier si une requête de base de données retournera des résultats?

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

  •  08-07-2019
  •  | 
  •  

Question

Notre site Web utilise Perl pour fournir un mécanisme simple permettant à notre personnel des RH de publier des offres d'emploi sur notre site Web. Il a été développé par une tierce partie, mais ils ont été mis en contact depuis longtemps et, malheureusement, nous ne disposons d'aucune compétence Perl en interne. C’est ce qui se produit lorsque les spécialistes du marketing contournent leur équipe informatique interne!

Je dois apporter une simple modification à cette application. Actuellement, la page des postes vacants indique "Nous avons actuellement les postes vacants suivants:", qu'il y ait ou non des postes vacants! Nous voulons donc la changer pour que cette ligne ne soit affichée qu'aux moments appropriés.

Je pourrais évidemment commencer à apprendre un peu Perl, mais nous prévoyons déjà un site de remplacement et celui-ci n’utilisera certainement pas Perl. Donc, comme la solution sera simple pour ceux qui possèdent ces compétences, je pensais que je demanderais une aide ciblée.

Vous trouverez ci-dessous le début de la procédure répertoriant les postes vacants.

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...

La ligne de clé est while (mon $ ref = $ sth- > fetchrow_hashref ()) {. Je suppose que cela signifie «alors que je peux retirer un autre poste vacant du jeu d'enregistrements renvoyé ...». Si je place mon relevé imprimé avant cette ligne, il sera toujours affiché. après cette ligne et il a été répété pour chaque poste vacant.

Comment puis-je déterminer qu'il y a des postes vacants à afficher, sans passer prématurément au jeu d'enregistrements renvoyé?

Je pouvais toujours copier le code dans la boucle while et le placer dans une instruction if () (précédant la boucle while) qui inclurait également mon instruction print. Mais je préférerais simplement utiliser l'approche plus simple de Si des enregistrements sont imprimés, puis "Nous avons actuellement ...". ligne . Malheureusement, je n'ai aucune idée de coder même cette simple ligne.

Vous voyez, je vous ai dit que c’était un problème trivial, même en tenant compte de mon explication échevelée!

TIA

Chris

Était-ce utile?

La solution

Un moyen très simple serait:

$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";
}

Autres conseils

Si vous utilisez Mysql, les " lignes " la méthode fonctionne très bien:

$sth->execute();

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

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

La méthode et certaines mises en garde sont décrites en détail dans "perldoc DBI". Commencez toujours par "perldoc".

Ce n'est pas tant une question Perl que c'est une question de base de données, et il n'y a pas de bonne manière de savoir combien de résultats vous avez jusqu'à ce que vous les ayez. Vous avez deux choix ici:

  1. Effectuez une requête qui effectue un " select count (*) " pour voir combien de lignes il y a, puis une autre requête pour obtenir les lignes réelles ou
  2. Faites la requête et stockez les résultats dans un hachage, puis comptez le nombre d'entrées que vous avez dans le hachage, puis parcourez le hachage et imprimez les résultats.

Par exemple, par coeur:

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

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

Puisque tout le monde veut optimiser les tests répétés pour savoir si l'en-tête a été imprimé dans la solution de Graeme, je présente cette variation mineure:

$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";
}

Votre requête étant un SELECT , vous ne pouvez pas tirer parti de lignes ou de la valeur renvoyée par exécuter lui-même.

Cependant, vous pouvez pré-dénombrer le nombre de lignes (c.-à-d. les postes vacants) que votre requête sélectionnera en ajoutant une autre requête ... à peu près comme ceci:

# 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();

    ...
}

Ou, de la même manière, au lieu de "préparer" et "exécuter" la requête, puis utiliser "fetchrow_array" , vous Vous pouvez tout faire en un seul appel en utilisant selectrow_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";

Il en va de même pour selectall_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";

Toutefois, si vous utilisez selectrow_array ou selectall_arrayref , vous pouvez également récupérer le nombre de postes vacants directement à partir du résultat de la requête d'origine:

# 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";

Un moyen un peu plus efficace (éviter une condition dans la boucle), si cela ne vous dérange pas de changer la façon dont la page est affichée un peu (tout à la fois plutôt qu'une ligne à la fois), vous pouvez créer une variable maintenir la sortie juste avant la boucle:

my $output = '';

puis dans la boucle, modifiez n'importe quelle instruction print pour qu'elle ressemble à ceci:

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

puis après la boucle:

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

Ajoutez simplement une autre requête .. quelque chose comme ceci:

# 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) {
        ...
    }
}

dit 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.

La réponse est donc de vérifier la valeur de retour de $ sth- & execute ():

 my $returnval = $sth->execute;
 if (defined $returnval && $returnval == 0) {
     carp "Query executed successfully but returned nothing";
     return;
 }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top