久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術(shù)文章
文章詳情頁

PHP 5 數(shù)據(jù)對象 (PDO) 抽象層與 Oracle

瀏覽:7日期:2024-01-29 16:40:07

一名新 PHP 數(shù)據(jù)對象 (PDO) 數(shù)據(jù)抽象層的原始開發(fā)人員為您簡要介紹該抽象層,重點(diǎn)講述與 Oracle 一起運(yùn)行的情況。

需要 PHP:5.0需要其他:Oracle 8 或更高版本客戶端庫下載用于 Oracle 的 PDO (Windows):php_pdo.dll, php_pdo_oci.dll下載用于 Oracle 的 PDO (Unix):pdo, pdo_oci

PDO 簡介

PHP 主要是由志愿者完成的項(xiàng)目;盡管有少數(shù)一些固定的“核心”開發(fā)人員,但是我們沒有一個(gè)人在全職受薪的開發(fā) PHP。除此之外,我們分別位于世界不同地方,您可以想象長期開發(fā)的協(xié)調(diào)工作是何等困難。因此,PHP 主要是基于突發(fā)奇想的個(gè)人短期需求來發(fā)展的,其原因也多種多樣,有的是試驗(yàn),有的則是因?yàn)椤懊魈煊谢钜弧薄1M管這樣通常每一步都會改善 PHP,但從長遠(yuǎn)來看則是缺乏完整性 - 數(shù)據(jù)庫擴(kuò)展就是一個(gè)重要的例子。

在各種不同的數(shù)據(jù)擴(kuò)展(oci、mysql、postgresql、mssql 等)之間根本沒有真正的一致性,甚至在某些情況下,在這些擴(kuò)展內(nèi)部也沒有真正的一致性。幾乎所有這些擴(kuò)展都在使用與基礎(chǔ)數(shù)據(jù)庫 API 緊密相連的不同代碼完成著相同種類的任務(wù)。而且因?yàn)槲覀儯≒HP 核心開發(fā)人員和擴(kuò)展開發(fā)人員)的人手非常有限,因此這就造成了代碼更加難以維護(hù),從而為 PHP 帶來了很大的問題。

由于 PHP 越來越受歡迎并不斷成功,因此主要 PHP 數(shù)據(jù)庫擴(kuò)展的維護(hù)者們參加了在德國舉行的 LinuxTag 2003 大會,在會上我們交換了對 PHP 前景的看法。在討論 PHP 發(fā)展的隨機(jī)性時(shí),我們確定了在 PHP 中進(jìn)行數(shù)據(jù)庫訪問的一些目標(biāo):

·提供一種輕型、清晰、方便的 API ·統(tǒng)一各種不同 RDBMS 庫的共有特性,但不排除更高級的特性。 ·通過 PHP 腳本提供可選的較大程度的抽象/兼容性。

我們之所以提出了這種 PHP 數(shù)據(jù)對象 (PDO) 的概念,是因?yàn)槲覀兿Mㄟ^采用 Zend Engine 2(PHP 5 的核心)先進(jìn)的面向?qū)ο筇匦垣@得該 API 的一些更優(yōu)秀的性能。

PHP 中的數(shù)據(jù)抽象層概念一點(diǎn)都算不上新;在 Google 中查詢“PHP database abstraction”會找到大約 83,200 個(gè)匹配項(xiàng)。它幾乎是許多 PHP 開發(fā)人員夢寐以求的,而其產(chǎn)生則部分歸因于我們不完整的 API。如果您曾經(jīng)嘗試過使用第三方抽象層來完成任何真正重要的工作,通常會發(fā)現(xiàn)這些抽象層對于手頭的工作來說設(shè)計(jì)的功能過于強(qiáng)大了 - 或者表現(xiàn)為在使用前需要進(jìn)行大量學(xué)習(xí),或者表現(xiàn)為接口速度緩慢,參數(shù)需要經(jīng)過多層腳本函數(shù)調(diào)用才能到達(dá)數(shù)據(jù)庫自有的 API;通常是存在上述兩種表象。

為什么這些抽象層會存在這種問題?這些抽象層總是在試圖完成太多的任務(wù),甚至可能是不可能的任務(wù)。我們決定以實(shí)用為目標(biāo),僅將一些最常見的數(shù)據(jù)庫 API 特性作為我們的基礎(chǔ),并使得 PDO 驅(qū)動程序能夠?qū)⑺鼈兲囟ㄓ诋a(chǎn)品的特性暴露為常規(guī)擴(kuò)展函數(shù)。

為什么使用 PDO?

聽過有關(guān)數(shù)據(jù)庫抽象擴(kuò)展謠傳的大多數(shù)人會立刻對 PDO 的擴(kuò)展方面產(chǎn)生疑惑 - 我們是否要分析 SQL,將其轉(zhuǎn)換為相應(yīng)的后端方言呢?我們?nèi)绾翁幚硖匦?X 或特性 Y,等等。因此,當(dāng)您聽說我們在 PDO 中根本不用為此而擔(dān)憂時(shí)可能會大吃一驚;我們不希望使所有內(nèi)容都完全統(tǒng)一,因?yàn)橐沟眠@種統(tǒng)一成為可能,只能是將自己限制在最低的通用標(biāo)準(zhǔn)。

如果 PDO 不是一個(gè)整體的抽象層,那還有什么別的原因值得您考慮使用它嗎?

·性能。PDO 從一開始就吸取了現(xiàn)有數(shù)據(jù)庫擴(kuò)展成功和失敗的經(jīng)驗(yàn)教訓(xùn)。因?yàn)?PDO 的代碼是全新的,所以我們有機(jī)會重新開始設(shè)計(jì)性能,以利用 PHP 5 的最新特性。 ·能力。PDO 旨在將常見的數(shù)據(jù)庫功能作為基礎(chǔ)提供,同時(shí)提供對于 RDBMS 獨(dú)特功能的方便訪問。 ·簡單。PDO 旨在使您能夠輕松使用數(shù)據(jù)庫。API 不會強(qiáng)行介入您的代碼,同時(shí)會清楚地表明每個(gè)函數(shù)調(diào)用的過程。 ·運(yùn)行時(shí)可擴(kuò)展。PDO 擴(kuò)展是模塊化的,使您能夠在運(yùn)行時(shí)為您的數(shù)據(jù)庫后端加載驅(qū)動程序,而不必重新編譯或重新安裝整個(gè) PHP 程序。例如,PDO_OCI 擴(kuò)展會替代 PDO 擴(kuò)展實(shí)現(xiàn) Oracle 數(shù)據(jù)庫 API。還有一些用于 MySQL、PostgreSQL、ODBC 和 Firebird 的驅(qū)動程序,更多的驅(qū)動程序尚在開發(fā)。

您可能想了解 PDO 與其他常用的抽象層的對比情況,例如 PEAR DB 或 ADODB。無論在 API 方面還是在性能方面,PDO 都比其他常見抽象層要輕型,但是涉及到在各個(gè)數(shù)據(jù)庫后端之間提供統(tǒng)一性方面,則不如那些抽象層,例如用于處理大量可移植性問題的 PEAR MDB 2 抽象層。

在哪里可以獲得 PDO?

PDO 是通過 PECL(發(fā)音為“pee-kle”,歐洲語言風(fēng)格),即 PHP 擴(kuò)展庫提供的。如果您在運(yùn)行 Linux 計(jì)算機(jī),請按照下面的說明進(jìn)行設(shè)置;稍后是在 Windows 上安裝的詳細(xì)信息。

請注意,PDO 及其驅(qū)動程序當(dāng)前處于“alpha”狀態(tài);這就意味著我們會合理保證沒有重大缺陷,但是該程序包功能并不完善 - 我們還要添加很多功能。雖然我們鼓勵(lì)您測試該程序包,但是實(shí)在不推薦在現(xiàn)階段將其用于生產(chǎn)。

