ADODB详解

ADODB参考手册:http://docs.haohtml.com/adodb/docs/docs-adodb.htm

PHP在数据库的支持上是很令人称道的,几乎所有的知名数据库系统都有对应的函数库支持,而且支持得很完整。但遗憾的是,每一群数据库支持函数无论在名称或参数结构上,都有很大的差异,这使得PHP的系统开发者在面临更换数据库时,总会觉得痛苦万分。

难道这个问题就没有解决方法吗?当然有,答案就是将要介绍的ADODB这个PHP类库。

ADODB提供了完整的方法和属性,可以用来控制数据库系统,更棒的是你只要记得它的功能即可,因为不同的数据库系统,只要修改一个属性值,ADODB就会自动依据设定取用正确的PHP函数。

此外,再配合数据库系统修改SQL命令,这样PHP系统就可以在最短的时间内更换到另一个数据库系统;如果在编写程序时,对SQL命令能做妥善规划,那就更快了。

经过以上的介绍,相信你已经对ADODB的功用有所了解了,以下为ADODB的详细介绍。

下载ADODB:可以在http://adodb.sourceforge.net/ 取得最新版的ADODB(见图17-2)。

图17-2

ADODB的最新版本是adodb495a版,根据需要,可以下载完整版本的ADODB。如果您主要使用MySQL,则可以下载ADODB的lite版本,减少体积和一些不必要的系统开销。

17.4.1 使用ADODB
由于PHP的数据库存取函数没有标准化,所以需要一组函数库或类别来隐藏不同数据库函数界面间的差异。可以实现相对简单的数据库系统移植,这就是ADODB抽象层要实现的目标。

ADODB目前支持的数据库系统MySQL、Oracle、MS SQL Server、Sybase/Sybase SQL Anywhere、Informix、PostgreSQL、FrontBase、Interbase(Firebird及Borland版本)、Foxpro、Access、ADO和ODBC连接。

与其他数据库抽象层相比,其他类大多集中在处理与Select操作有关的内容,而ADODB对于Insert及Update操作也提供额外的支持,并且可以很快连接到多类数据库,提供的统计方法,在底层实现字串连接及字串标记变量的差异处理(在某些数据库中,字串的连接和标记符号是有差异的)。

字段类型对照系统是ADODB抽象层的特性之一,所以我们可以描述像CHAR、TEXT(而Oracle是Clob类型)及STRING这样的通用字段类型,而不必理会采用的数据库使用的是哪种类型,它会在底层替我们做对应和转换。

因此使用ADODB开发,对于系统来说移植相对变得容易,因为所有与数据库相依存的程序代码被都隐藏在后端,使用者不再需要去移植类别里的逻辑。

ADODB拥趸者很多,很多著名的开源软件:PostNuke、phpWiki、Mambo、eGroupware等,都使用ADODB作为数据库抽象类库。

17.4.2 ADODB安装
首先要将全部文件解压缩到Web服务器目录里,如lib/adodb。要测试ADODB则需要一个数据库,打开testdatabase.inc.php 这个文件,并且修改连接参数,以适合你所使用的数据库。这个程序会在你的数据库中建立一个新的资料表,以支持我们提供的测试程序及范例。

17.4.3 启动ADODB
当要执行ADODB时,至少有两个文件要被加载进来,第一个是 ADOdb.inc.php,这里面包含了所有数据库类中要被使用的函数。而对数据库操作的程序代码则被放置在ADOdb.inc.php文件里。

ADODB可以连接的名称及对应的数据库系统,如表17-1所示。

表17-1

连接标识
access
mssql
mysql
oci8
postgres7

数据库名称
MS Access
MS SQL Server
MySQL
oracle 8
PostgreSQL 7

下面我们来看怎么使用ADODB连接数据库。

1.连接MySQL数据库
我们使用如下方法连接一个MySQL数据库:

require_coce(‘/libs/adodb/ADOdb.inc.php’);

$conn = &ADONewConnection(‘mysql’);

无论连接到一个什么类型的数据库,我们都要使用ADONewConnection()函数来创建一个连接对象。

ADONewConnection接收一个选择性参数:,用以表示要连接的数据库。如果没有参数被指定,它将会使用ADOLoadCode() 内部方法所载入的最后一个数据库。

当建立好一个连接对象后,我们还没有真正连接上数据库,需要使用$conn->Connect()或者$conn->PConnect() 两个方法,任选其一来完成真正的数据库连接:

