データベースクエリが結果を返すかどうかを確認するにはどうすればよいですか?
質問
私たちのウェブサイトはPerlを使用して、人事担当者がウェブサイトに空席を投稿するためのシンプルなメカニズムを提供しています。サードパーティによって開発されましたが、彼らは長い間連絡を取り合っており、残念ながら社内にはPerlスキルがありません。これは、マーケティング担当者が社内のITチームを回避したときに発生します!
このアプリケーションに簡単な変更を加える必要があります。現在、空席のページには、空席があるかどうかに関係なく、「現在、次の空席があります:」と表示されます。したがって、この行が適切な時間にのみ表示されるように変更します。
明らかに、少し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-&gt; fetchrow_hashref()){
です。私は、これが「返されたレコードセットから別の空席を引き出すことができる間...」と言っていると考えています。この行の前にprintステートメントを配置すると、常に表示されます。この行の後、空席ごとに繰り返されます。
返されるレコードセットを早めに移動せずに、表示する空きがあることを確認するにはどうすればよいですか?
常にwhileループ内のコードをコピーし、printステートメントを含むif()ステートメント(whileループの前)内にコードを配置できます。しかし、レコードがある場合は、「現在持っている..」を印刷するという、より単純なアプローチが望ましいです。行
。残念ながら、この単純な行でさえコーディングする手掛かりがありません。
ほら、それは些細な問題だと言ったのに、私のおかしな説明を考えても!
TIA
クリス
解決
本当に簡単な方法は次のとおりです。
$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を使用している場合、&quot; rows&quot;メソッドはうまく動作します:
$sth->execute();
if($sth->rows) {
print "We have data!\n";
}
while(my $ref = $sth->fetchrow_hashref()) {
...
}
このメソッドといくつかの注意事項は、「perldoc DBI」に詳細に文書化されています。常に&quot; perldoc&quot;で始まります。
これはデータベースの質問であるため、Perlの質問ではありません。また、結果が得られるまで、結果の数を知る良い方法はありません。ここには2つの選択肢があります:
- &quot; select count(*)&quot;を実行するクエリを実行します行数を確認してから、実際の行を取得する別のクエリまたは
- クエリを実行して結果をハッシュに保存し、ハッシュにあるエントリの数をカウントしてから、ハッシュを通過して結果を出力します。
たとえば、私の頭の上から:
my @results = ();
while (my $ref = $sth->fetchrow_hashref()) {
push @results, $ref;
}
if ($#results == 0) {
... no results
} else {
foreach $ref (@results) {
my $temp = $template;
....
}
誰もがGraemeのソリューションでヘッダーが印刷されているかどうかの繰り返しテストを最適化することを望んでいるので、この小さなバリエーションを紹介します:
$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";
}
クエリは SELECT であるため、 行 または execute 自体。
ただし、別のクエリを追加することで、クエリが選択する行数(空席)を事前にカウントできます。次のようになります。
# 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();
...
}
または同様に、&quot; prepare&quot; および&quot; execute&quot; クエリの代わりに&quot; fetchrow_array&quot; を使用すると、 selectrow_array を使用して、1回の呼び出しですべてを実行できます。 :
# 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";
そして、 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";
ただし、 selectrow_array または selectall_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-&gt; execute()の戻り値を確認することです:
my $returnval = $sth->execute;
if (defined $returnval && $returnval == 0) {
carp "Query executed successfully but returned nothing";
return;
}