PDO之綁定變量

用綁定變量 SQL時,客戶端向服務器發送了一個 SQL語句的原型,服務器端收到了這個 SQL語句“框架”後,經過解析、預處理、生成並存儲該部分的執行計劃,然後返回給客戶端一個句柄,之後每次執行這類查詢,都應使用這個句柄,之後的每次查詢,只需要發送某些變量的值就可以了。

這樣看來,當一次會話中要執行多次類似的SQL時,使用綁定變量 SQL是更高效的,因爲在 MySQL服務器端,只需要解析一次 SQL語句了,也能省去部分執行計劃的生成。同時,每次查詢都只需要發送某些變量的值,相比於每次使用完整的 SQL語句,減少了網絡開銷。

同時,綁定變量 SQL也更加安全,無需在應用程序中對用戶輸入進行轉義了,MySQL服務器將每次傳過來的值進行轉義,這也比在應用程序轉義更加安全。

注意,使用PDO的綁定變量時,一定要將 PDO::ATTR_EMULATE_PREPARES 設置爲 false,否則只是在客戶端中模擬綁定變量,一系列操作包括轉義,都是在客戶端完成的,每次發送給 MySQL服務器的都只是一個普通的查詢。

$dsn = 'mysql:host=localhost;dbname=sakila';
$username = 'root';
$passwd = 'root';
$pdo = new PDO( $dsn, $username, $passwd, [
    PDO::ATTR_EMULATE_PREPARES => false,
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
]);
$sql = "SELECT * FROM address WHERE city_id = :city_id ";
$stmt = $pdo->prepare($sql);

$stmt->bindValue(":city_id", 300);
$stmt->execute();

$stmt->bindValue(":city_id", "' or 1 = 1#");
$stmt->execute();

//  未展示 bindParam 用法

在MySQL命令行中輸入 SET GLOBAL general_log = ‘ON’ ,就可以在日誌中記錄所有執行過的 SQL了。運行上述代碼,MysSQL 執行過程爲:

Connect root@localhost on sakila using TCP/IP
Prepare select * from address where city_id = ?
Execute select * from address where city_id = '300'
Execute select * from address where city_id = '\' or 1 = 1#'
Close stmt  
Quit

如果不將設爲false,那麼 MySQL服務器執行過程將是:

Connect root@localhost on sakila using TCP/IP
Query   select * from address where city_id = '300'
Query   select * from address where city_id = '\' or 1 = 1#'
Quit    

完全沒有用到 PREPARE 和 EXECUTE。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章