$conn -> Connect(DB_HOST,DB_USER,DB_PASSWORD,$database)

下面是创建一个mysql数据库连接对象,并创建一个数据库连接:

$conn = ADONewConnection(‘mysql’); //创建一个ADODB连接对象

$mysql_obj = $conn->connect(‘localhost’,’root’,’passwd’,’dbname’); //连接到MySQL服务器

if (!$ora_obj) {

echo $mysql_conn->ErrorMsg(); //显示连接的错误信息

exit();

}else{

$mysql_conn -> SetFetchMode(3);

}

Var_dump($mysql_obj);

这样我们就创建好与本地MySQL服务器的连接了。可以看到,ADODB连接数据库同样很方便。

2.连接Oracle数据库
如果要连接Oracle数据库该如何写呢?结合表17-1,我们可以编写脚本如下:

require_once (“libs/adodb/adodb.inc.php”);

$ora_conn = &ADONewConnection(‘oci8’);

$ora_obj = $ora_conn -> Connect(‘localhost’,’oracle’,’oracle’,’oradb’);

if (!$ora_obj) {

echo $ora_conn->ErrorMsg();

exit();

}else{

$ora_conn -> SetFetchMode(3);

}

Var_dump($ora_conn);

注意:连接Oracle数据库需要在PHP本地环境安装好Oracle的客户端驱动,以及连接文件设置。

其中,SetFetchMode(3)指的是取得记录集时,返回的是二维关联数组。也可以使用字符形式,这样更明了一些:

$mysql_conn->SetFetchMode(ADODB_FETCH_ASSOC);

17.4.4 ADODB的查询方法
ADODB的查询方法如下。

1.直接查询
Excute()方法通过连接句柄执行SQL查询,并返回一个变量,如下:

$sql=’Select * FROM ice_cream Where flavor LIKE ?’;

$res = $cnx->Execute($sql,array(‘Chocolate’));

2.缓存查询
ADODB提供内置的缓存机制,CacheExecute()方法用于每次查询数据时,会把相应的结果序列化后保存到文件中,以后同样的查询语句就可以不用直接查询数据库,而是从缓存文件中获取,从而提高Web系统的性能。CacheExecute()方法的格式如下:

CacheExecute($ttc,$sql)

该方法以缓存的形式执行一段查询,其中$ttc为缓存的时间,请看如下代码:

$ADODB_CACHE_DIR = “/var/tmp/adodb_cache”; //缓存保存的文件目录

$sql = “Select surname, age FROM employees”; //构造一个查询

$rs = &$db->CacheExecute(600,$sql); // 缓存式查询,缓存将被保存600秒后更新

3.清除缓存
CacheFlush()

该方法用来清除所有ADODB数据库的缓存。

17.4.5 移动记录集
记录集(Record Set):从执行的方法中返回指定的记录,使用moveFirst()、moveLast()、moveNext()和move($n)方法访问记录集中的一个指定记录。例如:

$rs=$cnx->Execute(‘Select flavor,price FROM ice_cream’);

$rs->MoveLast();

print “Flavor “.$rs->fields[0].” costs ”

.$rs->fields[2].”\n”;

$rs->MoveFirst();

//省略…

$rs->Move(2);

//省略…

$rs->MoveNext();

设置一个全局变量$ADODB_FETCH_MODE,从ADODB_FETCH_NUM(或从ADODB_FETCH_ASSOC返回)中取得数字索引(或关联索引)数组。例如:

$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC ;

$rs=$cnx->Execute(‘Select flavor,price FROM ice_cream’);

print ”

\n”;while (! $rs->EOF) {

 

print ”

“.

\n”;

$rs->MoveNext();

}

print ”

“.$rs->fields[‘flavor’]}.” “.$rs->fields[‘price’]”.”

\n”;

FetchObject()方法也是一个记录集变量。

17.4.6 使用ADODB生成HTML
ADODB的rs2html($res)函数,它提供一个简单的方法,从$res变量中的记录自动生成HTML表格。

它在tohtml.inc.php中,使用时需要包含进来,如下代码:

require ‘adodb/tohtml.inc.php’; //引入rs2html函数

require ‘adodb/adodb.inc.php’;

//省略…

$rs = $cnx->Execute(‘Select flavor,calories,price FROM ice_cream’);

rs2html($rs);

