新葡亰496net 新葡亰编程 PHP 5 数据对象 抽象层与 Oracle_php基础_脚本之家

PHP 5 数据对象 抽象层与 Oracle_php基础_脚本之家

连接 PDO

php 5.1.*

省略 try..catch
控制结构并无裨益。如果在应用程序的较高级别没有定义异常处理,则在无法建立数据库连接的情况下,该脚本会终止。

代码
数据库连接代码都一样.
复制代码 代码如下:
$protol = ‘mysql:host=localhost;dbname=test’;
$username = ‘monty’;
$passwd = ‘0818’;
$dbh = new PDO($protol, $username, $passwd);

// bind the inputs to php variables; specify that the data will be
strings// with a maximum length of 64
characters$stmt->bindParam(‘:extension’,$extension,PDO_PARAM_STR,
64);$stmt->bindParam(‘:name’, $name,PDO_PARAM_STR, 64);

测试3(limit绑定:page)
复制代码 代码如下:$stmt =
$dbh->prepare(‘select * from t2 where name=:name limit :page’);
$params = array();
$params[‘name’] = ‘rentao’;// 这里加不加”:”都能成功执行
$params[‘page’] = 2;
foreach($params as $k=>$v){
$stmt->bindParam($k, $v);
}
$stmt->execute();
echo “HERE1n”;
$item = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
var_dump($row);
}
echo “HERE2n”;
$stmt = null;
$dbh = null;

while ($row = $stmt->fetch {echo “Extension $row[EXTENSION] by
$row[NAME]
“;}

PHP 5.2.*

在上述两种情况下,都需要首先调用“pear
install”;上述示例中的版本号在本文编写之时是最新的,但随着开发的继续进行会发生变化。

PHP 5.1.* PHP 5.2.*
打印出结果,但未按order by进行排序 执行正常:打印不出结果

可移植性

$params[‘name’] = ‘rentao’
和$params[‘:name’]=’rentao’这两个都能执行,说明不受“:”限制。

我们希望在 PHP 5.1 中默认启用 PHP 扩展,但是在此之前,我们希望能让 PDO
在 PHP 5.0
发布时稳定运行,但是我们日常工作中的压力稍稍拖延了这些工作。同时,通过
PECL 发布 PDO 使我们能够在收到问题报告时做出回应,并根据不同于 PHP 5.0
发布时间表的时间表发布修复版本,因此您在 PHP 5.1 发布前即可使用 PDO。

结论:

最后一种模式为 PDO_FETCH_BOUND,该模式会告知 PDO
您已经将所有列绑定到了 PHP
变量,并且除了要它在到达行集的末尾时通知您外不需要它执行别的任何操作。绑定输出列在概念上与绑定输入参数相似,只是绑定输出列可以用于所有数据库驱动程序。您可以将
PHP 变量绑定到命名列,PDO 将在每次调用 execute()
时对其进行更新。此技术可用来剃去结果集中每列、每行的一些虚拟机器操作码。这种技术的缺点在于,可能会使您的代码难以跟踪,您使用变量名称时需要倍加小心。下面的代码说明了绑定输出列的使用。请注意,您不必指定
PDO_FETCH_BOUND 即可使用 $stmt->bindColumn();PDO_FETCH_BOUND
只是一个对于您了解只能使用绑定值的情况的一种优化。

PHP 5.1.*

getMessage(); }?>

以下是一些测试。注意里面的SQL和for或者foreach语句!
测试1(用key值进行绑定)
复制代码 代码如下:
$stmt = $dbh->prepare(‘select * from t1 where name=:name’);
$params = array();
$params[‘name’] = ‘rentao’;
foreach($params as $k=>$v){
$stmt->bindParam($k, $v);
}
$stmt->execute();
$item = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
var_dump($row);
}
$stmt = null;
$dbh = null;

if {echo $dbh->errorCode() .”
“;$info = $dbh->errorInfo();// $info[0] == $dbh->errorCode()
统一的错误代码// $info[1] 是驱动程序特定的错误代码// $info[2]
是驱动程序特定的错误字符串}

