天天看點

Php Adodb 初探

PHP ADODB 1.99版手冊中文翻譯

翻譯作者:Tripc

修正作者:heiyeluren

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

修正說明:因為之前的版本是台灣版的,是以很多語句不符合大陸的使用習慣,于是我稍微用Editplus修正了一下,希望給學習ADODB的同志們一個參考。

(heiyeluren修正于2005-6-22)

ADODB

PHP 在資料庫的支援上是很令人稱道的,幾乎所有的知名資料庫系統都有對應的函數群支援,而且支援的很完整。但很不幸的,每一群資料庫支援函數無論在名稱或參數結構上,都有很大的差異,這使得PHP的系統開發者在面臨更換資料庫時,總會覺得痛苦萬分。難道這個問題就沒有解決方法嗎?呵呵,當然有,答案就是我現在要介紹的 ADODB 這個PHP物件。

ADODB提供了完整的方法和屬性讓工程師去控制資料庫系統,更棒的是你隻要記得它的功能就好了,因為不同的資料庫系統,隻要修改一個屬性值就可以了,ADODB會自動依據設定取用正确的PHP函數。此外,最多再配合資料庫系統修改修改SQL指令,你的PHP系統就可以在最短的時間内更換到另一個資料庫系統了,如果在編寫程式時,對SQL指令能做妥善規劃,那就更快了。

經過以上的介紹,相信你已經對ADODB的功用有所了解,以下為ADODB的詳細介紹。

取得ADODB

你可以在 http://php.weblogs.com/ADOdb 取得最新版的ADODB。我在編寫本文時,最新版本是1.99版,版權采BSD-Style及LGPL雙軌制,換句話就是Freeware,沒有什麼限制。但在取得ADODB後,最好還是要看一下相關版權說明及用法,并和本文對照一下,以免錯誤。

使用ADODB

基本上使用ADODB是相當容易的,取得壓縮檔案後解開,我建議将整個内容都解到ADODB的目錄裡。然後你可以一邊參考本文,一邊研究裡面的範例,就放在裡面的test目錄下。

由于ADODB附上的說明十分完整詳實,以下的說明大部份來自ADODB的readme.htm,這裡不是全部的内容,我把一些我認為沒有用的内容都去掉了,像版本差異說明、何編寫支援ADODB的驅動程式等與應用無關的部份。想要了解全部内容的讀者還是可以自己去參考 readme.htm。

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

簡介

特色

安裝

啟動ADODB

ADONewConnection

NewADOConnection

支援的資料庫

學習手冊

範例 1 : Select

範例 2 : 進階 Select

範例 3 : Insert

範例 4 : 除錯及 rs2html 範例

範例 5 : MySQL 及選單

範例 6 : 一次連接配接兩個資料庫

範例 7 : 産生更新及新增的SQL指令

範例 8 : 用下一筆及上一筆實作卷動

客制化錯誤處理及PEAR錯誤

資料集快取

參考手冊

ADOConnection

連接配接資料庫:Connect PConnect

執行SQL:Execute CacheExecute SelectLimit CacheSelectLimit Prepare PrepareSP GetOne GetRow

産生 更新/新增:GetUpdateSQL GetInsertSQL

BLOB : UpdateBlob UpdateClob UpdateBlobFile

換頁/卷頁 : PageExecute CachePageExecute

清除 : CacheFlush Close

交易 : BeginTrans CommitTrans RollbackTrans

提取資料 : $ADODB_FETCH_MODE BlankRecordSet

字串 : Concat qstr

日期 : DBDate DBTimeStamp UnixDate UnixTimeStamp

"列"管理器 : Affected_Rows Insert_ID GenID

錯誤處理 : ErrorMsg ErrorNo

資料辭典 : MetaDatabases MetaTables MetaColumns MetaColumnNames

反對 : Bind (? 沒有說明)

ADORecordSet

取單筆記錄 : FetchRow FetchInto FetchObject FetchNextObject GetRowAssoc Fields GetAssoc

取全部記錄 : GetArray GetRows

卷動 : Move MoveNext MoveFirst MoveLast AbsolutePosition CurrentRow AtFirstPage AtLastPage AbsolutePage

選單制作 : GetMenu GetMenu2

日期 : UserDate UserTimeStamp UnixDate UnixTimeStamp

記錄資訊 : RecordCount PO_RecordSet

字段資訊 : FieldCount FetchField MetaType

清除 : Close

rs2html 公用函式說明  範例

簡介

由于PHP的資料庫存取函數沒有标準化,是以我們需要一組函數庫或是類别來隐藏不同資料庫函數介面間的差異,讓我們可以很簡單的去切換資料庫,而這,就是ADODB的目的。

ADODB目前支援MySQL, Oracle, Microsoft SQL Server, Sybase, Sybase SQL Anywhere, Informix, PostgreSQL, FrontBase, Interbase (Firebird 及 Borland 版本), Foxpro, Access, ADO 和 ODBC。ADODB也有透過ODBC成功連接配接Progress及DB2的報告,我們希望能有更的人提供驅動介面來支援更多的資料庫。

PHP4支援連接配接變量(session variables),使用者可以透過ADODB儲存連接配接資訊,以達成真正的可攜性及彈性,相關的用法及資訊請自行參考ADOdb-session.php這個範例。

另外,如果要編寫一個具有高度可移植性的SQL碼,也可以參閱 http://php.weblogs.com/portable_sql 這篇文章。

特色

對熟悉Windows的工程師而言,ADODB很容易使用,因為ADODB裡的很多功能和Microsoft的ADO很像。

與其它的PHP資料庫類别不同,它們大多集中在處理與 select 指令有關的東西,而ADODB對于 inserts 及 update 也提供額外的支援,并且可以很快的連接配接到多資料庫。所提供的方法更擴及日期的掌握,字串的連接配接及字串标記字元差異處理(在某些資料庫間字串的連接配接和标記符号是有差異的)

類型對照系統是内建的,是以我們可以設定或描述像CHAR,TEXT及STRING在不同的資料庫間其實是相同的資料類型。

更容易去移植,因為所有與資料庫相依的程式碼被都隐藏在後端,是以使用者不再需要去移植類别裡的邏輯。

支援 PHP4 連接配接變量,請參考 ADOdb-session.php。

安裝

首先要确定你所使用的PHP版本是 4.01pl2 或是之後的版本(因為ADODB使用到了 require_once及include_once兩個函數)。解壓縮全部的檔案到你的Web伺服器可以存取的一個目錄裡。

要測試ADODB你需要一個資料庫,開啟 testdatabase.inc.php 這個檔案,并且修改連接配接參數,以适合你所使用的資料庫。這個程式會建立一個新的資料表在你的資料庫中,以支援我們提供的測試程式及範例。

就這樣,你安裝好了。

啟動ADODB

當要執行ADODB時,至少有兩個檔案要被載進來,第一個是 ADOdb.inc.php ,這裡面包含了所有資料庫類中要被使用的函數。而對資料庫實作的程式碼則被置放在ADOdb-????.inc.php檔案裡。

例如說,要連接配接一個mysql資料庫:

include('/path/to/set/here/ADOdb.inc.php');$conn = &ADONewConnection('mysql');

無論何時你需要連接配接到一個資料庫時,你必需使用ADONewConnection()函數建立了一個連接配接物件。ADONewConnection接受一個選擇性參數, <database-name-here>。如果沒有參數被指定,它将會使用被 ADOLoadCode() 所載入的最後一個資料庫。 NewADOConnection() 是另一個相同的函數。

當你建立好一個連接配接物件時,你并沒有真的連接配接上你的資料庫。你仍需要使用 $conn->Connect() 或者 $conn->PConnect() 兩個方法來完成真正的連接配接。

你可以參考教學手冊裡的範例,對上面的說明做更深入的了解。

支援的資料庫

名稱

 測試狀态

 資料庫

 RecordCount() 支援與否

 需安裝的驅動程式

 作業系統

access

 B

 Microsoft Access/Jet. 需要建立一個 ODBC/DSN。

 Y/N

 ODBC

 Windows only

ado

 B

 一般未經特别指定的資料庫系統, 透過ADO,允許不設定 DSN連接配接,使用OLEDB以提供較佳的效能。

 ? 視資料庫而定

 ADO or OLEDB provider

 Windows only

ado_access

 B

 Microsoft Access/Jet 透過ADO,允許不設定 DSN連接配接,使用OLEDB以提供較佳的效能。

 Y/N

 ADO or OLEDB provider

 Windows only

ado_mssql

 B

 Microsoft SQL Server 透過ADO,允許不設定 DSN連接配接,使用OLEDB以提供較佳的效能。

 Y/N

 ADO or OLEDB provider

 Windows only

db2

 C

 DB2. 可以透過ODBC獲得可以信賴的運作效果。

 Y/N

 DB2 CLI/ODBC interface

 Unix and Windows. Unix install hints.

vfp

 A

 Microsoft Visual FoxPro,需要建立一個ODBC/DSN

 Y/N

 ODBC

 Windows only

fbsql

 C

 FrontBase.

 Y

 ?

 Unix and Windows

ibase

 B

 Interbase 6或更早的版本。有些使用者報告必需使用如下的方式連接配接

