天天看點

php -- PDO預處理

POD是PHP一個擴充,PDO擴充為PHP通路資料庫定義了一個輕量級的、一緻性的接
口,它提供了一個資料通路抽象層,這樣,無論使用什麼資料庫,都可以通過一緻
的函數執行查詢和擷取資料。


PDO對預處理語句的支援需要使用PDOStatement類對象,但該類對象并不是通過
NEW關鍵字執行個體化出來的,而是通過PDO對象中的prepare()方法,在資料庫服務
器中準備好一個預處理的SQL語句後直接傳回的。如果通過之前執行PDO對象中的
query()方法傳回的PDOStatement類對象,隻代表的是一個結果集對象。而如
果通過執行PDO對象中的prepare()方法産生的PDOStatement類對象,則為一
個查詢對象,能定義和執行參數化的SQL指令。PDOStatement類中的全部成員方
法如下所示:

PDOStatement::bindColumn — 綁定一列到一個 PHP 變量
PDOStatement::bindParam — 綁定一個參數到指定的變量名
PDOStatement::bindValue — 把一個值綁定到一個參數
PDOStatement::closeCursor — 關閉遊标,使語句能再次被執行。
PDOStatement::columnCount — 傳回結果集中的列數
PDOStatement::debugDumpParams — 列印一條 SQL 預處理指令
PDOStatement::errorCode — 擷取跟上一次語句句柄操作相關的 SQLSTATE
PDOStatement::errorInfo — 擷取跟上一次語句句柄操作相關的擴充錯誤信
息
PDOStatement::execute — 執行一條預處理語句
PDOStatement::fetch — 從結果集中擷取下一行
PDOStatement::fetchAll — 傳回一個包含結果集中所有行的數組
PDOStatement::fetchColumn — 從結果集中的下一行傳回單獨的一列。
PDOStatement::fetchObject — 擷取下一行并作為一個對象傳回。
PDOStatement::getAttribute — 檢索一個語句屬性
PDOStatement::getColumnMeta — 傳回結果集中一列的中繼資料
PDOStatement::nextRowset — 在一個多行集語句句柄中推進到下一個行集
PDOStatement::rowCount — 傳回受上一個 SQL 語句影響的行數
PDOStatement::setAttribute — 設定一個語句屬性
PDOStatement::setFetchMode — 為語句設定預設的擷取模式。

、準備語句

重複執行一個SQL查詢,通過每次疊代使用不同的參數,這種情況使用預處理語句
運作效率最高。使用預處理語句,首先需要在資料庫伺服器中先準備好“一個SQL
語句”,但并不需要馬上執行。PDO支援使用“占位符”文法,将變量綁定到這個預
處理的SQL語句中。對于一個準備好的SQL語句,如果在每次執行時都要改變一些
列值,這種情況必須使用“占位符号”而不是具體的列值。在PDO中有兩種使用占位
符的文法:“命名參數”和“問号參數”,使用哪一種文法要看個人的喜好。

使用命名參數作為占位符的INSERT插入語句:

$dbh->prepare(“insert into contactinfo(name,address,phone) 
values(:name,:address,:phone)”);


需要自定義一個字元串作為“命名參數”,每個命名參數需要冒号(:)開始,參數
的命名一定要有意義,最好和對應的字段名稱相同。
使用問号(?)參數作為占位符的INSERT插入語句:

$dbh->prepare(“insert into contactinfo(name,address,phone) 
values(?,?,?)”);


問号參數一定要和字段的位置順序對應。不管是使用哪一種參數作為占位符構成的
查詢,或是語句中沒有用到占位符,都需要使用PDO對象中的prepare()方法,
去準備這個将要用于疊代執行的查詢,并傳回PDOStatement類對象。


、綁定參數

當SQL語句通過PDO對象中的prepare()方法在資料庫伺服器端準備好了以後,如
果使用了占位符,就需要在每次執行時替換輸入的參數。可以通過
PDOStatement對象中的bindParam()方法,把參數變量綁定到準備好的占位符
上(位置或名字要對應)。方法bindParame()的原型如下所示:


bool PDOStatement::bindParam ( mixed $parameter , mixed 
&$variable [, int $data_type = PDO::PARAM_STR [, int 
$length [, mixed $driver_options ]]] )



第一個參數parameter是必選項,如果在準備好的查詢中占位符文法使用名字參
數,那麼将名字參數字元串作為bindParam()方法的第一個參數提供。如果占位
符文法使用問号參數,那麼将準備好的查詢中列值占位符的索引偏移量,作為該方
法的第一個參數。


第二個參數variable也是可選項,提供供給第一個參數所指定占位符的值。因為
該參數是按引用傳遞的,是以隻能提供變量作為參數,不能直接提供數值。

第三個參數data_type是可選項,為目前被綁定的參數設定資料類型。可以為以
下值。

PDO::PARAM_BOOL 代表boolean資料類型。
PDO::PARAM_NULL 代表SQL中的NULL類型。
PDO::PARAM_INT 代表SQL中的INTEGER資料類型。
PDO::PARAM_STR 代表SQL中的CHAR、VARCHAR和其他字元串資料類型。
PDO::PARAM_LOB 代表SQL中大對象資料類型。

