Perl / MySQL关系查询

时间:2012-11-06 21:30:28

标签: mysql sql perl relationship

我有以下最终将成为网页的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";

上面的查询确实有效但是我想要找到的是有什么方法可以运行一个SQL查询并从站点数据库获取db_site_code和db_long_name而不运行第二个查询?硬件DB在站点Db中具有外键“id”。

当你阅读关于关系数据库的任何内容时,他们都说它是迄今为止从数据库中获取数据的最有效方法,但我只是看不出这是如何比运行2个选择查询更快。我上面所做的肯定需要比"select from hardware where srv_name = $srv_name"然后"select from sites where id = db_site_id"更长的时间?非常感谢任何评论。

2 个答案:

答案 0 :(得分:0)

除了@ tadman建议使用占位符之外,我还将此标记为sql问题,但您的解决方案是简单地添加

  

srv_name = \“$ srv_name \”

到你的第二个where子句,以便你的陈述是:

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

我强烈反对@ tadman的建议 - 尽可能使用准备好的陈述和/或占位符。

答案 1 :(得分:0)

以下是如何使用占位符以及组合查询执行此操作的示例。如果我正确理解您的数据库,您可以省略第一个查询并在第二个查询中添加服务器名称而不是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一起删除。为您节省击键次数,使您的代码更具可读性。
  • 您可以(但不必,这是首选项!)在没有参数的方法调用之后省略了parens。为自己做决定。
  • 正如已经指出的那样,始终使用placeholders和DBI。它们非常简单。现在你不必用反斜杠逃脱"。相反,只需使用?
  • 将查询合并后,您可以将其置于heredoc(<<'SQLQUERY')中。它是一个从下一行到分隔符(SQLQUERY)的字符串。这样,您的查询就更容易阅读。
  • 您可以使用其中一种参考 - fetchrow - 方法将所有结果列添加到一个哈希中。我使用$sth->fetchrow_hashref因为我发现它最方便。您已获得完整的行,所有列都被命名为哈希键。
  • 如果在小范围内调用(例如短sub),则不需要finish语句句柄。一旦超出范围,Perl就会自动完成并销毁它。

关于表现的另一个问题:如果这只是偶尔运行,不要担心它。您可以使用DBI::Profile对查询进行分析,以查看哪种方式更快,但只有在您确实需要时才应该这样做。

根据我的经验,特别是对于非常大的查询和非常繁忙的数据库,两个或三个查询比一个大查询要好得多,因为它们不接管服务器资源。但同样,这是你需要分析和基准的东西(如果需要的话)。