[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > Perl > 正文
Perl DBI 入門
不詳 (2001-05-02 04:02:21)
目錄
基本功能 
建立連線 
選項 
下達 SQL 
進階功能 
SELECT 述 
高等技巧 
交易機制 
注意事項 
其他資訊 


本文是以 Perl DBI Examples 為藍本,配合 DBMaker 好學易用的特性,以及幾個淺顯易懂的例子,希望能夠一步步地帶領使用者學習 Perl DBI modules 存取 DBMaker 資料庫的方法。而原作者撰寫主要原動力是希望藉由這篇文章的問世,以降低 DBI mailing list 中一再重出現的 FAQ。

讀完本文之後,我們就能學到利用 DBI 建立一個完備的資料庫程式。 以下就先由 DBI 的基本功能開始,然後再逐步研究改善效能與可靠度技巧。

基本功能
DBI - Database independent interface for Perl. Perl DBI 是 Perl 程式語言存取資料庫時的標準應用程式介面 (API)。 DBI 中定義了一組函數、變數和一致性的資料庫介面, 可滿足與特定資料庫無關的特性。

值得一提的,DBI 只是一個程式介面,利用一組十分輕巧的層面, 將你的應用程式與一個以上的資料庫驅動程式緊密地結合在一起, DBI 的架構主要只是提供標準的介面,目的是為了方便使用者下達一些簡單的指令, 就可以輕易地讓那些驅動程式發揮作用

首先該做的事就是建構以及安裝 DBI, 詳細的步驟可參考 DBI INSTALL 文件中有說明. 然後再來就是建構出所需的資料庫驅動程式,或是參考 DBD. 在每個 DBD 套件中都應該會有建構程序。 與其他 Perl 模組相較之下, 安裝 DBI/DBD 步驟算是相當容易

 localhost:~/DBI-1.08$ perl Makefile.PL && make 
        && make test && make install 
在 DBI 與 DBD 安裝完成之後, 您可以執行下列指令閱讀更多的資訊: 

 localhost:~$ perldoc DBI 
建立連線
每一種資料庫都有不同的連線方式, 若是想知道特殊用法, 請務必閱讀 DBD 所提供的說明文件。 下面的例子是連線到 DBMaker 的基本方法.

use strict;
use DBI;

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jerrypassword',
                      );
    
上述的 connect 函數用到了三個參數: 資料來源名稱 (data source name, DSN), 使用者名稱和密碼。 其中 DSN 的格式為 dbi:DriverName:instance. 不過我們要如何知道連線成不成功呢? 首先可以查看 connect 的傳回值,true 代表成功,false 就是代表失敗。 其次,當有錯誤發生時, DBI 會把錯誤訊息存放在 package variable $DBI::errstr 之中。 

use strict;
use DBI;

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jerrypassword',
                      )
          || die "Database connection not made: $DBI::errstr";
$dbh->disconnect();
    
結束資料庫連線請使用 disconnect() 函數, 正確地使用可避免錯誤訊息 "Database handle destroyed without explicit disconnect" 的發生. 

選項
在連線資料庫時 connect() 這個方法可以接受 hash 型態的選項,常用的選項包括了: AutoCommit,設為 true 表示資料庫交易自動確認; RaiseError,告訴 DBI 在錯誤發生時觸發例外 croak $DBI::errstr 而不只是僅傳回錯誤代碼;PrintError,讓 DBI 以警告方式 warn $DBI::errstr 傳回錯誤訊息. 

在下一段程式中,是希望進行採交易處理的用法,設定成 AutoCommit off,RaiseError on,而讓 PrintError 使用內定值 on. 

use strict;
use DBI;

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jerrypassword',
                        {
                          RaiseError => 1,
                          AutoCommit => 0
                        }
                      )
          || die "Database connection not made: $DBI::errstr";
$dbh->disconnect();
    
有一點要特別注意,如果資料庫本身不支援交易處理的功能時,設定 AutoCommit off 會接收到錯誤發生的傳回值. 

下達 SQL
現在開始可以對我們的資料庫做一些有意義的事了. 下達至資料庫的 SQL 述分成兩類. 一是查詢指令,預期會有數筆資料傳回,例如 SELECT,這一類的指令我們會使用 prepare 方法. 另一類的指令,如 CREATE 和 DELETE,我們會使用 do 方法. 我們先看看後者如何使用. 

這一段程式示在資料庫中建立一個員工資料表格的方法. 

use strict;
use DBI;

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jerrypassword',
                        {
                          RaiseError => 1,
                          AutoCommit => 0
                        }
                      )
          || die "Database connection not made: $DBI::errstr";

my $sql = qq{ CREATE TABLE employees ( id INTEGER NOT NULL, 
                                       name VARCHAR(128), 
                                       title VARCHAR(128), 
                                       phone CHAR(10) 
                                     ) };
$dbh->do( $sql );
$dbh->commit();
$dbh->disconnect();
    
進階功能
我們已經學會了連線資料庫,錯誤偵測,以及下達簡單的 SQL 述的方法. 是該學一些更有用的程式語法的時候了. 

SELECT 述
在 SQL 的述中,最常使用的指令莫過於 SELECT 述. 為了使用 SELECT,我們應該先 prepare 這一段述,然後進行 execute 動作. 在下面的程式片段中,我們都會使用 statement handle $sth 有存取 SELECT 的結果. 

use strict;
use DBI;

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jeerrypassword',
                        {
                          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();
    
上述程式要求 DBMaker 資料庫為查詢指令先準備好執行計畫,之後再執行該查詢指令. 到目前為止還沒有任何一筆記錄傳回. 稍後我們會使用 bind_columns 的技術以取得資料庫輸出的記錄. bind_columns 分別將每個輸出欄位結到一個 scalar reference. 一旦呼叫到 fetch 時,這些 scalars 就會填入這資料庫傳回的值. 

use strict;
use DBI;

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jerrypassword',
                        {
                          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 述做一次 prepare,就能夠高速地執行許多次. 

use strict;
use DBI;

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jerrypassword',
                        {
                          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, $_);
  $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 文件指出,如果想作一套穩固的交易機制,就應該配合 eval{...} 區塊來攔截錯誤的發生,最後再使用 commit 或 rollback 來完成整個交易程序. 這就是我們以下所要談的內容. 

本程式示保四筆記錄寫入資料庫的方法. 

use strict;
use DBI qw(:sql_types);

my $dbh = DBI->connect( 'dbi:DBMaker:dbsample',
                        'jerry',
                        'jerrypassword',
                        {
                          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]);
    $sth->bind_param( 2, @$_->[1]);
    $sth->bind_param( 3, @$_->[2]);
    $sth->bind_param( 4, @$_->[3]);
    $sth->execute();
    $dbh->commit();
  };

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

$sth->finish();
$dbh->disconnect();
    
注意事項
關於 finish 的呼叫在我們的例子並不是必要的. 這個函數適用於 statement handle 完成時所使用。 
永遠要加上 use strict。 
仔細閱讀 Perl DBI manual 以深入解 DBI 架構 
其他資訊
DBI - A Database Interface Module for Perl 5 
DBI at Hermetica 
DBI mailing list information 
DBI mailing list archives 
Persistent connections with mod_perl 

--------------------------------------------------------------------------------

This document rewrite to Chinese by Jackie Yu. Last modified 20 May 1999 
This document Copyright Jeffrey William Baker. Last modified 10 October 1998   
 
 
(http://www.fanqiang.com)
    進入【UNIX論壇

相關文章

======
 

★  樊強制作 歡迎分享  ★