$db->PConnect('localhost:c:/ibase/employee.gdb', "sysdba", "masterkey")目前沒有支援 Affected_Rows 方法

 Y/N

 Interbase client

 Unix and Windows

firebird

 C

 interbase的Firebird版本

 Y/N

 Interbase client

 Unix and Windows

borland_ibase

 C

 Borland 的Interbase 6.5 或更新版

 Y/N

 Interbase client

 Unix and Windows

informix

 C

 Informix

 Y/N

 Informix client

 Unix and Windows

mssql

 A

 Microsoft SQL Server 7.也可以和Microsoft SQL Server 2000運作的很好。但在日期格式上仍有一些問題。例如在日期時間的傳回值上,就不會傳回秒數數值。

 Y/N

 Mssql client

 Unix and Windows.

Unix install howto.

mysql

 A

 MySQL 不支援交易處理

 Y/N

 MySQL client

 Unix and Windows

mysqlt 或 maxsql

 A

 MySQL 支援交易處理

 Y/N

 MySQL client

 Unix and Windows

oci8

 A

 Oracle 8/9. 支援比 oracle 驅動程式還多的功能 (例如: Affected_Rows). 在連接配接之前,你可能需要先配好環境變量('ORACLE_HOME=...')

有兩個方式進行連接配接,用伺服器的IP或服務名稱:

PConnect('serverip:1521','scott','tiger','service')

PConnect('', 'scott', 'tiger', 'tnsname').

 Y/N

 Oracle client

 Unix and Windows

oci8po

 A

 Oracle 8/9 可攜式驅動程式

 Y/N

 Oracle client

 Unix and Windows

odbc

 A

 标準 ODBC

用 PConnect('DSN','user','pwd').連接配接。

 ? depends on database

 ODBC

 Unix and Windows. Unix hints.

odbc_mssql

 C

 用 ODBC 連接配接 MSSQL

 Y/N

 ODBC

 Unix and Windows.

odbc_oracle

 C

 用 ODBC 連接配接 ORACLE

 Y/N

 ODBC

 Unix and Windows.

oracle

 C

 支援舊的 Oracle 7 client API. 不支援 $ADODB_FETCH_MODE.

 Y/N

 Oracle client

 Unix and Windows

postgres

 A

 PostgreSQL 不支援 LIMIT 指令.

 Y

 PostgreSQL client

 Unix and Windows.

postgres7

 A

 PostgreSQL 支援 LIMIT 及其它版本 7 功能

 Y

 PostgreSQL client

 Unix and Windows.

sqlanywhere

 C

 Sybase SQL Anywhere.

 Y/N

 SQL Anywhere ODBC client

 ?

sybase

 C

 Sybase.

 Y/N

 Sybase client

 Unix and Windows. Unix hints.

 

測試狀态欄的代碼說明如下:

A=已經經過很多人驗證及測試,可靠度最高。

B=已經測試并使用了,但可能仍有一些功能沒有達成。

C=使用者自行配置或試用的驅動程式,可能沒有完全支援ADODB的功能。

"RecordCount()支援與否",指的是RecordCount()函數是否會傳回用SELECT指令取得的記錄筆數(不支援時傳回- 1)。如果這個字段的值出現了 Y/N ,那表示當全域變量 $ADODB_COUNTER=true 時,會以模拟的方式取得,而這是預設值。要注意的是,如果你預測記錄筆數會很大時,最好把這個值設為false,也就是關掉這個模拟功能,因為這會耗掉非常多的記憶體,以做為快取之用。由于這個變量在每次執行時都會檢查,是以你可以選擇性的使用或不使用。

所有支援$ADODB_FETCH_MODE的資料庫都支援 ADODB_FETCH_NUM(以字段順序存取) 及 ADODB_FETCH_ASSOC(以字段名稱存取),兩種模式。而将值設為 ADODB_FETCH_DEFAULT(資料庫預設模式存取),則是由資料庫的功能來決定的,是以不具備可攜性,而 ADODB_FETCH_BOTH(雙模式存取) 也一樣。

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

學習手冊

範例 1: Select 指令

任務:連接配接到 Access 的 Northwind DSN,然後在每一列顯示頭2個字段。(Northwind 北風資料庫,在ODBC設定的DSN,是Access的标準範例資料庫)

在這個範例中,我們建立一個 ADOConnection 物件,它代表了和資料庫的連接配接。連接配接是以 PConnect 函數來初始化的,然後會持續的連接配接着。任何時候我們要查詢資料庫時,我們就調用 ADOConnection.Execute() 函數,這将會傳回一個 ADORecordSet物件。事實上它隻是一個指向在fields[]陣列中,目前記錄的名額,我們使用MoveNext()來在記錄間移動。

注意:另一個很有用的函數 SelectLimit 并沒有在這個範例裡使用,這個函數允許我們去限制顯示的資料筆數。

<?include('ADOdb.inc.php');       # 載入ADODB$conn = &ADONewConnection('access');    # 建立一個連接配接$conn->PConnect('northwind');   # 連接配接到 MS-Access 北風資料庫$recordSet = &$conn->Execute('select * from products');if (!$recordSet)         print $conn->ErrorMsg();elsewhile (!$recordSet->EOF) {        print $recordSet->fields[0].' '.$recordSet->fields[1].'<BR>';        $recordSet->MoveNext();}$recordSet->Close(); # 選擇性執行$conn->Close(); # 選擇性執行?>

在這個例子中,$recordSet傳回了存在$recordSet ->fields陣列裡,目前所指向的記錄。以字段編号為索引,起始值為0。我們使用MoveNext()函數來移動到下一筆記錄,當到了最後一筆時,EOF屬性會被設定為true。當Execute()函數執行有錯誤時,會傳回一個false值,而不是一個recordset物件。

$recordSet->fields[]陣列是由PHP資料庫擴充函數庫所産生的。有一些資料庫擴充函數庫僅支援以編号來進行索引,而不支援以字段名為索引。要強迫使用字段名索引,也就是要使用關連式陣列,請使用 $ADODB_FETCH_MODE 全域變量來設定。當一個資料集被Execute()或是SelectLimit()函數建立時,都會儲存而且使用儲如此類的設定模式。

       $ADODB_FETCH_MODE = ADODB_FETCH_NUM;        $rs1 = $db->Execute('select * from table');        $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;        $rs2 = $db->Execute('select * from table');        print_r($rs1->fields); # shows array([0]=>'v0',[1] =>'v1')        print_r($rs2->fields); # shows array(['col1']=>'v0',['col2'] =>'v1')

上面的範例說明,如果要以順序來存取字段,就将 $ADODB_FETCH_MODE 的值設為 ADODB_FETCH_NUM,要以關連式陣列(以字段名)存取字段,就要将值設為 ADODB_FETCH_ASSOC。

要取得在被選到的記錄筆數,你可以使用$recordSet->RecordCount()方法。注意,如果不能确定得到的記錄筆數,會傳回 -1 。

範例 2: 進階的 Select 指令(使用 Field 物件)

任務:選取一個資料表,顯示最前面的二欄。如果第二欄是一個日期或時間型态字段,将它格式化成US格式。

<?include('ADOdb.inc.php');       $conn = &ADONewConnection('access');    $conn->PConnect('northwind');   $recordSet = &$conn->Execute('select CustomerID,OrderDate from Orders');if (!$recordSet)         print $conn->ErrorMsg();elsewhile (!$recordSet->EOF) {        $fld = $recordSet->FetchField(1);        $type = $recordSet->MetaType($fld->type);        if ( $type == 'D' || $type == 'T')                print $recordSet->fields[0].' '.                        $recordSet->UserDate($recordSet->fields[1],'m/d/Y').'<BR>';        else                 print $recordSet->fields[0].' '.$recordSet->fields[1].'<BR>';        $recordSet->MoveNext();}$recordSet->Close(); # optional$conn->Close(); # optional?>

在這個例子中,我們使用 FetchField() 函數來檢查第二個字段的資料類型。這将會傳回一個至少有三個字段的物件,字段說明如下:

name: 字段名

type: 字段的資料原生類型native field type of column

max_length: 字段的最大長度,部份資料庫像MySQL,并不傳回字段的正确值,以這個例子而言,就會傳回 -1 。

然後我們使用 MetaType() 去轉換原生類型成通用類型,目前通用類型定義如下:

C:  character 字段,應該使用 <input type="text"> 标記來取值。

X: 文字字段(Text) , 長文字字段,使用 <textarea> 标記來顯示資料。

B: Blob 字段或者大型的二位元物件(像程式,圖檔等)。

D: 日期字段

T: 時間字段

L: 邏輯字段(真假值)或位元字段

N: 數字字段,包含自動進位、編号、整數、浮點數、實數等。

R: 序列字段,包含了序列、自動增進整數,隻對被選擇的資料庫作用。

如果對應類型是日期或時間,那你可以使用 UserDate() 函數來設定輸出的日期格式。這個函數會轉換 PHP SQL 日期字串格式為使用者定義的格式。 另一個使用MetaType()的時機是在進行SQL新增或更新指令時,資料格式驗證用。

範例 3: 新增

新增一筆記錄到訂單資料表,裡面包含了日期和字串,為了能被資料庫正常存取,字串必需校正,以避免部份标記字元。例如:有單引号的字串,John's。

