【轉】 PDO使用歸納【PHP】

【任務】將PDO封裝成類

new PDO("mysql:host=localhost;dbname=php100","root","pwd" [,driverOptions]);
如果需要長連接,需要長最後一個參數driverOption:persistent:/aj/持續的,不斷的
new PDO("連接信息","root","pwd",array(PDO::ATTR_PERSISTENT=>true));
使用array()來傳入最後一個參數,是可以帶多個選項值,
如:
$pdo = new PDO('mysql:host=localhost;dbname=forum','root','123456',array(PDO::ATTR_PERSISTENT=>TRUE,PDO::ATTR_CASE=>PDO::CASE_UPPER,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION));
上面分別指定了:長連接開啓,強制PDO獲取的列字符大寫,以及使用PDOException拋出異常。
對於這個屬性參數,也可以用setAttribute來更改,如下:
$pdo->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
那麼接下去就可以用$row['city']來訪問列值,而不必要用$row['CITY']大寫方式來訪問。

PDO常用方法:
PDO::query() 主要用於有記錄結果返回的操作,特別是select操作。
PDO::exec()主要是針對沒有結果集合返回的操作。如insert,update等操作。返回影響行數。
PDO::lastInsertId()返回上次插入操作最後一條ID,但要注意:如果用insert into tb(col1,col2) values(v1,v2),(v11,v22)..的方式一次插入多條記錄,lastinsertid()返回的只是第一條(v1,v2)插入時的ID,而不是最後一條記錄插入的記錄ID。
PDOStatement::fetch()是用來獲取一條記錄。配合while來遍歷。
PDOStatement::fetchAll()是獲取所有記錄集到一箇中。
PDOStatement::fetchcolumn([int column_indexnum]) 用於直接訪問列,參數column_indexnum是該列在行中的從0開始索引值,但是,這個方法一次只能取得同一行的一列,只要執行一次,就跳到下一行。因此,用於直接訪問某一列時較好用,但要遍歷多列就用不上。
PDOStatement::rowcount()適用於當用query("select ...")方法時,獲取記錄的條數。也可以用於預處理中。$stmt->rowcount();
PDOStatement::columncount()適用於當用query("select ...")方法時,獲取記錄的列數。

註解:
1、選fetch還是fetchall?

小記錄集時,用fetchall效率高,減少從數據庫檢索次數,但對於大結果集,用fetchall則給系統帶來很大負擔。數據庫要向WEB前端傳輸量太大反而效率低。
2、fetch()或fetchall()有幾個參數:
mixed pdostatement::fetch([int fetch_style [,int cursor_orientation [,int cursor_offset]]])
array pdostatement::fetchAll(int fetch_style)

fetch_style參數:
■$row=$rs->fetchAll(PDO::FETCH_BOTH); FETCH_BOTH是默認的,可省,返回關聯和索引。
■$row=$rs->fetchAll(PDO::FETCH_ASSOC); FETCH_ASSOC參數決定返回的只有關聯數組。
■$row=$rs->fetchAll(PDO::FETCH_NUM); 返回索引數組
■$row=$rs->fetchAll(PDO::FETCH_OBJ); 如果fetch()則返回對象,如果是fetchall(),返回由對象組成的二維數組,如:
Array
(
    [0] => stdClass Object
        (
            [cityid] => 2
            [city] => 福州
            [countryid] => 1
        )

    [1] => stdClass Object
        (
            [cityid] => 3
            [city] => 廈門
            [countryid] => 1
        )
...
);
遍歷:
foreach($row as $r)
{
echo "{$r->cityid}:城市 {$r->city}.
";
//或echo "{$r[0]}:城市 {$r[1]}.
";
}
■$row=$rs->fetch(PDO::FETCH_LAZY); FETCH_LAZY返回對象:如:
PDORow Object
(
    [queryString] => select * from city
    [cityid] => 2
    [city] => 福州
    [countryid] => 1
)
■ $row = $stmt->fetch(PDO::FETCH_BOUND);用於使fetch返回true,並將獲取的列值賦給bindParam()方法中指定的相應變量。參考最後一個示例。----相當於mysqli綁定到結果。
-----------------------------------------------
例:概要
$rs=$db->query("select * from php100");
while($row = $rs->fetch())
{
print_r($row);
}
或不使用while來遍歷:
$rs=$db->query("select * from php100");
$row=$rs->fetchall();
print_r($row);

