PHP ADODB 1.99版手册中文翻译(转)

PHP ADODB 1.99版手册中文翻译
翻译作者:Tripc
------------------

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。


简介

由於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_bindocibindbyname 在 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>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
欢迎使用 ADO Microsoft® ActiveX® Data Objects (ADO) 使您的客户端应用程序能够通过 OLE DB 提供者访问和操作在数据库服务器中的数据。 ADO 程序员参考 ADO 支持用于建立基于客户端/服务器和 Web 的应用程序的主要功能。其主要优点是易于使用、高速度、低内存支出和占用磁盘空间较少。ADO 同时具有远程数据服务 (RDS) 功能,通过 RDS 可以在一次往返过程中实现将数据从服务器移动到客户端应用程序或 Web 页、在客户端对数据进行处理然后将更新结果返回服务器的操作。 有关 ADO 的详细信息,请参阅 ADO 概述。请在 http://www.microsoft.com/data/ado 中参阅 Microsoft 有关 ADO 发布说明的 Web 页。 ADO Extensions for DDL and Security (ADOX) 程序员参考 ActiveX Data Objects Extensions for DDL and Security (ADOX) 将 ADO 扩展为包括创建、修改和删除模式对象,如表格和过程。它还包括安全对象,用于维护用户和组,以及授予和撤消对象的权限。 有关 ADOX 的详细信息,请参阅 ADOX 概述。请在 http://www.microsoft.com/data/ado 中参阅 Microsoft 有关 ADOX 发布说明的 Web 页。 ADO MD 程序员参考 ActiveX Data Objects (Multidimensional) (ADO MD) 将 ADO 扩展为包括指定到多维数据的对象,并允许浏览多维模式、查询立方和检索结果。 有关 ADO MD 的详细信息,请参阅 ADO MD 概述。请在 http://www.microsoft.com/data/ado 中参阅 Microsoft 有关 ADO MD 发布说明的 Web 页。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值