<?include('ADOdb.inc.php');       # load code common to ADOdb$conn = &ADONewConnection('access');    # create a connection$conn->PConnect('northwind');   # connect to MS-Access, northwind dsn$shipto = $conn->qstr("John's Old Shoppe");$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";$sql .= "values ('ANATR',2,".$conn->DBDate(time()).",$shipto)";if ($conn->Execute($sql) === false) {        print 'error inserting: '.$conn->ErrorMsg().'<BR>';}?>

在這個範例中,我們看見了ADODB更進一步的日期及标點符号的處理方式。Unix 日期時間标示(長整數)被DBDate()格式化成Access可以接受的格式,而帶了縮寫符号的 John's Old Shoppe 則被 qstr() 函數處理成 John''s Old Shoppe 字串,以被資料庫合法存取。

觀察 Execute 指令的錯誤處理。如果 Execute() 執行有錯誤發生時,會傳回 False 值。而最後的錯誤資訊可以由  ErrorMsg() 來顯示。

附記:php_track_errors旗标可以被啟動,以便将錯誤資訊儲存起來。

範例 4: 除錯

<?include('ADOdb.inc.php');       # load code common to ADOdb$conn = &ADONewConnection('access');    # create a connection$conn->PConnect('northwind');   # connect to MS-Access, northwind dsn$shipto = $conn->qstr("John's Old Shoppe");$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";$sql .= "values ('ANATR',2,".$conn->FormatDate(time()).",$shipto)";$conn->debug = true;if ($conn->Execute($sql) === false) print 'error inserting';?>

在上面的例子中,我們藉由設定 debug=true 來啟動除錯模式。這将會在執行指令時會先将SQL指令顯示,并且會顯示所有的錯誤資訊,而不需要去調用 ErrorMsg() 。顯示資料集的部份,可以參考 rs2html() 範例。

其它的請參考自定錯誤處理的說明。

範例 5: MySQL及選單

連接配接到MySQL資料庫agora ,并且從SQL指令中建立一個 <select> 選單,<option>的标題是第一個字段,傳回值是第二個字段。

<?include('ADOdb.inc.php'); # load code common to ADOdb$conn = &ADONewConnection('mysql');  # create a connection$conn->PConnect('localhost','userid','','agora');# connect to MySQL, agora db$sql = 'select CustomerName, CustomerID from customers';$rs = $conn->Execute($sql);print $rs->GetMenu('GetCust','Mary Rosli');?>

Here we define a menu named GetCust, with the menu option 'Mary Rosli' selected. See GetMenu(). We also have functions that return the recordset as an array: GetArray(), and as an associative array with the key being the first column: GetAssoc().

這裡,我們定義了一個名為GetCust的選單,預設值是'Mary Rosli'。相關說明請參考 GetMenu() 。我們也将資料集以陣列傳回的方式寫在 GetArray()方法裡。而另外傳回關聯式陣列的方法則使用 GetAssoc() ,其中第一個字段是這個字段的鍵值。

在 1.50 版以後的 ADODB 裡,是使用公共變量 $ADODB_FETCH_MODE 來設定傳回的陣列是以編号或是關連式字串做索引。

範例 6: 一次連接配接兩個資料庫

<?include('ADOdb.inc.php');     # 載入 ADOdb$conn1 = &ADONewConnection('mysql');  # 建立一個 mysql 連接配接$conn2 = &ADONewConnection('oracle');  # 建立一個 oracle 連接配接$conn1->PConnect($server, $userid, $password, $database);$conn2->PConnect(false, $ora_userid, $ora_pwd, $tnsname);$conn1->Execute('insert ...');$conn2->Execute('update ...');?>

範例 7: 産生 Update 及 Insert 的SQL指令

ADODB 1.31版起,新增了兩個資料集函數:GetUpdateSQL()及GetInsertSQL()。這允許你在執行了像"SELECT * FROM table query WHERE..."這樣的查詢函數後,建立一個 $rs->fields複本,改變這些字段,然後自動産生出更新或是新增的SQL指令。

以下我們展示如何運用這些函數,我們将存取一個資料表,帶有下列字段:(ID,FirstName,LastName,Created)。在這些函數被執行前,你需要藉由一個對資料表的查詢指令(select)來初始化一個資料集。

<?

#==============================================

#  GetUpdateSQL() 及 GetInsertSQL() 範例碼

#==============================================

include('ADOdb.inc.php');

include('tohtml.inc.php');

#==========================

# 以下的程式碼測試新增狀态

$sql = "SELECT * FROM ADOXYZ WHERE id = -1";

# 從資料庫中查詢出一個空的資料集

$conn = &ADONewConnection("mysql");  # 建立一個連接配接

$conn->debug=1;

$conn->PConnect("localhost", "admin", "", "test"); # 連接配接到 MySQL, 資料庫名稱為 test

$rs = $conn->Execute($sql); # 執行查詢,并取得一個空的資料集

$record = array(); # 初始化一個陣列,以便存放記錄資料供新增用

# 設定記錄中的字段值

$record["firstname"] = "Bob";

$record["lastname"] = "Smith";

$record["created"] = time();

# 傳入空的資料集及字段資料陣列到GetInsertSQL函數中,以執行功能

# 這個函數将會依傳入的資料,傳回一個全格式的 INSERT SQL指令

$insertSQL = $conn->GetInsertSQL($rs, $record);

$conn->Execute($insertSQL); # 将記錄挿入資料庫中

#==========================

# 以下的程式碼測試更新狀态

$sql = "SELECT * FROM ADOXYZ WHERE id = 1";

# 選擇一筆記錄以便更新

$rs = $conn->Execute($sql); # 執行這個查詢,并取得一個存在的記錄來更新

$record = array(); # 初始化一個陣列,以存放要更新的資料

# 設定字段裡的值

$record["firstname"] = "Caroline";

$record["lastname"] = "Smith"; # 更新 Caroline的姓由 Miranda 變成 Smith

# 傳入這個隻有單一記錄的資料集以及含有資料的陣列到 GetUpdateSQL函數裡

# 函數将會傳回一個具有正确 WHERE 條件的 UPDATE(更新) SQL 指令

$updateSQL = $conn->GetUpdateSQL($rs, $record);

$conn->Execute($updateSQL); # 更新資料庫中的記錄

$conn->Close();

?>

範例 8: 使用上一筆及下一筆實作卷動

我們使用HTTP取得 $next_page 變量,以追蹤要跳去那一頁并且儲存目前頁碼在 session 變量 $curr_page 裡。

我們調用連接配接物件的 PageExecute()函收去取得我們要的資料集,然後我們使用資料集的 AtFirstPage() 及 AtLastPage() 函數去決定是否顯示下一頁和上一頁按鈕。

<?phpinclude_once('ADOdb.inc.php');include_once('tohtml.inc.php');session_register('curr_page');$db = NewADOConnection('mysql');$db->Connect('localhost','root','','xphplens');$num_of_rows_per_page = 10;$sql = 'select * from products';if (isset($HTTP_GET_VARS['next_page']))        $curr_page = $HTTP_GET_VARS['next_page'];if (empty($curr_page)) $curr_page = 1; ## at first page$rs = $db->PageExecute($sql, $num_of_rows_per_page, $curr_page);if (!$rs) die('Query Failed');if (!$rs->EOF && (!$rs->AtFirstPage() || !$rs->AtLastPage())) {        if (!$rs->AtFirstPage()) {?><a href="<?php echo $PHPSELF,'?next_page=',$rs->AbsolutePage() - 1 ?>" target="_blank" rel="external nofollow" >Previous page</a><?php        }        if (!$rs->AtLastPage()) {?><a href="<?php echo $PHPSELF,'?next_page=',$rs->AbsolutePage() + 1 ?>" target="_blank" rel="external nofollow" >Next page</a><?php        }        rs2html($rs);}?>

以上的程式碼可以在 testpaging.php 範例裡找到。

使用自定錯誤處理及 PEAR_Error

在之前的版本,你可以使用像 $con->debug=true ; 這樣的設定來進行除錯。但在 1.50 版後,我們提供了另一種方法來處理錯誤狀态。我們讓工程師可以使用 ADODB 的自訂錯誤處理程式功能。

ADODB 提供了兩種自訂處理方式,你可以配合你的的需要而修訂。第一個方法放在 ADOdb-errorhandler.inc.php 檔案裡。這讓你可以使用标準的 PHP 函數 err_reporting 去控制要顯示怎樣的錯誤資訊及 trigger_error 去調用 PHP 預設的錯誤處理程式。

引入了上述檔案後(ADOdb-errorhandler.inc.php),當發生了下列的錯誤後,将會使得 trigger_error($errorstring,E_USER_ERROR)被調用。

Connect() 或 PConnect() 執行失敗時。

執行 SQL 指令的函數失敗時,如 Execute() 或 SelectLimin() 。

GenID() 進入了無限回圈時。

這裡的 $errorstring 變量是由 ADODB 所産生的。而且會包含了有用的除錯資訊,類似于随後會建立的 error.log 資料。是以,為了要能正确提供除錯資訊,你要在建立 ADOConnection 物件前,就把 ADOdb-errorhandler.inc.php 引入到程式碼中。

