PHP PDO prepare()、execute()和bindParam()方法詳解

每次將查詢發送給MySQL服務器時,都必須解析該查詢的語法,確保結構正確並可以執行。這是這個過程當中必要的步驟,但也確實帶來了一些開銷。作一次是必要的,但若是反覆地執行相同的查詢,批量插入多行並只改變列值時會怎麼樣呢?預處理語句會在服務器上緩存查詢的語法和執行過程,而只在服務器和客戶端之間傳輸有變化的列值,以此來消除這些額外的開銷。php

PDO爲支持此特性的數據庫提供了預處理語句功能。由於MySQL支持這個特性,因此能夠在適當時使用預處理語句。html

預處理語句是使用兩個方法實現的:prepare()方法負責準備要執行的查詢,execute()方法使用一組給定的列參數反覆地執行查詢。這些參數能夠顯式地做爲數組傳遞給execute()方法,也可使用經過bindParam()方法指定的綁定參數提供給execute()方法。mysql


使用預處理語句——prepare()方法

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()方法

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()方法進行綁定來傳遞查詢參數。


綁定參數——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:該參數顯式地設置參數的數據類型,能夠爲如下值:

  • PDO_PARAM_BOOL:SQL BOOLEAN類型。
  • PDO_PARAM_INPUT_OUTPUT:參數傳遞給存儲過程時使用此類型,所以,能夠在過程執行後修改。
  • PDO_PARAM_INT:SQL INTEGER數據類型。
  • PDO_PARAM_NULL:SQL NULL數據類型。
  • PDO_PARAM_LOB:SQL大對象數據類型。
  • PDO_PARAM_STMT:PDOStatement對象類型,當前不可操做。
  • PDO_PARAM_STR:SQL CHAR、VARCHAR和其它字符串數據類型。

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數據表中的數據記錄以下圖所示:

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數據表中的數據記錄以下圖所示:

執行實例代碼後tb_chengji數據表中的數據記錄


提示

當使用PHP中PDO的prepare()、execute()和bindParam()方法時,網頁的編碼必定要設置爲utf-8:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

不然,將不能輸入中文漢字數據。

相關文章
相關標籤/搜索