$db->exec('insert into ...');
------------------------------------------------
例:select 遍歷記錄和取得記錄總數

try{
$pdo = new PDO("mysql:host=localhost;dbname=forum","root","123456");
}catch(PDOException $e){
echo '連接錯誤:'.$e->errorcode();
}

$q="select * from city";
$rs=$pdo->query($q);
$row=$rs->fetchAll();
foreach($row as $r)
{
echo "{$r['cityid']}:城市 {$r['city']}.
";
//或echo "{$r[0]}:城市 {$r[1]}.
";
}
echo "共有{$rs->rowcount()}條記錄" //$rs->rowcount()返回行數。

返回的數組格式:可以看到,每一組都帶有關聯和索引的兩種形式:
Array
(
    [0] => Array
        (
            [cityid] => 2
            [0] => 2
            [city] => 福州
            [1] => 福州
            [countryid] => 1
            [2] => 1
        )

    [1] => Array
        (
            [cityid] => 3
            [0] => 3
            [city] => 廈門
            [1] => 廈門
            [countryid] => 1
            [2] => 1
        )
)

如果用:while($row = $rs->fetch()){ print_r($row);}
while返回的每一個數組格式是:
Array
(
    [cityid] => 2
    [0] => 2
    [city] => 福州
    [1] => 福州
    [countryid] => 1
    [2] => 1
)
可以看到:
$rs->fetch()一次返回一個,
$rs->fetchAll()一次返回所有的記錄,
兩者相同的是:都可以用索引數組或關聯數組來取得最終字段值,
兩者不同的是,fetchAll()返回的是二維數組。可以用foreach遍歷。

-----------------------------
例:插入記錄
$affectedrows = $pdo->exec("insert into city(cityid,city,countryid) values(NULL,'北京',2),(NULL,'南京',2)");
echo '共影響行數:'.$affectedrows.'
';
echo '最後插入的記錄ID爲:'.$pdo->lastinsertid();
這裏當用insert into city(cityid,city,countryid) values(NULL,'北京',2)時,返回的正確的ID值,但按上例的方法插入多條記錄,則返回的依舊是北京那一條記錄的ID,解決辦法是把這個值 lastinsertid()+行數-1。

------------------------------
例:返回exec或query錯誤
把上例的insert隨便改一個,使插入錯誤,再加上一行:
print_r($pdo->errorinfo());
返回:數組0表示存儲SQL標準中定義的SQLSTATE碼。1表示錯誤碼,0表示錯誤消息,這裏是指city表插入的外鍵在country表中不存在。
Array
(
    [0] => 00000
    [1] => 1452
    [2] => Cannot add or update a child row: a foreign key constraint fails (`forum`.`city`, CONSTRAINT `FK_city_country` FOREIGN

KEY (`countryid`) REFERENCES `country` (`country_id`))
)

***************************************************************
PDO的預處理:準備語句

0、連接:$pdo = new PDO(....);
1、準備:查詢和mysqli的方式不同,支持兩種參數佔位方式:問號參數“?”命名參數“:字段名”;命名參數更明確。
     $q="insert into city(city,countryid) values(?,?)"; //或$q = "insert into city(city,countryid) values(:city,:countryid)";
     $stmt = $pdo->prepare($q);
2、執行execute:$pdo->lastinsertid();對預處理也是可用的。
   有兩種方式:注意兩種方式用“?”問號參數綁定時有不同的execute佔位引用方式。並且偏移基數不同。
    (1)顯式地把參數值做爲參數傳給execute: boolean PDOSTatement::execute([array input_parameters])
命名參數方式:
        $q = "insert into city(city,countryid) values(:city,:countryid)";
        $stmt = $pdo->prepare($q);
        $stmt->execute(array(':city'=>'太原',':countryid'=>'2'));//本條可多次執行。注意,countryid是數值型,但也要用單引號來包住。