If you define error_reporting(0), no errors will be shown. If you set error_reporting(E_ALL), all errors will be displayed on the screen.

如果你設定了 error_reporting(0) 的話,将不會有任何錯誤被顯示。如果你設定了 error_reporting(E_ALL),那将會顯示所有的錯誤資訊。

以下是一個簡單的範例:

<?phperror_reporting(E_ALL); # 顯示所有的錯誤資訊include('ADOdb-errorhandler.inc.php');include('ADOdb.inc.php'); include('tohtml.inc.php');$c = NewADOConnection('mysql');$c->PConnect('localhost','root','','northwind');$rs=$c->Execute('select * from productsz'); #不正确的資料表 productsz');if ($rs) $rs2html($rs);?>

如果你要把錯誤資訊記錄下來,你可以定義兩個選擇性常數 ADODB_ERROR_LOG_TYPE, ADODB_ERROR_LOG_DEST。有關于 ADODB_ERROR_LOG_TYPE 的值,你可以去參考 PHP 使用手冊中有關于 error_log 的說明。在以下的範例中,我使将它設為 3,意思是指将資訊記錄到常數 ADODB_ERROR_LOG_DEST 所設定的檔案中。

<?phperror_reporting(0); # 不顯示任何的錯誤資訊define('ADODB_ERROR_LOG_TYPE',3);define ('ADODB_ERROR_LOG_DEST','C:/errors.log');include('ADOdb-errorhandler.inc.php');include('ADOdb.inc.php');include('tohtml.inc.php');$c = NewADOConnection('mysql');$c->PConnect('localhost','root','','northwind');$rs=$c->Execute('select * from productsz'); ## 不正确的資料表 productszif ($rs) $rs2html($rs);?>

以下則是寫在 error.log 檔的錯誤資訊:

