日期:2014-05-16  浏览次数:20509 次

DBI 数据库模块剖析:Perl DBI 数据库通讯模块规范,工作原理和实例

原文:http://tech.ddvip.com/2010-06/1275904179154934.html

???? 本文详细地介绍了 Perl 语言中用于和数据库通讯的 DBI 模块。以细腻的笔法和生动地示例给读者讲述了 DBI 模块的主要组成部分,结构和供用户编程时调用的方法。同时,本文也涉及了一些 DBI 模块中的高级主题,如对存储过程的调用,对并发事务的处理和数据库及执行语句句柄属性的设置和元数据的处理。除此之外,本文还对 DBD 模块的接口给予了入门级的介绍,希望可以对读者在专研第三方数据库的 DBD 模块时可以有所帮助。在本文的最后,通过定义了一套通用的 DBI 模块测试接口,对三种主流数据库 DB2,Sybase 和 MySql 进行测试,通过比较测试结果,得出了 DBI 模块在这三种数据库上的异同点和支持上的盲点。

  DBI 数据库模块剖析

  为了和数据库进行通讯,Perl 的社区开发出了统一数据库通讯接口模块:DBI。DBI 作为 Perl 语言中和数据库进行通讯的标准接口,它定义了一系列的方法,变量和常量,成功地提供一个和具体数据库平台无关的数据库持久层。

  DBI 模块的体系结构

  概述

  整个 DBI 模块的结构可以被分成两个主要的部分:DBI 模块本身和实现与具体数据库平台通讯的驱动模块。DBI 模块用于定义提供给 Perl 开发者使用的编程接口,和对不同数据库驱动模块的调用方法。具体的数据库通讯驱动模块的实现和特定的数据库平台有关,并且负责和具体数据通讯的实际操作。

  DBI 模块中的三种句柄

  在 DBI 模块的定义中,用户可以创建三种不同类型的句柄。

  驱动模块句柄(Driver Handle):驱动模块句柄代表一个在内存中加载的驱动,它在 DBI 模块加载其对应的驱动模块被创建。它和实际的驱动模块之间是一一对应的关系。驱动模块句柄提供了两个主要的方法是 data_sources() 和 connect()。

  数据库句柄(Database Handles):数据库句柄是程序员使用 DBI 模块和后台数据库进行通讯的第一步,它包含了一个到特定数据库的某个独立的连接。表一给出了对于常见数据库的连接字符串:

  执行语句句柄(Statement Handles):执行语句句柄在 DBI 规范中被定义为和数据库进行交互和操作的接口。这些句柄包装了一条条 SQL 语句,并将它们交送给后台数据库执行。一个使用执行语句句柄执行 SQL 语句的例子见程序一。

表 1. 常见数据库的连接字符串

?

数据库 连接字符串(示例)
DBD::mysql “DBI:mysql:database=$dbname;host=$hostname;port=$port”;
DBD::Oracle “dbi:Oracle:$dbname”; “dbi:Oracle:host=$hostname;sid=$sid”;
DBD::DB2 “dbi:DB2:$dbname”;
DBD::Sybase “dbi:Sybase:host=$hostname;database=$dbname;port=$port”;

?

清单 1. 使用 DBI 模块连接数据库并执行 SQL 语句

 $dbh = DBI->connect ($connection_string, $userid, $passwd); 
 $sth = $dbh->prepare (“SELECT * FROM tbl”); 
 $sth->execute(); 
 while (@row = $sth->fetchrow_array()) { 
 print “Each record: @row \n”; 
 } 
 $sth->finish(); 
 $dbh->disconnect(); 

  建立和释放连接

  使用 DBI 模块提供的 connect()方法创建一个数据库句柄是,程序员必须提供一个数据源用于指定要连接的数据库。DBI 模块的规范要求数据源的名字并须以 dbi: 开头,然后接上数据库通讯驱动模块的名字并且以‘ : ’结尾,比如‘ dbi:db2: ’。和 connect()方法相对应,DBI 模块中还定义了一个 disconnect()方法。

  通过调用 DBI->available_drivers()方法,程序员可以得到已安装在当前机器上的所有数据库通讯驱动模块的列表。接着用驱动模块名作为参数,调用 DBI->data_sources()方法,可以得到对应此驱动模块的所有数据源的列表,程序二给出了一个这样的例子 .

清单 2. 得到所有支持驱动模块的所有数据源

 my @drivers = DBI->available_drivers(); 
 die “No dirvers defined! \n” unless @drivers; 
 foreach my $driver (@drivers) { 
 print “Driver: $driver \n”; 
 my @data_sources = DBI->data_sources ($driver) { 
 foreach my $data_source (@data_sources) { 
  print “\t Data Source: $data_source \n”; 
 } 
 print “\n”; 
 } 

  错误处理

  在 DBI 模块中提供了两种错误处理的方法。第一种方法依靠程序员手工检测被调用方法的返回值;第二种方法通过 DBI 模块对错误进行自动检测,这种方法类似于程序的异常处理机制。对于手工错误处理,可以通过将“PrintError”和“RaiseError”两个变量设定为 0 来激活。在默认情况下,“PrintError”参数是被激活的。

  方法一,在调用 DBI 的 connect()函数的参数中设置:

 %attr = (PrintError => 0, RaiseError=>0); 
 my $dbh = DBI->connect (“dbi:Oracle:testdb”, “username”, “password”, \%attr); 

  方法二,在数据库句柄中直接设置:

 $dbh->{PrintError} = 0; $dbh->{RaiseError} = 0; 

  对于自动错误检测,DBI 提供了两种不同级别的错误处理方法。用于句柄的“PrintError”参数在被设置为 1 的时候,DBI 模块会调用 warn()函数进行错误处理。它会将错误信息打印到屏幕,但是并不会中止进程。而用于句柄的“RaiseError”参数在被设置为 1 的时候,DBI 模块会调用 die()函数,并且中止进程。这两个不同级别的错误处理方法可以在 DBI 模块的任何一个有效的句柄中被激活。

  除了错误处理手段以外,DBI 模块还提供了对错误信息进行诊断的方法。这些方法可以对于任何一个有效的句柄进行使用,它们的返回值包括错误号和错误信息。

 $rv = $h->err(); $str = $h->errstr(); $str = $h->state(); 

  $h->err()方法返回一个由底层数据库生成的错误号;$h->errstr()方法则返回一个由底层数据库生成的错误信息描述;$h->state()方法返回一个 5 位的 SQLSTATE 错误字符串。除了上面的三种方法会返回错误信息供排错之外,在 DBI 模块级别,$DBI::err,$DBI::errstr,$DBI::state 会返回和上述函数同样的值。一个利用 DBI 模块内置错误处理方法的例子见程序三。

清单 3. 利用 DBI 模块的内置错误处理方法

 while (1) { 
 my $dbh; 
 # disable automatic error handle 
 until { 
 $dbh = DBI