Unix/Linux 安裝

如果您以前尚未嘗試過 PHP 5,則請花一點(diǎn)時(shí)間來通讀一下“新聞”和各種聲明。在 UNIX 計(jì)算機(jī)上,您可能要安裝或升級 libxml2;如果沒有 libxml2,“pear”程序包管理工具就無法運(yùn)行,您安裝 PDO 時(shí)就會遇到很多困難。獲取 PHP 5,并將其編譯和安裝。確保指定的前綴不是 /usr/local/,這樣它就不會與 PHP 4 安裝發(fā)生沖突了:

% ./configure --prefix=/usr/local/php5 --with-zlib [此處指定其他選項(xiàng)]% make install

現(xiàn)在您就可以使用“pear”工具獲取并安裝 PDO 以及用于 PDO 的 Oracle 驅(qū)動程序了。因?yàn)?PDO 當(dāng)前標(biāo)記為 alpha,所以默認(rèn)情況下 pear 工具不會下載該程序包。在該程序包名稱后面添加后綴“-alpha”,通知該 pear 工具可以安裝 alpha 版本:

% PATH='/usr/local/php5/bin:$PATH'% pear install PDO-alpha

您需要告知 PHP 從專用于 PHP 5 的 php.ini 文件加載 PDO 驅(qū)動程序。如果您使用的前綴與我使用的一樣,PHP 則會在 /usr/local/php5/lib/php.ini 中查找 php.ini 文件。向該文件中添加以下行:

extension=pdo.so

現(xiàn)在您需要獲取數(shù)據(jù)庫特定的驅(qū)動程序;對于 Oracle,此特定程序稱為 PDO_OCI。在 shell 中,鍵入:

% pear install PDO_OCI-alpha

此驅(qū)動程序也需要從 php.ini 文件加載;將下行添加到前面添加的那行之后:

extension=pdo_oci.so

現(xiàn)在檢查一下,確保它能夠運(yùn)行:

% php -m

在模塊列表中,您應(yīng)該會看到 PDO 和 PDO_OCI。

防火墻礙事了?

如果您位于防火墻的后面,則在使用 pear 安裝程序獲取程序包時(shí)可能會遇到一些問題。如果發(fā)生這種情況,則可以按照下列說明手動下載并安裝這些程序包:

% wget http://pecl.php.net/get/PDO% pear install PDO-0.1.1.tgz

[ 將 extension=pdo.so 添加到 php.ini ]

% wget http://pecl.php.net/get/PDO_OCI% pear install PDO_OCI-0.1.tgz

[ 將 extension=pdo_oci.so 添加到 php.ini ]

在上述兩種情況下,都需要首先調(diào)用“pear install”(后跟下載的真正程序包);上述示例中的版本號在本文編寫之時(shí)是最新的,但隨著開發(fā)的繼續(xù)進(jìn)行會發(fā)生變化。

Windows 安裝

如果您正在運(yùn)行 Windows,則請按照下列說明執(zhí)行:

·從 http://www.php.net/downloads.php#v5 獲取 PHP 5,將其解壓縮到 C:php5。 ·從 http://snaps.php.net/win32/PECL_5_0/php_pdo.dll 和http://snaps.php.net/win32/PECL_5_0/php_pdo_oci.dll 分別獲取 PDO 和 PDO_OCI,將其放入 C:php5ext。或者,您可以從 PHP 5 下載頁上列出的“用于 PHP 5.0.0 的 PECL 模塊集合”zip 文件中找到所有這些 PDO 驅(qū)動程序,以及所有 PECL 程序包的所有 Windows 版本。 ·編輯 C:php5php.ini 文件,并添加下列內(nèi)容:

extension=php_pdo.dllextension=php_pdo_oci.dll

編輯 php.ini 文件時(shí),有一點(diǎn)很重要,即要在任何其他 PDO 驅(qū)動程序之前先加載 PDO 擴(kuò)展,否則就不能正確初始化(在這種情況下會出錯(cuò))。

如果在 Windows 目錄中有一個(gè) PHP 4 的全局 php.ini 文件,則可能會遇到問題。最好的解決方法是,移動該 php.ini 文件,使其與 PHP 4 SAPI 位于相同的文件夾中,以隔離 PHP 4 安裝;例如,將其移動到與 php4apache.dll 相同的文件夾中。請注意,PHP 5 程序中并非所有文檔都是最新的;推薦的安裝過程如上面所述 - 如 install.txt 文件所聲明的,請勿將任何 DLL 復(fù)制到 windows 文件夾或 system 文件夾中 - 任何內(nèi)容都是自包含的。如果您運(yùn)行的是 apache,并且遇到無法加載 DLL 的錯(cuò)誤,則檢查一下是否將 C:php5 添加到了 PATH 中。另外,還要注意 PHP 5 的 CGI 版本現(xiàn)在的名稱為 php-cgi.exe。

連接 PDO

首先創(chuàng)建 PDO 類的一個(gè)實(shí)例,將其用作數(shù)據(jù)庫句柄。使用哪個(gè)基礎(chǔ)驅(qū)動程序并不重要;您總要使用 PDO 類名。構(gòu)造函數(shù)的第一個(gè)參數(shù)為數(shù)據(jù)源名稱 (DSN),第二個(gè)參數(shù)為用戶名,第三個(gè)參數(shù)為該用戶名的口令。DSN 的 PDO 命名慣例為 PDO 驅(qū)動程序的名稱,后面一個(gè)冒號,再后面是可選的驅(qū)動程序特定的信息。在我們的示例中,會加載 OCI 驅(qū)動程序但不指定任何其他信息;這樣會使用默認(rèn)的數(shù)據(jù)庫。對于其他驅(qū)動程序,如 ODBC 驅(qū)動程序,第一個(gè)冒號后面的所有內(nèi)容都將被用作 ODBC DSN。MySQL 驅(qū)動程序會同樣以不同的方式解釋它的 DSN。

如果無法加載該驅(qū)動程序,或者發(fā)生了連接失敗,則會拋出一個(gè) PDOException,以便您可以決定如何最好地處理該故障。

<?phptry {$dbh = new PDO('OCI:', 'scott', 'tiger');} catch (PDOException $e) {echo 'Failed to obtain database handle ' .$e->getMessage(); }?>

在連接字符串中,您可以指定兩個(gè)可選參數(shù);第一個(gè)是數(shù)據(jù)庫名稱,第二個(gè)是字符集;這些參數(shù)與可選的第三個(gè)和第四個(gè)參數(shù)相對應(yīng),后兩個(gè)參數(shù)您可能在 oci8 擴(kuò)展函數(shù) ociconnect() 或 ociplogon() 中使用過。要使用特定的字符集連接一個(gè)特定的數(shù)據(jù)庫,則可以執(zhí)行下列操作:

<?phptry {$dbh = new PDO('OCI:dbname=accounts;charset=UTF-8', 'scott', 'tiger');} catch (PDOException $e) {echo 'Failed to obtain database handle ' .$e->getMessage(); }?>

省略 try..catch 控制結(jié)構(gòu)并無裨益。如果在應(yīng)用程序的較高級別沒有定義異常處理,則在無法建立數(shù)據(jù)庫連接的情況下,該腳本會終止。

連接管理

目前,PDO 完全沒有執(zhí)行自己的任何連接管理,因此每個(gè)“新 PDO”調(diào)用都會建立一個(gè)新的數(shù)據(jù)庫連接。該連接在 $dbh 變量越界時(shí),或者當(dāng)您為其指定 NULL 值時(shí)會被釋放。

<?phptry {$dbh = new PDO('OCI:dbname=accounts;charset=UTF-8', 'scott', 'tiger');} catch (PDOException $e) {echo 'Failed to obtain database handle ' .$e->getMessage();exit; }// 在此處對數(shù)據(jù)庫執(zhí)行一些操作 // ... // 現(xiàn)在完成,釋放該連接$dbh = null;?>

