PHP ADODB 1.99版手册中文翻译 <修正版>PHP ADODB 1.99版手册中文翻译 修正说明:因为之前的版本是台湾版的,所以很多语句不符合大陆的使用习惯,于是我稍微用Editplus修正了一下,希望给学习ADODB的同志们一个参考。 |
|||||||||
ADODBPHP 在数据库的支持上是很令人称道的,几乎所有的知名数据库系统都有对应的函数群支持,而且支持的很完整。但很不幸的,每一群数据库支持函数无论在名称或参数结构上,都有很大的差异,这使得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。
简介由于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 这篇文章。 特色
安装首先要确定你所使用的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() 是另一个相同的函数。 当你建立好一个连接物件时,你并没有真的连接上你的数据库。你仍需要使用 你可以参考教学手册里的范例,对上面的说明做更深入的了解。 支持的数据库 |
|||||||||
名称 |
测试状态 |
数据库 |
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或更早的版本。有些使用者报告必需使用如下的方式连接 |
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. |
||||
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或服务名称: |
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=已经经过很多人验证及测试,可靠度最高。 "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() 函数来检查第二个字段的数据类型。这将会返回一个至少有三个字段的物件,字段说明如下:
然后我们使用 MetaType() 去转换原生类型成通用类型,目前通用类型定义如下:
如果对应类型是日期或时间,那你可以使用 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)来初始化一个数据集。 <? #========================== $sql = "SELECT * FROM ADOXYZ WHERE id = -1"; $conn = &ADONewConnection("mysql"); # 建立一个连接 $record = array(); # 初始化一个阵列,以便存放记录数据供新增用 # 设定记录中的字段值 # 传入空的数据集及字段数据阵列到GetInsertSQL函数中,以执行功能 $insertSQL = $conn->GetInsertSQL($rs, $record); $conn->Execute($insertSQL); # 将记录挿入数据库中 #========================== $sql = "SELECT * FROM ADOXYZ WHERE id = 1"; $rs = $conn->Execute($sql); # 执行这个查询,并取得一个存在的记录来更新 $record = array(); # 初始化一个阵列,以存放要更新的数据 # 设定字段里的值 # 传入这个只有单一记录的数据集以及含有数据的阵列到 GetUpdateSQL函数里 $conn->Execute($updateSQL); # 更新数据库中的记录 范例 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 提供了两种自订处理方式, |