BEGIN块中的DBI连接和未定义的值

时间:2014-02-08 04:07:36

标签: perl dbi

遵循指南here我想在我的perl代码中放​​置一个DBI连接处理子例程。我认为BEGIN块是一个合理的位置,所以如果我遇到DBI连接的问题,它将在移动剩余(这是相当长的)之前失败。

BEGIN {
        my $dbh;
        use constant {
                my_host => 'database=MYDB;host=MYHOST',
                my_user => 'USER',
                my_pass => 'PASSWORD'
        };

        sub get_db_handle {
                unless (defined ($dbh)) {
                my $dbh = DBI->connect(
                                ('DBI:mysql:' . my_host),
                                my_user, my_pass,
                                {PrintError => 0, AutoCommit => 0}
                                ) or die $DBI::errstr;
        }
        return $dbh;
        }
}

...
        # Everything works fine without it being in the BEGIN
        my $db = get_db_handle();
        my $sth = $db->prepare($sql);

运行时,我得到预期的错误:

  

无法调用方法"准备"在未定义的值

为了解决这个问题,我在声明use constant值之后立即运行DBI连接字符串并且它有效,但这似乎不是最好的方法,并且作者没有任何关于这个实施发布了。

是否有一个典型的用法说明这种方法,创建DBI处理程序和一个sub来传递我应该查看的脚本,或者是否有更好的方法来defined语句,这将允许我使用上面的方法?

3 个答案:

答案 0 :(得分:5)

删除第2个my $dbh

sub get_db_handle {
                unless (defined ($dbh)) {
                $dbh = DBI->connect(# <- no "my" here
                                ('DBI:mysql:' . my_host),
                                my_user, my_pass,
                                {PrintError => 0, AutoCommit => 0}
                                ) or die $DBI::errstr;
        }

答案 1 :(得分:3)

问题是您在$dbh块中声明了两个 BEGIN变量。

unless检查外部 $dbh是否已定义,如果没有,则声明新的$dbh,为其分配数据库句柄,以及然后扔掉它。

子程序返回外部 $dbh的值,该值始终为undef

解决方案是从my语句的开头删除connect;然后在任何地方都会引用相同的变量。

答案 2 :(得分:2)

您要声明两个名为$dbh的变量。使用$dbh代替my $dbh来使用现有变量。


此外,您实际上并不想在编译时尝试连接,而忘记检查prepare是否成功。修正:

use constant {
   MY_HOST => 'database=MYDB;host=MYHOST',
   MY_USER => 'USER',
   MY_PASS => 'PASSWORD',
};

{
   my $dbh;

   sub get_db_handle {
       $dbh ||= DBI->connect(
          'DBI:mysql:' . MY_HOST,
          MY_USER, MY_PASS,
          { PrintError => 0, AutoCommit => 0 },
       )
          or die $DBI::errstr;

       return $dbh;
   }
}

# Make sure DB errors are discovered early.
BEGIN { get_db_handle(); }

...

my $dbh = get_db_handle();
my $sth = $dbh->prepare($sql)
   or die $DBI::errstr;

如果您使用RaiseError => 1,则可以缩短为

use constant {
   MY_HOST => 'database=MYDB;host=MYHOST',
   MY_USER => 'USER',
   MY_PASS => 'PASSWORD',
};

{
   my $dbh;

   sub get_db_handle {
       return $dbh ||= DBI->connect(
          'DBI:mysql:' . MY_HOST,
          MY_USER, MY_PASS,
          { RaiseError => 1, PrintError => 0, AutoCommit => 0 },
       );
   }
}

# Make sure DB errors are discovered early.
BEGIN { get_db_handle(); }

...

my $dbh = get_db_handle();
my $sth = $dbh->prepare($sql);

不确定缓存启用了事务的句柄有多大意义。