用于登录数据库并进行简单查询的 Perl 模块?

Perl module to log in database and do a simple query?

我似乎无法找出我的 .pm 文件和脚本的问题。我是 Perl 的新手。

我有一个名为 "project" 的 数据库,还有一个 table 名为 "mailing". 邮件 table 有 7 个条目,我想使用模块显示这些条目。

所以,我有这个自定义模块来登录数据库并进行查询。此模块的名称为 DB.pm

DB.pm 存储在我的 FEDORA 20 上 /root/mysql/GUI/DB.pm.

DB.pm定义如下:

package GUI::DB;

use strict;
use DBI;

use vars qw(@ISA @EXPORT);
use Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(dbConnect query);

#
# dbConnect - connect to the database, get the database handle
#
sub dbConnect {
        # Read database settings from config file:
        print "Works";
    my $dsn = "DBI:mysql:project";
    my   $dbh = DBI->connect( $dsn,
                'root',
                'mydatabasepassword',
                                { RaiseError => 1 } 
    );
        return $dbh;

}

#
# query - execute a query with parameters
#       query($dbh, $sql, @bindValues)
#
sub query {
        my $dbh = shift;
        my $sql ="SELECT * FROM mailing";
        my @bindValues = @_;            # 0 or serveral parameters

        my @returnData = ();

        # issue query
        my $sth = $dbh->prepare($sql);  //**line number 39 that is giving** error

        if ( @bindValues ) {
                $sth->execute(@bindValues);
        } else {
                $sth->execute();
        }

        if ( $sql =~ m/^select/i ) {
                while ( my $row = $sth->fetchrow_hashref ) {
                        push @returnData, $row;
                }
        }

        # finish the sql statement
        $sth->finish();

        return @returnData;
}
1;

现在我想在我的脚本中使用这个模块。这是我试过的:

#!/usr/bin/perl

use warnings;
use strict;
use lib '/root/mysql/';

use GUI::DB qw(dbConnect query);
dbConnect();
query();

这是我遇到的错误 -->

无法在 /root/mysql/GUI/DB.pm 第 39 行的未定义值上调用方法 "prepare"。

请帮我解决这个问题。我不确定如何进行。我猜这与参数传递有关。数据库没有问题。它在 CLI 中运行良好。

谢谢:)

_x_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X__X_X_X_X_X__X

直到这里解决了

_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X__X_X_X

进一步的问题是 SQL 命令不起作用。 在我的数据库的邮件 table 中,我有不同域的电子邮件 ID。 例如,一些 ID 是 xyz@gmail.com、12343@gmail.com、bae@yahoo.com 等等,我假设新的电子邮件 ID 将添加到邮件 tables每天都有不同的域名。

我正在尝试编写一个脚本来更新另一个 table,它按域名保存每天的电子邮件地址计数。这是我试过的:

#!/usr/bin/perl

use warnings;
use strict;
use lib '/root/mysql/';
use 5.016;
use Data::Dumper;

use GUI::DB qw(dbConnect query);

my $data = dbConnect();
my @domain = query($data, "SELECT substr(addr,locate('\@',addr)+1) as maildomain, count (*) as mailcount FROM mailing GROUP BY maildomain ORDER BY mailcount DESC");

for my $key (@domain){
        say Dumper ($key);
}

但是我收到一个错误,

您的 SQL 语法有误;检查与您的 MariaDB 服务器版本相对应的手册,了解在第 1 行 /root/mysql/GUI/DB.pm 第 44 行 /root/mysql/GUI/DB.pm line 44.

相同的 SQL 语句在 CLI 中没有问题。 任何帮助,将不胜感激。 :)

1) 你的错误是说这里 $dbh 是未定义的:

sub query {
    my $dbh = shift;
    ...
    # issue query
    my $sth = $dbh->prepare($sql);  #<***LOOK HERE***

...这意味着此处必须未定义 $dbh:

sub query {
    my $dbh = shift;  #<***LOOK HERE***
    ...
    # issue query
    my $sth = $dbh->prepare($sql);  

2) 让我们看看为什么。您的 dbConnect() 方法 returns $dbh:

sub dbConnect {
    # Read database settings from config file:
    print "Works";
    my $dsn = "DBI:mysql:project";

    my   $dbh = DBI->connect( 
        $dsn,
        'root',
        'mydatabasepassword',
        { RaiseError => 1 } 
    );

    return $dbh;  #<***LOOK HERE*****
}

3) 但是,您可以这样调用 dbConnect():

dbConnect();

因为您从未在任何地方保存 return 值,$dbh 被丢弃。

4) 此外,您可以这样调用 query():

query();

然而,您这样定义了 query():

sub query {
        my $dbh = shift;

query() sub 认为第一个参数将是数据库句柄——但您没有使用任何参数调用 query()。

您需要这样做:

my $data_base_handle = dbConnect();

my @results = query($data_base_handle);

#do something with @results

回复评论

I printed @results, this is what I see HASH(0x1d05be8) HASH(0x1d05ba0) HASH(0x1d05b58) HASH(0x1d05b10) HASH(0x1d05ac8) HASH(0x1d05a80) HASH(0x1d05a38)

您写道:

my $row = $sth->fetchrow_hashref;

...这要求 DBI return 每行作为对散列的引用。然后你写道:

push @returnData, $row;

...将每个散列引用推入一个数组。所以 query() return 是一个散列引用数组。符号 HASH(0x1d05be8) 是打印散列引用时 perl 输出的内容。

如果您想查看这些哈希值中的内容,请执行以下操作:

use 5.016;  #enable say()
use Data::Dumper;
...
...

for my $href (@results) {
    say Dumper($href);
}

要访问哈希引用中的数据,您可以这样做:

use strict;
use warnings;
use 5.016;
use Data::Dumper;

my $href = {
    c => 3,
    a => 1,
    b => 2,
};

my %hash = %{$href};  #dereference, {}, the reference into a hash, %

for my $key ( keys %hash ) {
    say "$key $hash{$key}";
}

--output:--
c 3
a 1
b 2

回复下一条评论: (答案发表在 op 下的评论中。)

顺便说一下,perl 非常擅长文本处理,所以如果您无法找出查询的问题,可以使用 perl 处理电子邮件地址:

use strict; 
use warnings; 
use 5.012;
use Data::Dumper;

use DBI;
use DBD::mysql;

# CONFIG VARIABLES
my $db_type = "mysql";
my $database = "my_db";
my $host = "localhost";
my $port = "3306";
my $user = "root";
my $pword = "";

# DATA SOURCE NAME
my $dsn = "dbi:$db_type:$database:$host:$port";

# PERL DBI CONNECT
my $dbh = DBI->connect($dsn, $user, $pword);

# PREPARE THE QUERY
my $tablename = "mailing";

my $select =<<"END_OF_SELECT";
    select addr from $tablename
END_OF_SELECT

my $addr_aref = $dbh->selectcol_arrayref($select);  #Returns a reference to a flat array containing all the email addresses
$dbh->disconnect;

my %count_for;

for my $addr (@{$addr_aref}) {
    $addr =~ s/.*@//;
    $count_for{$addr}++;
}

say Dumper(\%count_for);

--output:--
$VAR1 = {
          'google.com' => 2,
          'gorilla.com' => 1,
          'yahoo.com' => 3
        };