計(jì)劃在不久的將來為 PDO 增加連接緩存功能;就當(dāng)前的 oci8 擴(kuò)展而言,會重用與現(xiàn)有服務(wù)器的連接,并且在這些連接中,還會重用閑置的登錄。當(dāng)在緩存連接模式中運(yùn)行時(shí),如上面的代碼段所示釋放 $dbh 時(shí)會將該登錄標(biāo)記為可由其他連接重用。

如果您使用 ODBC 驅(qū)動程序訪問 Oracle,則可能會很高興地注意到,默認(rèn)情況下 PDO_ODBC 驅(qū)動程序支持 ODBC 連接池。

使用 PDO

了解一個(gè)編程 API 的最好方式就是使用它,因此我們來看一下附帶的這個(gè)演示,以了解如何進(jìn)行批次更新(代碼如下)。

<?php

// Create a PDO database handle object// the 'oci:' string specifies that the OCI driver should be used// you could use 'oci:dbname=name' to specify the database name.// The second and third parameters are the username and password respectively$dbh = new PDO('oci:', 'scott', 'tiger');

// Create a test table to hold the data from credits.csv$dbh->exec('CREATE TABLE CREDITS (extension varchar(255),name varchar(255))');

// start a transaction$dbh->beginTransaction();

// prepare to insert a large quantitiy of data$stmt = $dbh->prepare('INSERT INTO CREDITS (extension, name) VALUES (:extension, :name)');

// bind the inputs to php variables; specify that the data will be strings// with a maximum length of 64 characters$stmt->bindParam(':extension',;$extension,;PDO_PARAM_STR, 64);$stmt->bindParam(':name', ;;$name,;;PDO_PARAM_STR, 64);

// Open the .csv file for import$fp = fopen('credits.csv', 'r');while (!feof($fp)) {list($extension, $name) = fgetcsv($fp, 1024);$stmt->execute();}fclose($fp);

// Commit the changes$dbh->commit();

?>

既然我們已經(jīng)成功連接到了 Oracle,那么現(xiàn)在就可以創(chuàng)建一個(gè)表來保存一些數(shù)據(jù)了。對于此示例,我們使用一些 PHP 擴(kuò)展及其作者,并將這些內(nèi)容輸入一個(gè)數(shù)據(jù)庫中。數(shù)據(jù)庫句柄對象的 exec() 方法可用來發(fā)出不會返回結(jié)果集的快速一次性查詢,因此我們在這里使用該方法來發(fā)出 CREATE TABLE 查詢。

為了使得示例更自然,我從 PHP 源代碼中抽取了擴(kuò)展及其作者的信息,并將其存儲到了一個(gè) CSV 文件中(請參見“相關(guān)附件:credits.csv”)。這就代表一個(gè)常見情形:從 CSV 文件批次導(dǎo)入數(shù)據(jù)。在我們的示例中,我們充分利用了 Oracle 的預(yù)處理語句和綁定參數(shù),以獲得一個(gè)高效的數(shù)據(jù)導(dǎo)入腳本。在講述該示例之前,有必要了解一下 PDO 處理事務(wù)的方式。

PDO 中的事務(wù)處理

Oracle 具有一個(gè)敏感的默認(rèn)操作模式:當(dāng)您進(jìn)行連接時(shí),將會位于一個(gè)隱式事務(wù)處理中,在提交事務(wù)之前其中的更改不會完全生效。除了事務(wù)處理的標(biāo)準(zhǔn)優(yōu)點(diǎn)(原子性、一致性、隔離性、可持久性 - ACID)之外,數(shù)據(jù)庫服務(wù)器在執(zhí)行每次更新之后還不需要重新構(gòu)建索引和其他內(nèi)部結(jié)構(gòu);它可以延遲到提交之后進(jìn)行。這樣會加速代碼的執(zhí)行。Oracle 這點(diǎn)確實(shí)很好。

但不幸的是,并非每個(gè)數(shù)據(jù)庫供應(yīng)商都支持事務(wù)處理,并且因?yàn)?PDO 旨在以一種相對可移植的方式支持這些事務(wù)處理,所以它默認(rèn)情況下以自動提交模式運(yùn)行。啟用自動提交模式后,數(shù)據(jù)庫驅(qū)動程序會隱式提交每個(gè)成功的更新。當(dāng)您調(diào)用 $dbh->beginTransaction() 時(shí),就會請求關(guān)閉自動提交,直到調(diào)用 $dbh->commit() 或者 $dbh->rollBack() 才會重新啟用,具體取決于您的代碼是怎樣編寫的。如果基礎(chǔ)驅(qū)動程序不支持事務(wù)處理,則會拋出一個(gè) PDOException。

如果發(fā)生了問題并且 PHP 出錯(cuò),您的腳本將退出并且事務(wù)處于待批狀態(tài);或者您關(guān)閉數(shù)據(jù)庫句柄時(shí),PDO 會自動針對任何待批的事務(wù)調(diào)用 $dbh->rollBack()。此行為會減少向數(shù)據(jù)庫中提交可能未定義或者已損壞數(shù)據(jù)的可能性,這是用于處理已放棄事務(wù)的標(biāo)準(zhǔn)語義。

預(yù)處理語句、存儲過程

PDO 支持使用 Oracle 樣式命名的占位符語法將變量幫定到 SQL 中的預(yù)處理語句(與 oci8 擴(kuò)展中的 ocibindbyname() 類似)。PDO 還為其他數(shù)據(jù)庫(如 ODBC)提供了命名占位符模擬,甚至可以為生來就不支持該概念的數(shù)據(jù)庫(如 MySQL)模擬預(yù)處理語句和綁定參數(shù)。這是 PHP 向前邁進(jìn)的積極一步,因?yàn)檫@樣可以使開發(fā)人員能夠用 PHP 編寫“企業(yè)級”的數(shù)據(jù)庫應(yīng)用程序,而不必特別關(guān)注數(shù)據(jù)庫平臺的能力。

使用 PDO 預(yù)處理語句非常簡單,調(diào)用數(shù)據(jù)庫句柄的 prepare() 方法即可。它會返回一個(gè)語句句柄對象,然后您可以使用該對象來綁定參數(shù)和執(zhí)行語句。在此示例中,我們將要定義兩個(gè)命名占位符,“:extension”和“:name”,這兩個(gè)占位符分別與 .CSV 文件中的 PHP 擴(kuò)展名稱和其中一個(gè)作者的姓名相對應(yīng)。

$stmt = $dbh->prepare('INSERT INTO CREDITS (extension, name) VALUES (:extension, :name)');

預(yù)處理了語句之后,我們使用 bindParam() 方法來將這些命名參數(shù)分別與 PHP 變量名稱“$extension”和“$name”相關(guān)聯(lián)(這與 ocibindbyname() 類似)。我們還會通知 Oracle,這些數(shù)據(jù)將要格式化為字符串,最大長度為 64 個(gè)字符。

$stmt->bindParam(':extension', $extension, PDO_PARAM_STR, 64);$stmt->bindParam(':name',;;;$name,;;;PDO_PARAM_STR, 64);

我們現(xiàn)在即準(zhǔn)備好插入數(shù)據(jù)了 - 我們只需要打開該 CSV 文件,并從中獲取數(shù)據(jù)即可。通過使用 fopen() 和 fgetcsv() 函數(shù)可以相當(dāng)簡單地完成此操作。然后,我們可以使用 PHP list() 構(gòu)造函數(shù)直接將 CSV 的列指定給變量“$extension”和“$name”。因?yàn)檫@些變量已經(jīng)綁定到了語句中,所以我們現(xiàn)在要做的只是調(diào)用該語句對象的 execute() 方法使其執(zhí)行插入。這種方式既方便又快捷 - 在事務(wù)處理時(shí)每個(gè)迭代循環(huán)只有兩行。到達(dá)文件尾時(shí),我們就可以立即使用數(shù)據(jù)庫句柄的 commit() 方法來提交這些更改了。