使用rs2html($res,’CLASS=”myClass”)这种格式,表示指定表格使用的myClass的样式表类进行显示。

17.4.7 使用ADODB进行分页
ADODB_Pager(该方法定义在adodb-pager.inc.php中)提供一种简单分页显示记录的方法。

require ‘adodb/adodb.inc.php’;

require ‘adodb/adodb-pager.inc.php’;

$pager=new ADODB_Pager($cnx,”Select id,flavor,price FROM ice_cream_big”);

$pager->Render();

使用$pager->Render($num)来设置每次显示的行数,默认值为10。

17.4.8 生成下拉选择菜单
getMenu($selectName)方法将帮助我们生成一个标签,即从记录集中生成一个下拉菜单。其中,$selectName是该表单中select的name标签。例如:

$rs = $cnx->execute(‘Select flavor,id FROM ice_cream’);

print $rs->GetMenu(‘which_flavor’);

相关说明如下:

Ø getMenu($sN,$selected,$blank,$mult,$nm):其中,$selected (string)为默认选择的值/项。

Ø $blank (boolean):默认初始值或布尔值为true时,下拉选项为空。

Ø $mult (boolean):下拉菜单是否可以允许多选。

Ø $nm (integer):设置菜单多重选择的属性,也就是默认几行。

17.4.9 ADODB开发实例
为了能更好地理解和使用ADODB,下面一起做一个完整的实例。

首先准备一个简单的表,名为“library”,用于保存书籍目录。结构与记录内容如下:

mysql> Select * FROM library;

+—-+——————–+—————+

| id | title | author |

+—-+——————–+—————+

| 14 | ASP.NET 2.0网络编程 | Dennis Lehane |

| 15 | For Kicks | Dick Francis |

| 16 | XML and PHP | Vikram Vaswani |

| 17 | Where Eagles Dare | Jack Higgins |

+—-+——————–+—————-+

在library表中,包含3个字段,分别为:

Ø id——主键,用于保存书的序列号;

Ø title——用于保存书的标题;

Ø author——用于保存作者信息。

下面看使用PHP的传统开发方式,即使用PHP的MySQL API库进行编写的代码,如下:

// 创建一个数据库连接
$connection = mysql_connect(“localhost”, “root”, “passwd”) or die (“Unable to connect!”);
// 选择数据库
mysql_select_db(“adodb”) or die (“Unable to select database!”);
// 构建SQL和开始查询
$query = “Select * FROM library”;
$result = mysql_query($query) or die (“Error in query: $query. ” . mysql_error());
// 遍历记录集,并显示字段的内容
while ($row = mysql_fetch_row($result)){
echo “$row[1] – $row[2]\n”;
}
// 显示返回的记录行数
echo “\n[” . mysql_num_rows($result) . ” 行记录被返回]\n”;
// 关闭数据库连接
mysql_close($connection);
?>

输出结果如下:

ASP.NET 2.0网络编程- Dennis Lehane
For Kicks – Dick Francis
XML and PHP – Vikram Vaswani
Where Eagles Dare – Jack Higgins

[4 行记录被返回]

可以看到此例子比较简洁,连接到数据库,执行查询,取回结果后显示出来。

上述例子用mysql_fetch_row()的抽取功能,取得记录后生成一个连续整数的索引数组,数据内容分别对应数据表中的字段。与此相似的还有mysql_fetch_assoc(),它生成一个关联数组,或者mysql_fetch_object函数,它生成一个对象(其属性相当于字段名)。

这段代码是没有任何问题的,但如果我们想从MySQL迁移到PostgreSQL数据库或者Oracle怎么办呢?代码需要重写了!这时,就需要数据抽象层ADODB上场了。

我们把上例改用ADODB重新编写,请看下面的代码:

include_once(“libs/adodb/adodb.inc.php”);
// 创建一个MySQL连接对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);
// 执行一个查询
$query = “Select * FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 遍历返回的记录集内容,打印返回列的内容:TITLE 和AUTHOR
while (!$result->EOF) {
echo $result->fields[1] . ” – ” . $result->fields[2] . “\n”;
$result->MoveNext();
}
// 显示返回的记录行数
echo “\n[” . $result->RecordCount() . ” 行记录被返回]\n”;
// 关闭数据库连接
$db->Close();
?>

这个程序和上面程序的实现功能是一样的,但是由于采用ADODB抽象层,而没有采用PHP的本地API(mysql或mysqli扩展),因此可以灵活地更换数据库系统,无论哪个数据库以及如何更换,这段代码都是可用的。

