若是有任何链接错误,将抛出一个 PDOException
异常对象。若是想处理错误状态,能够捕获异常,或者选择留给经过 set_exception_handler()
设置的应用程序全局异常处理程序。php
<?php try { $dbh = new PDO('mysql:host=localhost;dbname=test',$user,$pass); foreach($dbh->query('select * from FOO') as $row){ print_r($row); } } catch(PDOException $e){ print "ERROR!:".$e->getMessage()."<br/>"; die(); } ?>
事务支持四大特性(ACID):原子性(Atomicity
)、一致性(Consistency)
、隔离性(Isolation)
以及持久性(Durability)
。mysql
若是须要一个事务,则必须用 PDO::beginTransaction()
方法来启动。若是底层驱动不支持事务,则抛出一个 PDOException 异常(无论错误处理设置是怎样的,这都是一个严重的错误状态)。一旦开始了事务,可用 PDO::commit()
或 PDO::rollBack()
来完成,这取决于事务中的代码是否运行成功。sql
当脚本结束或链接即将被关闭时,若是尚有一个未完成的事务,那么 PDO 将自动回滚该事务。这种安全措施有助于在脚本意外终止时避免出现不一致的状况——若是没有显式地提交事务,那么假设是某个地方出错了,因此执行回滚来保证数据安全。数据库
Example #1 在事务中执行批处理安全
在下面例子中,假设为新员工建立一组条目,分配一个为23的ID。除了登记此人的基本数据以外,还须要记录他的工资。两个更新分别完成起来很简单,但经过封闭在 PDO::beginTransaction()
和PDO::commit()
调用中,能够保证在更改完成以前,其余人没法看到这些更改。若是发生了错误,catch 块回滚自事务启动以来发生的全部更改,并输出一条错误信息。函数
<?php try{ $dbh = new PDO('odbc:SAMPLE','db2inst1','ibmdb2',array(PDO::ATTR_PERSISTENT =>true)); echo "Connected\n"; }catch(Exception $e){ die("Unable to connect:".$e->getMessage()); } try{ $dbh -> setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); $bdh -> beginTransaction(); $bdh -> exec("insert into staff (id,first,last) values(23,'JOE','Bloggs')"); $bdh -> exec("insert into salarychange (id,amount,changedate) values (23,5000,Now())"); $dbh -> commit(); }catch(Exception $e) { $dbh -> rollBack(); echo "Failed:".$e -> getMeseeage(); } ?>
Example #1 用预处理语句进行重复插入fetch
<?php $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"); $stmt->bindParam(':name', $name); $stmt->bindParam(':value', $value); // 插入一行 $name = 'one'; $value = 1; $stmt->execute(); // 用不一样的值插入另外一行 $name = 'two'; $value = 2; $stmt->execute(); ?>
Example #2 用预处理语句进行重复插入google
下面例子经过用 name 和 value 取代 ? 占位符的位置来执行一条插入查询。code
<?php $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)"); $stmt->bindParam(1, $name); $stmt->bindParam(2, $value); // 插入一行 $name = 'one'; $value = 1; $stmt->execute(); // 用不一样的值插入另外一行 $name = 'two'; $value = 2; $stmt->execute(); ?>
Example #3 使用预处理语句获取数据对象
下面例子获取数据基于键值已提供的形式。用户的输入被自动用引号括起来,所以不会有 SQL 注入攻击的危险。
<?php $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?"); if ($stmt->execute(array($_GET['name']))) { while ($row = $stmt->fetch()) { print_r($row); } } ?>
Example #6 占位符的无效使用
<?php $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'"); $stmt->execute(array($_GET['name'])); // 占位符必须被用在整个值的位置 $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?"); $stmt->execute(array("%$_GET[name]%")); ?>
PDO 提供了三种不一样的错误处理模式,以知足不一样风格的应用开发:
Example #1 建立 PDO 实例并设置错误模式
<?php $dsn = 'mysql:dbname=testdb;host=127.0.0.1'; $user = 'dbuser'; $password = 'dbpass'; try { $dbh = new PDO($dsn, $user, $password); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); } ?>
Note: 无论当前是否设置了 PDO::ATTR_ERRMODE ,若是链接失败,PDO::__construct() 将老是抛出一个 PDOException 异常。未捕获异常是致命的。 Example #2 建立 PDO 实例并在构造函数中设置错误模式
<?php $dsn = 'mysql:dbname=test;host=127.0.0.1'; $user = 'googleguy'; $password = 'googleguy'; /* 使用 try/catch 围绕构造函数仍然有效,即便设置了 ERRMODE 为 WARNING, 由于若是链接失败,PDO::__construct 将老是抛出一个 PDOException 异常。 */ try { $dbh = new PDO($dsn, $user, $password, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING)); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); exit; } // 这里将致使 PDO 抛出一个 E_WARNING 级别的错误,而不是 一个异常 (当数据表不存在时) $dbh->query("SELECT wrongcolumn FROM wrongtable"); ?>
以上例程会输出:
Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.wrongtable' doesn't exist in /tmp/pdo_test.php on line 18