disconnect会使1活动无效 声明句柄(要么毁灭 语句处理或调用完成 他们在断开连接之前)
以下从MySQL获取数据的代码成功执行,但会导致Apache在错误日志中生成上述消息:
my $driver = "mysql";
my $server = "localhost:3306";
my $database = "test";
my $url = "DBI:$driver:$database:$server";
my $user = "apache";
my $password = "";
#Connect to database
my $db_handle = DBI->connect( $url, $user, $password )
or die $DBI::errstr;
#SQL query to execute
my $sql = "SELECT * FROM tests WHERE id=?";
#Prepare SQL query
my $statement = $db_handle->prepare($sql)
or die "Couldn't prepare query '$sql': $DBI::errstr\n";
#Execute SQL Query
$statement->execute($idFromSomewhere)
or die "Couldn't execute query '$sql': $DBI::errstr\n";
#Get query results as hash
my $results = $statement->fetchall_hashref('id');
$db_handle->disconnect();
会有任何可怕的后果吗? 忽略上述错误/警告? 代码已经运行了一个星期 没有任何不良影响。
代码有什么问题 或者这只是一个无害的警告?
修改
代码通过mod_perl执行。
答案 0 :(得分:12)
您应该在$statement->finish();
之前致电$db_handle->disconnnect();
。
通常您不需要致电finish
,除非您没有获得所有行。如果使用fetchrow_array
在循环中获得所有结果,则除非中止循环,否则不会在结束时调用finish。
我不确定为什么MySQL驱动程序在fetchall_hashref
之后没有完成语句。手册建议您的查询可能因错误而中止:
如果发生错误,请输入fetchall_hashref 返回到目前为止提取的数据, 可能没有。你应该检查一下 $ sth->事后错误(或使用 RaiseError属性)以发现是否 数据已完成或被截断 由于错误。
答案 1 :(得分:3)
这是由句柄仍处于活动状态引起的。通常它应该关闭自己,但你似乎没有从中获取所有数据。来自DBI上的perldoc:
获取所有数据后 从SELECT语句,驱动程序 应该自动调用完成 您。所以你通常不需要 明确地称它为除外 知道你没有拿走所有的 来自语句句柄的数据。最多 常见的例子是你只想要的时候 获取一行,但在那种情况下 selectrow_ *方法通常更好 无论如何。添加调用后完成 每个获取循环都是一个常见错误, 不要这样做,它可以掩盖真实 像未捕获的错误一样的问题。
答案 2 :(得分:0)
虽然可能不是你得到这个警告的原因(这是manual声称它是什么),但我在略有不同的情况下遇到了同样的警告,并想在这里建议而不是打开我自己的问题。
如果您执行查询以获取某些行,您可能会发现自己处于这种情况 - 但仅限于了解是否存在匹配行的行。在我的情况下,如果找到匹配,我们将更新行,否则插入。
因为找不到所发现的行,所以我认为这构成了遵循警告线索的情况。因此,在断开连接之前,我在选择处理程序上调用finish()
。
免责声明:作为DBI的新手,可能有更好的方法。我会使用->do()
,除了the documentation指出它应该不在重复执行时使用 - 由于某种原因也不鼓励SELECT
语句,以及!
这是一些perl伪代码,显示我登陆的内容:
$selectHandler = $dbh->prepare($queryString) or die "Cannot prepare: ".$dbh->errstr;
#Loop through a list of keys to check existence {
$selectHandler.execute($uniqueID);
$found = 0;
$found = $selectHandler->fetch();
if (!$found) {
# Do an insert of $uniqueID
} else {
# Do an update of $uniqueID
}
#}
# Having not done anything with the selectHandler's result (when rows were
# found) close it now that the loop is complete
$selectHandler->finish(); # we don't need you any more select handler!
$dbh->disconnect or warn "Disconnection error: $DBI::errstr\n";
希望这有助于其他人,如果我误导任何人,请随时纠正我的方法。