許多成熟的資料庫都支援預處理語句(Prepared Statements
)的概念。它們是什麼東西?你可以把它們想成是一種編譯過的要執行的SQL語句模板,可以用不同的變數參數來客製化它。預處理語句有兩個主要的優點:
查詢只需要被解析(或準備)一次,但可以使用相同或不同的參數執行多次。當查詢準備好(Prepared)之後,資料庫就會分析,編譯並最佳化它要執行查詢的計畫。對於複雜查詢來說,如果你要重複執行許多次有不同參數的但結構相同的查詢,這個過程會佔用大量的時間,使得你的應用程式變慢。使用一個預處理語句你就可以避免重複分析、編譯、最佳化的環節。簡單來說,預處理語句使用較少的資源,執行速度也就更快。
傳給預處理語句的參數不需要使用引號,底層驅動會為你處理這個。如果你的應用程式獨佔使用預處理語句,你就可以確信沒有SQL注入會發生。 (然而,如果你仍然在用基於不受信任的輸入來構建查詢的其他部分,這仍然是具有風險的).
正因為預處理語句是如此有用,它成了PDO唯一為不支援此特性的資料庫提供的模擬實作。這使你可以使用統一的資料存取規範而不必關心資料庫本身是否具備此特性。
/* 使用预处理语句重复插入数据(1) 此示例演示了一个通过向命名占位符代入一个name和一个value值来执行的INSERT查询 */ 连接数据库:$dbh = new PDO("mysql:host=127.0.0.1;dbname=dbname",'username','123'); 注:如果插入数据后出现乱码的话,注意检查各个页面的字符集设置,尤其是关于pdo处理的php页面仅有header头设置为utf-8有时也不行,这时就在执行SQL语句前设置数据库的字符集$dbh->query("set names utf8"); $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(); /* 使用预处理语句重复插入数据(2) 此示例演示了一个通过向用?表示的占位符代入一个name和一个value值来执行的INSERT查询 */ $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(); /* 通过预处理语句获取数据 此示例演示使用从表单获取的数据为关键值来执行查询获取数据。用户的输入会被自动添加引号,所以这儿不存在SQL注入攻击的危险。 */ $stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?"); if ($stmt->execute(array($_GET['name']))) { while ($row = $stmt->fetch()) { print_r($row); } }
如果資料庫驅動支持,你也可以像綁定輸入參數那樣綁定輸出參數。輸出參數常用於預存程序的回傳值。輸出參數用起來比輸入參數稍微複雜一些,使用時你必須知道它回傳的參數值有多大。如果它回傳的參數值比你建議的大,就會發生錯誤。
//调用一个带有输出参数的存储过程 $stmt = $dbh->prepare("CALL sp_returns_string(?)"); $stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000); //执行存储过程 $stmt->execute(); print "procedure returned $return_value/n";
你也可以指定既代表輸入又代表輸出的參數,語法類似輸出參數。在下個程式碼範例中,「hello」字串被傳遞到預存程序中,當它傳回時,hello就會被預存程序的回傳值取代。
//调用一个带有输入/输出参数的存储过程 $stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)"); $value = 'hello'; $stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000); // 执行存储过程 $stmt->execute(); print "procedure returned $value/n"; //占位符的错误使用 $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]%”));
若有錯,請指出,若想了解更多相關問題請訪問PHP中文網:PHP視頻教程,
相信裡面豐富的內容以及講解會給您一個滿意的答案。
以上是什麼是預處理語句?又該如何使用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!