第四個參數length是可選項,用于指定資料類型的長度。

第五個參數driver_options是可選項,通過該參數提供任何資料庫驅動程式特定的選項。
使用命名參數作為占位符的參數綁定示例:

<?php
//...省略PDO連接配接資料庫代碼
$query = "insert into contactinfo (name,address,phone) values(:name,:address,:phone)";
$stmt = $dbh->prepare($query);          //調用PDO對象中的prepare()方法

$stmt->blinparam(':name',$name);        //将變量$name的引用綁定到準備好的查詢名字參數":name"中
$stmt->blinparam(':address',$address);
$stmt->blinparam(':phone',phone);
//...
?>

使用問号(?)作為占位符的參數綁定示例:

<?php
//...省略PDO連接配接資料庫代碼
$query = "insert into contactinfo (name,address,phone) 
values(?,?,?)";
$stmt = $dbh->prepare($query);          //調用PDO對象中的prepare()方法

$stmt->blinparam(,$name,PDO::PARAM_STR);        //将變
量$name的引用綁定到準備好的查詢名字參數":name"中
$stmt->blinparam(,$address,PDO::PARAM_STR);
$stmt->blinparam(,phone,PDO::PARAM_STR,);
//...
?>

、執行準備語句

當準備語句完成,并綁定了相應的參數後,就可以通過調用PDOStatement類對
象中的execute()方法,反複執行在資料庫緩存區準備好的語句了。在下面的示
例中,向前面提供的contactinfo表中,使用預處理方式連續執行同一個
INSERT語句,通過改變不同的參數添加兩條記錄。如下所示:

<?php
try {
     $dbh = new PDO('mysql:dbname=testdb;host=localhost', 
 $username, $passwd);
}catch (PDOException $e){
    echo '資料庫連接配接失敗:'.$e->getMessage();
    exit;
}

$query = "insert into contactinfo (name,address,phone) 
values(?,?,?)";
$stmt = $dbh->prepare($query);

$stmt->blinparam(,$name);     
$stmt->blinparam(,$address);
$stmt->blinparam(,phone);

$name = "趙某某";
$address = "海澱區中關村";
$phone = "15801688348";

$stmt->execute();           //執行參數被綁定後的準備語句
?>


如果你隻是要傳遞輸入參數,并且有許多這樣的參數要傳遞,那麼你會覺得下面所
示的快捷方式文法非常有幫助。是通過在execute()方法中提供一個可選參數,
該參數是由準備查詢中的命名參數占位符組成的數組,這是第二種為預處理查詢在
執行中替換輸入參數的方式。此文法使你能夠省去對$stmt->bindParam()的調
用。将上面的示例做如下修改:

<?php
//...省略PDO連接配接資料庫代碼
$query = "insert into contactinfo (name,address,phone) 
values(?,?,?)";
$stmt = $dbh->prepare($query);

//傳遞一個數組為預處理查詢中的命名參數綁定值,并執行一次。
$stmt->execute(array("趙某某","海澱區","15801688348"));
?>

另外,如果執行的是INSERT語句,并且資料表中有自動增長的ID字段,可以使用
PDO對象中的lastinsertId()方法擷取最後插入資料表中的記錄ID。如果需要
檢視其他DML語句是否執行成功,可以通過PDOStatement類對象中的
rowCount()方法擷取影響記錄的行數。
           
執行個體:
<?php
$stmt = $db->prepare("select * from uf_users");
$stmt->execute();
var_dump($stmt->fetchAll());

?>
執行個體:
<?php
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();

/* 運用 PDOStatement::fetch 風格 */
print("PDO::FETCH_ASSOC: ");
print("Return next row as an array indexed by column name\n");
$result = $sth->fetch(PDO::FETCH_ASSOC);
print_r($result);
print("\n");

print("PDO::FETCH_BOTH: ");
print("Return next row as an array indexed by both column name and number\n");
$result = $sth->fetch(PDO::FETCH_BOTH);
print_r($result);
print("\n");

print("PDO::FETCH_LAZY: ");
print("Return next row as an anonymous object with column names as properties\n");
$result = $sth->fetch(PDO::FETCH_LAZY);
print_r($result);
print("\n");

print("PDO::FETCH_OBJ: ");
print("Return next row as an anonymous object with column names as properties\n");
$result = $sth->fetch(PDO::FETCH_OBJ);
print $result->NAME;
print("\n");
?>  


以上例程會輸出:


PDO::FETCH_ASSOC: Return next row as an array indexed by column name
Array
(
    [NAME] => apple
    [COLOUR] => red
)

PDO::FETCH_BOTH: Return next row as an array indexed by both column name and number
Array
(
    [NAME] => banana
    [] => banana
    [COLOUR] => yellow
    [] => yellow
)

PDO::FETCH_LAZY: Return next row as an anonymous object with column names as properties
PDORow Object
(
    [NAME] => orange
    [COLOUR] => orange
)

PDO::FETCH_OBJ: Return next row as an anonymous object with column names as properties
kiwi