如果您只是要傳遞輸入?yún)?shù),并且有許多這樣的參數(shù)要傳遞,那么您會覺得下面所示的快捷方式語法非常有幫助;此語法使您能夠省去對 $stmt->bindParam() 的調(diào)用。

$stmt = $dbh->prepare('INSERT INTO CREDITS (extension, name) VALUES (:extension, :name)');$stmt->execute(array(':extension' => $extension, ':name' => $name));

您還可以使用 bindParam 來為存儲過程設(shè)置輸入/輸出參數(shù);語法是完全相同的,只是查詢有所不同。下面的代碼演示如何調(diào)用一個(gè)名為“sp_add_item”的存儲過程;其目的是要針對輸入設(shè)置 $item_name,然后該存儲過程將在返回時(shí)更新 $error_code。

$stmt = $dbh->prepare('begin sp_add_item(:item_name, :error_code); end');$stmt->bindParam(':item_name', $item_name, PDO_PARAM_STR,; 12);$stmt->bindParam(':error_code', $error_code, PDO_PARAM_STR, 12);$stmt->execute();

抓取數(shù)據(jù)

使用 PDO 抓取數(shù)據(jù)與進(jìn)行插入或更新相似,只是您執(zhí)行完查詢之后,將要重復(fù)調(diào)用 fetch() 方法來獲取結(jié)果集的下一行。進(jìn)行獲取的最簡單情況如下所示,值得注意的一點(diǎn)是,您還可以將參數(shù)綁定到查詢,以控制如 WHERE 子句這樣的內(nèi)容;執(zhí)行此操作的語法與我們已經(jīng)看到的 bindParam() 代碼完全相同。

$stmt = $dbh->prepare('SELECT extension, name from CREDITS');if ($stmt->execute()) {while ($row = stmt->fetch()) {print_r($row); }}

PDO 支持一些不同的抓取策略,這些策略在方便性和性能方面有所差別;通過將下列選項(xiàng)之一指定為 fetch() 方法的參數(shù),您可以更改其返回值以適應(yīng)您的語法:

·PDO_FETCH_NUM - 每個(gè)行抓取返回一個(gè)按照列位置索引的數(shù)組,并且以 0 為基數(shù)(第一列是第 0 個(gè)元素)。

while ($row = $stmt->fetch(PDO_FETCH_NUM)) {printf('Extension %s, by %s<br>', $row[0], $row[1]);}

·PDO_FETCH_ASSOC - 每個(gè)行抓取根據(jù)行集中的列名,返回一個(gè)按列名索引的數(shù)組。

while ($row = $stmt->fetch(PDO_FETCH_ASSOC)) {echo 'Extension $row[EXTENSION] by $row[NAME]<br>';}

·PDO_FETCH_BOTH - 每個(gè)行抓取返回一個(gè)既按照列位置又按照列名索引的數(shù)組。也就是上述兩種情況的直接組合。如果沒有指定抓取模式,則該模式為默認(rèn)模式。 ·PDO_FETCH_OBJ - 每個(gè)行抓取返回一個(gè)匿名對象,其屬性名與列名對應(yīng)。

while ($row = $stmt->fetch(PDO_FETCH_ASSOC)) {echo 'Extension {$row->EXTENSION} by {$row->NAME}<br>';}

·PDO_FETCH_LAZY - 每個(gè)行抓取返回一個(gè)引用語句對象的重載對象。這“看起來”好像是 PDO_FETCH_OBJ 和 PDO_FETCH_BOTH 的組合,只是只有當(dāng)您在腳本中訪問 PHP 變量時(shí)才創(chuàng)建這些變量。 ·PDO_FETCH_BOUND - 抓取每行,返回 TRUE。在使用綁定輸出列時(shí)這種方式非常有用,它可以避免創(chuàng)建不需要的任何數(shù)組或?qū)ο蟆#ㄕ垍⒁娤旅娴氖纠?

無論您使用哪種抓取策略,當(dāng)沒有其他行可抓取時(shí),fetch() 方法將會返回 FALSE。

現(xiàn)在我要講述一些技巧,如果您需要最后再調(diào)整一下腳本性能的話,這些技巧可能會對您有所幫助。但先給你一個(gè)忠告:要像躲避瘟疫一樣避免不成熟的優(yōu)化。您應(yīng)該總是首選最清晰、可維護(hù)性最好的解決方案。請記住,在一個(gè)典型的 Web 應(yīng)用程序中,您不能衡量各種抓取模式間的區(qū)別,除非腳本要處理很多行。我再重復(fù)一遍:抓取模式間的性能區(qū)別非常小 - 請使用最適合您代碼的模式。

請記住,使用 PDO_FETCH_NUM 的花銷最小,因?yàn)樵L問列數(shù)據(jù)只是一個(gè)簡單的數(shù)值查詢。PDO_FETCH_OBJ 使您能夠使用 OO 語法將數(shù)據(jù)集的列作為對象的屬性來訪問,但是每個(gè)屬性訪問都涉及一個(gè)附加的散列查詢,使得使用它的花銷基本上與 PDO_FETCH_ASSOC 相同。每個(gè)這樣的模式都會復(fù)制整行,從而占用稍多的內(nèi)存。

很多數(shù)據(jù)庫驅(qū)動程序都會代表您預(yù)先抓取并緩存一定數(shù)量的行。PHP 每次訪問其中一個(gè)這樣行中的列時(shí),它都需要將其復(fù)制到自己的專用內(nèi)存區(qū)域中。如果您的查詢涉及很多行,而只需要基于某種復(fù)雜的邏輯訪問給定行的特定列,則您會發(fā)現(xiàn) PDO_FETCH_LAZY 是一種避免使用很多內(nèi)存的有用方法,因?yàn)樗挥性谀L問給定列時(shí)才復(fù)制該列。使用此方式時(shí)要注意,從某個(gè)給定語句為每個(gè) fetch() 抓取的“惰性對象”是每次迭代時(shí)使用的同一對象(以減少每次創(chuàng)建/銷毀它的開銷)。這就暗示著您不能只是簡單地存儲該對象用于以后的比較,因?yàn)樗匀粫迷撜Z句的當(dāng)前行 - 您需要手動復(fù)制所需要的部分。

最后一種模式為 PDO_FETCH_BOUND,該模式會告知 PDO 您已經(jīng)將所有列綁定到了 PHP 變量,并且除了要它在到達(dá)行集的末尾時(shí)通知您外不需要它執(zhí)行別的任何操作。綁定輸出列在概念上與綁定輸入?yún)?shù)相似,只是綁定輸出列可以用于所有數(shù)據(jù)庫驅(qū)動程序。您可以將 PHP 變量綁定到命名列,PDO 將在每次調(diào)用 execute() 時(shí)對其進(jìn)行更新。此技術(shù)可用來剃去結(jié)果集中每列、每行的一些虛擬機(jī)器操作碼(這種代碼速度比原生碼要慢)。這種技術(shù)的缺點(diǎn)在于,可能會使您的代碼難以跟蹤(也稱為 WTF 系數(shù)較高),您使用變量名稱時(shí)需要倍加小心。下面的代碼說明了綁定輸出列的使用。請注意,您不必指定 PDO_FETCH_BOUND 即可使用 $stmt->bindColumn();PDO_FETCH_BOUND 只是一個(gè)對于您了解只能使用綁定值的情況的一種優(yōu)化。

$stmt = $dbh->prepare('SELECT extension, name from CREDITS');if ($stmt->execute()) {$stmt->bindColumn('EXTENSION', $extension);$stmt->bindColumn('NAME',;;;$name);while ($stmt->fetch(PDO_FETCH_BOUND)) {echo 'Extension:$extension, Author:$namen'; }}