(2001-10-28 14:20:38) mysql error: [1146: Table 'northwind.productsz' doesn't exist] in EXECUTE("select * from productsz")

第二種錯誤處理方法是 ADOdb-errorpear.inc.php 。使用這種方式,在錯誤發生時會産生 PEAR_Error 衍生物件,而最後産生的 PEAR_Error 物件可以被 ADODB_Pear_Errir() 函數取回。

<?phpinclude('ADOdb-errorpear.inc.php');include('ADOdb.inc.php');include('tohtml.inc.php');$c = NewADOConnection('mysql');$c->PConnect('localhost','root','','northwind');$rs=$c->Execute('select * from productsz'); #不正确的資料表 productsz');if ($rs) $rs2html($rs);else {        $e = ADODB_Pear_Error();        echo '<p>',$e->message(),'</p>';}?>

在引入 ADOdb-errorpear.inc.php 檔之前,藉由定義 ADODB_PEAR_ERROR_CLASS 常數,你可以使用一個 PEAR_Error 衍生類别。為了友善除錯,你可以在 PHP 程式碼的最前面定義預設的錯誤理方式為 PEAR_ERROR_DIE,這将會使得程式一出錯,馬上就輸出錯誤資訊,并且停止執行。

include('PEAR.php');PEAR::setErrorHandling('PEAR_ERROR_DIE');

注意,當錯誤産生時,ADODB并沒有明确的傳回一個 PEAR_Error 物件給你。你必需要去調用 ADODB_Pear_Error() 函數去取回最後的錯誤内容。或者,你可以使用 PEAR_ERROR_DIE 這個技巧。

資料集快取

現在,ADODB使用 CacheExecute(),CachePageExecute()及CacheSelectLimit()函數來支援資料集快取。用法類似于沒有快取的函數,除了要加上一個新的參數 $secs2cache。

以下是一個範例 :

include('ADOdb.inc.php'); # 載入ADODB$ADODB_CACHE_DIR = '/usr/ADODB_cache';$conn = &ADONewConnection('mysql');  # 建立一個連接配接$conn->PConnect('localhost','userid','','agora');# 連接配接到 MySQL, agora 資料庫$sql = 'select CustomerName, CustomerID from customers';$rs = $conn->CacheExecute(15,$sql);

第一個參數是設定查詢的快取秒數。随後調用的查詢将會使用存放在由  $ADODB_CACHE_DIR 變量指定的快取資料。要強迫查訊執行,并且更新快取記錄,使用 CacheExecute() 函數,并且将第一個參數設為 0 。或者,使用 CacheFlush($sql) 也行。

基于安全的考量,如果你要使用 $ADODB_CACHE_DIR,我們建議你将在 php.ini 裡的 register_globals 設成 off。

在 ADODB 1.80版以後,在 CacheSelectLimit() 及 CacheExecute() 中,參數 secs2cache 是選擇性的。如果你不填上去,系統将會使用 $connection->cacheSecs 屬性的值,它的預設值是 60 分鐘。

       $conn->Connect(...);        $conn->cacheSecs = 3600*24; // 快取24小時        $rs = $conn->CacheExecute('select * from table');

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

參考手冊

以[]包起來的參數為選用參數,可有可無。

共用變量

$ADODB_COUNTRECS

當本變量($ADODB_COUNTRECS)被設為 true 時,如果資料庫驅動程式介面(API)不支援傳回被 SELECT 指令所選取的資料筆數,那麼 RecordCount() 函數将會自動模拟,并傳回正确的資料筆數,預設值即為 true。模拟方式是建立一個記憶體暫存區來放置這些資料,是以當取回的資料筆數很大時,會占用很大量的記憶體。當設定本變量值為 false 時,會有最好的效能。本變量在每次執行查訊時都會自動檢查,是以你可以依實際需要在每次查詢前進行設定。

$ADODB_CACHE_DIR

如果你使用了資料集快取功能,那麼那些快取資料都會被置放到這個變量所指定的目錄裡。是以當你要使用諸如 CacheExecute() 函數前,你應該要先設定好本變量。期于安全的考量,如果你要使用 $ADODB_CACHE_DIR,我們建議你将在 php.ini 裡的 register_globals 設成 off。

$ADODB_FETCH_MODE

這個共用變量決定了資料集以那種方式将資料傳給陣列。資料集在被建立時(如 Execute()或SelectLimit())會把本變量($ADODB_FETCH_MODE)的值儲存下來,而随後本變量($ ADODB_FETCH_MODE)的任何改變都不會影響到現存的資料集,隻有在以後資料集被建立起來時才會改變。

以下為為已定義的常數:

define('ADODB_FETCH_DEFAULT',0);

define('ADODB_FETCH_NUM',1);

define('ADODB_FETCH_ASSOC',2);

define('ADODB_FETCH_BOTH',3);

以下為一個使用的例子:

       $ADODB_FETCH_MODE = ADODB_FETCH_NUM;        $rs1 = $db->Execute('select * from table');        $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;        $rs2 = $db->Execute('select * from table');        print_r($rs1->fields); # 顯示 array([0]=>'v0',[1] =>'v1')        print_r($rs2->fields); # 顯示 array(['col1']=>'v0',['col2'] =>'v1')

在本範例中,如你所見兩個資料集在被Execute()建立時,會依據 $ADODB_FERCH_MODE 的值來決定儲存及使用的存取模式。

如果沒有任何的模式被設定,預設值則是 ADODB_FETCH_DEFAULT。呈現的模式則依據資料庫驅動程式而有所不同。為了可攜性,我們建議你固定為 ADODB_FETCH_NUM 及 ADODB_FETCH_ASSOC,因為有許多驅動程式并不支援 ADODB_FETCH_BOTH 。

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

ADOConnection

提供連接配接資料庫,執行SQL指令以及一組準格式化的SQL相關函數等功能的物件。

ADOConnection 屬性

databaseType: 要連接配接的資料庫系統名稱,如 odbc,mssql,mysql┅等。詳細内容請參考上表。

dataProvider: 下層的資料庫結結機制,除了使用 odbc 或 ado 外,一般正常會設為  native。

host: 資料庫主機名稱,可用IP或來源名稱(DSN)進行連接配接。如203.74.225.22 , dbs1.nukepro.com , "localhost" , "odbc_dsn1"

database: 資料庫或連接配接名稱,如果使用了 ado,則會控制 ado 資料提供驅動程式(ado data provider)。

user: 登入時的 ID,密碼則基于安全考量沒有保留。

raiseErrorFn: 允許你定義一個錯誤處理函數,請參考 ADOdb-errorhandler.inc.php 的範例.

debug: 被設定為 true 時,會顯示除錯資訊。

concat_operator: 連接配接運算元,一般會設為 '+' 或 '||'。這個運算元是為了在 SQL 裡連接配接字串的。會在 Concat 函數中被用到。

fmtDate: 日期格式,在DBDate函數中會使用到,做為送日期資料到資料庫的依據。在Access格式為'#Y-m-d#',在MySQL格式為"/Y-m-d/"。

fmtTimeStamp: 時間格式,在 DBTimeStamp 函數中要送時間資料到資料庫時會使用到。

true: 資料中真值的表現方式,如在Foxpro用'T',MS SQL用'1'。

false: 資料中假值的表現方式,如在Foxpro用'F',MS SQL用'0'。

replaceQuote: 這個字串用來處理逸出符号。例如在 Microsoft SQL 裡的雙引号,MySQL裡的反斜線符号。主要使用于 qstr 。

autoCommit: 設定是否啟動自動交易模式,預設值為 true。

charSet: 設定使用的字元集,目前隻有 interbase 支援。

metaTablesSQL: 使用SQL指令,以傳回一份可用的資料表清單。例如在 MySQL 裡的 SHOW TABLES。

genID: 如果資料庫有支援的話,這裡會存放由GetID()所取得的最後值。

cacheSecs: 快取資料集的秒數。用于當使用者利用 CacheExecute() 或 CacheSeletLimit() 函數,又沒有設定 $secs2cache 參數時的預設值。

sysDate: 利用資料庫函數去取得目前的日期和時間。會使用到原生的日期時間标記格式。

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

ADOConnection 主要函數

ADOConnection( )

建構函數,請不要直接調用,使用 ADONewConnection() 來代替。

Connect($host,[$user],[$password],[$database])

對伺服器或資料來源 $host 非持續性連接配接,使用者認證代碼為 $user ,密碼為 $password ,如果伺服器支援多資料庫,則指定連接配接到資料庫$database。

連接配接成功傳回 true , 失敗則傳回 false 。

注意:如果你使用的是 Microsoft ADO,而非 OLEDB,你可以設定 $database 參數為你正在使用的 OLEDB 資料供應器。

PostgreSQL:另一種選擇性的連接配接方法是将标準的PostgreSQL連接配接字串放在 $host 參數裡,那麼其它的參數都會被呼略。

對于 Oracle 及 Oci8,有兩個方法可以連接配接。第一,使用你定義的區域 tnsnames.ora 裡的 TNS 名稱,将這個名稱放在 $database 參數裡,然後将 $host 設為 false。另一種方法,設定 $host 為伺服器,而 $database 則設成資料庫SID ,這将會不透過 tnsnames.ora 連接配接。

範例:

 $conn->Connect(false, 'scott', 'tiger', 'name_in_tnsnames'); # 使用 tnsnames.ora $conn->Connect('server:1521', 'scott', 'tiger', 'OracleSID'); # 不使用 tnsnames.ora

還有許多的資料庫連接配接範例在網站 php.weblogs.com/ADOdb 以及在本版所附的 testdatabase.inc.php 檔案裡。

PConnect($host,[$user],[$password],[$database])

對伺服器或資料來源 $host 持續性連接配接,使用者認證代碼為 $user ,密碼為 $password ,如果伺服器支援多資料庫,則指定連接配接到資料庫$database。

連接配接成功傳回 true , 失敗則傳回 false 。其它資料請參考 Connect()。

Execute($sql,$inputarr=false)

執行 SQL 指令 $sql ,如果成功,就傳回一個對應的 ADORecordSet 物件。要注意的是這個指令如果執行成功時,一定會傳回一個資料集,即使是執行 insert 或 update 指令也一樣。

傳回對應的 ADORecordSet 物件。例如,如果連接配接的是 mysql ,那麼 ADORecordSet_mysql 将會被傳回。當SQL指令執行失敗時會傳回 false 值。

$inputarr 參數則用來做為傳入的結合變量。以下是 Oracle 的範例:

 $conn->Execute("SELECT * FROM TABLE WHERE COND=:val", array('val'=> $val));

另一個例子,使用 ODBC ,以 '?' 符号做為協定。

  $conn->Execute("SELECT * FROM TABLE WHERE COND=?", array($val));

結合變量(Binding variables)

變量的結合可以加速SQL指令編譯及快取的速度,産生較佳的效能。目前隻有 Oracle 及 ODBC 支援變量結合。 ODBC 類的 ? 結合在不支援的資料庫裡,是以模拟的方式來做到的。

變量結合在 odbc 及 oci8po 驅動程式裡的用法。

$rs = $db->Execute('select * from table where val=?', array('10'));

變量結合在 oci8 驅動程式裡的用法。

$rs = $db->Execute('select name from table where val=:key',array('key' => 10));

CacheExecute($secs2cache,$sql,$inputarr=false)

類似于 Execute 函數,除了将資料集暫存在 $ADODB_CACHE_DIR 指定的目錄裡 $secs2cache 秒外。如果 CacheExecute() 被相同的參數、資料庫、使用者ID及密碼,而且快取也沒有過期,那麼快取中的資料集将會被傳回。

  include('ADOdb.inc.php');   include('tohtml.inc.php');  $ADODB_CACHE_DIR = '/usr/local/ADOdbcache';  $conn = &ADONewConnection('mysql');   $conn->PConnect('localhost','userid','password','database');  $rs = $conn->CacheExecute(15, 'select * from table'); # 快取15秒  rs2html($rs);

另外,從ADODB 1.80 版起,$secs2cache 參數成為選擇性(也就是可以不加)

       $conn->Connect(...);        $conn->cacheSecs = 3600*24; // cache 24 hours        $rs = $conn->CacheExecute('select * from table');

如果 CacheExecute() 被多次調用,而且資料集也持續在快取中,$secs2cache 參數不會延長被快取的資料集保留時間(因為會被呼略掉),CacheExecute()隻能使用在 SELECT 指令上。

效能備注:我曾經作了一些效能測試,并且發現這些快取的效益極為顯着。尤其是在資料庫伺服器運作效率慢于WEB伺服器或資料庫的負荷非常重的時候。 ADODB的快取好在它減少了資料庫伺服器的負荷。當然,如果你的資料庫伺服器負荷不大,而且運作速度也比WEB伺服器快,那快取反而會降低效能。

SelectLimit($sql,$numrows=-1,$offset=-1,$inputarr=false)

執行成功會傳回一個資料集。完成一個SELECT指令,類似于 PostgreSQL中 SELECT 指令裡的LIMIT $numrows OFFSET $offset 宣告。

在 PostgreSQL,SELECT * FROM TABLE LIMIT 3 将會隻傳回從頭開始的三筆記錄。相同的,$connection->SelectLimit('SELECT * FROM TABLE',3)也有同樣的意思。

而 SELECT * FROM TABLE LIMIT 3 OFFSET 2 将會傳回記錄 3,4及5三筆(也就是在記錄2之後,傳回三筆記錄)。相同的,在ADODB裡是以 $connection->SelectLimit('SELECT * FROM TABLE',3,2) 來做的。

要注意,LIMIT宣告,在MySQL裡是相反位置的。你可以設定 $connection->SelectLimit('select * from table',-1,10) 去取得從第11筆起到最後一筆的記錄。

最後一個參數 $inputarr 是針對支援變量結合功能的資料庫,像 Oracle oci8。這個大大的減少了 SQL 編譯的負荷。底下是 Oracle 範例:

 $conn->SelectLimit("SELECT * FROM TABLE WHERE COND=:val", 100,-1,array('val'=> $val));

oci8po 驅動程式(oracle portable driver)使用更為标準的變量結合:

 $conn->SelectLimit("SELECT * FROM TABLE WHERE COND=?", 100,-1,array('val'=> $val));

Ron Wilson 報告說 SelectLimit 在SQL指令有含 UNION 時會無效,并且建議了針對 mssql 的對策:

> 事實上,我發現一個可以立即最佳化的建構 Select Union 方法。這适用于 MS-SQL,至于其它資料庫是否适合,就不确定了。當更新求助檔時,你可以參考這個範例。注意,這個方法不适用于 MySQL。>> 改變:>  Select column1 From table1>  Union>  Select column2 From table2> > 成為:>  Select * From (>   Select column1 From table1>   Union>   Select column2 From table2>   )>  As dummytable> > Ron

CacheSelectLimit($secs2cache, $sql, $numrows=-1,$offset=-1,$inputarr=false)

類似于 SelectLimit,除了将資料集暫存在 $ADODB_CACHE_DIR 指定的目錄裡 $secs2cache 秒外。

自 1.80版起,$secs2cache成為了選擇性參數:

 $conn->Connect(...);        $conn->cacheSecs = 3600*24; // 快取24小時        $rs = $conn->CacheSelectLimit('select * from table',10);

CacheFlush($sql)

更新(删除)以 $sql 指令存放在 $ADODB_CACHE_DIR 指定目錄内的全部快取資料集。如果你企圖更新所有的快取資料集,請執行如下的PHP指令碼(僅針對 Unix 有效):system("rm -f find ".ADODB_CACH_DIR." -name ADODB_*.cache") ;

ErrorMsg()

傳回最後狀态或是錯誤資訊。即使沒有錯誤發生,本函數也會傳回一個字串。一般情況下,你不需要調用這個函數,除非ADODB函數因為錯誤狀态傳回了false值。

注意:如果 debug 旗标被啟動了,SQL 錯誤資訊将會在Execute函數被調用時發生錯誤後出現。

ErrorNo()

傳回最後的錯誤号碼。注意一點,舊版本的 PHP(4.0.6以前),不支援ODBC的錯誤編号。一般情況下,你不需要調用這個函數,除非ADODB函數因為錯誤狀态傳回了false值。

GenID($seqName = 'ADOdbseq',$startID=1)

産生一個順序号碼(在mssql是一個整數值)。對 interbase,mysql,postgresql,oci8,oci8po,ODBC核心類驅動程式(如 access,vfp,db2等等) 都支援。使用 $seqName做為順序名。如果資料庫沒有值,那麼GenID()将會自動為你産生一個序号(産生使用者 id 時允許如此),換句話說,你必需自行建立序号。

如果你的資料庫驅動程式要模拟序号,資料表的名稱就是序号名(sequence name),而這個資料表必需有一個字段"id",而其資料類型為整數,或你需要更大些的 numeric(16)。

對于沒有支援序号原生功能的ODBC及資料庫(如 mssql,mysql),我們對每一個序号建立一個資料表。如果序号沒有被預先定義,那啟如的号碼值就設定成 $startID。

注意,mssql驅動程式的 GenID()會産生一個16位元的GUID。自1.90版起,我們将傳回整數。

UpdateBlob($table,$column,$val,$where)

允許你以 $where 條件儲存一個BLOB(存在 $val裡的)值到 $table 裡的 $column 字段。

例:

 

       # for oracle        $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, empty_blob())');        $conn->UpdateBlob('blobtable','blobcol',$blobvalue,'id=1');        # non oracle databases        $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');        $conn->UpdateBlob('blobtable','blobcol',$blobvalue,'id=1');

如果成功,會傳回 true ,否則傳回 false 值。目前有 MySQL, PostgreSQL, Oci8, Oci8po 及 Interbase 支援。其它驅動程式可能有效,仍在持續開發中。

要注意,在PHP 4.1.0 以前的版本,當 Interbase的 blob 值被 SELECT 取回值時,它仍需要被解碼,請使用 $connection->DecodeBlob($blob); 以還原它的内容。

UpdateClob($table,$column,$val,$where)

允許你以 $where 條件儲存一個BLOB(存在 $val裡的)值到 $table 裡的 $column 字段。類似于 UpdateBlog,但主要針對文字大型檔案物件。

例:

 

       # for oracle        $conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, empty_clob())');        $conn->UpdateBlob('clobtable','clobcol',$clobvalue,'id=1');        # non oracle databases        $conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)');        $conn->UpdateBlob('clobtable','clobcol',$clobvalue,'id=1');

UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')

如同 UpdateBlob ,但我們将值改成一個檔案路徑,将整個檔案存入。

成功傳回 true 否則為 false。

GetUpdateSQL(&$rs, $arrFields, $forceUpdate=false,$magicq=false)

建立一個 SQL 以更新一個被給予的資料集 $rs ,被修改的字段存放在陣列 $arrFields中(這個陣列必需是具名陣列,字段名為索引,值為修正值),會與原來的資料集做一個比較,如果 $forceUpdate被設為 true,那麼即使 $arrFields與 $rs->fields完全相同,也會産生出更新的SQL指令。資料集必需在連接配接狀态。$magicq 被用于指出魔術引号功能是否被啟動。

GetInsertSQL(&$rs, $arrFields,$magicq=false)

建立一個 SQL 以新增一筆記錄到被給予的資料集 $rs。這個查詢必需是在連接配接狀态。$magicq 被用于指出魔術引号功能是否被啟動。

PageExecute($sql, $nrows, $page, $inputarr=false)

使用資料集的頁碼功能,參數 $page 是以 1 為啟使值,請參考範例 8.

CachePageExecute($secs2cache, $sql, $nrows, $page, $inputarr=false)

使用資料集的頁碼功能,參數 $page 是以 1 為啟使值,請參考範例 8.PageExecute 的快取版。

Close( )

關閉資料庫的連接配接。PHP4 以資料庫連接配接結束時不需要特别去清除而享有盛名,因為其參考計數機制會自動幫我們清除掉。

BeginTrans( )

啟始一筆交易。會關閉自動結案功能。執行成功會傳回 true 。如果不支援交易功能,部份資料庫會一直傳回 false 值。Interbase,Oracle 及 MSSQL 支援交易機制。請注意,因為 PHP 4.02 版的臭蟲,交易支援在微軟的 ADO 上是無效的。你必需使用你關連式資料庫的原生交易支援功能。當連接配接結束時,任何開啟的交易都會被還原。

CommitTrans( )

成功的結束一次交易。如果成功,傳回 true。如果資料庫并不支援交易功能,那麼就隻會傳回 true ,以表示資料總是交易成功的。

RollbackTrans( )

結束一次交易,恢複所有改變。執行成功會傳回 true 。如果資料庫并不支援交易功能,那麼就隻會傳回 false ,以表示資料總是不能恢複。

GetOne($sql)

Executes the SQL and returns the first field of the first row as an array. The recordset and remaining rows are discarded for you automatically. If an error occur, false is returned.

執行SQL指令,并且以陣列的方式傳回第一筆記錄的第一個字段。資料集及其馀的記錄将會被自動清除,如果發生錯誤,就傳回 false 值。

譯者注:這個功能在驗證某筆記錄在不在特别有用,可以減少系統記憶體及資源的用量。

GetRow($sql)

執行SQL指令,并且以陣列的方式傳回第一筆記錄。資料集及其馀的記錄将會被自動清除,如果發生錯誤,就傳回 false 值。

Prepare($sql )

預先編譯一個SQL查詢,以便于重覆執行。如果有任何文法錯誤,Prepare()不會顯示任合錯誤,但允許 Execute() 去取得及顯示錯誤。内部實作支援 interbase ,oci8 及選擇性的 ODBC-based 驅動程式。其馀的都是以模拟的方式支援。在模拟的情況下,使用 Prepare() 對效能的增進沒有任何效果。

傳回一個包含了原始描述為第一個陣列元素的陣列,其馀的元素内容則視驅動程式而定。如果有錯誤或是模拟方式的 Prepare(),會傳回原來的 $sql 字串。那是因為所有的錯誤處理都被集中到 Execute() 裡去了。

範例 :

$stmt = $DB->Prepare('insert into table (col1,col2) values (?,?)');for ($i=0; $i < $max; $i++) $DB->Execute($stmt,array((string) rand(), $i));

PrepareSP($sql)

在 mssql 驅動程式裡,預編譯預儲程式必需要透過一個特别的函數來調用 mssql_init(),這個動作目前由本函數來處理了。PrepareSP() 可以在所有的驅動程式由被調用,而且以調用 Prepare() 的方式來模拟。使用範例請參考以下的 Parameter() 說明。

和上面的 Prepare() 傳回一樣的陣列或 $sql 字串。

Parameter($stmt, $var, $name, $isOutput=false, $maxLen = 4000, $type = false )

在運作中增加一個結合參數。目前相容于 Microsoft SQL 及 Oracle oci8。以下是參數說明:

$stmt  由 Prepare() 或 PrepareSP() 傳回的指令。

$var 要結合的 PHP 變量。

$name 要結合的預儲程式的變量名。

[$isOutput] 設定參數傳導的方向,0/false = IN 1=OUT 2= IN/OUT 。 在 oci8 中這個參數會被忽略,因為驅動程式會自動偵測。

[$maxLen] 參數變量的最大長度。

[$type] 參考 mssql_bind 及 ocibindbyname 在 PHP.NET 的檔案說明以取得更多正确值的資訊。

在 mssql,$opt 可以被下列的元素所影響:mssql_bind and ocibindbyname 。 例如 ;

# @RETVAL = SP_RUNSOMETHING @myid,@group$stmt = $db->PrepareSP('SP_RUNSOMETHING'); # note that the parameter name does not have @ in front!$db->Parameter($stmt,$id,'myid'); $db->Parameter($stmt,$group,'group',false,64);# return value in mssql - RETVAL is hard-coded name $db->Parameter($stmt,$ret,'RETVAL',true); $db->Execute($stmt);

一個 oci8 的例子:

# 對于 oracle, Prepare 及 PrepareSP 是相同的$stmt = $db->PrepareSP(        "declare ret integer;     begin                 :RETVAL := SP_RUNSOMETHING(:myid,:group);     end;");$db->Parameter($stmt,$id,'myid');$db->Parameter($stmt,$group,'group',false,64);$db->Parameter($stmt,$ret,'RETVAL',true);$db->Execute($stmt);

請注意,在 oci8 及 mssql 間隻有文法上的不同,那是各資料庫實作 SQL 文法問題,ADODB 對于這一部份無能為力。

如果 $type 參數被設定成 false 。在 mssql ,$type 将會動态的由 PHP 變量傳來的類型決定(string => SQLCHAR, boolean =>SQLINT1, integer =>SQLINT4 或  float/double=>SQLFLT8),在 oci8,$type 可以被設成 OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) 及 OCI_B_ROWID (ROWID)。如果要傳入空值,使用  $db->Parameter($stmt, $null=null, 'param')。