下面对上述代码进行详细的解释说明。

首先,我们引用ADODB主类文件:

include_once(“libs/adodb/adodb.inc.php”);

实际上,ADODB库并非只有这一个文件,事实上有超过30个不同的文件,负责驱动不同的数据库系统。我们不用担心是否完全将类包含完全,该文件会自动识别和匹配当前的PHP版本及数据库系统,并自动包含相关的类库文件。

然后,创建ADODB的对象实例:

// 创建一个mysql连接对象

$DB = NewADOConnection(“mysql”);

通过对象的构造参数,告诉ADODB连接数据库,这里连接的是MySQL数据库服务器,对于其他数据库,还可以相应地使用”pgsql”或”oci8″。可以连接的数据库及连接标识参见表17-1。

接下来,连接数据库,这是通过Connect()方法完成的,必须设置一套连接参数:

// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);

以上代码试图打开一个MySQL连接,3个参数分别为主机名、用户名和密码。

一旦Connect()方法建立连接后,就可以调用该对象的Execute()方法进行SQL数据库查询。

// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());

当查询执行成功后,则返回含有查询结果的对象。特别说明的是errormsg()方法,可以用来获取查询的一个错误信息。

从返回的结果集中循环取值:

// 遍历返回的记录集内容,打印返回列的内容:TITLE 和AUTHOR
while (!$result->EOF) {
echo $result->fields[1] . ” – ” . $result->fields[2] . “\n”;
$result->MoveNext();
}

在这种情况下,在循环体内,使用对象的movenext()方法进行记录的移动,每次循环打印后就移动到下一条记录。

取得记录集后,可以使用recordcount()方法取得记录的条数。

// 遍历返回的记录集内容,打印返回列的内容:TITLE 和AUTHOR
echo “\n[” . $result->RecordCount() . ” 行记录被返回]\n”;

最后,使用Close()方法关闭数据库的连接。

// 关闭数据库连接

$db->Close();

如果有人决定要更换数据库,唯一需要改变的是将上述脚本的连接改为新的数据库名称和主机地址即可。

这就是数据抽象层最好的优势之一,它提供一些尽可能通用的方法,将与数据库打交道的代码隐藏在内部,从而使PHP代码简单、清爽、可维护性好,并且缩短开发周期,以及拥有软件包的整体感。

ADODB还提供了一些不同的方法处理结果记录集。例如,我们可以取回结果集为一个关联数组。请看如下脚本:

include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “john”, “doe”, “adodb”) or die(“Unable to connect!”);
// 将结果保存为一个关联数组,也可以使用数值3
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 遍历记录集,显示列的内容:TITLE 和AUTHOR
while (!$result->EOF) {
echo $result->fields[‘title’] . ” – ” . $result->fields[‘author’] . “\n”;
$result->MoveNext();
}
// 取得和显示返回的记录行数
echo “\n[” . $result->RecordCount() . ” 行记录被返回]\n”;
// 关闭数据库连接
$db->Close();
?>

在这个例子里,$ADODB_FETCH_MODE的值用于确定ADODB如何构建结果记录集。

你也可以把取得的行转变为一个对象,其属性相当于字段名,这就是ADODB的FetchNextObject()方法,请看如下脚本例子:

include(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接对象实例
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “john”, “doe”, “adodb”) or die(“Unable to connect!”);
// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 遍历记录集,显示列的内容:TITLE 和AUTHOR
while ($row = $result->FetchNextObject()) {
echo $row->TITLE . ” – ” . $row->AUTHOR . “\n”;
}
// 取得和显示返回的记录行数
echo “\n[” . $result->RecordCount() . ” 行记录被返回]\n”;
// 关闭数据库连接
$db->Close();
?>

值得一提的是,FetchNextObject()方法可以自动在记录集中移动到下一行,我们不需要再使用MoveNext()方法,当到达记录集尾部时,该方法返回false。

1.GetAll方法
我们可以使用GetAll方法代替Execute()方法,该方法返回的结果为一个二维关联数据,这样可以使用foreach或for循环语句处理,非常方便。另外,GetAll取得的数组与Smarty模板的foreach配合得非常好。

我们一起看下面的脚本例子:

include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “root”, “library”) or die(“Unable to connect”);
// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->GetAll($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 清除无用的对象
$db->Close();
// 可以使用print_r打印该数组的内容
// print_r($result); exit(0);
// 遍历记录集,显示列的内容:TITLE 和AUTHOR
foreach ($result as $row){
echo $row[1] . ” – ” . $row[2] . “\n”;
}
// 取得和显示返回的记录行数
echo “\n[” . sizeof($result) . ” 行记录被返回]\n”;
?>

GetAll()方法取得记录集后,产生一个二维数组,类似于下面的样子:

Array

(

[0] => Array

(

[0] => 14

[id] => 14

[1] => Mystic River

[title] => Mystic River

[2] => Dennis Lehane

[author] => Dennis Lehane

)

[1] => Array

(

[0] => 15

[id] => 15

[1] => For Kicks

[title] => For Kicks

[2] => Dick Francis

[author] => Dick Francis

)

//下略

)

我们在数组一章,提到过这类混合数组最适合用foreach来处理。这种方法是对Execute()方法的补充或替代,尤其适合在遍历查询整个表时使用。

另外,ADODB还提供取得一条记录的方法:GetOne()。

2.GetOne()方法
ADODB有个比较直接的方法可以比较方便地检测某条记录是否存在,那就是它的GetOne($sql)方法。

该方法返回查询记录的第1条第1个字段名的值,如果执行过程中出现错误,则返回布尔值false。

我们可以检测这个值是否存在:

Include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);

$rs = $db->GetOne(“Select * FROM library Where id=’$id'”);

if($rs){

echo ‘记录存在’;

}else {

echo ‘记录不存在’;

}

?>

不过这样有一个问题是,如果数据表中id=$id的记录有多条,不仅仅要知道是否存在有这样一条记录,还要把这条记录提取出来,则可以使用ADODB的GetRow()方法。

3.GetRow()方法
Include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);

$rs = $db->GetRow(“Select * FROM library Where id=’$id'”);

if(is_array($rs)){

echo ‘记录存在’;

print_r($rs);

} else {

echo ‘记录不存在’;

}

?>

需要注意的是,GetOne($sql) 和 GetRow($sql) 都能得到一条特定的记录,或者得到该记录不存在的信息,但是如果符合查询条件的记录存在多条时,则这两个方法只传回第一条记录,其他的都自动抛弃。

如果只要得到查询结果的行数,则可以使用结果集方法中的RecordCount()方法。

4.取得返回的记录行数
ADODB还提供了一批实用功能,如在进行查询时,提供了非常有用的RecordCount() 和FieldCount()方法,分别返回记录的数量和字段的数量,以下是应用这两个方法的例子。

include(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);
// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 取得和显示返回的记录行数
echo $result->RecordCount() . ” 行记录被返回\n”;
// 取得和显示返回的字段个数
echo $result->FieldCount() . ” 个字段被返回\n”;
// clea up
$db->Close();
?>

我们可以使用FetchField()方法取得字段的信息,其中含有该字段的详细资料,包括名称和类型等,请看如下的脚本例子。

include(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);
// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 取得记录集中字段的结构信息
for($x=0; $x<$result->FieldCount(); $x++){
print_r($result->FetchField($x));
}
// 清理无用的对象
$db->Close();
?>

下面输出的是有关id字段的结构信息。

stdClass myMagicbject

(

[name] => id

[table] => library

[def] =>

[max_length] => 3

[not_null] => 1

[primary_key] => 1

[multiple_key] => 0

[unique_key] => 0

[numeric] => 1

[blob] => 0

[type] => int

[unsigned] => 1

[zerofill] => 0

[binary] =>

)

5.其他相关方法
当执行一个Insert查询时,如果该表的主键是一个自动增量的字段,则可以使用ADODB的insert_id()方法,来获得最后数据插入时自动产生的增量值。

include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “root”, “adodb”) or die(“Unable to connect!”);
// 构造并执行Insert插入操作
$title = $db->qstr(“PHP5与MySQL5 Web开发技术详解”);
$author = $db->qstr(“杜江”);
$query = “Insert INTO library (title, author) VALUES ($title, $author)”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 显示插入的记录号
if ($result){
echo “最后插入的记录ID: ” . $db->Insert_ID();
}
// 清理无用的对象
$db->Close();
?>

脚本中的qstr()方法,功能是过滤SQL查询中的非法字符。

执行后,即无论查询(Select)、删除(Delete)或修改(Update)数据,如果想知道是否对表有影响,可以使用affected_rows()方法,它可以告诉我们操作后有多少(记录)行受到了影响。请看下面的脚本例子:

include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “root”, “adodb”) or die(“Unable to connect!”);
// 构造并执行一个查询
$query = “Delete FROM library Where author = ‘J. Luser'”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 取得和显示执行后影响的记录行数
if ($result){
echo $db->Affected_Rows() . ” 行已被删除”;
}
// 清理无用的对象
$db->Close();
?>

6.限制查询结果
上面我们讨论了如何通过使用一个数据库库函数使应用程序更简洁,更易于移植。比如从MS SQL Server转移到MySQL,在MS SQL Server中使用指令“Select TOP 15 name FROM employee”取得数据的前15条,可在MySQL中却不支持这种写法,而要写成:Select name FROM employee LIMIT 15。

它似乎对我们敲响了警钟,应该停止在查询语句中使用非标准SQL指令,而去认真地学习标准的SQL。

幸运的是,ADODB有一个处理 LIMIT的方法:SelectLimit(),这样我们就根本不用管连接的是MySQL还是MS SQL Server,ADODB会在底层为我们自动转换,请见下面的脚本例子:

include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);
// 构造并执行一个查询
// 我们要取得5行记录,从符合记录的第3行开始取
$query = “Select * FROM library”;
$result = $db->SelectLimit($query, 5, 3) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 遍历记录集
while (!$result->EOF) {
echo $result->fields[1] . ” – ” . $result->fields[2] . “\n”;
$result->MoveNext();
}
// 清理无用的对象
$db->Close();
?>

在这个例子中,selectlimit()方法类似于MySQL的LIMIT语句,可用于控制从某行开始查询,到某行的结果,从而取得我们指定的记录集。

我们可以利用ADODB提供的MetaDatabases()方法取得当前服务器中所有数据库的清单。还有一个方法和它很类似,即使用MetaTables()方法可以取得当前库中所有表的清单。请看下面的例子:

include(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);
// 取得数据列表
echo “数据库:\n”;
foreach($db->MetaDatabases() as $d){
echo “* $d\n”;
}
// 取得数据表清单
echo “\n当前数据库下的表:\n”;
foreach($db->MetaTables() as $table){
echo “* $table\n”;
}
// 清理无用的对象
$db->Close();
?>

7.快速存取
有时,我们需要对一些不同的值做一些特殊的查询,比如一系列的Insert(插入)语句。ADODB类提供了两个方法,可以使我们既节约时间又节省系统的开销,请看如下示例:

include(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);
// 构造准备查询,使用参数绑定
$query = $db->Prepare(“Insert INTO library (title, author) VALUES (?, ?)”);
// 从CSV 中取得要插入的标题和作者名称
$data = file(“./book_list.csv”);
// 遍历该文件,并执行插入操作
foreach ($data as $l){
$arr = explode(“,”, $l);
// 插入值并绑定准备语句
$result = $db->Execute($query, array($arr[0], $arr[1])) or die(“Error in query: $query. ” . $db->ErrorMsg());
}
// 清理无用的对象
$db->Close;
?>

prepare()函数,把一个SQL查询作为参数,读取一个查询,但并不立即执行。prepare()返回一个句柄给一个prepare查询,当保存和传递给Execute()方法后,则立即执行该查询。

8.处理事务
处理事务是许多应用程序的一个重要的特征(比如,钱从你的账户转出,然后转入到某个人的账户中。只要其中任意一步操作失败,这整个过程都必须被认定为失败。不然,钱被划出,而没有进对方的账户;或者,钱没有划出,但对方账户无端多了一笔钱)。

处理事务可以在代码级上进行机警地管理控制。常数错误检查被用来判断执行COMMIT(事务的所有各项都正确,执行正确,结束事务)还是执行ROLLBACK(事务中有错误,所有改动需要恢复原来状况)。

现在的数据库系统绝大多数都支持事务,如MySQL、Oracle、MS SQL Server等,ADODB提供一个非常好的功能,能够让你更透明地使用这一特性。请看下面的例子:

