You say eether and I say eyether,
You say neether and I say nyther;
Eether, eyether, neether, nyther -
Let's call the whole thing off !
You like potato and I like po-tah-to,
You like tomato and I like to-mah-to;
Potato, po-tah-to, tomato, to-mah-to -
Let's call the whole thing off !
我喜欢听这首歌,尤其是由Louis Armstrong 和 Ella 演唱的二重唱版本。这首歌完整地表达了即使是相爱的两个男女,他们彼此适应同样是多么地艰难。这是一个妥协和寻找共通之道的过程。这篇文章的意义也正在于此。
PHP能用最少的功夫和最多的乐趣来创建动态网站。为了创建这样的网站,我们需要使用数据库检索登录信息,在网页上显示动态新闻,存储论坛稿件。就以使用最通用的MySQL数据库来说,你们公司已经完成了如此神奇的工作,让你们的网站比你们所能想象的还有出名。接着你们也发现MySQL无法应付实际的工作量,是该更换数据库的时候了。
不幸的是,在PHP中不同数据库的存取有微小的不同。连接MySQL,你要使用mysql_connect()函数,当你决定升级到Oracle或Microsoft SQL Server时,你必须分别使用ocilogon()函数或mssql_connect()函数来连接。更糟糕的是不同连接所使用的参数也都不一样,有的数据库说po-tato(马铃薯的发音),别的数据库有说pota-to(马铃薯的一种发音)。喔...天啊。
我们不要放弃
当你需要确保你的程序的可移植性时,一个叫做ADODB的数据库封装程序库出现了。它提供给你一个通用的API来跟所有被支持的数据库沟通,因此你无须放弃!
ADODB是Active Data Objects DataBase 的缩写(很抱歉!玩电脑的有时候不是很有原创性)。ADODB当前支持的数据库有MySQL, PostgreSQL, Oracle, Interbase, Microsoft SQL Server, Access, FoxPro, Sybase, ODBC 和 ADO.
你可以从 http://php.weblogs.com/adodb下载ADODB。
MySQL的例子
PHP中最通用的数据库是MySQL,所以我想你应该熟悉以下的程序代码。它连接到localhost的MySQL服务器,,数据库名为mydb,并且执行一条SQL的Select语句。查询结果被一列列打印出来。
$db = mysql_connect("localhost", "root", "password");
mysql_select_db("mydb",$db);
$result = mysql_query("SELECT * FROM employees",$db);
if ($result === false) die("failed");
while ($fields = mysql_fetch_row($result)) {
for ($i=0, $max=sizeof($fields); $i < $max; $i++) {
print $fields[$i].' ';
}
print "<br>\n";
}
以上代码用颜色标记分段,第一段是连接部分,第二段是执行SQL语句,最后一段是显示字段。while循环扫描结果中的每一列,而for循环扫描每列的所有字段。
接下来是用ADODB写的等价代码。
include("adodb.inc.php");
$db = NewADOConnection('mysql');
$db->Connect("localhost", "root", "password", "mydb");
$result = $db->Execute("SELECT * FROM employees");
if ($result === false) die("failed");
while (!$result->EOF) {
for ($i=0, $max=$result->FieldCount(); $i < $max; $i++)
print $result->fields[$i].' ';
$result->MoveNext();
print "<br>\n";
}
现在改成指向Oracle数据库,程序代码只要修改第二行成NewADOConnection('oracle')即可。让我们看一下完整的程序代码...
连接数据库
include("adodb.inc.php");
$db = NewADOConnection('mysql');
$db->Connect("localhost", "root", "password", "mydb");
这里的连接代码比起原来MySQL的连接代码高级一些,因为我们正是需要更高级些的。在ADODB中,我们使用面向对象的方法来管理多种数据库的复杂性。我们用不同的类来处理不同的数据库。如果你还不熟悉面向对象编程,没关系--所有复杂的事情都被隐藏在NewADOConnection() 函数里。
为了节省内存,我们仅仅载入与你所连接的数据库相关的PHP程序代码。我们通过调用NewADOConnection(databasedriver)来完成这件事。合法的数据库驱动程序包括mysql, mssql, oracle, oci8, postgres, sybase, vfp, access, ibase
和许多其他驱动程序。
接着我们通过调用NewADOConnectiion()来从连接类中创建一个新的实例。最后我们使用$db->Connect()来连接数据库。
执行SQL语句
$result = $db->Execute("SELECT * FROM employees");
if ($result === false) die("failed");
直接传送SQL语句到服务器。Execute() 函数执行成功将返回一个recordset对象。你应该像我们上面那样检查$result.
一个困扰初学者的问题是,在ADODB中有两种类型的对象,连接对象和recordset对象。我们何时用这些对象呢?
连接对象($db)负责连接数据库,格式化你的SQL查询。而recordset对象($result)负责检索数据并将数据库执行结果格式化成文本或数组。
我唯一需要增加的事情是,ADODB提供了许多有用的函数来让INSERT和UPDATE语句更容易些,这点我们在稍后的章节中会提到。
检索数据
while (!$result->EOF) {
for ($i=0, $max=$result->FieldCount(); $i < $max; $i++)
print $result->fields[$i].' ';
$result->MoveNext();
print "<br>\n";
}
前面取得数据的范例很像读文件。对于每一行,我们首先检查它是否到了文件结尾(EOF)。如果没有到达文件尾,就扫描该行的每个字段。然后移动到下一行,重复以上动作。$result->fields[]数组是有PHP数据库扩展生成的。有些数据库扩展不以字段名索引数组。要强制以名称索引该数组,使用 $ADODB_FETCH_MODE 这个全局变量。
$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')
正如你在上面例子中所看到的,两个recordset存储使用不同的取用模式,它们是基于$ADODB_FETCH_MODE的不同设置,在recordset被Execute()创建之前。ADOConnection连接到数据库的对象,执行SQL语句并且有一组工具函数来标准格式化SQL语句,比如关联与日期格式的语句。
其他有用的函数
$recordset->Move($pos)滚动到指定行。ADODB支持所有数据库的前滚。一些数据库不支持向后滚动记录。这倒不是个问题,因为你能用缓存记录来模拟向后滚动。
$recordset->RecordCount() 返回SQL语句执行结果的记录条数。有些数据库因为不支持而返回-1.
$recordset->GetArray()以数组形式返回结果。
rs2html($recordset)是一个基于$recordset生成HTML表格的函数。
下例中以粗体显示相关用法:
include('adodb.inc.php');
include('tohtml.inc.php'); /* includes the rs2html function */
$conn = &ADONewConnection('mysql');
$conn->PConnect('localhost','userid','password','database');
$rs = $conn->Execute('select * from table');
rs2html($rs); /* recordset to html table */
还有许多有用的函数列在文档中,可从这个网站查得http://php.weblogs.com/adodb_manual.
高级题材
插入与更新
假设你想插入下列数据到数据库中
ID = 3
TheDate=mktime(0,0,0,8,31,2001) /* 31st August 2001 */
Note= sugar why don't we call it off
当你改用别的数据库,可能就不会成功插入数据。
第一个问题是,每个数据库各自有不同的默认日期格式。MySQL使用YYYY-MM-DD格式,而其他数据库则有不同的默认格式。ADODB提供DBDate() 函数来转换不同数据之间的日期默认格式。
下一个问题是单引号(don't)的表示法,在MySQL中,我们使用don\'t的形式,但是在其他数据库如Sybase, Access, Microsoft SQL Server,我们使用don''t的形式。qstr() 函数可以解决此问题。
我们如何使用这些函数呢?就像这样:
$sql = "INSERT INTO table (id, thedate,note)
values (" . $ID . ',' . $db->DBDate($TheDate) .',' . $db->qstr($Note).")";
$db->Execute($sql);
ADODB还支持$connection->Affected_Rows()函数,它返回最近一次执行delete或update语句受影响的行数。及$recordset->Insert_ID() 函数,它返回最后因insert语句执行而自动生成的编号。预先提醒大家,并不是所有数据库都支持这两个函数。
MetaTypes
你能够得到更多关于字段的信息,通过调用recordset的方法FetchField($fieldoffset)。该函数返回一个包含三个属性(name,type,max_length)的对象。
举例说明:
$recordset = $conn->Execute("select adate from table");
$f0 = $recordset->FetchField(0);
结果$f0->name的内容是‘adata’,$f0->type 将是‘date’。如果max_length不知道,其内容将会是-1。处理不同数据库的一个问题是,每个数据库对于相同的类型有不同的名字。比如timestamp类型在某些数据库称为datetime,而在另一个数据库中则称为time.所以ADODB提供MetaType($type,$max_length)函数来标准下列的类型。C: character and varchar types
X: text or long character (eg. more than 255 bytes wide).
B: blob or binary image
D: date
T: timestamp
L: logical (boolean)
I: integer
N: numeric (float, double, money)
在前面的例子中,
$recordset = $conn->Execute("select adate from table");
$f0 = $recordset->FetchField(0);
$type = $recordset->MetaType($f0->type, $f0->max_length);
print $type; /* should print 'D' */
select语句的limit和top支持
ADODB哟一个叫做 $connection->SelectLimit($sql,$nrows,$offset) 的函数,它允许你去检索recordset的一个子集。这是采用Microsoft产品中的selct top用法,以及PostgreSQL和MySQL中的select...limit用法。即使原来数据库并没有提供此用法,本函数也模拟提供该使用方式。
缓存支持
ADODB允许你在你的文件系统中缓存recordset数据,仅仅在$connection->CacheExecute($secs2cache,$sql) 和 $connection->CacheSelectLimit($secs2cache,$sql,$nrows,$offset). 设定的时间到达之后,才真正重新去查询数据库以节省时间。
PHP4 Session 支持
ADODB也支持PHP4 session handler,你可以存放你的session变量在数据库中,更多相关信息请访问http://php.weblogs.com/adodb-sessions
本文由黑龙江省PPP项目咨询研究中心www.hljppp.com机构推荐,欢迎各位网友阅读与转载。如您在日常工作中需要编写可行分析报告、项目申请书、资金申请报告、可行性研究报告、节能评估报告,请与中科万向联系,感谢该机构对本文编写的支持。