出现错误:“PHP Warning:  PDOStatement::execute(): SQLSTATE[HY093]:
Invalid parameter number: parameter was not defined”

数据类型

for($i=0,$iLen = count($params); $i < $iLen; $i++){
$k = $i+1;
$stmt->bindParam($k, $params[$i]);
}
echo “HERE1n”;
$stmt->execute();
echo “HERE2n”;

extension=pdo_oci.so

结论:

如果无法加载该驱动程序,或者发生了连接失败,则会抛出一个
PDOException,以便您可以决定如何最好地处理该故障。

执行正常

区分大小写的列

PHP 5.1.* PHP 5.2.*
执行正常 执行正常:打印不出结果

% wget pear install PDO-0.1.1.tgz

测试5—order by)

% wget pear install PDO_OCI-0.1.tgz

复制代码 代码如下:
$stmt = $dbh->prepare(‘select * from t1 where name=:name limit
2’);
$params = array();
$params[] = ‘rentao’;// 这里加不加”:”都能成功执行

很多数据库驱动程序都会代表您预先抓取并缓存一定数量的行。PHP
每次访问其中一个这样行中的列时,它都需要将其复制到自己的专用内存区域中。如果您的查询涉及很多行,而只需要基于某种复杂的逻辑访问给定行的特定列,则您会发现
PDO_FETCH_LAZY
是一种避免使用很多内存的有用方法,因为它只有在您访问给定列时才复制该列。使用此方式时要注意,从某个给定语句为每个
fetch()
抓取的“惰性对象”是每次迭代时使用的同一对象。这就暗示着您不能只是简单地存储该对象用于以后的比较,因为它仍然会引用该语句的当前行
- 您需要手动复制所需要的部分。

不能同时使用两种符号。如 select * from t2 where name=? limit :page

可移植脚本的另一个难题是处理从各种数据库处理程序返回的各种不同的错误消息;某些数据库对于程序化处理错误的支持能力很差,而其他一些数据库则具有非常丰富的错误代码。只要可行,PDO
将为您的脚本提供一个统一的错误代码,从而使您不必为应对可移植性的这个方面所累。当然,PDO
还会为驱动程序提供原生错误代码和错误消息,以防您需要用它来进行诊断,或者错误代码映射不完整。

介绍
今天发现php5.1.*和php5.2.*在数据库预编译代码执行的时候出现差异。
预编译优点
1.使用占位符,避免逐字输入数据到SQL中。自动处理引号和反斜线等字符的转义——增加安全性。
2.预先“准备”一条语句,然后在每次执行时绑定不同值达到重用的目的。——常用于以后被多次执行的语句。
3.可读性强。

为了使得示例更自然,我从 PHP
源代码中抽取了扩展及其作者的信息,并将其存储到了一个 CSV
文件中(请参见“相关附件:credits.csv”)。这就代表一个常见情形:从 CSV
文件批次导入数据。在我们的示例中,我们充分利用了 Oracle
的预处理语句和绑定参数,以获得一个高效的数据导入脚本。在讲述该示例之前,有必要了解一下
PDO 处理事务的方式。

PHP 5.1.* PHP 5.2.*
执行到$stmt->execute()时,进程一直处于等待状态中 执行正常:打印不出结果

·PDO_FETCH_BOTH -
每个行抓取返回一个既按照列位置又按照列名索引的数组。也就是上述两种情况的直接组合。如果没有指定抓取模式,则该模式为默认模式。
·PDO_FETCH_OBJ - 每个行抓取返回一个匿名对象,其属性名与列名对应。

执行正常

在哪里可以获得 PDO?

$item = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
var_dump($row);
}
$stmt = null;
$dbh = null;

需要 PHP:5.0需要其他:Oracle 8 或更高版本客户端库下载用于 Oracle 的 PDO
:php_pdo.dll, php_pdo_oci.dll下载用于 Oracle 的 PDO :pdo, pdo_oci