最後,在 oci8,結合參數可以重覆被使用,而無需再一次調用 PrepareSP() 或 Parameters。但這對 mssql 是不行的。一個 oci8 的範例如下:

$id = 0; $i = 0;$stmt = $db->PrepareSP( "update table set val=:i where id=:id");$db->Parameter($stmt,$id,'id');$db->Parameter($stmt,$i, 'i');for ($cnt=0; $cnt < 1000; $cnt++) {        $id = $cnt;        $i = $cnt * $cnt; # oci8 下可以運作        $db->Execute($stmt);}

Bind($stmt, $var, $size=4001, $type=false, $name=false)

這是一個低階函數,隻有 oci8 驅動程式支援。隻有你确定系統僅支援 Oracle 否則請避免使用它。Parameter() 函數是使用結合變量的另一個建議方式。

Bind() 允許你使用結合變量在你的 sql 叙述中。這裡結合一個PHP變量給一個在之前被 Prepare() 預先編譯的 Oracle sql 叙述裡定義的名稱。Oracle 以一個冒号為開頭來命名一個變量,而且 ADODB 需要一個被命名的變量去對應 :0,:1,:2,:3,等等。第一次被 Bind() 取得的将會代入 :0,而第二次将會代入 :1,依此類推。對 insert , select 及 update 指令,結合可以提供 100% 的效能提升。

在其馀的參數裡,$size 設定資料儲存的暫存區大小,$type 是 OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) 及 OCI_B_ROWID (ROWID) 的類别選項。最後,代替使用預設的 :0,:1 等等名稱,你可以使用 $name 來定義你自己的連接配接名稱。