include(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “root”, “adodb”) or die(“Unable to connect!”);
//关闭auto-commit自动提交事务
// 开始事务处理语句块
$db->BeginTrans();
// 第一次查询
$query = “Insert INTO library (title, author) VALUES (‘测试用书’, ‘佚名’)”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
//使用第一次查询返回的ID号
if ($result){
$id = $db->Insert_ID();
$query = “Insert INTO purchase_info (id, price) VALUES ($id, ‘RMB 31.9’)”;
$result = $db->Execute($query)

or die(“Error in query: $query. ” . $db->ErrorMsg());
}
// 如果操作成功
if ($result){
// 事务提交
$db->CommitTrans();
}// 否则回滚
else{
$db->RollbackTrans();
}
// 清理无用的对象
$db->Close;
?>

该脚本首先需要关掉数据库的auto commit功能,通过begintrans()方法来处理,这种方法也标志着一个事务的开始。可以使用CommitTrans()或RollbackTrans()函数来处理操作,一旦auto commit已经关掉,你就可以任意执行所需要的查询,确认事务的查询执行无误并完毕后,由我们自己决定何时执行commit操作。

每一次执行Execute()事务块后,它会返回一个布尔值,告诉我们是否成功地执行了查询。可以跟踪到这个值,以及使用的时间,以决定是否要进行整个交易行为。一旦你相信一切都没问题,则告诉数据库committrans()方法;如果发现有错误发生,则可以进行回滚操作——执行rollbacktrans()方法。

值得注意的是,注意您的数据库类型是否支持这些事务函数,前面已经说过,MySQL的InnoDB类型表支持事务,但是MyISAM类型并不支持。

9.使用缓存查询
在一个动态页面中,如果其中的一个查询指令很少改变且频繁被执行,我们则可以使用ADODB的缓存功能,可以将查询指令的结果缓存成静态文件,从而提高PHP脚本的性能。

当试图通过缓存来提高你的应用程序的性能之前,建议先去优化查询指令再开始本操作,这样才会起到事半功倍之效果。

ADODB最棒的功能就是提供查询缓存的功能。缓存可以大大改善应用程序的性能,尤其是网站系统,因为大部分用户都是在浏览网站,数据库完成的任务多半是查询(Select操作)。为了更好地理解与应用缓存查询的功能,我们来看下面的脚本例子。

include_once(“libs/adodb/adodb.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “root”, “adodb”) or die(“Unable to connect!”);
// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 遍历返回的记录集,显示列数据的内容 TITLE 和 AUTHOR
while (!$result->EOF) {
echo $result->fields[1] . ” – ” . $result->fields[2] . “\n”;
$result->MoveNext();
}
// 显示取得的记录行数
echo “\n[” . $result->RecordCount() . ” 行记录被返回]\n”;
// 关闭数据库连接
$db->Close();
?>

这段代码使用ADODB进行一个Select操作。比如说,这就是您的网站,平均有每分钟5000次的点击(PV,Page View)量,那么数据库系统每小时至少要被查询3万次以上,可以想象,这对我们的MySQL数据库的负载是相当繁重的。

因此ADODB提供了缓存的功能,可以将经常查询的结果保存起来,进而降低数据库服务器的负荷,同时也向用户提供更快速的内容响应。

下面是修改上面的脚本,改为使用CacheExecute来进行缓存查询的示例:

include(“libs/adodb/adodb.inc.php”);

//设置缓存保存的路径,.表示当前目录
$ADODB_CACHE_DIR = ‘.’; //为了管理方便,实际开发环境请指向到独立的目录中,如/tmp/adodb
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);

// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “adodb”) or die(“Unable to connect!”);

// 构造并执行一个查询
$query = “Select * FROM library”;
$result = $db->CacheExecute(300,$query) or die(“Error in query: $query. ” . $db->ErrorMsg());

// 遍历返回的记录集,显示列数据的内容 TITLE 和 AUTHOR
while (!$result->EOF) {
echo $result->fields[1] . ” – ” . $result->fields[2] . “\n”;
$result->MoveNext();
}

// 取得和显示返回的记录行数
echo “\n[” . $result->RecordCount() . ” 行记录被返回]\n”;

// 关闭数据库连接
$db->Close();
?>

CacheExecute()方法的第一个参数是缓存文件(缓存文件被命名为adodb_*.cache)将被保留的时间,以秒计时;第二个参数是SQL声明。第一个参数是可选择的,若没有限定时间,默认值是3600秒,也就是1个小时。

值得一提的是,使用CacheExcute()方法时,需要将php.ini中的参数magic_quotes_runtime设为0。

也可以根据需要,在程序运行时动态修改它的值:

set_magic_quotes_runtime(0);

