Domanda

Il nostro sito Web utilizza Perl per fornire un semplice meccanismo per le nostre risorse umane per pubblicare offerte di lavoro sul nostro sito Web. È stato sviluppato da una terza parte, ma sono stati da tempo messi in contatto, e purtroppo non abbiamo alcuna abilità Perl interna. Questo è ciò che accade quando gli addetti al marketing eludono il loro team IT interno!

Devo apportare una semplice modifica a questa applicazione. Attualmente, la pagina dei posti vacanti dice 'Al momento abbiamo i seguenti posti vacanti:', indipendentemente dal fatto che ci siano posti vacanti! Quindi vogliamo cambiarlo in modo che questa riga venga visualizzata solo nei momenti appropriati.

Potrei, ovviamente, iniziare a imparare un po 'di Perl, ma stiamo già pianificando un sito sostitutivo e sicuramente non useremo Perl. Quindi, poiché la soluzione sarà banale per chi ha queste capacità, ho pensato di chiedere un aiuto mirato.

Di seguito è riportato l'inizio della procedura che elenca i posti vacanti.

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 riga chiave è while (my $ ref = $ sth- > fetchrow_hashref ()) {. Sto immaginando che questo stia dicendo "mentre posso togliere un altro posto vacante dal recordset restituito ...". Se inserisco la mia dichiarazione di stampa prima di questa riga, verrà sempre mostrata; dopo questa riga ed è stato ripetuto per ogni posto vacante.

Come posso determinare se ci sono alcuni posti vacanti da visualizzare, senza spostarsi prematuramente nel recordset restituito?

Potrei sempre copiare il codice all'interno del ciclo while e inserirlo in un'istruzione if () (che precede il ciclo while) che includerà anche la mia dichiarazione di stampa. Ma preferirei avere solo l'approccio più semplice di Se qualche record quindi stampa " Al momento abbiamo .. " riga . Sfortunatamente, non ho la minima idea di codificare nemmeno questa semplice riga.

Vedi, ti ho detto che era un problema banale, anche considerando la mia spiegazione confusa!

TIA

Chris

È stato utile?

Soluzione

Un modo davvero semplice sarebbe:

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

Altri suggerimenti

Se stai usando Mysql, le " righe " Il metodo funziona bene:

$sth->execute();

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

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

Il metodo e alcuni avvertimenti sono documentati in dettaglio in "perldoc DBI". Inizia sempre con " perldoc " ;.

Questa non è tanto una domanda Perl quanto una domanda di database, e non c'è un buon modo per sapere quanti risultati hai fino a quando non li hai. Hai due scelte qui:

  1. Esegui una query che esegue un " select count (*) " per vedere quante righe ci sono, quindi un'altra query per ottenere le righe effettive o
  2. Esegui la query e archivia i risultati in un hash, quindi conta quante voci hai nell'hash, quindi passa attraverso l'hash e stampa i risultati.

Ad esempio, in cima alla mia testa:

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

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

Poiché tutti vogliono ottimizzare i test ripetuti per verificare se l'intestazione è stata stampata nella soluzione di Graeme, vi presento questa piccola variazione:

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

Poiché la tua query è un SELEZIONA , non puoi sfruttare righe o del valore restituito da esegui stesso.

Tuttavia, puoi pre-contare il numero di righe (ovvero i posti vacanti) che la tua query selezionerà aggiungendo un'altra query ... qualcosa del genere:

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

    ...
}

O, allo stesso modo, invece di " preparare " e " eseguire " la query e quindi utilizzare " fetchrow_array " , tu può fare tutto in una sola chiamata usando 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";

E lo stesso vale anche per 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";

Tuttavia, se si utilizza selectrow_array o selectall_arrayref , è anche possibile recuperare il numero di posti vacanti direttamente dal risultato della query originale:

# 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 modo un po 'più efficiente (evitando un condizionale all'interno del ciclo), se non ti dispiace cambiare il modo in cui la pagina viene emessa un po' (tutto in una volta anziché una riga alla volta) potresti creare una variabile per contenere l'output appena prima del ciclo:

my $output = '';

e quindi all'interno del ciclo, modifica qualsiasi istruzione di stampa in modo che sia simile a questa:

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

quindi dopo il ciclo:

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

Basta aggiungere un'altra query .. qualcosa del genere:

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

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

Quindi la risposta è verificare il valore di ritorno di $ sth- > execute ():

 my $returnval = $sth->execute;
 if (defined $returnval && $returnval == 0) {
     carp "Query executed successfully but returned nothing";
     return;
 }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top