可移植性

區(qū)分大小寫的列

PDO 旨在令使用可移植 SQL 的腳本運(yùn)行良好、可移植。本文中提及的所有查詢(調(diào)用存儲過程除外)在使用任何 PDO 驅(qū)動程序時(shí)其運(yùn)行性能應(yīng)該相同 - 包括所有綁定輸入變量和綁定輸出列。

但有一個(gè)轉(zhuǎn)換問題 - 當(dāng)您使用 PDO_FETCH_ASSOC 抓取數(shù)據(jù)時(shí),不同的驅(qū)動程序會以不同的方式返回列名 - 某些會將列名轉(zhuǎn)化為大寫,某些轉(zhuǎn)換為小寫,某些則會使其呈查詢中指定的樣式。這對于 PHP 腳本來說是一個(gè)潛在的問題,因?yàn)閿?shù)組鍵區(qū)分大小寫。PDO 提供了一個(gè)兼容性屬性來幫助規(guī)范腳本的結(jié)果。下面的小代碼段是上面 PDO_FETCH_BOUND 示例的可移植版本,因?yàn)?setAttribute() 方法調(diào)用會指導(dǎo) PDO 將抓取返回的列名全部轉(zhuǎn)換為大寫:

$dbh = new PDO('OCI:', 'scott', 'tiger');$dbh->setAttribute(PDO_ATTR_CASE, PDO_CASE_UPPER);stmt = $dbh->prepare('SELECT extension, name from CREDITS');if ($stmt->execute()) {$stmt->bindColumn('EXTENSION', $extension);$stmt->bindColumn('NAME',;;;$name);while ($stmt->fetch(PDO_FETCH_BOUND)) {echo 'Extension:$extension, Author:$namen'; }}

除了 PDO_CASE_UPPER 之外,還有 PDO_CASE_LOWER(它會將列名轉(zhuǎn)換為小寫)和 PDO_CASE_NATURAL(它是默認(rèn)選項(xiàng):使列保持?jǐn)?shù)據(jù)庫驅(qū)動程序返回的形式)。

錯(cuò)誤和錯(cuò)誤處理

可移植腳本的另一個(gè)難題是處理從各種數(shù)據(jù)庫處理程序返回的各種不同的錯(cuò)誤消息;某些數(shù)據(jù)庫對于程序化處理錯(cuò)誤的支持能力很差,而其他一些數(shù)據(jù)庫則具有非常豐富的錯(cuò)誤代碼。只要可行,PDO 將為您的腳本提供一個(gè)統(tǒng)一的錯(cuò)誤代碼,從而使您不必為應(yīng)對可移植性的這個(gè)方面所累。當(dāng)然,PDO 還會為驅(qū)動程序提供原生錯(cuò)誤代碼和錯(cuò)誤消息,以防您需要用它來進(jìn)行診斷,或者錯(cuò)誤代碼映射不完整。

另一個(gè)困擾 PHP 數(shù)據(jù)庫擴(kuò)展的一致性問題是錯(cuò)誤處理策略的一致性:某些擴(kuò)展會返回的錯(cuò)誤代碼需要您手動抓取錯(cuò)誤字符串,而其他一些擴(kuò)展則只是發(fā)出 PHP 警告。PDO 允許您從下列三種不同的錯(cuò)誤處理策略中選擇一種:

·PDO_ERRMODE_SILENT這是默認(rèn)模式;它只是使用語句和數(shù)據(jù)庫句柄對象的 errorCode() 和 errorInfo() 方法為您設(shè)置要檢查的錯(cuò)誤代碼。

if (!$dbh->exec($sql)) {echo $dbh->errorCode() .'<BR>';$info = $dbh->errorInfo();// $info[0] == $dbh->errorCode() 統(tǒng)一的錯(cuò)誤代碼// $info[1] 是驅(qū)動程序特定的錯(cuò)誤代碼// $info[2] 是驅(qū)動程序特定的錯(cuò)誤字符串}

·PDO_ERRMODE_WARNING除了設(shè)置錯(cuò)誤代碼之外,PDO 還會發(fā)出 PHP 警告,您可以使用常規(guī)的 PHP 錯(cuò)誤處理程序捕獲該警告,并集中應(yīng)用您準(zhǔn)備好用于應(yīng)用程序的任何錯(cuò)誤處理/記錄策略,或者只是使該錯(cuò)誤顯示在瀏覽器中(在內(nèi)部測試過程中非常有用)。 ·PDO_ERRMODE_EXCEPTION除了設(shè)置錯(cuò)誤代碼之外,PDO 還會拋出一個(gè) PDOException,并將其屬性設(shè)置為包含該錯(cuò)誤代碼和信息。然后,您可以在代碼的較高級別捕獲該異常,使用全局異常處理程序捕獲該異常,或者不對其進(jìn)行處理而終止腳本(此時(shí)將回滾任何未決的事務(wù))。

try {$dbh->exec($sql);} catch (PDOException $e) {// 顯示警告消息print $e->getMessage();$info = $e->errorInfo;// $info[0] == $e->code; unified error code// $info[1] 是驅(qū)動程序特定的錯(cuò)誤代碼// $info[2] 是驅(qū)動程序特定的錯(cuò)誤字符串}

請注意,與警告或異常相比,靜默模式針對運(yùn)行時(shí)錯(cuò)誤使用的資源最少,但是為了獲得該速度,您犧牲了一些簡單性,而變得有一點(diǎn)復(fù)雜。

統(tǒng)一錯(cuò)誤代碼表當(dāng)前包括下列常量: PDO_ERR_NONE、PDO_ERR_CANT_MAP、PDO_ERR_SYNTAX、PDO_ERR_CONSTRAINT、PDO_ERR_NOT_FOUND、PDO_ERR_ALREADY_EXISTS、PDO_ERR_NOT_IMPLEMENTED、PDO_ERR_MISMATCH、PDO_ERR_TRUNCATED、PDO_ERR_DISCONNECTED。

這些常量所代表的意思字面即可推知,但是 PDO_ERR_CANT_MAP 代碼除外;這是一個(gè) PDO 特定的代碼,也就是說它無法將驅(qū)動程序特定的代碼映射到統(tǒng)一的錯(cuò)誤代碼,因此您應(yīng)該查詢 errorInfo() 方法返回的驅(qū)動程序特定代碼來獲得更多信息。

數(shù)據(jù)類型

PDO 在某種程度上類型不可知,因此它喜歡將數(shù)據(jù)表示為字符串,而不是將其轉(zhuǎn)換為整數(shù)或雙精度類型。此時(shí)您可能對此有些迷惑,但是原因非常簡單:字符串類型是最精確的類型,在 PHP 中具有最廣泛的應(yīng)用范圍;過早地將數(shù)據(jù)轉(zhuǎn)換為整數(shù)或者雙精度類型可能會導(dǎo)致截?cái)嗷蛏崛脲e(cuò)誤。通過將數(shù)據(jù)以字符串抽出,PDO 為您提供了一些腳本控制,您可以使用普通的 PHP 類型轉(zhuǎn)換工具(如數(shù)學(xué)運(yùn)算過程中的轉(zhuǎn)換和隱式)來控制如何進(jìn)行轉(zhuǎn)換以及何時(shí)進(jìn)行轉(zhuǎn)換。

NULL

如果結(jié)果集中的某列包含一個(gè) NULL 值,PDO 則會將其映射為 PHP null 值。Oracle 在將數(shù)據(jù)返回 PDO 時(shí)會將空字符串轉(zhuǎn)換為 NULL,但是 PHP 支持的任何其他數(shù)據(jù)庫都不會這樣處理,從而導(dǎo)致了可移植性問題。PDO 提供了一個(gè)驅(qū)動程序級屬性 PDO_ATTR_ORACLE_NULLS,該屬性會為其他數(shù)據(jù)驅(qū)動程序模擬此行為:

$dbh = new PDO('OCI:', 'scott', 'tiger');$dbh->setAttribute(PDO_ATTR_ORACLE_NULLS, true);// 現(xiàn)在從此 $dbh 打開的任何語句中的// 空字符串都將被轉(zhuǎn)換為 NULL

POD 的現(xiàn)狀和未來

PDO 現(xiàn)在仍相當(dāng)不成熟,但是會快速成熟起來。在編寫本文之時(shí),我在本文中提到的任何內(nèi)容都能夠通過 PDO_OCI 驅(qū)動程序適用于 Oracle 8 或更高版本(在 Oracle 8.0 和 9.2 上測試過)。

已經(jīng)計(jì)劃增加以下主要特性,在不久將可以使用:

1.使用 PHP 流的 LOB 支持。 使用綁定參數(shù),您能夠?qū)⑷魏瘟髻Y源(如文件、套接字、HTTP 資源、壓縮/篩選的流)作為輸入或輸出參數(shù)傳遞到在 LOB 上運(yùn)行的查詢中。與之相似,類型為 LOB 的輸出參數(shù)將表現(xiàn)為 PHP 流,因此您可以使用 fread()、fwrite()、fseek() 和其他流函數(shù)來訪問這些參數(shù)。此時(shí),在 PDO 中根本沒有 LOB 支持。 2.持久性連接和緩存的預(yù)處理語句。 持久性連接使您能夠避免在每個(gè)頁面命中時(shí)打開和關(guān)閉數(shù)據(jù)庫服務(wù)器連接。緩存的預(yù)處理語句又前進(jìn)了一步,它使您能夠持久保持查詢的預(yù)處理版本以及數(shù)據(jù)庫句柄。 3.游標(biāo)。 目前,PDO 只提供前向只讀游標(biāo),但是將來會提供可滾動游標(biāo)(需要基礎(chǔ)驅(qū)動程序支持)、REF-CURSOR、使用游標(biāo)進(jìn)行定位更新,以及可更新滾動游標(biāo)。