接下來的例子展示3個連接配接變量,使用 p1,p2及p3來結合。這些變量将會配到 :0 , :1 及 :2 。

$stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)");$DB->Bind($stmt, $p1);$DB->Bind($stmt, $p2);$DB->Bind($stmt, $p3);for ($i = 0; $i < $max; $i++) {    $p1 = ?; $p2 = ?; $p3 = ?;   $DB->Execute($stmt);}

你也可以使用名稱變量:

$stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:name0, :name1, :name2)");$DB->Bind($stmt, $p1, "name0");$DB->Bind($stmt, $p2, "name1");$DB->Bind($stmt, $p3, "name2");for ($i = 0; $i < $max; $i++) {    $p1 = ?; $p2 = ?; $p3 = ?;   $DB->Execute($stmt);}

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

ADOConnection 公用函數

BlankRecordSet([$queryid])

不再使用,本版已移除。

Concat($s1,$s2,....)

産生一個結合 $s1,$s2,..等 sql 字串的字串,使用了在 concat_operator 字段定義的結合運算符号。如果結合運算符号不被使用,那這個函數将無效,例如 MySQL 。

本函數傳回含結合符号的字串。

DBDate($date)

格式化 $date 成資料庫可以接收的格式,這可以是一個 Unix 整數時間記錄格式或是一個 ISO 格式的 Y-m-d。使用 fmtDate 字段所定義的格式。如果傳入的是 null 或是 false 或是 '' ,那将會轉成一個 SQL 的 null。

傳回一個日期字串。

DBTimeStamp($ts)

格式化時間記錄格式的 $ts 成資料庫可接受的格式。這可以是一個 Unix 整數時間記錄格式或是一個 ISO 格式的 Y-m-d。使用 fmtDate 字段所定義的格式。如果傳入的是 null 或是 false 或是 '' ,那将會轉成一個 SQL 的 null。

傳回一個時間字串。

qstr($s,[$magic_quotes_enabled=false])

将一個字串放在引号内,以送到資料庫中。$magic_quotes_enabled 參數可能看起來很有趣,但這個想法是假設你已經用一個引号來處理了從 POST/GET 變量取來的字串後,然後以 get_magic_quotes_gpc() 做為第二個參數。這會确定這個變量不會被引号處理二次,一次被 qstr 處理,一次被 magic_quotes_gqc。

例如:  $s = $db->qstr(HTTP_GET_VARS['name'],get_magic_quotes_gpc());

傳回值是一個被引号處理過的字串。

Affected_Rows( )

傳回被SQL指令更新或被删除掉的資料筆數。如果資料庫不支援,傳回一個 false 值。

目前 interbase/firebird 不支援本函數。

Insert_ID( )

傳回最後插入時的自動增進值 ID。如果系統不支援,傳回 false。

隻支援有提供自動增進或物件 ID 的資料庫,目前像是 PostgreSQL, MySQL 以及 MSSQL 都有。PostgreSQL 傳回一個 OID,可以在資料庫重載入時改變。隻有使用持續連接配接方式,當你完成一筆交易時,這個函數才會有精确的結果。這是因為被 Execute() 宣告的連接配接可能和下一個 Execute() 時用的連接配接不同。

MetaDatabases()

傳回一個在伺服器中的資料庫清單于陣列裡。首先你必需連接配接到伺服器。目前隻支援 ODBC, MySQL 及 ADO。

MetaTables()

傳回目前資料庫中全部資料表名稱于一個陣列中。如果可能,這個陣列将會排除系統目錄資料表。

MetaColumns($table)

傳回一個 ADOFieldObject 的陣列,一個字段物件對應到一個 $table 的所有行。目前 Sybase 不能辨識資料類型,ADO 不能辨識正确的資料類型(是以我們預設為 varchar)..

MetaColumnNames($table)

傳回 $table 的行名于一個陣列中。

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

ADORecordSet(資料集)

當一個SQL指令成功的被 ADOConnection->Execute($sql)執行後,一個 ADORecordSet 物件會被傳回回來。這個物件提供了一個虛拟的名額,是以我們可以移動它,從一筆到一筆。也提供一些函數,以取得字段資訊和字段類别,并有協助函數去格式化結果,以展示給使用者看。

ADORecordSet 屬性

fields: 包含了目前記錄的陣列。不是關連式陣列,但它的索引值是從 0 到 字段數 - 1。請參考函數 Fields ,這個函數的動作就像是一個關連式陣列。

dataProvider: 連接配接資料庫的底層機制,正常設定為 native ,除非是使用 odbc 或 ado 。

blobSize: 一個 char , string 或者 varchar object 在被轉成 Blob 前的最大長度(Blob 在顯示時應該使用 textarea)。其它請參考 MetaType 函數。

sql: 儲存了建立本資料集所使用的 sql 指令。

canSeek: 如果 Move() 函數有作用,會被設成 true 。

EOF: 當名額被移動到最後一筆時,這個值會被設定成 true 。

ADORecordSet 函數

ADORecordSet( )

建構函數。一般來說你不需要自己調用這個函數。

GetAssoc([$force_array])

如果字段數大于 2 ,那麼從資料集中産生一個關連式陣列。這個陣列是從目前的名額起一直到檔尾(EOF)。這個資料集的第一個字段會成為陣列的索引。如果字段數剛好是2,當這陣列被每一個鍵值所建立時,那麼索引會直接對應到值,除非  $force_array 被設成 true 。

範例:

以下是我們資料集的資料:

列1: Apple, Fruit, Edible

列2: Cactus, Plant, Inedible

列3: Rose, Flower, Edible

GetAssociation 将會産生一個如下的關聯式陣列:

Apple => [Fruit, Edible]

Cactus => [Plant, Inedible]

Rose => [Flower,Edible]

傳回值:

關連式陣列,錯誤則傳回 false 。

GetArray([$number_of_rows])

從目前名額位置産生一個陣列,索引值從 0 到 $number_of_rows - 1 。如果 $number_of_rows 沒有被定義,那會到檔尾(EOF)。

GetRows([$number_of_rows])

是 GetArray() 的同義函數,是為了與 Microsoft ADO 相容才有的。

GetMenu($name, [$default_str=''], [$blank1stItem=true], [$multiple_select=false], [$size=0], [$moreAttr=''])

建立一個 HTML 選單  (<select><option><option></select>) 。資料集的第一欄 (fields[0]) 将會作為 <option> 裡的顯示字串。如果資料集有超過一個以上的字段,第二欄 (fields[1]) 将設定成傳回給WEB伺服器的值(即 value)。選單将被給予 $name 為名稱。

如果 $default_str 被定義了,那麼如果 $default_str == fields[0] , 那麼這個字段将會被選取。如果 $blank1stItem 為 true ,那第一個選項将會是空值。$Default_str 在對于可多選清單盒時,可以是一個陣列。

要産生一個選單區,設定 $size 為一個非 0 值(或者傳入 $default_str 為一個陣列)。如果 $multiple_select 為 true ,那麼一個選單區将會被産生成有 $size 個項目可見的選單(如果 $size ==  0 那預設為 5 個),而且ADODB将會傳回一個陣列給伺服器。最後,你可以使用 $moreAttr 去增加其它的屬性,像是 javascrīpt 或樣式表。

選單範例 1: GetMenu('menu1','A',true) 将會産生一個像這樣的選單 : A B C 這裡的資料 (A,1), (B,2), (C,3). 請參考 範例 5 。

選單範例 2: 相同的資料, GetMenu('menu1',array('A','B'),false) 将會産生一個 A 及 B 被選取的選單 : A B C

GetMenu2($name, [$default_str=''], [$blank1stItem=true], [$multiple_select=false], [$size=0], [$moreAttr=''])

近似于 GetMenu ,除了 $default_str 将會和 fields[1] 做比對,也就是選項值。

選單範例 3: 給予在範例 2 裡的資料 , GetMenu2('menu1',array('1','2'),false) 将會産生一個選單,A及B将會被選取。然而,這一次的被選取的比對基準是第二個字段,也就是存放要被傳回給伺服器裡的值。

UserDate($str, [$fmt])

轉換日期字串 $str 為另一個格式,UserDate 調用 UnixDate 來解譯 $str ,而 $fmt 預設值是 Y-m-d 。

