将数据库连接传递给子例程还是创建一个新例程?

时间:2018-01-31 14:38:43

标签: perl

我应该将打开的数据库连接传递给我所有使用过的子例程吗?

my $dbh = MysqlConnect();
my $title = GetTitle($id, $dbh);
my $price = GetPrice($id, $dbh);
my $author = GetAuthor($id, $dbh);
MysqlDisconnect($dbh);

sub GetTitle {
my $id = shift;
my dbh = shift;
.... # get title from database
}
sub GetPrice {...}
sub GetAuthor {...}

或者我应该在我使用的每个子例程中打开一个新连接吗?

my $title = GetTitle($id);
my $price = GetPrice($id);
my $author = GetAuthor($id);

sub GetTitle {
my $id = shift;
my $dbh = MysqlConnect();
.... # get title from database
MysqlDisconnect($dbh);
}
sub GetPrice {...}
sub GetAuthor {...}

诚恳 扬

2 个答案:

答案 0 :(得分:1)

打开数据库连接存在开销,因此您应尽可能多地重用连接。

此规则的主要例外是您的子例程分叉新进程或在新线程中运行。在不同的进程或线程中重用相同的句柄通常是不安全的,因此您应该为每个进程和线程创建一个新的连接。

答案 1 :(得分:1)

我会在一个SELECT中获取所有信息,就像这样

sub get_info {
    my ($dbh, $id) = @_;

    my $sth = $dbh->prepare('SELECT title, price, author FROM table WHERE id = ?');
    $sth->execute($id);
    $sth->fetchrow_array;
}

my ( $title, $price, $author ) = GetInfo($dbh, $id);

或者,更好的是,获取表格中所有内容的哈希并挑选出您需要的部分

sub get_info_hash {
    my ($dbh, $id) = @_;

    my $sth = $dbh->prepare('SELECT * FROM table WHERE id = ?');
    $sth->execute($id);
    $sth->fetchrow_hashref;
}

my $info = get_info_hash($dbh, $id);
my ( $title, $price, $author ) = @{$info}{qw/ title price author /};

Perl代码的主流命名标准是将snake_case用于词法变量,将大写字母用于全局变量

最好避免每次重复prepare,并且只在第一次需要时执行一次。这更适合于面向对象的方法,其中断开数据库也会使所有缓存的语句句柄无效,但如果数据库句柄永远不可能断开连接,那么一个简单的闭包就足够了

{
    my $sth;

    sub get_info_hash {
        my ($dbh, $id) = @_;

        $sth //= $dbh->prepare('SELECT * FROM table WHERE id = ?');
        $sth->execute($id);
        $sth->fetchrow_hashref;
    }
}

my $info = get_info_hash($dbh, $id);
my ( $title, $price, $author ) = @{$info}{qw/ title price author /};

请注意,您需要为这些选项添加一些错误处理