总结
PHP在使用PDO做数据库预编译操作的时候,尽量避免使用limit, order by, group
by
做预编译处理。绑定变量我们尽量使用统一标准,要不然都使用“?”,要不然使用“:key”。

$stmt = $dbh->prepare(“SELECT extension, name from CREDITS”);if
{while {print_r; }}

有用的命令,我在php5.1.*进行测试,测试完了,我通过scp把文件传输到php5.2.*服务器上
复制代码 代码如下:scp -P9888 index.php
rentao@192.168.10.4:/home/rentao

·提供一种轻型、清晰、方便的 API ·统一各种不同 RDBMS
库的共有特性,但不排除更高级的特性。 ·通过 PHP
脚本提供可选的较大程度的抽象/兼容性。

执行正常

$dbh = new PDO(‘OCI:’, ‘scott’,
‘tiger’);$dbh->setAttribute(PDO_ATTR_ORACLE_NULLS, true);//
现在从此 $dbh 打开的任何语句中的// 空字符串都将被转换为 NULL

如果把”:name”改成”?”,那么两个版本都可以顺利进行。

既然我们已经成功连接到了
Oracle,那么现在就可以创建一个表来保存一些数据了。对于此示例,我们使用一些
PHP 扩展及其作者,并将这些内容输入一个数据库中。数据库句柄对象的 exec()
方法可用来发出不会返回结果集的快速一次性查询,因此我们在这里使用该方法来发出
CREATE TABLE 查询。

PHP 5.2.*

———–关于作者Wez Furlong 是 Brain Room Ltd.
的技术总监,他在该公司不但使用 PHP 用于 Web 开发,还将其用作 Linux 和
Windows 应用程序和系统的嵌入式脚本引擎。Wez 是 PHP
的核心开发人员,经常向 SQLite、COM/.Net、ActivePHP、mailparse 和 Streams
API 等投稿,他是 PECL 即 PHP 扩展社区库的“头儿”。他的咨询公司的网页为

结论:

PDO
在某种程度上类型不可知,因此它喜欢将数据表示为字符串,而不是将其转换为整数或双精度类型。此时您可能对此有些迷惑,但是原因非常简单:字符串类型是最精确的类型,在
PHP
中具有最广泛的应用范围;过早地将数据转换为整数或者双精度类型可能会导致截断或舍入错误。通过将数据以字符串抽出,PDO
为您提供了一些脚本控制,您可以使用普通的 PHP
类型转换工具来控制如何进行转换以及何时进行转换。

测试4(在limit下进行预编译操作:page)——使用“?”机制运行
复制代码 代码如下:
$stmt = $dbh->prepare(‘select * from t2 where name=? limit ?’);
$params = array();
$params[] = ‘rentao’;
$params[] = 2;
for($i=0,$iLen = count($params); $i < $iLen; $i++){
$k = $i+1;
$stmt->bindParam($k, $params[$i]);
}
$stmt->execute();
$item = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
var_dump($row);
}
$stmt = null;
$dbh = null;

// Commit the changes$dbh->commit();

测试2(数字下标去绑定,但是绑定的起始参数是1)——”:key”在php5.2.*上不能用数字下标绑定