UserTimeStamp($str, [$fmt])

轉換時間字串 $str 為另一個格式,時間字串格式是 Y-m-d H:i:s , 像是 "2002-02-28 23:00:12"。UserTimeStamp 調用 UnixTimeStamp 來解譯 $str ,而 $fmt 預設值為 Y-m-d H:i:s 。

UnixDate($str)

将日期字串 $str 解譯,并且轉換成 unix mktime 格式(從 1970.01.01 00:00:00 起到現在的秒數)後傳回。預設日期是以 Y-m-d H:i:s 格式來傳入的。而對于 Sybase 及 Microsoft SQL Server 而言 M d Y 也是可以接受的(三個字元的月份表示法是被一個全域陣列所控制的,這個部份可能需要在地化 )。

自 1.91 版起,這個函數存在于 ADORecordSet 及 ADOConnection兩個地方。

UnixTimeStamp($str)

将時間字串 $str 解譯,并且轉換成 unix mktime 格式(從 1970.01.01 00:00:00 起到現在的秒數)後傳回。預設日期是以 Y-m-d H:i:s 格式來傳入的。而對于 Sybase 及 Microsoft SQL Server 而言 M d Y 也是可以接受的(三個字元的月份表示法是被一個全域陣列所控制的,這個部份可能需要在地化 )。

自 1.91 版起,這個函數存在于 ADORecordSet 及 ADOConnection兩個地方。

MoveNext( )

移動内部名額到下一筆,fields 陣列将會自動的更新。如果不能移動,會傳回 false 值,其它情況則會傳回 true 。

範例 :

$rs = $db->Execute($sql);if ($rs)         while (!$rs->EOF) {                ProcessArray($rs->fields);                $rs->MoveNext();        }

Move($to)

移動内部名額到指定的列 ($to) 。 列數是零基的,例如,0是第一列。fields 陣列将會自動更新。對于不支援内部卷動的資料庫,ADODB将會自動模拟卷動。部份資料庫不支援向後卷動。對大多數的資料庫言,如果 $to 的位置在 EOF 之後,$to 将會被移動到資料集的最後一筆。有些無名的資料庫使用 odbc 時,可能會沒有動作。

注意:這個函數使用了絕對定址,不像 Microsoft 的 ADO。

傳回值是 true 或是 false。如果是 false ,這個内部名額在大多數的實際運作上并沒有移動,是以 AbsolutePosition() 将會傳回名額在執行 Move() 之前最後的位置

MoveFirst()

實際上是調用 Move(0) 。注意,有一些資料庫并不支援這個函數。

MoveLast()

實際上是調用 Move(RecordCount() - 1)。注意,有一些資料庫并不支援這個函數。

GetRowAssoc($toUpper=true)

這個函數并不能持續的以理想的方式維持關連陣列的内容(每換一筆記錄,就要重新執行一次)。使用 $ADODB_FETCH_MODE 共用變量來替代它。

傳回一個包含了目前記錄的關連式陣列,陣列的索引值就是字段名。字段名全都是大寫的,以便存取。要取得下一筆記錄,你要調用 MoveNext() 。

範例 :

Array ( [ID] => 1 [FIRSTNAME] => Caroline [LASTNAME] => Miranda [CREATED] => 2001-07-05 )

注意:不要同時使用 GetRowAssoc() 和 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC 。因為他們有相同的功能,會彼此互動幹擾。

AbsolutePage($page=-1)

傳回目前的頁碼,需要先調用 PageExecute() / CachePageExecute() 。參考 Example 8 。

AtFirstPage($status='')

如果在第一頁,傳回 true (1基式),需要先調用 PageExecute() / CachePageExecute() 。參考 Example 8 。

AtLastPage($status='')

如果在最後一頁,傳回 true (1基式),需要先調用 PageExecute() / CachePageExecute() 。參考 Example 8 。

Fields($colname)

不鼓勵使用,請改以 $ADODB_FETCH_MODE 取代。

當使用原生函數庫時,有些資料庫函數傳回具名及索引雙陣列(如 MySQL)。GetRowAssoc() 并不傳回結合了具名及索引的陣列元素。

本函數傳回由 $colname 所指欄名,在目前記錄裡的的字段值。

字段名區分大小寫。

FetchRow()

傳回目前記錄内容的陣列,如果是檔尾(EOF),傳回 false 。注意:不要把 FetchRow 和 MoveNext() 混用。

用法 :

$rs = $db->Execute($sql);if ($rs)        while ($arr = $rs->FetchRow()) {           # process $arr        }

FetchInto(&$array)

設定 $array 到目前的記錄裡。如果在檔尾(EOF),傳回 PEAR_Error 物件。如果成功,傳回 1 (DB_OK 常數)。

如果 PEAR 未定義,當 EOF 時傳回 false 。FetchRow() 很容易使用,請參考之前的例子。

FetchField($column_number)

傳回一個物件,包含了所指字段的名稱,類别及最大長度。如果最大長度不能被明确決定,将會傳回 -1 。 行号是以 0 基為計算起點的,請參考 範例 2 。

FieldCount( )

傳回資料集裡字段數。

RecordCount( )

傳回資料集裡的記錄筆數。如果無法從資料庫驅動程式API裡取得正确的數字,ADODB将會把所有的記錄内容,存放在記憶體裡,等全部取完後,再傳回記錄總筆數。這個記憶體可以藉由設定全域變量 $ADODB_COUNTERECS = false 而被取消(基于執行效能的理由)。當取消後,對某些資料庫,RecordCount() 将會傳回 -1 。相關支援狀況,請參考前面的資料庫支援表有詳細的說明。

RowCount 和 RecordCount 是同義函數。

PO_RecordCount($table, $where)

傳回在資料集裡的記錄筆數。如果資料庫不支援,那麼将傳回對 $table 資料表下達以 $where 為條件的 SELECT COUNT(*) 指令後傳回的值。

$numrows = $rs->PO_RecordCount("articles_table", "group=$group");

會傳回資料庫執行 SELECT COUNT(*) FROM articles_table WHERE group=$group 的結果。

FetchObject($toupper=true)

傳回目前的記錄為一個物件。如果 $toupper 為 true ,那麼物件字段名将會設為大寫。注意:較新的 FetchNextObject() 是取得記錄物件較被建議的方式,請參看後續說明。

FetchNextObject($toupper=true)

取得目前的記錄成一個物件,并且自動移動到下一個記錄。如果在檔尾,傳回 false 。如果 $toupper 為 true ,那麼物件字段名将會設為大寫。

$rs = $db->Execute('select firstname,lastname from table');if ($rs) {        while ($o = $rs->FetchNextObject()) {                print "$o->FIRSTNAME, $o->LASTNAME<BR>";        }}

在使用 FetchNextObject() 時會影響效能,如果效能很重要,你應該使用 fields[] 陣列來存取。

CurrentRow( )

目傳目前資料集的記錄編号,0 表示是第一筆。

AbsolutePosition( )

和 CurrentRow 是相同的函數,是為了和 ADO 相容而存在的。

MetaType($nativeDBType[,$field_max_length],[$fieldobj])

設定資生資料庫裡的原生類型 $nativeDBType 為那一種通用資料類型,以及它的最大長度。請注意,如果長度未知,可以設為 -1 。字段物件可以使用 $fieldobj 傳入。這對于像是 mysql 這一類字段物件有較多屬性的資料庫來說,是很有用的。

使用字段 blobsize 及比較 $field_max_length 去決定目前的字段是否為 blob 。

傳回值:

C:  character 字段,應該使用 <input type="text"> 标記來取值。

X: 文字字段(Text) , 長文字字段,使用 <textarea> 标記來顯示資料。

B: Blob 字段或者大型的二位元物件(像程式,圖檔等)。

D: 日期字段

T: 時間字段

L: 邏輯字段(真假值)或位元字段

N: 數字字段,包含自動進位、編号、整數、浮點數、實數等。

I: 整數字段

R: 序列字段,包含了序列、自動增進整數,隻對被選擇的資料庫作用。

Close( )

關閉目前的資料集。

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

function rs2html($adorecordset,[$tableheader_attributes], [$col_titles])

這是一個獨立的函數 (rs2heml = recordset to html) ,相當于 PHP 中的 odbc_result_all 函數。本函數會輸出一整個 ADORecordSet,$adorecordset 如同一個 HTML表格。$tableheader_attributes 允許你控制表格裡的參數如 cellpadding,cellspacing 及 border 等的屬性。最後,你可以透過 $col_titles 陣列,更換資料庫字段名稱,使用你自己的字段擡頭。這是設計用來快速除錯的機制,不是一個好的表格記錄浏覽器。

要使用這個函數,你必需引入 tohtml.inc.php 。

rs2html 範例:

<?include('tohtml.inc.php'); # load code common to ADOdb include('ADOdb.inc.php'); # load code common to ADOdb $conn = &ADONewConnection('mysql');   # create a connection $conn->PConnect('localhost','userid','','agora');# connect to MySQL, agora db$sql = 'select CustomerName, CustomerID from customers'; $rs   = $conn->Execute($sql); rs2html($rs,',array('Customer Name','Customer ID'));?>