我們希望在 PHP 5.1 中默認(rèn)啟用 PHP 擴(kuò)展(距此目標(biāo)尚遠(yuǎn)),但是在此之前,我們希望能讓 PDO 在 PHP 5.0 發(fā)布時(shí)穩(wěn)定運(yùn)行,但是我們?nèi)粘9ぷ髦械膲毫ι陨酝涎恿诉@些工作。同時(shí),通過 PECL 發(fā)布 PDO 使我們能夠在收到問題報(bào)告時(shí)做出回應(yīng),并根據(jù)不同于 PHP 5.0 發(fā)布時(shí)間表的時(shí)間表發(fā)布修復(fù)版本,因此您在 PHP 5.1 發(fā)布前即可使用 PDO。

我們需要您的反饋

如果您試用了 PDO,并且發(fā)現(xiàn)了問題,請務(wù)必使用我們的錯(cuò)誤跟蹤軟件將其報(bào)告給我們。如果您使用的是 Oracle 驅(qū)動程序,則請使用此頁:

http://pecl.php.net/bugs/report.php?package=PDO_OCI

如果您使用的是其他驅(qū)動程序,則請用其名稱替換該 URL 中 PDO_OCI。

如果您使用 PDO 時(shí)遇到問題,或者針對某些特性存在疑問,或者具有特性請求,請聯(lián)系 pecl-dev@lists.php.net。如果您愿意,當(dāng)然還可以直接聯(lián)系我 (wez@php.net),但是請注意,我每天都會收到大量有關(guān) PHP 的電子郵件;您可能會發(fā)現(xiàn)如果首先與前面的郵件列表聯(lián)系會更快得到答復(fù)。

-----------關(guān)于作者Wez Furlong 是 Brain Room Ltd. 的技術(shù)總監(jiān),他在該公司不但使用 PHP 用于 Web 開發(fā),還將其用作 Linux 和 Windows 應(yīng)用程序和系統(tǒng)的嵌入式腳本引擎。Wez 是 PHP 的核心開發(fā)人員,經(jīng)常向 SQLite、COM/.Net、ActivePHP、mailparse 和 Streams API 等投稿,他是 PECL 即 PHP 擴(kuò)展社區(qū)庫的“頭兒”。他的咨詢公司的網(wǎng)頁為 http://www.thebrainroom.net。

