PHP ADODB1.99版手册 (修正版)

PHP ADODB 1.99版手册中文翻译 <修正版>

感谢
记事

PHP ADODB 1.99版手册中文翻译 <修正版>

感谢
记事


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

mysqltmaxsql

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();
else
while (!$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();
else
while (!$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() 函数去决定是否显示下一页和上一页按钮。

<?php
include_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 ?>">Previous page</a>
<?php
        }
        if (!$rs->AtLastPage()) {
?>
<a href="<?php echo $PHPSELF,'?next_page=',$rs->AbsolutePage() + 1 ?>">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)被调用。

  1. Connect() 或 PConnect() 执行失败时。

  2. 执行 SQL 指令的函数失败时,如 Execute() 或 SelectLimin() 。

  3. 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),那将会显示所有的错误信息。

以下是一个简单的范例:

<?php
error_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 所设定的文件中。

<?php
error_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'); ## 不正确的数据表 productsz
if ($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() 函数取回。

<?php
include('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: 下层的数据库结结机制,除了使用 odbcado 外,一般正常会设为  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); /* recordset to html table */  

另外,从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 ,除非是使用 odbcado

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 去增加其它的属性,像是 javascript 或样式表。

选单范例 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,'border=2 cellpadding=3',array('Customer Name','Customer ID'));
?>

感谢
——————

PHP ADODB 1.99版手册中文翻译
Tripc <tripc.tw@yahoo.com.tw>

Published by

风君子

独自遨游何稽首 揭天掀地慰生平