当前位置: 首页 > 工具软件 > Perl DBI > 使用案例 >

Perl DBI实例

华良平
2023-12-01
本文来源:http://www.saturn5.com/~jwb/dbi-examples.html
翻译:Aylazhang
日期:2007/07/25
----------------------------------------------------------------------------------------------------------------

内容:

  基础知识:

            建立连接
            选项
            发出SQL

    中级

           
  • SELECT 声明

        高级

                事务处理
                Oracle存储过程
        备注
        其他资源


    此文档的目的是给使用Perl DBI模块访问数据库的开发人员提供一些实列。也为了减轻Perl DBI邮件列表的负担。
    通过此文档,我们将建立更加友好的DBI程序来访问Oracle数据库。我们将从DBI基础知识开始,然后介绍一些关于提高性能跟稳定性的概念。

    基础知识:
    我们要做的第一件事情是安装DBI模块。这在 DBI INSTALL 文档中有介绍。接着我们需要安装数据库驱动,或者称为DBD。其安装简介也在每个

    DBD的包中有介绍。如大多数Perl模块一样,安装DBI/DBD是很容易的:
    localhost:/opt/src/perl_modules/DBI-1.13$ perl Makefile.PL && make && make test && make install
    装完DBI 跟 DBD,你可以这样得到更多的信息:
    localhost:~$ perldoc DBI

    连接数据库
    连接不同的数据库需要不同的方法。为得到详尽的信息,请阅读来在DBD的说明文档。 下面的例子适用于连接Oracle:
    use strict;
    use DBI;

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                          );
                         
                         
    上面的连接字符串(DSN)有三个参数:数据源,用户名和密码。DSN(数据源名称) 形式是这样的:dbi:驱动名称:实列 。但是我们怎么知道
    连接是成功还是失败了呢?首先,如果connect方法连接成功,将返回一个true,否则返回false。其次,DBI将在包变量$DBI::errstr设置
    一个错误消息串。

    use strict;
    use DBI;

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                          ) || die "Database connection not made: $DBI::errstr";
    $dbh->disconnect();
    使用disconnect()方法将避免出现“Database handle destroyed without explicit disconnect”这样的错误。

    选项
    connect()方法可以带一个哈希选项。常用的哈希选项包括:AutoCommit,当它为true时,事务处理将被自动提交。RaiseError,它在DBI遇到
    错误时调用croak $DBI::errstr。PrintError,它将调用DBI的warn $DBI::errstr。

    在这个程序中,我们想使用事务处理,因此我们关闭AutoCommit,开启RaiseError,PrintError用其默认设置。 

    use strict;
    use DBI;

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                            {
                              RaiseError => 1,
                              AutoCommit => 0
                            }
                          ) || die "Database connection not made: $DBI::errstr";
    $dbh->disconnect();

    注意的是,对于不支持事务处理的数据库而言,设置AutoCommit为false将导致严重错误。

    发出SQL
    现在我们打算在数据库上作些有用的事。有两种得到数据库SQL声明的方法。对于查询,将发挥行记录,比如SELECT,我们将使用prepare 方法
    对于其他查询,比如CREATE  跟 DELETE,我们将使用 do 方法。让我们先来看一下后者,等一下下再看前一种情况。

    这个程序将在数据库中建立一个雇员表 :
    use strict;
    use DBI;

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                            {
                              RaiseError => 1,
                              AutoCommit => 0
                            }
                          ) || die "Database connection not made: $DBI::errstr";

    my $sql = qq{ CREATE TABLE employees ( id INTEGER NOT NULL,
                                           name VARCHAR2(128),
                                           title VARCHAR2(128),
                                           phone CHAR(8)
                                         ) };
    $dbh->do( $sql );

    $dbh->disconnect();
       
       
       
     
    中级
    我们已经看到了怎样连接数据库,怎样发现错误以及发出简单SQL声明了。现在让我们继续前进看看更有用的代码吧。

    SELECT 声明:
    SELECT大概是SQL中最常用使用的了。为了用SELECT声明,我们首先将prepare(准备)声明,然后execute(执行)它。下列代码中,
    $sth 变量是声明句柄,我们将利用它来访问SELECT的结果。

    use strict;
    use DBI;

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                            {
                              RaiseError => 1,
                              AutoCommit => 0
                            }
                          ) || die "Database connection not made: $DBI::errstr";

    my $sql = qq{ SELECT * FROM employees };
    my $sth = $dbh->prepare( $sql );
    $sth->execute();

    $dbh->disconnect();
          
    以上清单将使数据库安排一个执行声明的计划,然后执行声明。实际上它对返回结果行没有进行任何操作。在接下来的代码清单中,我们
    将使用bind_columns从数据库中取出记录。bind_columns方法绑定每个数据库行和对应的一个标量引用,然后当fetch方法被调用时,这些
    变量将装载从数据库里取来的值。

    use strict;
    use DBI;

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                            {
                              RaiseError => 1,
                              AutoCommit => 0
                            }
                          ) || die "Database connection not made: $DBI::errstr";

    my $sql = qq{ SELECT id, name, title, phone FROM employees };
    my $sth = $dbh->prepare( $sql );
    $sth->execute();

    my( $id, $name, $title, $phone );
    $sth->bind_columns( undef, /$id, /$name, /$title, /$phone );

    while( $sth->fetch() ) {
      print "$name, $title, $phone/n";
    }

    $sth->finish();
    $dbh->disconnect();

    这是个打印公司电话薄的好程序。但是WHERE字句怎么处理呢?我们将使用 bind_param方法一次准备一个SQL声明,执行将非常快。

    use strict;
    use DBI qw(:sql_types);

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                            {
                              RaiseError => 1,
                              AutoCommit => 0
                            }
                          ) || die "Database connection not made: $DBI::errstr";

    my @names = ( "Larry%", "Tim%", "Randal%", "Doug%" );

    my $sql = qq{ SELECT id, name, title, phone FROM employees WHERE name LIKE ? };
    my $sth = $dbh->prepare( $sql );

    for( @names ) {
      $sth->bind_param( 1, $_, SQL_VARCHAR );
      $sth->execute();

      my( $id, $name, $title, $phone );
      $sth->bind_columns( undef, /$id, /$name, /$title, /$phone );

      while( $sth->fetch() ) {
        print "$name, $title, $phone/n";
      }
    }

    $sth->finish();
    $dbh->disconnect();


    高级:
        事务处理:
        截止到现在,我们还没有用事务处理来做任何事情。但是如果我们想发出UPDATE 或者  DELETE声明,我们将会使用事务处理。通过参考
    DBI文档,用DBI执行健壮的事务处理的最好方法是使用eval{...} 块去捕获错误。然后使用commit() 或者 rollback()来结束事务处理。这
    就是我们下面的代码清单所做的事情。

    程序往数据库里装载四条记录。
    use strict;
    use DBI qw(:sql_types);

    my $dbh = DBI->connect( 'dbi:Oracle:orcl',
                            'jeffrey',
                            'jeffspassword',
                            {
                              RaiseError => 1,
                              AutoCommit => 0
                            }
                          ) || die "Database connection not made: $DBI::errstr";

    my @records = (
                    [ 0, "Larry Wall",      "Perl Author",  "555-0101" ],
                    [ 1, "Tim Bunce",       "DBI Author",   "555-0202" ],
                    [ 2, "Randal Schwartz", "Guy at Large", "555-0303" ],
                    [ 3, "Doug MacEachern", "Apache Man",   "555-0404" ]
                  );

    my $sql = qq{ INSERT INTO employees VALUES ( ?, ?, ?, ? ) };
    my $sth = $dbh->prepare( $sql );


    for( @records ) {
      eval {
        $sth->bind_param( 1, @$_->[0], SQL_INTEGER );
        $sth->bind_param( 2, @$_->[1], SQL_VARCHAR );
        $sth->bind_param( 3, @$_->[2], SQL_VARCHAR );
        $sth->bind_param( 4, @$_->[3], SQL_VARCHAR );
        $sth->execute();
        $dbh->commit();
      };

      if( $@ ) {
        warn "Database error: $DBI::errstr/n";
        $dbh->rollback(); #just die if rollback is failing
      }
    }

    $sth->finish();
    $dbh->disconnect();

      调用Oracle存储过程:
      通过DBI用户邮件列表,我通常被问及的一个问题是,怎么用DBD::Oracle调用存储过程。这里我给出复杂多变的例子。
     
    这个程序用一个参数调用存储过程,没有返回值。我们假设这个不过不调用commit。注意程序中位置占位符的使用,同时也注意eval块的使用
    :如果你的Oracle程序产生了列外,在你的Perl程序中将被“翻译”成die,错误信息将被保留在$@ 和 $DBI::errstr变量中。


    use strict;
    use DBI;

    my $dbh = DBI->connect(
        'dbi:Oracle:orcl',
        'jeffrey',
        'jeffspassword',
        {
            RaiseError => 1,
            AutoCommit => 0
        }
    ) || die "Database connection not made: $DBI::errstr";

    eval {
        my $func = $dbh->prepare(q{
            BEGIN
                jwb_function(
                    parameter1_in => :parameter1
                );
            END;
        });
     
        $func->bind_param(":parameter1", 'Bunce'); #位置占位符时方便的
        $func->execute;
     
        $dbh->commit;
    };

    if( $@ ) {
        warn "Execution of stored procedure failed: $DBI::errstr/n";
        $dbh->rollback;
    }

    $dbh->disconnect;

    下一个程序调用带返回值的存储过程,从一个函数中返回一个值,我们使用bind_param_inout来绑定占位符。当使用这种方法时,我们必须
    通知DBD::Oracle模块返回值有多少字节。

    use strict;
    use DBI;

    my $dbh = DBI->connect(
        'dbi:Oracle:orcl',
        'jeffrey',
        'jeffspassword',
        {
            RaiseError => 1,
            AutoCommit => 0
        }
    ) || die "Database connection not made: $DBI::errstr";

    my $rv; #holds the return value from Oracle stored procedure
    eval {
        my $func = $dbh->prepare(q{
            BEGIN
                :rv := jwb_function(
                    parameter1_in => :parameter1
                );
            END;
        });
     
        $func->bind_param(":parameter1", 'Bunce');
        $func->bind_param_inout(":rv", /$rv, 6);
        $func->execute;
     
        $dbh->commit;
    };

    if( $@ ) {
        warn "Execution of stored procedure failed: $DBI::errstr/n";
        $dbh->rollback;
    }

    print "Execution of stored procedure returned $rv/n";

    $dbh->disconnect;


    备注:
    1.这些例子中的finish方法不是必需的。如果你是用声明句柄而不是你自己的程序来做,那么你应该调用finish方法。
    2.永远使用use strict句法。

    其他资源:
    DBI home page
    How to use mod_perl and Apache::DBI

    文档著作权归 Jeffrey William Baker. 最后更新 2003年11月11日
 类似资料: