PHP連接數據庫學習手冊
範例 1: Select 指令
任務:連結到 Access 的 Northwind DSN,然後在每一列顯示頭2個字段。(Northwind 北風數據庫,在ODBC設定的DSN,是Access的標準範例數據庫)
在這個範例中,我們建立一個 ADOConnection 對象,它代表了和數據庫的連結。連結是以 PConnect 函數來初始化的,然後會持續的連結著。任何時候我們要查詢數據庫時,我們就唿叫 ADOConnection.Execute() 函數,這將會回傳一個ADORecordSet對象。事實上它隻是一個指向在fields[]數組中,目前記錄的指針,我們使用MoveNext()來在記錄間移動。
注意:另一個很有用的函數 SelectLimit 並沒有在這個範例裏使用,這個函數允許我們去限製顯示的數據筆數。
<?
include('ADOdb.inc.php'); # 加載ADODB
$conn = &ADONewConnection('access'); # 建立一個連結
$conn->PConnect('northwind'); # 連結到 MS-Access 北風數據庫
$recordSet = &$conn->Execute('select * from products');
if (!$recordSet)
print $conn->ErrorMsg();
else
while (!$recordSet->EOF) {
print $recordSet->fields[0].' '.$recordSet->fields[1].'<BR>';
$recordSet->MoveNext();
}
$recordSet->Close(); # 選擇性執行
$conn->Close(); # 選擇性執行
?>
在這個例子中,$recordSet回傳了存在$recordSet->fields數組裏,目前所指向的記錄。以字段編號為索引,起始值為0。我們使用MoveNext()函數來移動到下一筆記錄,當到了最後一筆時,EOF屬性會被設定為true。當Execute()函數執行有錯誤時,會回傳一個false值,而不是一個recordset對象。
$recordSet->fields[]數組是由PHP數據庫擴充函數庫所產生的。有一些數據庫擴充函數庫僅支持以編號來進行索引,而不支持以字段名為索引。要強迫使用字段名索引,也就是要使用關連式數組,請使用 $ADODB_FETCH_MODE 全域變量來設定。當一個數據集被Execute()或是SelectLimit()函數建立時,都會儲存而且使用儲如此類的設定模式。
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs1 = $db->Execute('select * from table');
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rs2 = $db->Execute('select * from table');
print_r($rs1->fields); # shows array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); # shows array(['col1']=>'v0',['col2'] =>'v1')
上麵的範例說明,如果要以順序來存取字段,就將 $ADODB_FETCH_MODE 的值設為 ADODB_FETCH_NUM,要以關連式數組(以字段名)存取字段,就要將值設為 ADODB_FETCH_ASSOC。
要取得在被選到的記錄筆數,你可以使用$recordSet->RecordCount()方法。注意,如果不能確定得到的記錄筆數,會回傳 -1 。
範例 2: 進階的 Select 指令(使用 Field 對象)
任務:選取一個資料表,顯示最前麵的二欄。如果第二欄是一個日期或時間型態字段,將它格式化成US格式。
<?
include('ADOdb.inc.php');
$conn = &ADONewConnection('access');
$conn->PConnect('northwind');
$recordSet = &$conn->Execute('select CustomerID,OrderDate from Orders');
if (!$recordSet)
print $conn->ErrorMsg();
else
while (!$recordSet->EOF) {
$fld = $recordSet->FetchField(1);
$type = $recordSet->MetaType($fld->type);
if ( $type == 'D' || $type == 'T')
print $recordSet->fields[0].' '.
$recordSet->UserDate($recordSet->fields[1],'m/d/Y').'<BR>';
else
print $recordSet->fields[0].' '.$recordSet->fields[1].'<BR>';
$recordSet->MoveNext();
}
$recordSet->Close(); # optional
$conn->Close(); # optional
?>
在這個例子中,我們使用 FetchField() 函數來檢查第二個字段的資料型別。這將會回傳一個至少有三個字段的對象,字段說明如下:
· name: 字段名
· type: 字段的資料原生型別native field type of column
· max_length: 字段的最大長度,部份數據庫像MySQL,並不回傳字段的正確值,以這個例子而言,就會回傳 -1 。
然後我們使用 MetaType() 去轉換原生型別成通用型別,目前通用型別定義如下:
· C: character 字段,應該使用 <input type="text"> 標記來取值。
· X: 文字字段(Text) , 長文字字段,使用 <textarea> 標記來顯示資料。
· B: Blob 字段或者大型的二位對象(像程序,圖文件等)。
· D: 日期字段
· T: 時間字段
· L: 邏輯字段(真假值)或位字段
· N: 數字字段,包含自動進位、編號、整數、浮點數、實數等。
· R: 序列字段,包含了序列、自動增進整數,隻對被選擇的數據庫作用。
如果對應型別是日期或時間,那你可以使用 UserDate() 函數來設定輸出的日期格式。這個函數會轉換 PHP SQL 日期字符串格式為使用者定義的格式。 另一個使用MetaType()的時機是在進行SQL新增或更新指令時,資料格式驗證用。
範例 3: 新增
新增一筆記錄到訂單資料表,裏麵包含了日期和字符串,為了能被數據庫正常存取,字符串必需校正,以避免部份標記字符。例如:有單引號的字符串,John's。
<?
include('ADOdb.inc.php'); # load code common to ADOdb
$conn = &ADONewConnection('access'); # create a connection
$conn->PConnect('northwind'); # connect to MS-Access, northwind dsn
$shipto = $conn->qstr("John's Old Shoppe");
$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";
$sql .= "values ('ANATR',2,".$conn->DBDate(time()).",$shipto)";
if ($conn->Execute($sql) === false) {
print 'error inserting: '.$conn->ErrorMsg().'<BR>';
}
?>
在這個範例中,我們看見了ADODB更進一步的日期及標點符號的處理方式。Unix 日期時間標示(長整數)被DBDate()格式化成Access可以接受的格式,而帶了縮寫符號的 John's Old Shoppe 則被 qstr() 函數處理成 John''s Old Shoppe 字符串,以被數據庫合法存取。
觀察 Execute 指令的錯誤處理。如果 Execute() 執行有錯誤發生時,會傳回 False 值。而最後的錯誤訊息可以由 ErrorMsg() 來顯示。
附記:php_track_errors旗標可以被激活,以便將錯誤訊息儲存起來。
範例 4: 除錯
<?
include('ADOdb.inc.php'); # load code common to ADOdb
$conn = &ADONewConnection('access'); # create a connection
$conn->PConnect('northwind'); # connect to MS-Access, northwind dsn
$shipto = $conn->qstr("John's Old Shoppe");
$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";
$sql .= "values ('ANATR',2,".$conn->FormatDate(time()).",$shipto)";
$conn->debug = true;
if ($conn->Execute($sql) === false) print 'error inserting';
?>
在上麵的例子中,我們藉由設定 debug=true 來激活除錯模式。這將會在執行指令時會先將SQL指令顯示,並且會顯示所有的錯誤訊息,而不需要去唿叫 ErrorMsg() 。顯示資料集的部份,可以參考 rs2html() 範例。
其它的請參考自定錯誤處理的說明。
範例 5: MySQL及選單
連結到MySQL數據庫 agora ,並且從SQL命令中建立一個 <select> 選單,<option>的標題是第一個字段,回傳值是第二個字段。
<?
include('ADOdb.inc.php'); # load code common to ADOdb
$conn = &ADONewConnection('mysql'); # create a connection
$conn->PConnect('localhost','userid','','agora');# connect to MySQL, agora db
$sql = 'select CustomerName, CustomerID from customers';
$rs = $conn->Execute($sql);
print $rs->GetMenu('GetCust','Mary Rosli');
?>
Here we define a menu named GetCust, with the menu option 'Mary Rosli' selected. See GetMenu(). We also have functions that return the recordset as an array: GetArray(), and as an associative array with the key being the first column:GetAssoc().
這裏,我們定義了一個名為GetCust的選單,默認值是'Mary Rosli'。相關說明請參考 GetMenu() 。我們也將資料集以數組回傳的方式寫在 GetArray()方法裏。而另外回傳關係型數組的方法則使用 GetAssoc() ,其中第一個字段是這個字段的鍵值。
在 1.50 版以後的 ADODB 裏,是使用公共變量 $ADODB_FETCH_MODE 來設定回傳的數組是以編號或是關連式字符串做索引。
範例 6: 一次連結兩個數據庫
<?
include('ADOdb.inc.php'); # 加載 ADOdb
$conn1 = &ADONewConnection('mysql'); # 建立一個 mysql 連結
$conn2 = &ADONewConnection('oracle'); # 建立一個 oracle 連結
$conn1->PConnect($server, $userid, $password, $database);
$conn2->PConnect(false, $ora_userid, $ora_pwd, $tnsname);
$conn1->Execute('insert ...');
$conn2->Execute('update ...');
?>
範例 7: 產生 Update 及 Insert 的SQL指令
ADODB 1.31版起,新增了兩個數據集函數:GetUpdateSQL()及GetInsertSQL()。這允許你在執行了像"SELECT * FROM table query WHERE..."這樣的查詢函數後,建立一個 $rs->fields複本,改變這些字段,然後自動產生出更新或是新增的SQL指令。
以下我們展示如何運用這些函數,我們將存取一個資料表,帶有下列字段:(ID,FirstName,LastName,Created)。在這些函數被執行前,你需要藉由一個對資料表的查詢指令(select)來初始化一個數據集。
<?
#==============================================
# GetUpdateSQL() 及 GetInsertSQL() 範例碼
#==============================================
include('ADOdb.inc.php');
include('tohtml.inc.php');
#==========================
# 以下的程序代碼測試新增狀態
$sql = "SELECT * FROM ADOXYZ WHERE id = -1";
# 從數據庫中查詢出一個空的資料集
$conn = &ADONewConnection("mysql"); # 建立一個連結
$conn->debug=1;
$conn->PConnect("localhost", "admin", "", "test"); # 連結到 MySQL, 數據庫名稱為 test
$rs = $conn->Execute($sql); # 執行查詢,並取得一個空的資料集
$record = array(); # 初始化一個數組,以便存放記錄資料供新增用
# 設定記錄中的字段值
$record["firstname"] = "Bob";
$record["lastname"] = "Smith";
$record["created"] = time();
# 傳入空的資料集及字段資料數組到GetInsertSQL函數中,以執行功能
# 這個函數將會依傳入的資料,回傳一個全格式的 INSERT SQL指令
$insertSQL = $conn->GetInsertSQL($rs, $record);
$conn->Execute($insertSQL); # 將記錄挿入數據庫中
#==========================
# 以下的程序代碼測試更新狀態
$sql = "SELECT * FROM ADOXYZ WHERE id = 1";
# 選擇一筆記錄以便更新
$rs = $conn->Execute($sql); # 執行這個查詢,並取得一個存在的記錄來更新
$record = array(); # 初始化一個數組,以存放要更新的數據
# 設定字段裏的值
$record["firstname"] = "Caroline";
$record["lastname"] = "Smith"; # 更新 Caroline的姓由 Miranda 變成 Smith
# 傳入這個隻有單一記錄的資料集以及含有資料的數組到 GetUpdateSQL函數裏
# 函數將會回傳一個具有正確 WHERE 條件的 UPDATE(更新)
SQL 指令
$updateSQL = $conn->GetUpdateSQL($rs, $record);
$conn->Execute($updateSQL); # 更新數據庫中的記錄
$conn->Close();
?>
範例 8: 使用上一筆及下一筆實作卷動
我們使用HTTP取得 $next_page 變量,以追蹤要跳去那一頁並且儲存目前頁碼在 session 變量 $curr_page 裏。
我們唿叫連結對象的 PageExecute()函收去取得我們要的資料集,然後我們使用數據集的 AtFirstPage() 及 AtLastPage() 函數去決定是否顯示下一頁和上一頁按鈕。
<?php
include_once('ADOdb.inc.php');
include_once('tohtml.inc.php');
session_register('curr_page');
$db = NewADOConnection('mysql');
$db->Connect('localhost','root','','xphplens');
$num_of_rows_per_page = 10;
$sql = 'select * from products';
if (isset($HTTP_GET_VARS['next_page']))
$curr_page = $HTTP_GET_VARS['next_page'];
if (empty($curr_page)) $curr_page = 1; ## at first page
$rs = $db->PageExecute($sql, $num_of_rows_per_page, $curr_page);
if (!$rs) die('Query Failed');
if (!$rs->EOF && (!$rs->AtFirstPage() || !$rs->AtLastPage())) {
if (!$rs->AtFirstPage()) {
?>
<a href="<?php echo $PHPSELF,'?next_page=',$rs->AbsolutePage() - 1 ?>">Previous page</a>
<?php
}
if (!$rs->AtLastPage()) {
?>
<a href="<?php echo $PHPSELF,'?next_page=',$rs->AbsolutePage() + 1 ?>">Next page</a>
<?php
}
rs2html($rs);
}
?>
以上的程序代碼可以在 testpaging.php 範例裏找到。
使用自定錯誤處理及 PEAR_Error
在之前的版本,你可以使用像 $con->debug=true ; 這樣的設定來進行除錯。但在 1.50 版後,我們提供了另一種方法來處理錯誤狀態。我們讓工程師可以使用 ADODB 的自訂錯誤處理程序功能。
ADODB 提供了兩種自訂處理方式,你可以配合你的的需要而修訂。第一個方法放在 ADOdb-errorhandler.inc.php 檔案裏。這讓你可以使用標準的 PHP 函數 err_reporting 去控製要顯示怎樣的錯誤訊息及 trigger_error 去唿叫 PHP 預設的錯誤處理程序。
引入了上述檔案後(ADOdb-errorhandler.inc.php),當發生了下列的錯誤後,將會使得 trigger_error($errorstring,E_USER_ERROR)被唿叫。
1. Connect() 或 PConnect() 執行失敗時。
2. 執行 SQL 指令的函數失敗時,如 Execute() 或 SelectLimin() 。
3. GenID() 進入了無限循環時。
這裏的 $errorstring 變量是由 ADODB 所產生的。而且會包含了有用的除錯訊息,類似於隨後會建立的 error.log 資料。所以,為了要能正確提供除錯訊息,你要在建立 ADOConnection 對象前,就把 ADOdb-errorhandler.inc.php 引入到程序代碼中。
If you define error_reporting(0), no errors will be shown. If you set error_reporting(E_ALL), all errors will be displayed on the screen.
如果你設定了 error_reporting(0) 的話,將不會有任何錯誤被顯示。如果你設定了 error_reporting(E_ALL),那將會顯示所有的錯誤訊息。
以下是一個簡單的範例:
<?php
error_reporting(E_ALL); # 顯示所有的錯誤訊息
include('ADOdb-errorhandler.inc.php');
include('ADOdb.inc.php');
include('tohtml.inc.php');
$c = NewADOConnection('mysql');
$c->PConnect('localhost','root','','northwind');
$rs=$c->Execute('select * from productsz'); #不正確的資料表 productsz');
if ($rs) $rs2html($rs);
?>
如果你要把錯誤訊息記錄下來,你可以定義兩個選擇性常數 ADODB_ERROR_LOG_TYPE, ADODB_ERROR_LOG_DEST。有關於 ADODB_ERROR_LOG_TYPE 的值,你可以去參考 PHP 使用手冊中有關於 error_log 的說明。在以下的範例中,我使將它設為 3,意思是指將訊息記錄到常數 ADODB_ERROR_LOG_DEST 所設定的檔案中。
<?php
error_reporting(0); # 不顯示任何的錯誤訊息
define('ADODB_ERROR_LOG_TYPE',3);
define('ADODB_ERROR_LOG_DEST','C:/errors.log');
include('ADOdb-errorhandler.inc.php');
include('ADOdb.inc.php');
include('tohtml.inc.php');
$c = NewADOConnection('mysql');
$c->PConnect('localhost','root','','northwind');
$rs=$c->Execute('select * from productsz'); ## 不正確的資料表 productsz
if ($rs) $rs2html($rs);
?>
以下則是寫在 error.log 文件的錯誤訊息:
(2001-10-28 14:20:38) mysql error: [1146: Table 'northwind.productsz' doesn't exist] in
EXECUTE("select * from productsz")
第二種錯誤處理方法是 ADOdb-errorpear.inc.php 。使用這種方式,在錯誤發生時會產生 PEAR_Error 衍生對象,而最後產生的 PEAR_Error 對象可以被 ADODB_Pear_Errir() 函數取回。
<?php
include('ADOdb-errorpear.inc.php');
include('ADOdb.inc.php');
include('tohtml.inc.php');
$c = NewADOConnection('mysql');
$c->PConnect('localhost','root','','northwind');
$rs=$c->Execute('select * from productsz'); #不正確的資料表 productsz');
if ($rs) $rs2html($rs);
else {
$e = ADODB_Pear_Error();
echo '<p>',$e->message(),'</p>';
}
?>
在引入 ADOdb-errorpear.inc.php 檔之前,藉由定義 ADODB_PEAR_ERROR_CLASS 常數,你可以使用一個 PEAR_Error 衍生類別。為了方便除錯,你可以在 PHP 程序代碼的最前麵定義預設的錯誤理方式為 PEAR_ERROR_DIE,這將會使得程序一出錯,馬上就輸出錯誤訊息,並且停止執行。
include('PEAR.php');
PEAR::setErrorHandling('PEAR_ERROR_DIE');
注意,當錯誤產生時,ADODB並沒有明確的回傳一個 PEAR_Error 對象給你。你必需要去唿叫 ADODB_Pear_Error() 函數去取回最後的錯誤內容。或者,你可以使用 PEAR_ERROR_DIE 這個技巧。
資料集快取
現在,ADODB使用 CacheExecute(),CachePageExecute()及CacheSelectLimit()函數來支持數據集快取。用法類似於沒有快取的函數,除了要加上一個新的參數 $secs2cache。
以下是一個範例 :
include('ADOdb.inc.php'); # 加載ADODB
$ADODB_CACHE_DIR = '/usr/ADODB_cache';
$conn = &ADONewConnection('mysql'); # 建立一個連結
$conn->PConnect('localhost','userid','','agora');# 連結到 MySQL, agora 數據庫
$sql = 'select CustomerName, CustomerID from customers';
$rs = $conn->CacheExecute(15,$sql);
第一個參數是設定查詢的快取秒數。隨後唿叫的查詢將會使用存放在由 $ADODB_CACHE_DIR 變量指定的快取數據。要強迫查訊執行,並且更新快取記錄,使用 CacheExecute() 函數,並且將第一個參數設為 0 。或者,使用 CacheFlush($sql) 也行。
基於安全的考量,如果你要使用 $ADODB_CACHE_DIR,我們建議你將在 php.ini 裏的 register_globals 設成 off。
在 ADODB 1.80版以後,在 CacheSelectLimit() 及 CacheExecute() 中,參數 secs2cache 是選擇性的。如果你不填上去,係統將會使用 $connection->cacheSecs 屬性的值,它的默認值是 60 分鍾。
$conn->Connect(...);
$conn->cacheSecs = 3600*24; // 快取24小時
$rs = $conn->CacheExecute('select * from table');
最後更新:2017-04-03 16:48:45