Perl访问数据库最经常使用的包是DBI,能够在www.cpan.org找到。使用ppm命令便可图形化安装。另外还须要安装对应数据库的驱动包,例如DBD::MySQL、DBD::Oracle、DBD::Sybase或者DBD::ODBC等。html
1、基本流程mysql
通常来讲,数据库操做由如下几个步骤组成一个常见的流程:sql
1. 创建一个数据库链接数据库
2. 经过创建的数据库链接,执行SQL语句数组
3. 执行SQL后获取返回的数据集服务器
4. 在数据集中对记录进行处理,通常是一个循环的过程oracle
5. 处理完毕,关闭数据库链接,释放资源性能
下面是按照上述的流程,在Perl中访问MySQL的一段代码,以这段代码为例,详细说明DBI的使用方法。fetch
#!/usr/bin/perl -w use strict; use DBI; my $dbh = DBI->connect("DBI:mysql:test:192.168.1.2", 'root', 'password'); my $sth = $dbh->prepare("SELECT * FROM test1"); $sth->execute(); while ( my @row = $sth->fetchrow_array() ) { print join('\t', @row)."\n"; } $sth->finish(); $dbh->disconnect();
1.1 链接数据库优化
my $dbh = DBI->connect("DBI:mysql:test:192.168.1.2", 'root', 'password');
调用DBI的方法DBI->connect
来创建一个数据库的链接,若是链接成功则返回一个数据库链接句柄,以后执行SQL等操做都要把这个链接句柄做为一个操做参数。在connect调用中,首先要提供一个数据库链接串。这个链接串用冒号分为了几个部分:
小节 | 说明 |
---|---|
DBI | 接口类型 |
mysql | 数据库类型 |
test | 数据库名称 |
192.168.1.2 | 数据库主机地址 |
在前面例子中的链接串中,DBI表示这是DBI接口的一个链接串;mysql表示要链接的数据库是MySQL数据库(若是要链接Oracle数据 库,这里则是oracle),不一样的数据库有不一样的链接串定义,能够参考DBI对应的访问驱动的说明;test指明了链接到数据库主机上的数据库名 称;192.168.1.2就是MySQL服务器的IP地址。这里要注意的是,链接串中的数据库类型mysql必须小写。若是省略了主机名,则缺省为 localhost。connect方法的后面两个参数是链接数据库主机的用户名和密码,这个但是不可缺乏的 J
若是在链接过程当中出现任何错误,则connect的返回值都会是undef(和C语言中的NULL是一回事)。这里为了简化而略去了错误检查,实际作项目的时候应当对这些错误和返回值的进行检查。
my $sth = $dbh->prepare("SELECT * FROM test1"); $sth->execute(); $dbh->do(“UPDATE test1 SET time=now()”);
链接上了数据库,得到了数据库链接句柄,就能够利用这个句柄来对数据库进行操做了。要执行一条SQL语句,为了提升性能,DBI分两个步骤来作。先把 SQL语句经过prepare方法提交到数据库,数据库为该语句分配执行资源,以后调用execute方法通知数据库执行该SQL语句。注意 prepare方法是经过数据库链接句柄调用的,若是成功则返回一个该SQL的句柄,以后经过该SQL语句句柄调用execute执行SQL。 通常来讲execute执行的都是返回数据的语句(例如SELECT语句)。反之若是执行INSERT、UPDATE、DELETE、CREATE TABLE等不须要返回数据的语句,则有一个更方便、快速的方法 $dbh->do(SQL语句)
,能够省去prepare的步骤。do方法返回的是受该SQL影响的记录数量。
常写大段SQL的朋友可能会对于SQL中的引号很头痛,往往都由于引号的问题搞的SQL语句乱成一团分辨不清。还记得上篇文章讲过的qq吗?这里正 是它的好用处。因为qq中的字符串同双引号” ”内的字符串同样会对变量进行解释,同时qq还能够换行。所以使用它来对SQL进行排版是很是好的一个选择,例如像这样的一条SQL语句:
my $res_operator = $dbhandle->prepare( qq{ SELECT o_customerid, COUNT(*) AS totalMsgNum FROM mm4fcdrs WHERE (m_date>'$begindate') AND (m_date<'enddate') GROUP BY o_customerid });
1.2.2 经过SQL语句中的参数优化查询执行效率
在执行大量INSERT之类的语句的时候,反复向数据库服务器提交一样结构的一个SQL语句,在这种状况下能够利用prepare和SQL参数来优化执行效率:
1.先使用prepare提交一个SQL模板给数据库服务器,把其中值的部分用参数占位符代替。
2.使用prepare让服务器为该SQL准备了执行资源后,调用execute并在该方法中传入参数实际的值执行SQL。
3.以后能够反复调用execute,不须要服务器从新prepare
假设要执行这样的一个系列的SQL
INSERT INTO test1 VALUES (NULL, ‘a’, ‘2005-04-01’) ... ... INSERT INTO test1 VALUES (NULL, ‘z’, ‘2005-04-01’)
其中第二个字段的值是从a到z的字母。那么能够这样来优化执行效率:
my $sth = $dbh->prepare( qq{ INSERT INTO test1 VALUES (NULL, ?, ‘2005-04-01’) } ); for my $value('a'..'z') { $sth->execute($value); }
其中的问号就是前面说的参数占位符了,它的意思就是告诉在准备执行资源的服务器:这个SQL的这个位置会有一个值,可是如今还不知道,等下执行的时候再告 诉你。 prepare了以后,用一个循环产生a-z的字符给变量$value,而后将$value在execute方法中做为一个参数传入,服务器那里会自动用 传入的值替换前面的"?"。须要提醒的是,传入的参数个数必定要和SQL中的占位符的数量同样。
熟悉ADO的朋友必定知道里面有一个DataReader对象,DBI中读取数据的方法和它很是的类似。简单来讲,就是单向、流式的读取数据,也就是每次只能向后读一条数据直到没有数据能够读取。
文章开头的例子中,用了 $sth->fetchrow_array()
方法来读取数据。其实DBI读取数据还有几种常见的方法,这几个方法是相似的,所不一样的是返回记录的形式。
返回一个由字段的值组成的数组。该数组的第1个元素就是当前记录第1个字段的值。
while ( my @row = $sth->fetchrow_array() ) { print "$row[0], $row[1], $row[2]\n"; }
或者这样,不过要注意字段对应的顺序
while ( my ($id, $name, $time) = $sth->fetchrow_array() ) { print "$id, $name, $time\n"; }
返回由字段的值组成的数组的引用。同fetchrow_array
的区别很明显,fetchrow_arrayref
返回的数组的引用。
while ( my $row_ref = $sth->fetchrow_arrayref() ) { for (my $i = 0; $i < @{$row_ref}; $i++) { print "$row_ref->[$i]\t"; } print "\n"; }
这里要注意的是,若是要取字段的个数,须要把这个引用转成数组的形式得到 @{$row_ref}
。获取数组元素的值的时候,由于$row_ref是引用,所以须要使用->
操做符。
返回一个由”字段名-字段值”这样的”键-值”对组成的HASH表。关键的不一样就是,只有这个方法能够经过一个字段名得到它的值,而没必要关心这个字段是第几个字段。而前者只能依靠索引来访问值。不过缺点就是,效率要比前面两个差一些。
while ( my $record = $sth->fetchrow_hashref() ) { for my $field( keys %{$record} ) { print "$field: $record->{$field}\t"; } print "\n"; }
这里须要复习一下HASH表的操做方法。keys操做符获取HASH的键(key)的数组,$record->{$field}
得到HASH表中$field对应的值。注意这里一样是引用,所以要用->
操做符。
使用上面三个方法能够基本解决问题了。此外,还有两个方法fetchall_arrayref
和selectall_arrayref
能够直接经过SQL一次性获取整个数据集,不过使用上稍微复杂一些,要涉及到 perl的scalar 操做符,这里就不赘述了。有兴趣的读者能够参考DBI的相关资料。
最后是收尾工做。
$sth->finish();
1.5 断开数据库链接
$dbh->disconnect();
http://dbi.perl.org/
http://www.perl.com/pub/1999/10/DBI.html