首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Perl模块登录数据库并做一个简单的查询?

Perl模块登录数据库并做一个简单的查询?
EN

Stack Overflow用户
提问于 2015-01-17 21:49:05
回答 1查看 933关注 0票数 1

我似乎无法解决我的.pm文件和脚本的问题。我对Perl相当陌生。

我有一个名为"project“的数据库,还有一个名为”name“的表。邮件表有7个条目,我想使用模块来显示。

因此,我有这个自定义模块来登录到数据库并执行查询。这个模块名为DB.pm

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

DB.pm的定义如下:

代码语言:javascript
复制
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;

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

代码语言:javascript
复制
#!/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行的未定义值上调用方法“准备”

请帮我处理这个。我不知道该如何进行。我猜这与争论的通过有关。数据库没有什么问题。它从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命令无法工作。在我的数据库邮件表中,我有具有不同域的电子邮件id。例如,一些id是xyz@gmail.com、12343@gmail.com、bae@yahoo.com等,我假设每天都会向具有不同域的邮件表添加新的电子邮件id。

我正在尝试编写一个脚本来更新另一个表,该表保存了他们的域名的电子邮件地址的每日计数。这就是我尝试过的:

代码语言:javascript
复制
#!/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服务器版本相对应的手册,以获得正确的语法,以便在/root/mysql/GUI/DB.pm第44行按邮件组按邮件域顺序从邮件组中使用邮件计数DESC。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-17 22:07:14

1)您的错误是在这里没有定义$dbh:

代码语言:javascript
复制
sub query {
    my $dbh = shift;
    ...
    # issue query
    my $sth = $dbh->prepare($sql);  #<***LOOK HERE***

...which意味着$dbh在这里必须是未定义的:

代码语言:javascript
复制
sub query {
    my $dbh = shift;  #<***LOOK HERE***
    ...
    # issue query
    my $sth = $dbh->prepare($sql);  

2)让我们看看为什么。dbConnect()方法返回$dbh:

代码语言:javascript
复制
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*****
}

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

代码语言:javascript
复制
dbConnect();

因为您从未将返回值保存在任何地方,所以$dbh将被丢弃。

4)此外,您还像这样调用query():

代码语言:javascript
复制
query();

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

代码语言:javascript
复制
sub query {
        my $dbh = shift;

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

你需要这样做:

代码语言:javascript
复制
my $data_base_handle = dbConnect();

my @results = query($data_base_handle);

#do something with @results

对评论的回应

我打印了@results,这就是我看到的散列(0x1d05be8)散列(0x1d05ba0)散列(0x1d05b58)散列(0x1d05b10)散列(0x1d05ac8)散列(0x1d05a80)散列(0x1d05a38)

你写道:

代码语言:javascript
复制
my $row = $sth->fetchrow_hashref;

...which要求DBI返回每一行作为对散列的引用。然后你写道:

代码语言:javascript
复制
push @returnData, $row;

...which将每个散列引用推入一个数组中。所以query()返回一个哈希引用数组。当您打印哈希引用时,HASH(0x1d05be8)符号就是perl输出的内容。

如果您想要查看这些散列中的内容,请执行以下操作:

代码语言:javascript
复制
use 5.016;  #enable say()
use Data::Dumper;
...
...

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

要访问散列引用中的数据,可以这样做:

代码语言:javascript
复制
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处理电子邮件地址:

代码语言:javascript
复制
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
        };
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28004708

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档