Perl 雖然對文字有強大的處理功能,但若要完整地儲存文字,最方便的方法還是將文字放入資料庫(Databases)。幾乎所有的 UNIX 系統都提供一套稱為 DBM (Database Management) 的標準程式庫,包含了對資料庫的建立、讀取、寫入、刪除等功能,但其資料庫格式是 UNIX 專用格式,並無法和一般資料庫(如 Oracle 或 MS Access)溝通。Perl 本身也支援 DBM 程式庫,因此也可以建立自己專用的資料庫,但由於格式和一般 Win32 資料庫(如 Access、SQL Server、Foxpro)無法溝通,所以較不方便。因此本節重點將以 Perl 如何存取 Win32 的資料庫(如 Microsoft Access、SQL Server等)為主。基本上,Perl 是經由 ODBC (Open Database Connectivity) 的介面和資料庫溝通。ODBC 是由數個大型資料庫廠商所訂定的標準,其功能就是提供一個完整的應用程式介面(API,Application Program Interface),讓其他應用程式或軟體能夠經由一致的介面來和任何平台、任何支援 ODBC 的資料庫溝通。事實上,Perl 還需要一套模組,才能和 ODBC 溝通,在 Win32 平台上,最常用的模組是 Win32::ODBC,這是由 Dave Roth 所設計的模組,專門讓 Perl 存取 Win32 的資料庫,相關網頁可見:
http://www.roth.net/odbc/ Perl程式碼、Win32::ODBC 模組,以及資料庫 ODBC Driver 的關係可用右圖來表示,其中 Perl 先呼叫 Win32::ODBC 中的各種方法來,Win32 再將相關的 SQL (Strucutre Query Language) 命令送到資料庫的 ODBC Drivers Win32::ODBC 模組具有下列優點:Perl 在和資料庫進行溝通之前,我們必須先設定「資料來源名稱」(Data Source Name,簡稱 DSN),這是一個連接至資料庫的代號,包含下列資訊:
- 簡單易用
- 函數用法類似 ODBC API
- 支援大部分的 ODBC 函數
- 可傳回完整的錯誤訊息
- 物件導向的設計
- 對於不同的資料庫和平台,都有很高的可攜性(Portability)
DSN 本身又分兩種類別:
- 資料庫資訊(類別、位置、檔名等)
- 使用者帳號
- 使用者密碼
- 連接至資料庫的相關資訊
欲產生新的 System DSN,可由下列方式來達成:
- 系統資料來源名稱(User DSN):只允許產生 DSN 的使用者來使用,適用於個人使用
- 使用者資料來源名稱(System DSN):允許網路上的使用者來使用,適用於 CGI
開始/設定/控制台/ODBC資料來源/系統資料來源名稱/新增 接著選取資料庫類別及位置,依序完成設定即可。若欲產生新的 User DSN,只需將上述的「系統資料來源名稱」改成「使用者資料來源名稱」即可。一旦設定 DSN 後,即可對資料庫進行讀寫的動作。一般而言,Perl 對資料庫讀寫的動作可以說明如下:
建立資料庫連結的典型程式碼如下:
- 經由 DSN 和資料庫建立連結
- 送出 SQL 命令
- 接受並處理 SQL 命令的結果
- 重複上述兩步驟,直到存取資料完成
- 關閉資料庫連結
$DSN = "Address"; $db = new Win32::ODBC($DSN); # 建立資料庫連結 若 DSN 的設定包含了使用者的帳號和密碼,則上述程式碼應加入帳號和密碼:$DSN = "DSN=Address;UID=Jang;PWD=my_passwd"; $db = new Win32::ODBC($DSN); # 建立資料庫連結 在上述範例中,帳號是「Jang」,密碼是「my_passwd」。在建立資料庫連結的過程中,若發生錯誤,我們應該印出錯誤訊息,因此上述程式碼的第二列可修改成較完整的寫法,如下:
if (!($db = new Win32::ODBC($dsn))) { print "Error in opening DSN \"$dsn\"!\n"; print "Reason: " . Win32::ODBC::Error(). "\n"; exit; } 請注意在上述程式片段中,若資料庫連結成功,則會回傳一個物件,反之,則會回傳 undef,並將 Win32::ODBC::Error() 傳回的錯誤訊息印出。連結資料庫成功後,接著我們就要送入 SQL 命令,可用 sql() 方法來達成,典型程式碼如下:$sql = "SELECT * FROM table1"; # 選出資料表 table1 中的所有欄位 if ($db->Sql($sql)) { print "Error in SQL query: \"$sql\"!\n"; print "Reason: " . $db->Error() . "\n"; $db->Close(); exit; } 請注意在上述程式碼中,若 SQL 命令執行成功,則 $db->sql($sql) 會回傳 undef,這和前述連結資料庫的回傳意義剛好顛倒。若 SQL 命令執行時發生任何錯誤,$db->Error() 會傳回相關的錯誤訊息。成功送入 SQL 命令後,接著我們要將回傳資料一筆一筆進行處理,典型程式碼如下:
while ($db->FetchRow()) { %Data = $db->DataHash(); … process result … } 上述 while-迴圈會一再執行,每次成功取得一筆資料時,$db->FetchRow() 即傳回 1,如此依序處理資料,直到所有資料都被處理完畢為止。在每次迴圈中,%Data 會取得每筆資料,並以 hash 的資料型態來儲存此筆資料,其中資料庫的欄位名稱就變成 %Data 的 key,而欄位值就變成 %Data 的 value。若只需要數個欄位,我們可把欄位名稱放入 $db->DataHash 的引數,例如,若只要取得欄位 Name 和 Positoin 的值,可改用下列程式碼:%Data = $db->DataHash("Name", "Position"); 在完成對所有資料的處理後,別忘了要使用下列程式碼來清除和資料庫的連結:$db->Close(); 以下是一個完整的例子,此範例會將 example/test.mdb 的資料庫逐筆印出,在嘗試此範例之前,請記得先要設定 DSN,亦即要將名稱為 AddressBook 的 DSN 設定至資料庫 example/test.mdb。此範例程式碼(listdb1.pl)如下:若要新增、刪除或修改資料庫,只要換用不同的 SQL 命令就可以了,請參閱有關 SQL 的章節。
在送入 SQL 命令時,字串欄位值要用單引號刮住,例如:
$sql = "select * from table1 where NAME = 'Roger'"; 但如果是數值欄位,就不需要使用單引號,例如:$sql = "select * from table1 where AGE = 38"; 如果是字串欄位,而且其欄位值還包含單引號,那麼就要使用兩個單引號,例如:$sql = "select * from table1 where NAME = 'Roger''s fish'"; 在上例中,欄位值是「Roger's fish」,將單引號重複一次後,就得到上述的 SQL 命令。另一個常碰到的問題是:如何使用「|」於欄位值?因為「|」在 SQL 裡面有特殊的意義,因此下面是一個錯誤的寫法:
$sql = "select * from table1 where NAME = 'P|Q'"; 正確的寫法,則是使用「|」的 ASCII 內碼,將 'P|Q' 轉換成 'P' & chr(124) & 'Q',所以正確寫法如下:$sql = "select * from table1 where NAME = 'P' & chr(124) & 'Q'";
Perl