若是有任何鏈接錯誤,將拋出一個 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