PHP基礎知識之————PDO預處理語句
轉載處:http://www.cnblogs.com/xiaohuochai/p/6133353.html
定義
在生成網頁時,許多PHP指令碼通常都會執行除引數之外,其他部分完全相同的查詢語句,針對這種重複執行一個查詢,每次迭代使用不同的引數情況,PDO提供了一種名為預處理語句(prepared statement)的機制。它可以將整個SQL命令向資料庫伺服器傳送一次,以後只有引數發生變化,資料庫伺服器只需對命令的結構做一次分析就夠了,即編譯一次,可以多次執行。會在伺服器上快取查詢的語句和執行過程,而只在伺服器和客戶端之間傳輸有變化的列值,以此來消除這些額外的開銷。這不僅大大減少了需要傳輸的資料量,還提高了命令的處理效率。可以有效防止SQL注入,在執行單個查詢時快於直接使用query()或exec()的方法,速度快且安全,推薦使用
PDO對預處理語句的支援需要使用PDOStatement類物件,但該類的物件並不是通過NEW關鍵字例項化出來的,而是通過執行PDO物件的prepare()方法,在資料庫伺服器中準備好一個預處理的SQL語句後直接返回的。如果通過之前執行PDO物件的query()方法返回的PDOStatement類物件,只代表的是一個結果集物件。而如果通過執行PDO物件中的prepare()方法產生的PDOStatement類物件,則為一個查詢物件,能定義和執行引數化的SQL命令
準備語句
重複執行一個SQL查詢,通過每次迭代使用不同的引數,這種情況使用預處理語句執行效率最高。使用預處理語句,首先需要在資料庫伺服器中先準備好“一個SQL語句”,但並不需要馬上執行。PDO支援使用“佔位符”語法,將變數繫結到這個預處理的SQL語句中。另外,PDO幾乎為所支援的所有資料庫提供了命令佔位符模擬,甚至可以為生來就不支援該概念的資料庫模擬預處理語句和繫結引數。這是PHP向前邁進的積極一步,因為這樣可以使開發人員能夠用PHP編寫“企業級”的資料庫應用程式,而不必特別關注資料庫平臺的能力
對於一個準備好的SQL語句,如果在每次執行時都要改變一些列值,這種情況必須使用“佔位符”而不是具體的列值,或者只要有需要使用變數作為值的地方,就先使用佔位符替代,準備好一個沒有傳值的SQL語句,在資料庫伺服器的快取區等待處理,然後再去單獨賦給佔位符具體的值,再通過這個準備好的預處理語句執行。在PDO中有兩種使用佔位符的語法:“命令引數”和“問號引數”,使用哪一種語法看個人的喜好
使用命名引數作為佔位符的INSERT查詢如下所示:
$dbh->prepare("INSERT INTO contactInto(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 ]]] )
繫結一個PHP變數到用作預處理的SQL語句中的對應命名佔位符或問號佔位符。不同於 PDOStatement::bindValue(),此變數作為引用被繫結,並只在PDOStatement::execute()被呼叫的時候才取其值
parameter表示引數識別符號(必須項)。對於使用命名佔位符的預處理語句,應是類似:name形式的引數名。對於使用問號佔位符的預處理語句,應是以1開始索引的引數位置
variable(必須項)表示繫結到 SQL 語句引數的 PHP 變數名
data_type(可選項)表示使用PDO::PARAM_*常量明確地指定引數的型別。要從一個儲存過程中返回一個INOUT引數,需要為data_type引數使用按位或操作符去設定PDO::PARAM_INPUT_OUTPUT位,可以為以下值
PDO:PARAM_BOOL:表示boolean資料型別 PDO:PARAM_NULL:表示NULL資料型別 PDO:PARAM_INT:表示INT資料型別 PDO:PARAM_STR:表示字串資料型別 PDO:PARAM_LOB:表示大物件資料型別
length(可選項)表示資料型別的長度。為表明引數是一個儲存過程的OUT引數,必須明確地設定此長度
使用bindParam()方法分別繫結上對應的引數。查詢中使用名字引數的繫結如下所示
$query = "INSERT INTO contactInfo (name,address,phone) VALUES (:name,:address,:phone)"; $stmt = $dbh->prepare($query); $stmt->bindParam(":name",$name); $stmt->bindParam(":address",$address); $stmt->bindParam(":phone",$phone); $name = '愛新覺羅'; $address = '東城'; $phone = '88888';
查詢中使用問號?引數的繫結如下所示
$query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->bindParam("1",$name); $stmt->bindParam("2",$address); $stmt->bindParam("3",$phone); $name = '司馬'; $address = '西城'; $phone = '666';
執行查詢
當準備好查詢並綁定了相應的引數後,就可以通過呼叫PDOStatement類物件中的execute()方法,反覆執行在資料庫快取區準備好的語句了。在下面的示例中,向前面提供的contactInfo表中,使用預處理方式連續執行同一個INSERT語句,通過改變不同的引數新增兩條記錄
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->bindParam("1",$name); $stmt->bindParam("2",$address); $stmt->bindParam("3",$phone); $name = '司馬'; $address = '西城'; $phone = '666'; $stmt->execute(); $name = '曹操'; $address = '平谷'; $phone = '1'; $stmt->execute(); ?>
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (:name,:address,:phone)"; $stmt = $dbh->prepare($query); $stmt->bindParam(":name",$name); $stmt->bindParam(":address",$address); $stmt->bindParam(":phone",$phone); $name = '愛新覺羅'; $address = '東城'; $phone = '88888'; $stmt->execute(); ?>
如果只是要傳遞輸入引數,並且有許多這樣的引數要傳遞,那麼通過在execute()方法中提供一個可選引數,該引數是由準備查詢中的命名引數佔位符組成的陣列,這是第二種為預處理查詢在執行中替換輸入引數的方式。此語法可以活動對bindParam()的呼叫
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->execute(array("張飛",'延慶','3')); $query = "INSERT INTO contactInfo (name,address,phone) VALUES (:name,:address,:phone)"; $stmt = $dbh->prepare($query); $stmt->execute(array(":name"=>"關羽",":address"=>"密雲",":phone"=>"2")); ?>
如果執行的是INSERT語句,並且資料表有自動增長的ID欄位,可以使用PDO物件中的lastInsertId()方法獲取最後插入資料表中的記錄ID。如果需要檢視其他DML語句是否執行成功,可以通過PDOStatement類物件中的rowCount()方法獲取影響記錄的行數
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "INSERT INTO contactInfo (name,address,phone) VALUES (?,?,?)"; $stmt = $dbh->prepare($query); $stmt->execute(array("孫權",'通州','123456')); echo $dbh->lastInsertId(); $query = "UPDATE contactInfo SET name=? WHERE uid=?"; $stmt = $dbh->prepare($query); $stmt->execute(array("天使","6")); echo $stmt->rowCount();//1 $query = "DELETE FROM contactInfo WHERE name= ?"; $stmt = $dbh->prepare($query); $stmt->execute(["孫權"]); echo $stmt->rowCount();//11 ?>
獲取資料
PDO的資料獲取方法與其他資料庫擴充套件都非常類似,只要成功執行SELECT查詢,都會有結果集物件生成。不管是使用PDO物件中的query()方法,還是使用prepare()和execute()等方法結合的預處理語句,執行SELECT查詢都會得到相同的結果集物件PDOStatement,都需要通過PDOStatement類物件中的方法將資料遍歷出來
fetch()
PDOStatement類中的fetch()方法可以將結果集中當前行的記錄以某種方式返回,並將結果集指標移到下一行,當到達結果集末尾時返回FALSE,該方法的原型如下:
mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] )
第一個引數fetch_style(可選項),用於控制下一行如何返回給呼叫者。此值必須是 PDO::FETCH_* 系列常量中的一個,預設為 PDO::ATTR_DEFAULT_FETCH_MODE 的值(預設為 PDO::FETCH_BOTH)
PDO::FETCH_ASSOC:返回一個索引為結果集列名的陣列 PDO::FETCH_BOTH(預設):返回一個索引為結果集列名和以0開始的列號的陣列 PDO::FETCH_BOUND:返回 TRUE ,並分配結果集中的列值給 PDOStatement::bindColumn() 方法繫結的 PHP 變數。 PDO::FETCH_CLASS:返回一個請求類的新例項,對映結果集中的列名到類中對應的屬性名。如果 fetch_style 包含 PDO::FETCH_CLASSTYPE(例如:PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE),則類名由第一列的值決定 PDO::FETCH_INTO:更新一個被請求類已存在的例項,對映結果集中的列到類中命名的屬性 PDO::FETCH_LAZY:結合使用PDO::FETCH_BOTH和PDO::FETCH_OBJ,建立供用來訪問的物件變數名 PDO::FETCH_NUM:返回一個索引為以0開始的結果集列號的陣列 PDO::FETCH_OBJ:返回一個屬性名對應結果集列名的匿名物件
第二個引數cursor_orientation(可選項)表示對於一個PDOStatement物件表示的可滾動遊標,該值決定了哪一行將被返回給呼叫者。此值必須是 PDO::FETCH_ORI_* 系列常量中的一個,預設為 PDO::FETCH_ORI_NEXT。要想讓 PDOStatement 物件使用可滾動遊標,必須在用 PDO::prepare() 預處理SQL語句時,設定 PDO::ATTR_CURSOR 屬性為 PDO::CURSOR_SCROLL
第三個引數offset(可選項)表示對於一個cursor_orientation引數設定為PDO::FETCH_ORI_ABS的PDOStatement物件代表的可滾動遊標,此值指定結果集中想要獲取行的絕對行號
對於一個 cursor_orientation 引數設定為 PDO::FETCH_ORI_REL 的PDOStatement 物件代表的可滾動遊標,此值指定想要獲取行相對於呼叫 PDOStatement::fetch() 前遊標的位置
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); //Array ( [uid] => 1 [0] => 1 [name] => 張三 [1] => 張三 [address] => 朝陽 [2] => 朝陽 [phone] => 123 [3] => 123 [email] => [email protected] [4] => [email protected] ) print_r($stmt->fetch()); echo "<br>"; //Array ( [uid] => 2 [0] => 2 [name] => 李四 [1] => 李四 [address] => 朝陽 [2] => 朝陽 [phone] => 123456789 [3] => 123456789 [email] => [email protected] [4] => [email protected] ) print_r($stmt->fetch()); echo "<br>"; ?>
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); /* Array ( [0] => 1 [1] => 張三 [2] => 朝陽 [3] => 123 [4] => [email protected] ) Array ( [0] => 2 [1] => 李四 [2] => 朝陽 [3] => 123456789 [4] => [email protected] ) Array ( [0] => 3 [1] => 王五 [2] => 海淀 [3] => 15011113456 [4] => [email protected] ) Array ( [0] => 4 [1] => 趙四 [2] => 海淀 [3] => 123456789 [4] => [email protected] ) Array ( [0] => 5 [1] => 諸葛 [2] => [3] => 120120120 [4] => [email protected] ) Array ( [0] => 6 [1] => 天使 [2] => [3] => 222 [4] => [email protected] ) Array ( [0] => 7 [1] => 司馬 [2] => 西城 [3] => 666 [4] => ) Array ( [0] => 8 [1] => 曹操 [2] => 平谷 [3] => 1 [4] => ) Array ( [0] => 9 [1] => 愛新覺羅 [2] => 東城 [3] => 88888 [4] => ) Array ( [0] => 10 [1] => 張飛 [2] => 延慶 [3] => 3 [4] => ) Array ( [0] => 11 [1] => 關羽 [2] => 密雲 [3] => 2 [4] => ) */ while($row = $stmt->fetch(PDO::FETCH_NUM)){ print_r($row); echo "<br>"; } ?>
下面以表格的形式輸出結果集
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; while(list($uid, $name, $address, $phone, $email) = $stmt -> fetch(PDO::FETCH_NUM)) { echo '<tr>'; echo '<td>'.$uid.'</td>'; echo '<td>'.$name.'</td>'; echo '<td>'.$address.'</td>'; echo '<td>'.$phone.'</td>'; echo '<td>'.$email.'</td>'; echo '</tr>'; } echo '</table>'; ?>
fetchAll()
fetchAll()方法與上一個方法fetch()類似,但是該方法只需要呼叫一次就可以獲取結果集中的所有行,並賦給返回的二維陣列。該方法的原型如下:
fetchAll([int fetch_style [,int column_index]])
第一個引數fetch_style是可選項,以何種方式引用所獲取的列取決於該引數。預設值為PDO::FETCH_BOTH,所有可用的值可以參考在fetch()方法中介紹的第一個引數的列表,還可以指定PDO::FETCH_COLUMN值,從結果集中返回一個包含單列的所有值
第二個引數column_index是可選項,需要提供一個整數索引,當在fetchAll()方法的第一個引數中指定PDO::FETCH_COLUMN值時,從結果集中返回通過該引數提供的索引所指定列的所有值
/* Array ( [0] => Array ( [uid] => 1 [0] => 1 [name] => 張三 [1] => 張三 [address] => 朝陽 [2] => 朝陽 [phone] => 123 [3] => 123 [email] => [email protected] [4] => [email protected] ) [1] => Array ( [uid] => 2 [0] => 2 [name] => 李四 [1] => 李四 [address] => 朝陽 [2] => 朝陽 [phone] => 123456789 [3] => 123456789 [email] => [email protected] [4] => [email protected] ) [2] => Array ( [uid] => 3 [0] => 3 [name] => 王五 [1] => 王五 [address] => 海淀 [2] => 海淀 [phone] => 15011113456 [3] => 15011113456 [email] => [email protected] [4] => [email protected] ) [3] => Array ( [uid] => 4 [0] => 4 [name] => 趙四 [1] => 趙四 [address] => 海淀 [2] => 海淀 [phone] => 123456789 [3] => 123456789 [email] => [email protected] [4] => [email protected] ) [4] => Array ( [uid] => 5 [0] => 5 [name] => 諸葛 [1] => 諸葛 [address] => [2] => [phone] => 120120120 [3] => 120120120 [email] => [email protected] [4] => [email protected] ) [5] => Array ( [uid] => 6 [0] => 6 [name] => 天使 [1] => 天使 [address] => [2] => [phone] => 222 [3] => 222 [email] => [email protected] [4] => [email protected] ) [6] => Array ( [uid] => 7 [0] => 7 [name] => 司馬 [1] => 司馬 [address] => 西城 [2] => 西城 [phone] => 666 [3] => 666 [email] => [4] => ) [7] => Array ( [uid] => 8 [0] => 8 [name] => 曹操 [1] => 曹操 [address] => 平谷 [2] => 平谷 [phone] => 1 [3] => 1 [email] => [4] => ) [8] => Array ( [uid] => 9 [0] => 9 [name] => 愛新覺羅 [1] => 愛新覺羅 [address] => 東城 [2] => 東城 [phone] => 88888 [3] => 88888 [email] => [4] => ) [9] => Array ( [uid] => 10 [0] => 10 [name] => 張飛 [1] => 張飛 [address] => 延慶 [2] => 延慶 [phone] => 3 [3] => 3 [email] => [4] => ) [10] => Array ( [uid] => 11 [0] => 11 [name] => 關羽 [1] => 關羽 [address] => 密雲 [2] => 密雲 [phone] => 2 [3] => 2 [email] => [4] => ) ) */ print_r($stmt->fetchAll());
下面以表格的形式輸出結果集
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; $allRows = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach($allRows as $row){ echo '<tr>'; echo '<td>'.$row['uid'].'</td>'; echo '<td>'.$row['name'].'</td>'; echo '<td>'.$row['address'].'</td>'; echo '<td>'.$row['phone'].'</td>'; echo '<td>'.$row['email'].'</td>'; echo '</tr>'; } echo '</table>'; ?>
下面使用fetchAll()方法輸出所有的姓名陣列
$query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); $row=$stmt->fetchAll(PDO::FETCH_COLUMN,1); echo '所有聯絡人的姓名:'; //所有聯絡人的姓名:Array ( [0] => 張三 [1] => 李四 [2] => 王五 [3] => 趙四 [4] => 諸葛 [5] => 天使 [6] => 司馬 [7] => 曹操 [8] => 愛新覺羅 [9] => 張飛 [10] => 關羽 ) print_r($row);
setFetchMode()
PDOStatement物件中的fetch()和fetchAll()兩個方法,獲取結果資料的引用方式預設是一樣的,既按列名索引又按列在行中的數值偏移(從0開始)索引的值陣列,因為它們的預設模式都被設定為PDO::FETCH_BOTH值,如果計劃使用其他模式來改變這個預設設定,可以在fetch()或fetchAll()方法中提供需要的模式引數。但如果多次使用這兩個方法,在每次呼叫時都需要設定新的模式來改變預設的模式。這時就可以使用PDOStatement類物件中的setFetchMode()方法,在指令碼頁面的頂部設定一次模式,以後所有fetch()和fetchAll()方法的呼叫都將生成相應引用的結果集,減少了多次在呼叫fetch()方法時的引數錄入
$query = "SELECT uid,name,address,phone,email FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); $stmt->setFetchMode(PDO::FETCH_ASSOC); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; $allRows = $stmt->fetchAll(); foreach($allRows as $row){ echo '<tr>'; echo '<td>'.$row['uid'].'</td>'; echo '<td>'.$row['name'].'</td>'; echo '<td>'.$row['address'].'</td>'; echo '<td>'.$row['phone'].'</td>'; echo '<td>'.$row['email'].'</td>'; echo '</tr>'; } echo '</table>';
bindColumn()
使用該方法可以將一個列和一個指定的變數名繫結,這樣在每次使用fetch()方法獲取各行記錄時,會自動將相應的列值賦給該變數,但必須是在fetch()方法的第一個引數設定為PDO::FETCH_BOTH值時。bindColumn()方法的原型如下所示:
bindColumn(mixed column,mixed $param[,int type]);//設定繫結列值到變數上
第一個引數column為必選項,可以使用整數的列偏移位置索引(索引值從1開始),或是列的名稱字串。第二個引數param也是必選項,需要傳遞一個引用,所以必須提供一個相應的變數名。第三個引數type是可選項,通過設定變數的型別來限制變數值,該引數支援的值和介紹bindParam()方法時提供的一樣
<?php try { //建立物件 $dbh = new PDO("mysql:host=localhost;dbname=testdb", "root", "***"); }catch(PDOException $e) { echo "資料庫連線失敗:".$e->getMessage(); exit; } $query = "SELECT * FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); $stmt->bindColumn(1,$uid); $stmt->bindColumn(2,$name); $stmt->bindColumn(3,$departmentID); $stmt->bindColumn('address',$address); $stmt->bindColumn('phone',$phone); $stmt->bindColumn(6,$email); $stmt->setFetchMode(PDO::FETCH_ASSOC); echo '<table border="1" >'; echo "<th>編號</th>"; echo "<th>姓名</th>"; echo "<th>部門</th>"; echo "<th>地址</th>"; echo "<th>電話</th>"; echo "<th>郵箱</th>"; while($stmt->fetch()){ echo '<tr>'; echo '<td>'.$uid.'</td>'; echo '<td>'.$name.'</td>'; echo '<td>'.$departmentID.'</td>'; echo '<td>'.$address.'</td>'; echo '<td>'.$phone.'</td>'; echo '<td>'.$email.'</td>'; echo '</tr>'; } echo '</table>'; ?>
除了可以通過上面幾種方式獲取資料表中記錄資訊外,還可以使用PDOStatement類物件的columnCount()方法獲取資料表中欄位的數量,並且可以通過PDOStatement類物件的getColumnMeta()方法獲取具體列的屬性資訊
PDOStatement::getColumnMeta
PDOStatement::getColumnMeta — 返回結果集中一列的元資料。引數column表示結果集中以0開始索引的列
array PDOStatement::getColumnMeta ( int $column )
$query = "SELECT * FROM contactInfo"; $stmt = $dbh->prepare($query); $stmt->execute(); echo $stmt->columnCount();//6 /* array (size=7) 'native_type' => string 'INT24' (length=5) 'pdo_type' => int 2 'flags' => array (size=2) 0 => string 'not_null' (length=8) 1 => string 'primary_key' (length=11) 'table' => string 'contactInfo' (length=11) 'name' => string 'uid' (length=3) 'len' => int 8 'precision' => int 0 */ var_dump($stmt->getColumnMeta(0));
大資料物件
在進行專案開發時,有時會需要在資料庫中在儲存“大型”資料。大型物件可以是文字資料,也可以是二進位制的圖片、電影等。PDO允許在bindParam()或bindColumn()呼叫中通過使用PDO::PARAM_LOB型別程式碼來使用大型資料型別。PDO::PARAM_LOB告訴PDO將資料對映為流,所以可以使用PHP中的檔案處理函式來操縱這樣的資料
下面將上傳的影象插入到一個數據庫
$stmt =$dbh->prepare("insert into images(mimetype, data) values(?, ?)"); $stmt->bindParam(1, $_FILES['pic']['type']); $fp = fopen($_FILES['pic']['tmp_name'], "rb"); //直接使用檔案資源就可以入庫,而不用讀出檔案,再插入 $stmt->bindparam(2, $fp, PDO::PARAM_LOB); $stmt->execute(); fclose($fp);
下面從資料庫中讀出一幅影象
$stmt = $dbh->prepare("select mimetype, data from images where id=?"); $stmt -> execute(array(1)); list($mimetype, $data) = $stmt->fetch(PDO::FETCH_NUM); header("Content-Type: {$mimetype}"); echo $data;
相關推薦
PHP基礎知識之————PDO預處理語句
轉載處:http://www.cnblogs.com/xiaohuochai/p/6133353.html 定義 在生成網頁時,許多PHP指令碼通常都會執行除引數之外,其他部分完全相同的查詢語句,針對這種重複執行一個查詢,每次迭代使用不同的引數情況,PDO提供了一種名為預處理語句(prepared st
PHP之PDO預處理語句操作資料庫
前面的話 本來要把預處理語句和前面的基礎操作寫成一篇的。但是,由於部落格園的限制,可能是因為長度超出,儲存時總是報錯,於是再開一篇。另一方面,相較於前面的exec()和query()語句來說,預處理語句更加常用 定義 在生成網頁時,許多PHP指令碼通常
PHP基礎知識之頁面跳轉
一.header指令頁面跳轉 1.header("location:regieter.html");//不友好直接跳轉到那個頁面 2.header("refresh:3;url=register.html");//延遲3秒頁面跳轉 die("非法訪問,請訪問註冊頁面");
【PHP基礎知識】——常用字串處理函式總結
一、概要 我們知道,字串操作是主流web程式語言的基礎,也是在日常開發中不可或缺的一項。PHP處理字串的能力非常強大,方法也是多種多樣。文章列舉了一些PHP中常見的字串處理方法。二、常用字串處理方法 1、判斷一個字串的長度:intstrlen ( string $strin
PHP丨PHP基礎知識之資料型別
PHP的資料型別主要有三大種:(細分的話8小種) 一、標量資料型別 標量資料型別包括以下幾種: (1)BOOLEAN:布林型 布林變數是PHP變數中最簡單的; 它儲存一個TRUE或者FALSE值; 其中TRUE或者FALSE是PHP的內部關鍵字; 設定一個布林型的變數,只需將TRUE或者FALSE賦值給該變數
面向物件,PDO基礎知識,PDO預處理,SQL事務處理
PDO:資料庫抽象層 PDO特點:跨資料庫,支援預處理,支援事務 PDO的基本使用 1,例項化物件 例項化物件( new PDO() ) $pdo=new PDO(引數1,引數2,引數3);
PDO的結果集物件方法、預處理語句、資料庫連線屬性
PDO中的結果集物件方法 方法名 註釋 execute() 執行一條預處理語句 rowCount() 返回上一個SQL語句影響的行數
React基礎知識之Ref回撥函式處理
程式碼地址請在github檢視,如果有新內容,我會定時更新,也歡迎您star,issue,共同進步 1.為DOM元素新增Ref react支援一個ref屬性,該屬性可以新增到任何的元件上。該ref屬性接收一個回撥函式,這個回撥函式在元件掛載或者解除安裝的時候
影象處理基礎知識之二
空域增強技術: 基礎知識1: 定義二維函式f(x,y),其中x,y是空間座標,f(x,y)是點(x,y)的幅值。 灰度影象是一個二維灰度(亮度)函式f(x,y);彩色圖片是由三個二維灰度函式f(x,
Vue:Vue基礎知識之利用v-if、v-else語句控制頁面文字內容的改變
1、v-if、v-else判斷語句例項 v-if='isLogin' //類似 if else v-else v-if:是vue 的一個內部指令,指令用在我們的html中。 v-if用來
基礎知識之php記憶體快取實現程式程式碼
php記憶體快取實現程式程式碼 1、普遍快取技術: 資料快取:這裡所說的資料快取是指資料庫查詢PHP快取機制,每次訪問頁面的時候,都會先檢測相應的快取資料是否存在,如果不存在,就連線資料庫,得到資料,並把查詢結果序列化後儲存到檔案中,以後同樣的查詢結果就直接從快取表或檔案中
PHP的預處理語句的使用
很多更成熟的資料庫都支援預處理語句的概念。什麼是預處理語句?可以把它看作是想要執行的 SQL 的一種編譯過的模板,它可以使用變數引數進行定製。預處理語句可以帶來兩大好處: • 查詢僅需解析(或預處理)一次,但可以用相同或不同的引數執行多次。當查詢準備好後,資料庫將分析、編
算法基礎知識之樹、二叉樹,
pan rect nbsp 結構 src class wiki 子節點 資料 一、樹 把它叫做“樹”是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。在計算機科學中,樹(英語:tree)是一種抽象數據類型(ADT)或是實作這種
算法基礎知識之樹、二叉樹
image inline cstyle width var mar span mes med 一、樹 把它叫做“樹”是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。在計算機科學中,樹(英語:tree)是一種抽象數據類型(AD
python基礎知識之將item寫入JSON文件:
ext self 它的 基礎 string 寫入 lan raw pre pipelines.py import json class xxPipeline(object): def __init__(self): self.filename=ope
scrapy基礎知識之 使用FormRequest.from_response()方法模擬用戶登錄:
imp gin req params level spa 密碼 重寫 start 通常網站通過 實現對某些表單字段(如數據或是登錄界面中的認證令牌等)的預填充 使用Scrapy抓取網頁時,如果想要預填充或重寫像用戶名、用戶密碼這些表單字段, 可以使用 FormRequest
scrapy基礎知識之 pycharm 調試小技巧:
.py 小技巧 char line awl spi cmd 調試 基礎知識 在項目根目錄下新建main.py文件,用於調試 from scrapy.cmdline import executeexecute(["scrapy","crawl","MySpider"])scr
scrapy基礎知識之 RedisCrawlSpider:
span 準備 動態 none efi pytho sel ext import 這個RedisCrawlSpider類爬蟲繼承了RedisCrawlSpider,能夠支持分布式的抓取。因為采用的是crawlSpider,所以需要遵守Rule規則,以及callback不能寫
scrapy基礎知識之 Scrapy-Redis分布式策略:
空間 spider head spi 指紋 負責 edi all redis Scrapy-Redis分布式策略: 假設有四臺電腦:Windows 10、Mac OS X、Ubuntu 16.04、CentOS 7.2,任意一臺電腦都可以作為 Master端 或 Slave
scrapy基礎知識之 關於爬蟲部分一些建議:
限制 支持 結束 攜程 target 經理 框架 實際應用 分享 1.盡量減少請求次數,能抓列表頁就不抓詳情頁,減輕服務器壓力,程序員都是混口飯吃不容易。 2.不要只看 Web 網站,還有手機 App 和 H5,這樣的反爬蟲措施一般比較少。 3.實際應用時候,一般防守方做到