問號參數:
      $q = "insert into city(city,countryid) values(?,?)";
      $stmt = $pdo->prepare($q);
      $stmt->execute(array('0'=>'武漢','1'=>'2')); //注意這裏不是用'?'的方式,而是用上面佔位符的從0開始的索引偏移,

    (2)綁定參數。boolean PDOSTatement::bindParam(mixed parameter,mixed &variable [,int datatype [,int length [,mixed driver_option]]])
       mixed parameter 是佔位符,當用?問號參數時,parameter是佔位符的從1開始的索引偏移,而不是‘?’,這和MYSQLI的預處理不相同。

       variable是綁定的變量值
datatype有以下幾種類型:
         PDO_PARAM_BOOL 布爾類型。
         PDO_PARAM_input_output 參數傳給存儲過程時使用此類型,可以在過程執行後修改。
         PDO_PARAM_INT 整型。
         PDO_PARAM_NULL NULL類型。
         PDO_PARAM_LOG   大對象類型。
         PDO_PARAM_STMT   PDO對象類型,當前不可操作。
         PDO_PARAM_STR   char,varchar和其它字符串類型。
length指定數據類型長度。只有當賦爲PDO_PARAM_input_output類型時才需要此參數。
driver_option用來傳遞任何數據庫驅動程序特定的選項。
   如:
       $q = "insert into city(city,countryid) values(?,?)";
       $stmt = $pdo->prepare($q);

       $city='大連';
       $country=1;
       $stmt->bindparam(1,$city); //注意這裏parameter不是用“'?'”方式。並且從1開始偏移。
       $stmt->bindparam(2,$country);

       $stmt->execute();

---------------------
預處理的綁定列:
boolean PDOStatement::bindcolum(mixed column_index,mixed &param [,int type [,int maxlen[,mixed driver_options]]]);
參數column_index是要綁定的行中列偏移,從1開始。當然也可以用列名。type就用來設置類型限制變量值,如PDO::PARAM_STR是限制文本,具體參bindParam()。通過maxlen限制其長度。
try{
$pdo = new PDO("mysql:host=localhost;dbname=forum","root","123456");
}catch(PDOException $e){
echo '連接錯誤:'.$e->errorcode();
}

$q="select * from city";
$stmt=$pdo->prepare($q);
$stmt->execute();
$rscount=$stmt->rowcount(); //總記錄數

$stmt->bindcolumn(1,$cityid);
$stmt->bindcolumn('city',$city,PDO::PARAM_STR,1);
$stmt->bindcolumn(2,$countryid);

for($i=1;$i<=$rscount;$i++)
{
   $row = $stmt->fetch(PDO::FETCH_BOUND);
   printf("%s 的ID是: %s ",$city,$cityid);
   echo '


';
}

**********************************************************
用PDO處理事務:
PDO->__construct()方法的作用是建立一個PDO鏈接數據庫的實例。  
PDO->beginTransaction(),PDO->commit(),PDO->rollBack()這三個方法是在支持回滾功能時一起使用的。PDO->beginTransaction()方法標明起始點,PDO->commit()方法標明回滾結束點,並執行SQL,PDO->rollBack()執行回滾。  
<?php  
try {  
    $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', '');  
    $dbh->query('set names utf8;');  
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  
$dbh->beginTransaction();
    $dbh->exec("INSERT INTO `test`.`table` (`name` ,`age`)VALUES ('mick', 22);");  
    $dbh->exec("INSERT INTO `test`.`table` (`name` ,`age`)VALUES ('lily', 29);");  
    $dbh->exec("INSERT INTO `test`.`table` (`name` ,`age`)VALUES ('susan', 21);");  
$dbh->commit();  
} catch (Exception $e) {  
$dbh->rollBack();
    echo "Failed: " . $e->getMessage();  
}  
?>

更多屬性和詳細介紹參:http://hi.baidu.com/traindiy/blog/item/06fd2b3f204fdce755e7232d.html

另,參考:http://hi.baidu.com/traindiy/blog/item/c3ff98453ec873348694732c.html
http://hi.baidu.com/traindiy

發佈了149 篇原創文章 · 獲贊 6 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章