// prepare to insert a large quantitiy of data$stmt =
$dbh->prepare(“INSERT INTO CREDITS VALUES ;

% php -m

PHP
主要是由志愿者完成的项目;尽管有少数一些固定的“核心”开发人员,但是我们没有一个人在全职受薪的开发
PHP。除此之外,我们分别位于世界不同地方,您可以想象长期开发的协调工作是何等困难。因此,PHP
主要是基于突发奇想的个人短期需求来发展的,其原因也多种多样,有的是试验,有的则是因为“明天有活要交”。尽管这样通常每一步都会改善
PHP,但从长远来看则是缺乏完整性 - 数据库扩展就是一个重要的例子。

连接管理

错误和错误处理

?>

extension=php_pdo.dllextension=php_pdo_oci.dll

1.使用 PHP 流的 LOB 支持。
使用绑定参数,您能够将任何流资源(如文件、套接字、HTTP
资源、压缩/筛选的流)作为输入或输出参数传递到在 LOB
上运行的查询中。与之相似,类型为 LOB 的输出参数将表现为 PHP
流,因此您可以使用 fread 和其他流函数来访问这些参数。此时,在 PDO
中根本没有 LOB 支持。 2.持久性连接和缓存的预处理语句。
持久性连接使您能够避免在每个页面命中时打开和关闭数据库服务器连接。缓存的预处理语句又前进了一步,它使您能够持久保持查询的预处理版本以及数据库句柄。
3.游标。 目前,PDO
只提供前向只读游标,但是将来会提供可滚动游标、REF-CURSOR、使用游标进行定位更新,以及可更新滚动游标。

统一错误代码表当前包括下列常量:
PDO_ERR_NONE、PDO_ERR_CANT_MAP、PDO_ERR_SYNTAX、PDO_ERR_CONSTRAINT、PDO_ERR_NOT_FOUND、PDO_ERR_ALREADY_EXISTS、PDO_ERR_NOT_IMPLEMENTED、PDO_ERR_MISMATCH、PDO_ERR_TRUNCATED、PDO_ERR_DISCONNECTED。

getMessage(); }?>

% ./configure –prefix=/usr/local/php5 –with-zlib [此处指定其他选项]%
make install

Unix/Linux 安装

在各种不同的数据扩展(oci、mysql、postgresql、mssql
等)之间根本没有真正的一致性,甚至在某些情况下,在这些扩展内部也没有真正的一致性。几乎所有这些扩展都在使用与基础数据库
API
紧密相连的不同代码完成着相同种类的任务。而且因为我们的人手非常有限,因此这就造成了代码更加难以维护,从而为
PHP 带来了很大的问题。

// Open the .csv file for import$fp = fopen;while {list =
fgetcsv;$stmt->execute;

try {$dbh->exec;} catch {// 显示警告消息print
$e->getMessage();$info = $e->errorInfo;// $info[0] ==
$e->code; unified error code// $info[1] 是驱动程序特定的错误代码//
$info[2] 是驱动程序特定的错误字符串}

在模块列表中,您应该会看到 PDO 和 PDO_OCI。

一名新 PHP 数据对象
数据抽象层的原始开发人员为您简要介绍该抽象层,重点讲述与 Oracle
一起运行的情况。

现在您需要获取数据库特定的驱动程序;对于 Oracle,此特定程序称为
PDO_OCI。在 shell 中,键入:

PDO 是通过 PECL,即 PHP 扩展库提供的。如果您在运行 Linux
计算机,请按照下面的说明进行设置;稍后是在 Windows 上安装的详细信息。

$stmt->bindParam(‘:extension’, $extension, PDO_PARAM_STR,
64);$stmt->bindParam(‘:name’, $name, PDO_PARAM_STR, 64);