標(biāo)簽: PHP
主站蜘蛛池模板: 欧美一级三级 | 日韩视频在线观看 | 日日日日干干干干 | 欧美精品一区二区三区四区在线 | 黄色影片免费在线观看 | 99久久国产 | 九九精品久久久 | 欧美成人精品一区二区男人看 | 欧美一级欧美三级在线观看 | 一级片在线观看视频 | 国产精品污www在线观看 | 欧美一区二区三区视频 | 午夜久久乐 | 99久久久国产精品 | 在线成人av | 午夜大片网 | 欧美国产日本一区 | 在线手机电影 | 日韩欧美国产一区二区三区 | 日韩电影中文字幕 | 一区二区三区四区免费观看 | 久久精品欧美 | 欧美日韩综合在线 | 国产精品日日做人人爱 | 91精品国产91久久久久游泳池 | 成人一区在线观看 | 夜夜夜夜夜操 | 国产精品久久精品 | 国产日韩欧美综合 | 精品久久一区二区三区 | 成人av免费 | 欧美一级二级三级视频 | 男女免费视频 | 国产欧美网址 | 精品国产乱码久久久久久久 | 国产精品亚洲一区二区三区 | 日韩精品一区二区三区在线播放 | 久久久久久免费看 | 超级碰在线视频 | 无码一区二区三区视频 | 欧美日韩高清在线一区 | 另类久久 | 中文字幕在线视频网站 | 免费一区二区三区 | 午夜久久久久 | 一级篇| 一区二区三区国产精品 | 9色网站| 伊人网页| 91久久久久久 | 一级黄色毛片 | 美女天天操 | 亚洲精品一区二区三区 | 成人妇女免费播放久久久 | 亚洲国产天堂久久综合 | 日本高清h色视频在线观看 日日干日日操 | 91视频久久 | 久草一区| 亚洲精品乱码久久久久久金桔影视 | 黄网站色大毛片 | 国产精品国产三级国产a | 电家庭影院午夜 | 日本欧美国产 | 国产精品视频久久久 | 亚洲欧美日韩精品 | 欧美国产在线观看 | 亚洲在线视频 | 99热国产精品 | 日韩一区二区在线播放 | 91色在线观看 | 国产一区二区免费视频 | 国产毛片视频 | 国产中文字幕在线 | 九九热热九九 | 黄毛片| 国产一区国产二区在线观看 | 91精品国产乱码久 | 婷婷丁香六月天 | jizz欧美大片| 国产成人精品亚洲777人妖 | 亚洲一区二区三区 | 在线精品亚洲欧美日韩国产 | 婷婷久| 日韩aaa久久蜜桃av | 欧美成人精品一区二区男人看 | 国产视频一区二区 | 成人精品网站在线观看 | 欧美激情一区二区 | 日本aaaa| 草草视频免费 | 在线观看国产 | 亚洲一区二区三区四区五区中文 | 爱色av | 亚洲精品一区在线观看 | 日韩av免费在线观看 | 亚洲国产二区三区 | 天天干天天操天天爽 | 免费黄色网止 | 欧美人体一区二区三区 | 欧美久久久久久久久久久久久久 | 精品久久久久av | a在线免费观看 | 美女视频一区 | 激情小网站 | 成人在线免费小视频 | 999在线观看精品免费不卡网站 | 精品国产影院 | 久久成人免费 | 久久av网 | 久久一精品 | 国产精品免费一区二区三区四区 | 精品一区二区三区免费视频 | 男人久久天堂 | 欧美精品成人一区二区三区四区 | 亚洲一区不卡 | 中文字幕成人免费视频 | 黄色毛片免费看 | 亚洲欧美中文日韩在线v日本 | 国产香蕉视频在线播放 | 成人av高清 | 日韩在线观看中文字幕 | 午夜天 | 成人福利网 | 日韩和的一区二在线 | 欧美黑人xx| 99精品欧美一区二区三区综合在线 | k8久久久一区二区三区 | 国产精品一码二码三码在线 | 在线电影亚洲 | 免费日韩视频 | 精品国产一区二区三区久久久蜜月 | 日韩亚洲一区二区 | 日韩精品免费在线观看 | 中文一区| 久久久久国产精品免费免费搜索 | 亚洲精品久久久一区二区三区 | 亚洲高清在线 | 蜜桃av在线播放 | 福利网在线| 在线观看国产小视频 | 日韩视频免费看 | 亚洲国产一区视频 | 国产伦精品一区二区三区四区视频_ | 中文字幕乱码一区二区三区 | 国产精品无码永久免费888 | 久久久精品| 久久久国产一区二区三区 | 免费中文字幕日韩欧美 | 日本一区二区三区免费观看 | 国产999精品久久久久久麻豆 | 国产精品国产三级国产aⅴ无密码 | 日韩成人免费视频 | 精品日韩欧美一区二区三区 | 国产精品视频免费播放 | 亚洲高清视频在线 | 日韩电影a | 国产91对白叫床清晰播放 | 亚洲免费国产视频 | 99精品欧美一区二区蜜桃免费 | 亚洲高清视频一区二区 | 在线 丝袜 欧美 日韩 制服 | 久久精品综合 | 久久精品亚洲一区二区 | 黄色大片免费网站 | 黄色片在线 | 在线观看亚洲精品 | 一本一道久久久a久久久精品91 | 成人免费在线观看视频 | 麻豆精品一区二区 | 日韩一区二区在线观看 | 99久久精品一区二区成人 | 欧美国产日韩一区 | 在线免费毛片 | 国产精品女同一区二区久久夜 | 亚洲成人精品一区二区三区 | 日韩免费高清视频 | 日本免费在线视频 | 九九热精品视频 | 国产精品久久久久毛片软件 | 久久av一区二区三区 | 美女一区| 久在线视频| 涩涩视频网站在线观看 | 亚洲欧洲精品成人久久奇米网 | 1区2区3区视频 | 亚洲网色| 免费观看一级特黄欧美大片 | 婷婷丁香六月天 | 欧美日韩一区精品 | 成人午夜sm精品久久久久久久 | 99re国产 | 亚洲精品电影在线一区 | ririsao久久精品一区 | 日韩精品视频三区 | 色花av | 日本激情网 | 国产精品一区二区无线 | 在线免费观看色视频 | 欧美色综合一区二区三区 | 国外成人在线视频网站 | 多p视频 | 日本一区二区三区中文字幕 | 91久久夜色精品国产网站 | 欧美精品一区二区视频 | 亚洲成人精品区 | 成人国产精品久久久 | 亚洲欧美91| 日韩成人精品视频在线观看 | 日韩av免费在线观看 | 国产成人小视频 | 国产精品久久久久国产a级 99精品欧美一区二区三区综合在线 | 91精品久久久久久久久久小网站 | 国产日韩精品在线观看 | 日韩91 | 成人午夜免费视频 | 中文天堂av | 久久久久久亚洲 | 国产精品久久久久久吹潮 | 国产精品久久免费视频 | 久久久久久国产精品 | 亚洲福利在线观看 | 97久久精品人人做人人爽50路 | 日韩精品一区二区三区第95 | 视频在线一区二区三区 | 日韩福利一区二区 | 色乱码一区二区三区网站 | 成人久久久久爱 | 免费三级电影网站 | 欧美另类综合 | 久久综合狠狠综合久久综合88 | 超碰人人艹 | 午夜午夜精品一区二区三区文 | 久久综合九九 | 日韩视频精品在线 | 亚洲中午字幕 | 成人爽a毛片一区二区免费 亚洲自拍偷拍精品 | 在线免费观看毛片 | 精品久久久久久久久久久久久 | 午夜精品一区二区三区在线视频 | 久久久精品欧美一区二区免费 | 一区二区三区四区在线播放 | 欧美一区二区精品 | 国产精品国产三级国产a | 91午夜精品一区二区三区 | 精品伊人 | 天天天天综合 | 日韩在线免费视频 | 视频一区在线播放 | av在线免费观看网站 | 欧美精品一区在线 | 天堂精品 | av7777| 国产1级片 | 麻豆乱码国产一区二区三区 | 天天夜碰日日摸日日澡 | 欧美日韩高清 | 国产一区二区欧美 | 亚洲色图在线播放 | 欧美一区2区三区4区公司二百 | 欧美日韩高清在线一区 | 日本精品在线 | www.久久| 日韩拍拍| 久草.com| 亚洲精品www| 最新av网址大全 | 国产成人精品一区二区三区在线 | 一区二区三区免费av | 久久精品在线 | 成人在线小视频 | 免费的一级视频 | 91精品国产高清自在线观看 | 一区二区久久 | 老熟女毛片 | 男人天堂网站 | 成人精品视频 | 91久久久久 | 看一级黄色大片 | 亚洲高清视频在线 | 天天拍天天干天天操 | 日本黄色一级电影 | 国产一级特黄视频 | 国产精品第一区 | 天天操天天干天天 | 国产精品色在线网站 | 精品毛片 | 国产精品九九九 | 99精品欧美一区二区三区综合在线 | 黄瓜av | 精品久久一二三区 | 久久视频国产 | 国产婷婷在线视频 | 亚洲激情av | 91精品视频在线播放 | 色偷偷噜噜噜亚洲男人 | 亚洲欧洲av在线 | 精品一区二区久久久久久久网站 | 成人亚洲免费 | 黄色一级电影免费观看 | 久久久国产精品 | 亚洲精品久久久久久久久久久久久 | 99精品国产高清一区二区麻豆 | 精品日韩一区二区三区 | 国产成人精品高清久久 | 日韩aaa视频 | 欧美激情专区 | 久久一二三区 | 噜噜噜噜狠狠狠7777视频 | 中文字幕一区在线观看视频 | 成人在线看片网站 | 天天草av| 国产男女免费视频 | 久久se精品一区精品二区 | 亚洲欧美综合一区 | 日韩精品久久久久久 | 国产中文字幕在线观看 | 91电影在线| 午夜免费一区二区播放 | 亚洲一区二区三区四区在线 | 日本久久久亚洲精品 | 夜夜av| 国产精品毛片一区二区在线看 | 草久在线观看 | 色婷婷在线视频观看 | 精品一区视频 | 在线观看理论电影 | 国产精品久久久久久久久久三级 | 久久久99国产精品免费 | 一级黄色片欧美 | 男人天堂网av| 99爱爱视频 | 91精品国产综合久久久久久蜜臀 | 亚洲精品一区二区三区 | 欧美午夜精品久久久 | 91综合在线观看 | 91黄在线观看 | 春色导航 | 国产欧美精品一区二区三区 | 人妖 丝袜 另类 亚洲 | 久久久久综合狠狠综合日本高清 | av一区在线 | 久久成人精品一区二区三区 | 蜜桃视频一区二区三区 | 欧美狠狠操 | 龙珠z国语版291集全 | 亚洲欧美网站 | 日本三级不卡 | 综合伊人久久 | 婷婷成人在线 | 久草美女| 精品一区二区三区在线观看 | 91精品国产福利在线观看 | 欧美激情自拍偷拍 | 亚洲精品一区二区三区 | 欧美激情在线播放 | 亚洲h视频| 欧美色图亚洲自拍 | 亚洲欧美国产精品专区久久 | 一级亚洲| 日韩中文字幕在线视频 | 成人欧美一区二区三区在线播放 | 日韩久久成人 | 欧美亚洲国产一区 | 一区二区三区国产精品 | 日韩av一区二区三区四区 | 青青草一区二区 | 日韩一区二区三区在线 | 激情91| 亚洲精品久久 | 一区二区三区欧美在线 | 欧美亚洲日本 | 日韩1区3区4区第一页 | 国产目拍亚洲精品99久久精品 | 亚洲成人av | 欧美视频xxx | 久久久网| 日韩欧美综合在线 | 日韩中文在线观看 | 免费毛片在线 | 欧美日韩国产综合视频 | 午夜视频在线观看网站 | 国产一区不卡 | 日韩激情二区 | 国产老女人精品毛片久久 | 亚洲欧美第一页 | 久在线视频 | 日韩一区在线视频 | 午夜免费小视频 | 福利视频网址导航 | 黄色一级电影免费观看 | 中文字幕一区二区在线观看 | 国产精品欧美一区二区三区不卡 | 国产精品欧美一区二区三区 | 久日精品 | 国产高清在线精品一区二区三区 | 99久久国产综合精品女不卡 | 色婷婷在线播放 | 精品久久久久久久久久久久久久久 | 欧美日韩国产一区二区三区不卡 | 黄色的视频免费 | 仙踪林久久久久久久999 | 亚洲国产欧美在线 | 午夜电影网 | 亚洲一区二区精品 | 九九综合九九 | 夜夜艹| 91成人在线视频 | 国产麻豆一区二区三区 | 成人久久18免费观看 | 久久久久在线 | 久久精品小视频 | 精品久久久久久久久久久 | a一级免费视频 | 成人 在线| 中文字幕在线观看一区二区三区 | 成人一区电影 | 黄色国产视频 | 欧美日韩一区在线 | 国产成人av一区二区 | 日本三级做a全过程在线观看 | 欧美精品一区二区三区在线 | 国产精品一区二区三区免费 | 亚洲欧美激情精品一区二区 | 国产美女自拍视频 | 欧美伦理一区二区 | 黄色一级片 | 日日摸日日碰夜夜爽亚洲精品蜜乳 | 伊人天堂在线 | 国产精品久久国产精品 | 男人超碰| 日韩综合网| 亚洲精品国产二区 | 嫩呦国产一区二区三区av | 欧美精品tv | 亚洲男人的天堂在线播放 | 国产美女久久 | 欧美午夜视频在线观看 | 午夜精品一区二区三区在线观看 | 91免费看| 一级毛片在线播放 | 欧美一区二区三区免费观看视频 | 久久黄视频 | 精品无码久久久久国产 | 欧美a级成人淫片免费看 | 欧美一级特| av三级在线观看 | 成人欧美一区二区三区在线播放 | 中文字幕99 | 九色91在线 | 国产精品第一国产精品 | 黄网在线观看 | 综合伊人 | 亚洲精品a | 毛片真人毛毛片毛片 | 亚洲精品乱码久久观看网 | 黄色电影天堂 | 99热这里有 | 久久久久国产精品一区二区三区 | 欧美日韩三级在线 | 国产精品99久久久久久www | 国产精品免费观看 | 亚洲精品视频在线看 | 欧美电影一区 | 日韩精品视频在线观看一区二区 | 国产成人午夜 | 色婷婷av一区二区三区软件 | 亚洲在线视频 | 少妇一级淫片免费放 | 国产精品久久国产愉拍 | 日韩性xxx | 欧美在线观看黄 | 免费国产一区二区 | 日韩精品在线一区 | 国产在线视频一区 | 亚洲综合无码一区二区 | 一级毛片免费 | 精品免费av | www久久精品 | 特黄特黄a级毛片免费专区 av网站免费在线观看 | 成年免费a级毛片 | 91精品国产91久久久久久吃药 | 欧美大片一区二区 | 中文字幕成人免费视频 | 亚洲精品久久久久久久久久久 | 日韩午夜 | 高清av在线 | 99视频只有精品 | 欧美狠狠操 | 国产2区 | 亚洲精品1| 91一区 | 亚洲一在线 | a久久| 成人免费视频网站在线观看 | 激情图区在线观看 | 九九精品久久久 | 人妖天堂狠狠ts人妖天堂狠狠 | 成人av在线播放 | 伊人超碰在线 | 精品国产乱码久久久久久密桃99 | 国产精品一区电影 | 亚洲综合无码一区二区 | 欧美自拍视频在线 | 国产一区二区三区视频在线观看 | 另类国产ts人妖高潮系列视频 | 亚洲精品日本 | 综合激情久久 | 欧美成人性生活视频 | 精品视频一区二区 | 欧美三级视频 | 99精品国产高清在线观看 | 国产精品福利视频 | 99爱免费观看 | 久久免费99精品久久久久久 | 国产精品91久久久久 | 日本黄色电影网站 | 天操天天干 | 中文字幕一区二区三区在线视频 | 久久久国产精品入口麻豆 | 日本韩国欧美一区 | www.久久 | 一本大道综合伊人精品热热 | 日韩一区二区视频 | 国产一区在线视频 | 国产精品网站在线观看 | 欧美久草 | 九色91在线 | www.一区 | 91免费国产 | 久久精品亚洲一区二区 | 九色在线观看 | 亚洲精品一区二区三区在线 | 亚洲精品一区二区三区 | 国产亚洲欧美一区二区三区 | 中文在线一区二区 | 日韩在线成人 | 中文字幕在线永久在线视频 | 日本久久久影视 | 欧美久草 | 国产精品高潮呻吟久久av黑人 | 国产欧美精品一区二区 | 日韩看片 | 久久国产精品免费一区二区三区 | 在线播放一区二区三区 | 国产精品一级 | 亚洲一区在线日韩在线深爱 | 午夜精品久久久久久久久久久久久 | 国产一区二区视频在线观看 | 91在线观看视频 | 亚洲小视频网站 | 国产精品粉嫩白浆在线观看 | 日韩免费 | 亚洲欧美电影 | 亚洲欧美第一页 | 亚洲三区在线观看 | 在线色综合| 国产真实精品久久二三区 | 啪一啪操一操 | 免费国产黄网站在线观看视频 | 日韩视频免费看 | 欧美成年网站 | 三级在线观看 | 中文字幕国产一区 | 凹凸日日摸日日碰夜夜 | 亚洲成人三区 | 欧美成视频 | 精品午夜久久久 | 欧洲亚洲视频 | 国产三级在线免费观看 | 龙珠z国语291集普通话 | 国产伦精品一区二区三区高清 | 午夜激情影院 | 日日操视频 | 欧洲一级毛片 | 毛片视频免费 | 日韩在线亚洲 | 精品国产一区二区三区久久久蜜臀 | 日日网| 国产精品99| 蜜臀网 | 国产色视频网站 | 成人av教育| 久久精品国产99国产精品 | 午夜免费电影 | 国产欧美精品区一区二区三区 | 日韩精品一区二区在线观看视频 | 国产成人一区二区三区 | 99pao成人国产永久免费视频 | 精品亚洲一区二区三区 | 美女福利视频网站 | 亚洲97| 国产午夜手机精彩视频 | 亚洲午夜免费视频 | 欧美黄色片 | 日韩欧美国产精品 | 国产一区二区在线观看视频 | 精品美女在线 | 国产在线观看一区 | 97av视频在线观看 | 91精品国产综合久久久久久丝袜 | 国产成人精品一区二 | 日韩精品一区二区在线观看 | 久久久久久免费视频 | 日本美女影院 | 国产成人久久精品一区二区三区 | 精品国产一区二区三区不卡蜜臂 | 日韩成人在线观看 | 麻豆自拍偷拍 | 在线视频一区二区三区 | 不卡免费视频 | 日本午夜影院 | 久在线| 欧美精品免费在线观看 | 国产精品毛片一区二区三区 | 久久久久久久久成人 |