注意:将上述代码放到调用数据库的指令之前,我们还可以在任何时候,通过调用CacheFlush()来清除过时的缓存。

10.生成下拉列表菜单
ADODB特意为Web开发任务提供几个通用的方法。其中,最有用的是GetMenu()方法,通过抽取数据库的记录集,自动地生成表单及菜单列表框。

下面介绍的就是从数据库动态构建下拉菜单(Option)的例子。

include_once(“libs/adodb/adodb.inc.php”);

// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);

// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “root”, “library”) or die(“Unable to connect!”);

// 构造并执行一个查询
$query = “Select title, id FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());

//显示HTML下拉列表菜单
echo $result->GetMenu(“library”, ”, false);

// 关闭数据库连接
$db->Close();
?>
GetMenu()方法需要传入参数,用来控制列表框的行为。上例中第一个参数是列表框的名字(这个例子为“library”);第二个参数是显示时默认的值,可以为空,从第一个记录开始;第三个参数,指定列表框的项目是否为空;第四个参数,控制是否允许用户多选。

上例的显示结果如下:

 

 

Mystic River

 

 

Where Eagles Dare

 

 

XML and PHP

 

 

可以看到,该列表菜单内容是从library表抽取的记录,列表框的名字为“library”,在记录集中,ID是菜单选项的值,名称为菜单框显示的元素。

由此可以看出,GetMenu()方法可以大幅度简化Web开发任务,大大减少代码量。

11.输出到文件
ADODB还允许我们将记录输出为一个不同形式的文件:如逗号分隔符CSV文件,制表符表格,甚至于HTML形式的表格。

这些功能属于ADODB的附属功能,在使用时需要包含相关ADODB类文件,下面是样例的内容。

include(“libs/adodb/adodb.inc.php”);
// 包含转换方法的文件
include_once(“libs/adodb/toexport.inc.php”);
// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);
// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “library”) or die(“Unable to connect!”);
// 构造并执行一个查询
$query = “Select title, id FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());
// 返回一个CSV字符串
echo rs2csv($result);
// 关闭数据库的连接
$db->Close();
?>

输出结果如下:

title,id

Mystic River,15

Where Eagles Dare,16

XML and PHP,17

我们也可以去除结果中第一行,即字段的名称,使用脚本格式如下:

// 返回一个 CSV 字符串

echo rs2csv($result, false);

脚本的输出结果将没有字段名称,如下:

Mystic River,15

Where Eagles Dare,16

XML and PHP,17

ADODB还提供生成制表符或分隔符文件功能,使用rs2tab()方法:

include(“libs/adodb/adodb.inc.php”);

// 包含转换方法的文件

include(“toexport.inc.php”);

//创建一个mysql连接实例对象

$db = NewADOConnection(“mysql”);

// 打开一个数据库连接

$db->Connect(“localhost”, “root”, “root”, “library”) or die(“Unable to connect!”);

// 构造并执行一个查询

$query = “Select title, id FROM library”;

$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());

// 返回一个TAB制表符分隔的字符串

echo rs2tab($result);

// 关闭数据库连接

$db->Close();

?>

显示结果如下:

title id

Mystic River 15

Where Eagles Dare 16

XML and PHP 17

ADODB还提供生成HTML表格的功能,使用rs2html()方法:

include_once(“libs/adodb/adodb.inc.php”);

// 包含转换方法的文件
include_once(“libs/adodb/tohtml.inc.php”);

// 创建一个mysql连接实例对象
$db = NewADOConnection(“mysql”);

// 打开一个数据库连接
$db->Connect(“localhost”, “root”, “passwd”, “library”) or die(“Unable to connect!”);

// 构造并执行一个查询
$query = “Select title, id FROM library”;
$result = $db->Execute($query) or die(“Error in query: $query. ” . $db->ErrorMsg());

// 返回一个HTML格式的表格
echo rs2html($result);

// 关闭数据库连接
$db->Close();
?>
输出结果如下:

ADODB启用Memcached缓存软件(需要adodb-memcache.lib.inc.php包含文件)

......
$driver = 'mysql';
$db = NewADOConnection($driver);
$db->Connect($dbhost, $dbuser, $dbpwd, $dbname) ;
//======== adodb memcached start
$db->memCache = true; /// should we use memCache instead of caching in files
$db->memCacheHost = '127.0.0.1'; /// memCache host
$db->memCachePort = 11211; /// this is default memCache port
$db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib)
//======== adodb memcached end
......