我正在尝试整理一些旧代码,它有两个用途。它使用DBI来创建一个数据库,然后再使用DBI来连接该数据库。不幸的是,它对于每个操作都使用了相同的代码。这意味着,如果您创建了一个名为
我们首先尝试解决的问题是让
因此,我第一次尝试解决这个问题的方法如下:
sales
的数据库,当您重新连接时,必须显式调用$dbh->do('use sales')
。这会导致各种问题,例如开发人员忘记这样做或数据库句柄重新连接并忘记所在的数据库。我们首先尝试解决的问题是让
DBI::connect()
方法使用HandleError
来重新连接MySQL,如果数据库不存在,则允许我们创建数据库。由于各种历史原因(是啊,我们都经历过),要在connect()
方法之外捕获“未知数据库”错误要困难得多。因此,我第一次尝试解决这个问题的方法如下:
use strict;
use warnings;
use DBI;
use PadWalker 'peek_my';
my $dbh = DBI->connect(
$dsn,
$user,
$pass,
{ RaiseError => 1,
PrintError => 0,
HandleError => \&reconnect_if_unknown_database,
},
);
sub reconnect_if_unknown_database {
my ($msg, $drh, $dbh) = @_;
return unless $msg =~ /Unknown database/;
my ($dsn, $user, $pass, $attr) = @{peek_my(1)}{qw/$dsn $user $pass $attr/};
unless ($dsn && $user && $pass && $attr) {
return; # don't do this if we can't get everything
}
# they're all scalar refs.
$_ = $$_ foreach $dsn, $user, $pass, $attr;
unless ($dsn =~ s/^[^;]+;/DBI:mysql:mysql;/) {
return; # can't parse dsn, so return
}
delete $attr->{HandleError}; # infinite loops tickle
$_[2] = DBI->connect($dsn, $user, $pass, $attr);
}
这种方法虽然可行,且对最终用户来说是透明的,但它看起来也像一堆杂乱的二进制代码。在连接失败时,有更好的重新连接到 不同 数据库的方法吗?