每次將查詢發送給MySQL服務器時,都必須解析該查詢的語法,確保結構正確並可以執行。這是這個過程當中必要的步驟,但也確實帶來了一些開銷。作一次是必要的,但若是反覆地執行相同的查詢,批量插入多行並只改變列值時會怎麼樣呢?預處理語句會在服務器上緩存查詢的語法和執行過程,而只在服務器和客戶端之間傳輸有變化的列值,以此來消除這些額外的開銷。php
PDO爲支持此特性的數據庫提供了預處理語句功能。由於MySQL支持這個特性,因此能夠在適當時使用預處理語句。html
預處理語句是使用兩個方法實現的:prepare()方法負責準備要執行的查詢,execute()方法使用一組給定的列參數反覆地執行查詢。這些參數能夠顯式地做爲數組傳遞給execute()方法,也可使用經過bindParam()方法指定的綁定參數提供給execute()方法。mysql
prepare()方法負責準備要執行的查詢。語法格式以下:sql
PDOStatement PDO::prepare(string statement[,array driver_options])
可是,用做準備語句的查詢與以住使用的查詢略有區別,由於對於每次執行迭代中要改變的值,必須使用佔位符而不是具體的列值。數據庫
查詢支持兩種不一樣的語法:命名參數和問號參數。數組
使用命名參數的查詢以下:緩存
INSERT INTO tb_chengji SET xuesheng=:xuesheng,yuwen=:yuwen;
其中,:xuesheng與:yuwen都是列佔位符。服務器
使用問號參數的查詢以下:ui
INSERT INTO tb_chengji SET xuesheng=?,yuwen=?;
其中,?也是列佔位符。編碼
選擇哪種語法均可以,可是前者更明確一些。
下面使用prepare()方法準備一個用於迭代執行的查詢:
<?php $pdo=new PDO($dsn,$user,$pwd); // 鏈接數據庫 $query="INSERT INTO tb_chengji SET xuesheng=:xuesheng,yuwen=:yuwen"; $result=$pdo->prepare($query); ?>
上面的代碼將查詢準備好了。繼續下面的操做。
execute()方法負責執行準備好的查詢。語法格式以下:
bool PDOStatement::execute([array input_parameters])
該方法須要有每次迭代執行中替換的輸入參數。這能夠經過兩種方法實現:做爲數組將值傳遞給方法,或者經過bindParam()方法把值綁定到查詢中相應的變量名或位置偏移。
下面介紹第一種方法,第二種方法在bindParam()方法中介紹。
實例代碼中準備了一條語句並經過execute()方法反覆執行,每次使用不一樣的參數:
<?php $pdo=new PDO($dsn,$user,$pwd); // 鏈接數據庫 $query="INSERT INTO tb_chengji SET xuesheng=:xuesheng,yuwen=:yuwen"; $result=$pdo->prepare($query); $result->execute(array(':xuesheng'=>'趙天平',':yuwen'=>'90')); // 執行一次 $result->execute(array(':xuesheng'=>'張冬雪',':yuwen'=>'115')); // 再執行一次 ?>
下面經過使用bindParam()方法進行綁定來傳遞查詢參數。
execute()方法中的input_parameters參數是可選的,雖然很方便,可是若是須要傳遞多個變量時,以這種方式提供數組會很快變得難以處理(當數組元素過多時,也就是當數據表中的列過多時,代碼設計會變得特別難以閱讀或出錯)。使用bindParam()方法能夠解決這個問題。語法格式以下:
boolean PDOStatement::bindParam(mixed parameter,mixed &variable[,int datatype [,int length[,mixed driver_options]]])
parameter:當在prepare()方法中使用命名參數時,parameter是預處理語句中使用語法(例如:xuesheng)指定的列值佔位符的名字;使用問號參數時,parameter是查詢中列值佔位符的索引偏移。
variable:該參數存儲將賦給佔位符的值。它按引用傳遞,由於結合準備存儲過程使用此方法時,能夠根據存儲過程的某個動做修改這個值。
datatype:該參數顯式地設置參數的數據類型,能夠爲如下值:
length:該參數指定數據類型的長度。只有當賦爲PDO_PARAM_INPUT_OUTPUT數據類型時才須要這個參數。
driver_options:該參數用來傳遞任何數據庫驅動程序特定的選項。
下面修改前面的實例,使用bindParam()方法來賦列值:
<?php $pdo=new PDO($dsn,$user,$pwd); // 鏈接數據庫 $query="INSERT INTO tb_chengji SET xuesheng=:xuesheng,yuwen=:yuwen"; $result=$pdo->prepare($query); $xuesheng='趙天平'; $yuwen='90'; $result->bindParam(':xuesheng',$xuesheng); $result->bindParam(':yuwen',$yuwen); $result->execute(); $xuesheng='張冬雪'; $yuwen='115'; $result->bindParam(':xuesheng',$xuesheng); $result->bindParam(':yuwen',$yuwen); $result->execute(); ?>
若是使用問號參數,語句則以下所示:
$query="INSERT INTO tb_chengji SET xuesheng=?,yuwen=?";
所以對應的bindParam()方法調用以下:
$xuesheng='趙天平'; $yuwen='90'; $result->bindParam(1,$xuesheng); $result->bindParam(2,$yuwen); ...... $xuesheng='張冬雪'; $yuwen='115'; $result->bindParam(1,$xuesheng); $result->bindParam(2,$xuesheng);
在執行下面的實例代碼以前,tb_chengji數據表中的數據記錄以下圖所示:
執行下面的實例代碼:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>PHP PDO prepare()、execute()和bindParam()方法詳解實例-www.baike369.com</title> </head> <body> <?php $dbms='mysql'; $dbname='db_xuesheng'; $user='root'; $pwd='1234'; $host='localhost'; $dsn="$dbms:host=$host;dbname=$dbname"; try{ $pdo=new PDO($dsn,$user,$pwd); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $query="INSERT INTO tb_chengji SET xuesheng = :xuesheng,yuwen = :yuwen,shuxue = :shuxue,yingyu = :yingyu"; $result=$pdo->prepare($query); $result->execute(array(":xuesheng"=>"週一剛",":yuwen"=>"55",":shuxue"=>"80",":yingyu"=>"78")); $result->execute(array(":xuesheng"=>"胡偉",":yuwen"=>"107",":shuxue"=>"99",":yingyu"=>"113")); $xuesheng="孫維維"; // 能夠接受<form>標籤傳遞過來的值 $yuwen="86"; $shuxue="66"; $yingyu="78"; $result->bindParam(":xuesheng",$xuesheng); $result->bindParam(":yuwen",$yuwen); $result->bindParam(":shuxue",$shuxue); $result->bindParam(":yingyu",$yingyu); $result->execute(); // 能夠屢次添加數據記錄 $xuesheng="王萍"; $yuwen="116"; $shuxue="45"; $yingyu="69"; $result->bindParam(":xuesheng",$xuesheng); $result->bindParam(":yuwen",$yuwen); $result->bindParam(":shuxue",$shuxue); $result->bindParam(":yingyu",$yingyu); $result->execute(); }catch(Exception $exception){ echo $exception->getMessage(); } ?> </body> </html>
上面的實例執行一次代碼,能夠添加多條數據記錄。固然,執行一次代碼,也能夠添加一條記錄。
上面的實例代碼,還能夠寫成下面的格式,效果是同樣的:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>PHP PDO prepare()、execute()和bindParam()方法詳解實例-www.baike369.com</title> </head> <body> <?php $dbms='mysql'; $dbname='db_xuesheng'; $user='root'; $pwd='1234'; $host='localhost'; $dsn="$dbms:host=$host;dbname=$dbname"; try{ $pdo=new PDO($dsn,$user,$pwd); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $query="INSERT INTO tb_chengji SET xuesheng=?,yuwen=?,shuxue=?,yingyu=?"; $result=$pdo->prepare($query); $result->execute(array("週一剛","55","80","78")); $result->execute(array("胡偉","107","99","113")); $xuesheng="孫維維"; // 能夠接受<form>標籤傳遞過來的值 $yuwen="86"; $shuxue="66"; $yingyu="78"; $result->bindParam(1,$xuesheng); $result->bindParam(2,$yuwen); $result->bindParam(3,$shuxue); $result->bindParam(4,$yingyu); $result->execute(); // 能夠屢次添加數據記錄 $xuesheng="王萍"; $yuwen="116"; $shuxue="45"; $yingyu="69"; $result->bindParam(1,$xuesheng); $result->bindParam(2,$yuwen); $result->bindParam(3,$shuxue); $result->bindParam(4,$yingyu); $result->execute(); }catch(Exception $exception){ echo $exception->getMessage(); } ?> </body> </html>
執行實例代碼之後,tb_chengji數據表中的數據記錄以下圖所示:
當使用PHP中PDO的prepare()、execute()和bindParam()方法時,網頁的編碼必定要設置爲utf-8:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
不然,將不能輸入中文漢字數據。