2

最終的にWebページになる次のperlコードがあります。

my($dbh) = DBI->connect("DBI:mysql:host=dbsrv;database=database","my_sqlu","my_sqlp") or die "Canny Connect";
my($sql) = "SELECT * FROM hardware where srv_name = \"$srv_name\"";
my($sth) = $dbh->prepare($sql);
$sth->execute();

$sth->bind_col( 1, \my($db_id));
$sth->bind_col( 2, \my($db_srv_name));
$sth->bind_col( 5, \my($db_site));
$sth->fetchrow();
$sth->finish ();
my($sql) = "SELECT sites.\`site_code\`, sites.\`long_name\` FROM \`hardware\` JOIN \`sites\` ON \`sites\`.id=\`hardware\`.\`site\` where \`hardware\`.\`id\`=\'$db_id\'";
my($sth) = $dbh->prepare($sql);
$sth->execute();
$sth->bind_col( 1, \my($db_site_code));
$sth->bind_col( 2, \my($db_long_name));
$sth->fetchrow();
$sth->finish ();
$dbh->disconnect;
print "$db_site_code<br>$db_long_name";

上記のクエリは機能しますが、1 つの SQL クエリを実行して、2 番目のクエリを実行せずにサイト DB から db_site_code と db_long_name を取得する方法はありますか? ハードウェア DB には、サイト Db に外部キー 'id' があります。

リレーショナル DB について何かを読むと、データベースからデータを取得する最も効率的な方法だと誰もが言いますが、これが 2 つの選択クエリを実行するよりも速いことはわかりません。私が上で行ったことは、確かにそれよりも時間がかかるでしょう"select from hardware where srv_name = $srv_name""select from sites where id = db_site_id"? どんなコメントでも大歓迎です。

4

2 に答える 2

0

プレースホルダーを使用するという@tadmanの推奨事項とは別に、これもSQLの質問としてタグ付けしますが、解決策は単に追加することです

srv_name = \"$srv_name\"

ステートメントが次のようになるように、2 番目の where 句に追加します。

"SELECT sites.\`site_code\`, sites.\`long_name\` FROM \`hardware\` JOIN \`sites\` ON \`sites\`.id=\`hardware\`.\`site\` where \`hardware\`.\`id\`=\'$db_id\'";

ただし、@tadman の提案を強く支持します。可能な限り、準備済みステートメントやプレースホルダーを使用してください。

于 2012-11-06T21:42:22.463 に答える
0

プレースホルダーと結合クエリを使用してこれを行う方法の例を次に示します。DB を正しく理解していれば、最初のクエリを省略して、2 番目のクエリで ID の代わりにサーバー名を追加できます。私はそこで間違っているかもしれませんが、私の例は依然として Perl の提案にとって価値があります。

use strict;
use warnings;
use DBI;

# Create DB connection
my $dbh = DBI->connect("DBI:mysql:host=dbsrv;database=database","my_sqlu","my_sqlp")
  or die "Cannot connect to database";
# Create the statement handle
my $sth = $dbh->prepare(<<'SQLQUERY') or die $dbh->errstr;
  SELECT s.site_code, s.long_name 
  FROM hardware h 
  JOIN sites s ON s.id=h.site 
  WHERE h.srv_name=?
SQLQUERY
$sth->execute('Server Name'); # There's the parameter
my $res = $sth->fetchrow_hashref; # $res now has a hash ref with the first row

print "$res->{'site_code'}<br>$res->{'long_name'}";

あなたのコードには、指摘したい問題がいくつかありました。

  • 常にと. _ 彼らはあなたの人生を楽にします!use strictuse warnings
  • 括弧(を残して で)外に出すことができmyます。キーストロークを節約し、コードを読みやすくします。
  • 引数を持たないメソッド呼び出しの後の括弧は省略できます (必須ではありません。これは好みです!)。これは自分で決めてください。
  • すでに指摘したように、DBIでは常にプレースホルダーを使用してください。それらは非常に単純です。バックスラッシュでエスケープする必要が"なくなりました。代わりに、 を使用して?ください。
  • クエリを結合したら、それをヒアドキュメント ( <<'SQLQUERY') に入れることができます。次の行から区切り文字 ( SQLQUERY) までの文字列です。そうすれば、クエリが読みやすくなります。
  • ref- - メソッドの 1 つを使用fetchrowして、すべての結果の列を 1 つのハッシュに取得できます。$sth->fetchrow_hashref一番便利だと思ったので利用しました。完全な行があり、すべての列にハッシュ キーという名前が付けられています。
  • 小さなスコープ ( short など) で呼び出される場合、ステートメント ハンドルsubは必要ありません。finish範囲外になると、Perl によって自動的に終了され、破棄されます。

パフォーマンスに関するもう 1 つの点: これが時々実行されるだけであれば、心配する必要はありません。DBI::Profileでクエリをプロファイリングして、どちらの方が速いかを確認できますが、本当に必要な場合にのみ実行してください。

私の経験では、特に非常に巨大なクエリと非常にビジーなデータベースでは、2 つまたは 3 つのクエリの方が、サーバー リソースを占有しないため、1 つの大きなクエリよりもはるかに優れています。しかし、繰り返しになりますが、これはプロファイルを作成してベンチマークする必要があるものです (必要に応じて)。

于 2012-11-06T22:50:02.850 に答える