$stmt = $dbh->prepare(“INSERT INTO CREDITS VALUES
;$stmt->execute(array(‘:extension’ => $extension, ‘:name’ =>
$name));

使用 PDO
抓取数据与进行插入或更新相似,只是您执行完查询之后,将要重复调用 fetch()
方法来获取结果集的下一行。进行获取的最简单情况如下所示,值得注意的一点是,您还可以将参数绑定到查询,以控制如
WHERE 子句这样的内容;执行此操作的语法与我们已经看到的 bindParam()
代码完全相同。

NULL

此驱动程序也需要从 php.ini 文件加载;将下行添加到前面添加的那行之后:

·PDO_ERRMODE_WARNING除了设置错误代码之外,PDO 还会发出 PHP
警告,您可以使用常规的 PHP
错误处理程序捕获该警告,并集中应用您准备好用于应用程序的任何错误处理/记录策略,或者只是使该错误显示在浏览器中。
·PDO_ERRMODE_EXCEPTION除了设置错误代码之外,PDO 还会抛出一个
PDOException,并将其属性设置为包含该错误代码和信息。然后,您可以在代码的较高级别捕获该异常,使用全局异常处理程序捕获该异常,或者不对其进行处理而终止脚本。

[ 将 extension=pdo.so 添加到 php.ini ]

·PDO_ERRMODE_SILENT这是默认模式;它只是使用语句和数据库句柄对象的
errorCode 方法为您设置要检查的错误代码。

抓取数据

由于 PHP 越来越受欢迎并不断成功,因此主要 PHP
数据库扩展的维护者们参加了在德国举行的 LinuxTag 2003
大会,在会上我们交换了对 PHP 前景的看法。在讨论 PHP
发展的随机性时,我们确定了在 PHP 中进行数据库访问的一些目标:

在连接字符串中,您可以指定两个可选参数;第一个是数据库名称,第二个是字符集;这些参数与可选的第三个和第四个参数相对应,后两个参数您可能在
oci8 扩展函数 ociconnect
中使用过。要使用特定的字符集连接一个特定的数据库,则可以执行下列操作:

首先创建 PDO
类的一个实例,将其用作数据库句柄。使用哪个基础驱动程序并不重要;您总要使用
PDO 类名。构造函数的第一个参数为数据源名称
,第二个参数为用户名,第三个参数为该用户名的口令。DSN 的 PDO 命名惯例为
PDO
驱动程序的名称,后面一个冒号,再后面是可选的驱动程序特定的信息。在我们的示例中,会加载
OCI
驱动程序但不指定任何其他信息;这样会使用默认的数据库。对于其他驱动程序,如
ODBC 驱动程序,第一个冒号后面的所有内容都将被用作 ODBC DSN。MySQL
驱动程序会同样以不同的方式解释它的 DSN。

// start a transaction$dbh->beginTransaction();

另一个困扰 PHP
数据库扩展的一致性问题是错误处理策略的一致性:某些扩展会返回的错误代码需要您手动抓取错误字符串,而其他一些扩展则只是发出
PHP 警告。PDO 允许您从下列三种不同的错误处理策略中选择一种:

如果发生了问题并且 PHP
出错,您的脚本将退出并且事务处于待批状态;或者您关闭数据库句柄时,PDO
会自动针对任何待批的事务调用
$dbh->rollBack()。此行为会减少向数据库中提交可能未定义或者已损坏数据的可能性,这是用于处理已放弃事务的标准语义。

使用 PDO 预处理语句非常简单,调用数据库句柄的 prepare()
方法即可。它会返回一个语句句柄对象,然后您可以使用该对象来绑定参数和执行语句。在此示例中,我们将要定义两个命名占位符,“:extension”和“:name”,这两个占位符分别与
.CSV 文件中的 PHP 扩展名称和其中一个作者的姓名相对应。

Oracle
具有一个敏感的默认操作模式:当您进行连接时,将会位于一个隐式事务处理中,在提交事务之前其中的更改不会完全生效。除了事务处理的标准优点(原子性、一致性、隔离性、可持久性

ACID)之外,数据库服务器在执行每次更新之后还不需要重新构建索引和其他内部结构;它可以延迟到提交之后进行。这样会加速代码的执行。Oracle
这点确实很好。

我们现在即准备好插入数据了 - 我们只需要打开该 CSV
文件,并从中获取数据即可。通过使用 fopen
函数可以相当简单地完成此操作。然后,我们可以使用 PHP list()
构造函数直接将 CSV
的列指定给变量“$extension”和“$name”。因为这些变量已经绑定到了语句中,所以我们现在要做的只是调用该语句对象的
execute() 方法使其执行插入。这种方式既方便又快捷 -
在事务处理时每个迭代循环只有两行。到达文件尾时,我们就可以立即使用数据库句柄的
commit() 方法来提交这些更改了。

如果您以前尚未尝试过 PHP 5,则请花一点时间来通读一下“新闻”和各种声明。在
UNIX 计算机上,您可能要安装或升级 libxml2;如果没有
libxml2,“pear”程序包管理工具就无法运行,您安装 PDO
时就会遇到很多困难。获取 PHP 5,并将其编译和安装。确保指定的前缀不是
/usr/local/,这样它就不会与 PHP 4 安装发生冲突了:

标签:

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图