2008年1月23日 星期三

MySQL欄位型態


建立資料表時,我們必須定義每個欄位所採用的資料型態,以下將介紹 MySQL 所支援的各種欄位型態。
 
數字型態
型態空間
需求
範圍
TINYINT[(M)]1 byteSigned: -128 to 127 (-27 to 27-1)
Unsigned: 0 to 255 (0 to 28-1)
SMALLINT[(M)]2 bytesSigned: -32768 to 32767 (-215 to 215-1)
Unsigned: 0 to 65535 (0 to 216-1)
MEDIUNINT[(M)]3 bytesSigned: -8388608 to 8388607 (-223 to 223-1)
Unsigned: 0 to 16777215 (0 to 224-1)
INT[(M)]
INTEGER[(M)]
4 bytesSigned: -2147483648 to 2147483647 (-231 to 231-1)
Unsigned: 0 to 4294967295 (0 to 232-1)
BIGINT[(M)]8 bytesSigned: -9223372036854775808 to 9223372036854775807 (-263 to 263-1)
Unsigned: 0 to 18446744073709551615 (0 to 264-1)
FLOAT(precision)4 or 8若 precision <= 24 的話,視為 FLOAT(單精數)
若 25 <= precision <= 53 的話,則視為 DOUBLE(倍精數)
FLOAT[(M,D)]4 bytes±1.175494351E-38 ±3.402823466E+38
DOUBLE[(M,D)]
REAL[(M,D)]
8 bytes±1.7976931348623157E+308 ±-2.2250738585072014E-308
DECIMAL[(M[,D])]
DEC[(M[,D])]
NUMERIC[(M[,D])]
M+2依 M 與 D 值而定
 上表中的 M 代表「最大顯示寬度」,其值不得大於 255。無論您將欄位的型態設定為「INT(4)」或「INT(5)」,都不影響它儲存數值的能力;但在顯示時,就可以發現其差異了。我們將兩個欄位分別設為「INT(4)」與「INT(5) ZEROFILL」(ZEROFILL 會在前頭的空位補 0),然後兩者均存入數字 4,在顯示其資料時,前者是「4」,後者則是「00004」。
 上表中的 D 代表「小數位數」,其值不得大於 30,也不能大於 M-2。
 如果您將上述欄位型態設定為 UNSIGNED 的話,對整數型態(TINYINT, SMALLINT, MEDIUNINT, INT, and BIGINT)而言,可以儲存較大的正整數;對其餘的浮點數型態而言,則可以避免被存入負的數值。
 若您存入的數值超過該欄位的範圍時,MySQL 只會取其所能處理的最大值。例如,您在 TINYINT 型態的欄位中存入「300」這個值,結果將只剩下「127」。

日期與時間型態
型態空間需求範圍
DATE3 bytes'1000-01-01' to '9999-12-31'
TIME3 bytes'-838:59:59' to '838:59:59'
DATETIME8 bytes'1000-01-01 00:00:00' to '9999-12-31 23:59:59'
TIMESTAMP[(M)]4 bytes自 1970 年起,至 2037 年的某時
YEAR[(2 | 4)]1 bytes4-digit format: 1901 to 2155
2-digit format: 1970 to 2069
 在使用 TIMESTAMP 型態時,您可以指定「最大顯示寬度」,就是 M。不同的 M 值與儲存所需空間無關,而是與顯示的格式有關。請見下表:
型態顯示格式
TIMESTAMP(14)YYYYMMDDHHMMSS
TIMESTAMP(12)YYMMDDHHMMSS
TIMESTAMP(10)YYMMDDHHMM
TIMESTAMP(8)YYYYMMDD
TIMESTAMP(6)YYMMDD
TIMESTAMP(4)YYMM
TIMESTAMP(2)YY

字串型態
型態空間需求最大長度
CHAR(M)M bytesM bytes
VARCHAR(M)L+1 bytesM bytes
TINYBLOB, TINYTEXTL+1 bytes28-1 bytes
BLOB, TEXTL+2 bytes216-1 bytes
MEDIUMBLOB, MEDIUMTEXTL+3 bytes224-1 bytes
LONGBLOB, LONGTEXTL+4 bytes232-1 bytes
ENUM('value1','value2',...)1 or 2 bytes65535 個成員
SET('value1','value2',...)1, 2, 3, 4, or 8 bytes64 個成員
 上表中的 L 代表「實際儲存的空間大小」,上述多種型態的空間需求都與實際存入的空間大小有關,意即,它們的空間需求是變動的。

CHAR 與 VARCHAR
 使用 CHAR 及 VARCHAR 型態時,必須宣告「最大儲存長度」,就是上表中的 M。這兩種型態是相似的,所能儲存的最大長度都是 255 bytes。其相異之處在於 CHAR 是個固定長度的型態,而 VARCHAR 是個長度可變的型態。我們從下表來看兩者在資料儲存上的表現:
字串內容CHAR(4)空間需求VARCHAR(4)空間需求
'''????'4 bytes''1 byte
'ab''ab??'4 bytes'ab'3 bytes
'abcd''abcd'4 bytes'abcd'5 bytes
'abcdefgh''abcd'4 bytes'abcd'5 bytes
 由於使用 CHAR 型態儲存資料時,MySQL 會以空白字元填補至最大儲存長度,所以無論存入的內容為何,所需的儲存空間都是固定的。當資料內容少於最大儲存長度時,VARCHAR 將可以有效地節省空間,這是它最大的優點;檢索時擁有較佳的效率,則是 CHAR 的長處。
 VARCHAR 和各類 TEXT 與 BLOB 都是長度可變的型態。當一資料表中同時選用 CHAR 和這類長度可變的型態時,CHAR 會被自動改為 VARCHAR,除非它的最大儲存長度少於 4。
 另一方面,若資料表中 VARCHAR 欄位的最大儲存長度少於 4 時,其型態也會被自動改為 CHAR。因為少於 4 bytes 的欄位在節省空間方面,實在沒多大的效果,不如改為 CHAR 以加快檢索的速度。

TEXT 與 BLOB
 BLOB 的全名是「binary large object」,與 TEXT 一樣,都是用來儲存長度較長的字串或是二元資料。兩者大同小異,唯一的差別在於,TEXT 是有區分大小寫的,而 BLOB 不分。

ENUM 與 SET
 ENUM 與 SET 是特別的字串型態,有人稱之為「列舉(enumeration)」型態。這兩種欄位的值只能從固定的項目中挑選,不能隨心所欲的存入資料。舉個例子來看,我們想調查使用者的性別與年齡分布狀況,所以設定了以下兩種欄位:
 sex ENUM("M", "F")
 age ENUM("0-20", "21-30", "31-40", "41-50", "51-100")
 若使用者填答時輸入「男性,32 歲」,我們則要用程式處理它,分別以 sex 的第 1 個選項與 age 的第 3 個選項存入。像 age 這個欄位,它已經將原始的輸入值以分組的形式來儲存,日後我們將無法得知使用者當時所輸入的精確數值。
 ENUM 型態最多可以建立 65535 個不同的成員,而 SET 型態少得多,只能建立 64 個不同的成員。除了「容量」有別之外,兩者還有一項相異之處:SET 型態可以從中挑選一組以上的值,而 ENUM 只能選其一。換句話說,ENUM 型態是單選,而 SET 型態則是複選。
 subject SET("Chinese", "English", "Math", "Music", "Art", "Sport")
 這是一個 SET 型態的例子,使用者在從上述 subject 欄位挑選所修習的科目時,就可以同時挑選多個項目。


摘自:http://chensh.loxa.edu.tw/php/C_2.php

2008年1月21日 星期一

JQuery的技巧總結

一、簡介

1.1、概述
隨著WEB2.0及ajax思想在 互聯網上的快速發展傳播,陸續出現了一些優秀的Js框架,其中比較著名的有Prototype、YUI、jQuery、mootools、Bindows 以及國內的JSVM框架等,通過將這些JS框架應用到我們的項目中能夠使程式師從設計和書寫繁雜的JS應用中解脫出來,將關注點轉向功能需求而非實現細節 上,從而提高專案的開發速度。

jQuery是繼prototype之後的又一個優秀的Javascript框架。它是由 John Resig 於 2006 年初創建的,它有助於簡化 JavaScript™ 以及Ajax 程式設計。有人使用這樣的一比喻來比較prototype和jQuery:prototype就像Java,而jQuery就像ruby. 它是一個簡潔快速靈活的JavaScript框架,它能讓你在你的網頁上簡單的操作文檔、處理事件、實現特效並為Web頁面添加Ajax交互。

它具有如下一些特點:
1、代碼簡練、語義易懂、學習快速、文檔豐富。
2、jQuery是一個羽量級的腳本,其代碼非常小巧,最新版的JavaScript包只有20K左右。
3、jQuery支持CSS1-CSS3,以及基本的xPath。
4、jQuery是跨流覽器的,它支持的流覽器包括IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+。
5、可以很容易的為jQuery擴展其他功能。
6、能將JS代碼和HTML代碼完全分離,便於代碼和維護和修改。
7、外掛程式豐富,除了jQuery本身帶有的一些特效外,可以通過外掛程式實現更多功能,如表單驗證、tab導航、拖放效果、表格排序、DataGrid,樹形功能表、圖像特效以及ajax上傳等。

jQuery的設計會改變你寫JavaScript代碼的方式,降低你學習使用JS操作網頁的複雜度,提高網頁JS開發效率,無論對於js初學者還是資深專家,jQuery都將是您的首選。

jQuery適合於設計師、開發者以及那些還好者,同樣適合用於商業開發,可以說jQuery適合任何JavaScript應用的地方,可用於不同的Web應用程式中。

官方網站:http://jquery.com/
中文網站:http://jquery.org.cn/

1.2、目的
通過學習本文檔,能夠對jQuery有一個簡單的認識瞭解,清楚JQuery與其他JS框架的不同,掌握jQuery的常用語法、使用技巧及注意事項。

二、使用方法
在需要使用JQuery的頁面中引入JQuery的js檔即可。
例如:
<script type="text/javascript" src="js/jquery.js"></script>
引入之後便可在頁面的任意地方使用jQuery提供的語法。

三、學習教程及參考資料
請參照《jQuery中文API手冊》和http://jquery.org.cn/visual/cn/index.xml
推薦兩篇不錯的jquery教程:《jQuery的起點教程》和《使用 jQuery 簡化 Ajax 開發》
(說明:以上文檔都放在了【附件】 中)

四、語法總結和注意事項

1、關於頁面元素的引用
通過jquery的$()引用元素包括通過id、class、元素名以及元素的層級關係及dom或者xpath條件等方法,且返回的物件為jquery物件(集合物件),不能直接調用dom定義的方法。

2、jQuery物件與dom物件的轉換
只有jquery物件才能使用jquery定義的方法。注意dom物件和jquery物件是有區別的,調用方法時要注意操作的是dom物件還是jquery物件。
普通的dom物件一般可以通過$()轉換成jquery物件。
如:
$(document.getElementById("msg"))
則為jquery物件,可以使用jquery的方法。

由於jquery物件本身是一個集合。所以如果jquery物件要轉換為dom物件則必須取出其中的某一項,一般可通過索引取出。

如:$("#msg")[0],$("div").eq(1)[0],$("div").get()[1],$("td")[5]這些都是dom物件,可以使用dom中的方法,但不能再使用Jquery的方法。
以下幾種寫法都是正確的:

$("#msg").html();
$("#msg")[0].innerHTML;
$("#msg").eq(0)[0].innerHTML;
$("#msg").get(0).innerHTML;


3、如何獲取jQuery集合的某一項
對於獲取的元素集合,獲取其中的某一項(通過索引指定)可以使用eq或get(n)方法或者索引號獲取,要注意,eq返回的是jquery對象,而get(n)和索引返回的是dom元素物件。對於jquery物件只能使用jquery的方法,而dom物件只能使用dom的方法,如要獲取第三個<div>元素的內容。有如下兩種方法:

$("div").eq(2).html(); //調用jquery物件的方法
$("div").get(2).innerHTML; //調用dom的方法屬性


4、同一函數實現set和get
Jquery中的很多方法都是如此,主要包括如下幾個:

$("#msg").html(); //返回id為msg的元素節點的html內容。
$("#msg").html("<b>new content</b>");
//將“<b>new content</b>” 作為html串寫入id為msg的元素節點內容中,頁面顯示粗體的new content

$("#msg").text(); //返回id為msg的元素節點的文本內容。
$("#msg").text("<b>new content</b>");
//將“<b>new content</b>” 作為普通文本串寫入id為msg的元素節點內容中,頁面顯示粗體的<b>new content</b>

$("#msg").height(); //返回id為msg的元素的高度
$("#msg").height("300"); //將id為msg的元素的高度設為300
$("#msg").width(); //返回id為msg的元素的寬度
$("#msg").width("300"); //將id為msg的元素的寬度設為300

$("input").val("); //返回表單輸入框的value值
$("input").val("test"); //將表單輸入框的value值設為test

$("#msg").click(); //觸發id為msg的元素的按一下事件
$("#msg").click(fn); //為id為msg的元素按一下事件添加函數

同樣blur,focus,select,submit事件都可以有著兩種調用方法

5、集合處理功能
對於jquery返回的集合內容無需我們自己迴圈遍歷並對每個物件分別做處理,jquery已經為我們提供的很方便的方法進行集合的處理。
包括兩種形式:

$("p").each(function(i){this.style.color=['#f00','#0f0','#00f'][i]})
//為索引分別為0,1,2的p元素分別設定不同的字體顏色。

$("tr").each(function(i){this.style.backgroundColor=['#ccc','#fff'][i%2]})
//實現表格的隔行換色效果

$("p").click(function(){alert($(this).html())})
//為每個p元素增加了click事件,按一下某個p元素則彈出其內容

6、擴展我們需要的功能
$.extend({
min: function(a, b){return a < b?a:b; },
max: function(a, b){return a > b?a:b; }
}); //為jquery擴展了min,max兩個方法
使用擴展的方法(通過“$.方法名”調用):
alert("a=10,b=20,max="+$.max(10,20)+",min="+$.min(10,20));


7、支援方法的連寫
所謂連寫,即可以對一個jquery物件連續調用各種不同的方法。
例如:

$("p").click(function(){alert($(this).html())})
.mouseover(function(){alert('mouse over event')})
.each(function(i){this.style.color=['#f00','#0f0','#00f'][i]});


8、操作元素的樣式
主要包括以下幾種方式:

$("#msg").css("background"); //返回元素的背景顏色
$("#msg").css("background","#ccc") //設定元素背景為灰色
$("#msg").height(300); $("#msg").width("200"); //設定寬高
$("#msg").css({ color: "red", background: "blue" });//以名值對的形式設定樣式
$("#msg").addClass("select"); //為元素增加名稱為select的class
$("#msg").removeClass("select"); //刪除元素名稱為select的class
$("#msg").toggleClass("select"); //如果存在(不存在)就刪除(添加)名稱為select的class


9、完善的事件處理功能
Jquery已經為我們提供了各種事件處理方法,我們無需在html元素上直接寫事件,而可以直接為通過jquery獲取的物件添加事件。
如:

$("#msg").click(function(){alert("good")}) //為元素添加了按一下事件
$("p").click(function(i){this.style.color=['#f00','#0f0','#00f'][i]})
//為三個不同的p元素按一下事件分別設定不同的處理
jQuery中幾個自訂的事件:
(1)hover(fn1,fn2):一個模仿懸停事件(滑鼠移動到一個物件上面及移出這個物件)的方法。當滑鼠移動到一個匹配的元素上面時,會觸發指定的第一個函數。當滑鼠移出這個元素時,會觸發指定的第二個函數。
//當滑鼠放在表格的某行上時將class置為over,離開時置為out。
$("tr").hover(function(){
$(this).addClass("over");
},
function(){
$(this).addClass("out");
});
(2)ready(fn):當DOM載入就緒可以查詢及操縱時綁定一個要執行的函數。
$(document).ready(function(){alert("Load Success")})
//頁面載入完畢提示“Load Success”,相當於onload事件。與$(fn)等價
(3)toggle(evenFn,oddFn): 每次點擊時切換要調用的函數。如果點擊了一個匹配的元素,則觸發指定的第一個函數,當再次點擊同一元素時,則觸發指定的第二個函數。隨後的每次點擊都重複對這兩個函數的輪番調用。
//每次點擊時輪換添加和刪除名為selected的class。
$("p").toggle(function(){
$(this).addClass("selected");
},function(){
$(this).removeClass("selected");
});
(4)trigger(eventtype): 在每一個匹配的元素上觸發某類事件。
例如:
$("p").trigger("click"); //觸發所有p元素的click事件
(5)bind(eventtype,fn),unbind(eventtype): 事件的綁定與反綁定
從每一個匹配的元素中(添加)刪除綁定的事件。
例如:
$("p").bind("click", function(){alert($(this).text());}); //為每個p元素添加按一下事件
$("p").unbind(); //刪除所有p元素上的所有事件
$("p").unbind("click") //刪除所有p元素上的按一下事件


10、幾個實用特效功能
其中toggle()和slidetoggle()方法提供了狀態切換功能。
如toggle()方法包括了hide()和show()方法。
slideToggle()方法包括了slideDown()和slideUp方法。

11、幾個有用的jQuery方法
$.browser.流覽器類型:檢測流覽器類型。有效參數:safari, opera, msie, mozilla。如檢測是否ie:$.browser.isie,是ie流覽器則返回true。
$.each(obj, fn):通用的反覆運算函數。可用於近似地反覆運算物件和陣列(代替迴圈)。


$.each( [0,1,2], function(i, n){ alert( "Item #" + i + ": " + n ); });

等價於:

var tempArr=[0,1,2];
for(var i=0;i<tempArr.length;i++){
alert("Item #"+i+": "+tempArr[i]);
}

也可以處理json資料,如

$.each( { name: "John", lang: "JS" }, function(i, n){ alert( "Name: " + i + ", Value: " + n ); });

結果為:

Name:name, Value:John
Name:lang, Value:JS


$.extend(target,prop1,propN):用一個或多個其他物件來擴展一個物件,返回這個被擴展的物件。這是jquery實現的繼承方式。
如:
$.extend(settings, options);
//合併settings和options,並將合併結果返回settings中,相當於options繼承setting並將繼承結果保存在setting中。
var settings = $.extend({}, defaults, options);
//合併defaults和options,並將合併結果返回到setting中而不覆蓋default內容。
可以有多個參數(合併多項並返回)
$.map(array, fn):陣列映射。把一個陣列中的專案(處理轉換後)保存到到另一個新陣列中,並返回生成的新陣列。
如:

var tempArr=$.map( [0,1,2], function(i){ return i + 4; });
tempArr內容為:[4,5,6]
var tempArr=$.map( [0,1,2], function(i){ return i > 0 ? i + 1 : null; });
tempArr內容為:[2,3]
$.merge(arr1,arr2):合併兩個陣列並刪除其中重複的項目。
如:$.merge( [0,1,2], [2,3,4] ) //返回[0,1,2,3,4]
$.trim(str):刪除字串兩端的空白字元。
如:$.trim(" hello, how are you? "); //返回"hello,how are you? "


12、解決自訂方法或其他類庫與jQuery的衝突
很多時候我們自己定義了$(id)方法來獲取一個元素,或者其他的一些js類庫如prototype也都定義了$方法,如果同時把這些內容放在一起就會引起變數方法定義衝突,Jquery對此專門提供了方法用於解決此問題。
使用jquery中的jQuery.noConflict();方法即可把變數$的控制權讓渡給第一個實現它的那個庫或之前自訂的$方法。之後應用Jquery的時候只要將所有的$換成jQuery即可,如原來引用物件方法$("#msg")改為jQuery("#msg")。
如:

jQuery.noConflict();
// 開始使用jQuery
jQuery("div p").hide();
// 使用其他庫的 $()
$("content").style.display = 'none';


摘自:http://www.hotajax.cn/content/view/206/237/

3G&3.5G的差別

3G跟3.5G都可以上網,只是3G就384K,3.5G可以到1.8M,3.6M,7.2M(目前是3.6M)。
WiFi:距離短200M就不錯了,穿透力差,但佈網成本低,使用公用的頻段,干擾多,適合短距離傳輸。
WCDMA:就是統稱的3G,傳資料只有384K。
HSDPA:就常說的3.5G,是在WCDMA的系統上將它原本的384K升級到1.8M,3.6M,7.2M,讓整個系統的傳輸效率增加。
另外可與HSDPA可以對抗的是Wimax系統,他的傳輸功能不會低於HSDPA,且建置成本會低,但實際會怎樣,全世界還沒有真正的使用,明年看看有沒有機會看到Wimax。
好不好主要是看你的使用方式來決定。

摘自:http://tw.knowledge.yahoo.com/question/?qid=1007110405520

2008年1月4日 星期五

[Manual]PHP adodb中文手冊

ADODB

PHP在資料庫的支援上是很令人稱道的,幾乎所有的知名資料庫系統都有對應的函數群支援,而且支援的很完整。但很不幸的,每一群資料庫支援函數無論在名稱或參數結構上,都有很大的差異,這使得PHP的系統開發者在面臨更換資料庫時,總會覺得痛苦萬分。難道這個問題就沒有解決方法嗎?呵呵,當然有,答案就是我現在要介紹的 ADODB 這個PHP物件。

ADODB提供了完整的方法和屬性讓工程師去控制資料庫系統,更棒的是你只要記得它的功能就好了,因為不同的資料庫系統,只要修改一個屬性值就可以了,ADODB會自動依據設定取用正確的PHP函數。此外,最多再配合資料庫系統修改修改SQL指令,你的PHP系統就可以在最短的時間內更換到另一個資料庫系統了,如果在撰寫程式時,對SQL指令能做妥善規劃,那就更快了。

經過以上的介紹,相信你已經對ADODB的功用有所瞭解,以下為ADODB的詳細介紹。

取得ADODB

你可以在 http://php.weblogs.com/ADOdb 取得最新版的ADODB。我在撰寫本文時,最新版本是1.99版,版權采BSD-Style及LGPL雙軌制,換句話就是Freeware,沒有什麼限制。但在取得ADODB後,最好還是要看一下相關版權說明及用法,並和本文對照一下,以免錯誤。

使用ADODB

基本上使用ADODB是相當容易的,取得壓縮檔後解開,我建議將整個內容都解到ADODB的目錄裡。然後你可以一邊參考本文,一邊研究裡面的範例,就放在裡面的test目錄下。

由於ADODB附上的說明十分完整詳實,以下的說明大部份來自ADODB的readme.htm,這裡不是全部的內容,我把一些我認為沒有用的內容都去掉了,像版本差異說明、何撰寫支援ADODB的驅動程式等與應用無關的部份。想要瞭解全部內容的讀者還是可以自己去參考 readme.htm。



簡介

由於PHP的資料庫存取函數沒有標準化,所以我們需要一組函數庫或是類別來隱藏不同資料庫函數介面間的差異,讓我們可以很簡單的去切換資料庫,而這,就是ADODB的目的。

ADODB目前支援MySQL, Oracle, Microsoft SQL Server, Sybase, Sybase SQL Anywhere, Informix, PostgreSQL, FrontBase, Interbase (Firebird 及 Borland 版本), Foxpro, Access, ADO 和 ODBC。ADODB也有透過ODBC成功連結Progress及DB2的報告,我們希望能有更的人提供驅動介面來支援更多的資料庫。

PHP4支援連結變數(session variables),使用者可以透過ADODB儲存連結資訊,以達成真正的可攜性及彈性,相關的用法及資訊請自行參考ADOdb-session.php這個範例。

另外,如果要撰寫一個具有高度可移植性的SQL碼,也可以參閱 http://php.weblogs.com/portable_sql 這篇文章。

特色

  • 對熟悉Windows的工程師而言,ADODB很容易使用,因為ADODB裡的很多功能和Microsoft的ADO很像。

  • 與其它的PHP資料庫類別不同,它們大多集中在處理與 select 指令有關的東西,而ADODB對於 inserts 及 update 也提供額外的支援,並且可以很快的連結到多資料庫。所提供的方法更擴及日期的掌握,字串的連結及字串標記字元差異處理(在某些資料庫間字串的連結和標記符號是有差異的)

  • 型別對照系統是內建的,所以我們可以設定或描述像CHAR,TEXT及STRING在不同的資料庫間其實是相同的資料型別。

  • 更容易去移植,因為所有與資料庫相依的程式碼被都隱藏在後端,所以使用者不再需要去移植類別裡的邏輯。

  • 支援 PHP4 連結變數,請參考 ADOdb-session.php。

安裝

首先要確定你所使用的PHP版本是 4.01pl2 或是之後的版本(因為ADODB使用到了 require_once及include_once兩個函數)。解壓縮全部的檔案到你的Web伺服器可以存取的一個目錄裡。

要測試ADODB你需要一個資料庫,開啟 testdatabase.inc.php 這個檔案,並且修改連結參數,以適合你所使用的資料庫。這個程式會建立一個新的資料表在你的資料庫中,以支援我們提供的測試程式及範例。

就這樣,你安裝好了。

啟動ADODB

當要執行ADODB時,至少有兩個檔案要被載進來,第一個是 ADOdb.inc.php ,這裡面包含了所有資料庫類中要被使用的函數。而對資料庫實作的程式碼則被置放在ADOdb-????.inc.php檔案裡。

例如說,要連結一個mysql資料庫:

include('/path/to/set/here/ADOdb.inc.php');
$conn = &ADONewConnection('mysql');

無論何時你需要連結到一個資料庫時,你必需使用ADONewConnection()函數建立了一個連結物件。ADONewConnection接受一個選擇性參數, <database-name-here>。如果沒有參數被指定,它將會使用被 ADOLoadCode() 所載入的最後一個資料庫。 NewADOConnection() 是另一個相同的函數。

當你建立好一個連結物件時,你並沒有真的連結上你的資料庫。你仍需要使用 $conn->Connect() 或者 $conn->PConnect() 兩個方法來完成真正的連結。

你可以參考教學手冊裡的範例,對上面的說明做更深入的瞭解。

支援的資料庫

名稱 測試狀態 資料庫 RecordCount() 支援與否 需安裝的驅動程式 作業系統
access B Microsoft Access/Jet. 需要建立一個 ODBC/DSN。 Y/N ODBC Windows only
ado B 一般未經特別指定的資料庫系統, 透過ADO,允許不設定 DSN連結,使用OLEDB以提供較佳的效能。 ? 視資料庫而定 ADO or OLEDB provider Windows only
ado_access B Microsoft Access/Jet 透過ADO,允許不設定 DSN連結,使用OLEDB以提供較佳的效能。 Y/N ADO or OLEDB provider Windows only
ado_mssql B Microsoft SQL Server 透過ADO,允許不設定 DSN連結,使用OLEDB以提供較佳的效能。 Y/N ADO or OLEDB provider Windows only
db2 C DB2. 可以透過ODBC獲得可以信賴的運作效果。 Y/N DB2 CLI/ODBC interface Unix and Windows. Unix install hints.
vfp A Microsoft Visual FoxPro,需要建立一個ODBC/DSN Y/N ODBC Windows only
fbsql C FrontBase. Y ? Unix and Windows
ibase B Interbase 6或更早的版本。有些使用者報告必需使用如下的方式連結
$db->PConnect('localhost:c:/ibase/employee.gdb', "sysdba", "masterkey")目前沒有支援 Affected_Rows 方法
Y/N Interbase client Unix and Windows
firebird C interbase的Firebird版本 Y/N Interbase client Unix and Windows
borland_ibase C Borland 的Interbase 6.5 或更新版 Y/N Interbase client Unix and Windows
informix C Informix Y/N Informix client Unix and Windows
mssql A Microsoft SQL Server 7.也可以和Microsoft SQL Server 2000運作的很好。但在日期格式上仍有一些問題。例如在日期時間的回傳值上,就不會回傳秒數數值。 Y/N Mssql client Unix and Windows.
Unix install howto
.
mysql A MySQL 不支援交易處理 Y/N MySQL client Unix and Windows
mysqltmaxsql A MySQL 支援交易處理 Y/N MySQL client Unix and Windows
oci8 A Oracle 8/9. 支援比 oracle 驅動程式還多的功能 (例如: Affected_Rows). 在連結之前,你可能需要先配好環境變數('ORACLE_HOME=...') 有兩個方式進行連結,用伺服器的IP或服務名稱:
PConnect('serverip:1521','scott','tiger','service')
PConnect('', 'scott', 'tiger', 'tnsname').
Y/N Oracle client Unix and Windows
oci8po A Oracle 8/9 可攜式驅動程式 Y/N Oracle client Unix and Windows
odbc A 標準 ODBC 用 PConnect('DSN','user','pwd').連結。 ? depends on database ODBC Unix and Windows. Unix hints.
odbc_mssql C 用 ODBC 連接 MSSQL Y/N ODBC Unix and Windows.
odbc_oracle C 用 ODBC 連接 ORACLE Y/N ODBC Unix and Windows.
oracle C 支援舊的 Oracle 7 client API. 不支援 $ADODB_FETCH_MODE. Y/N Oracle client Unix and Windows
postgres A PostgreSQL 不支援 LIMIT 指令. Y PostgreSQL client Unix and Windows.
postgres7 A PostgreSQL 支援 LIMIT 及其它版本 7 功能 Y PostgreSQL client Unix and Windows.
sqlanywhere C Sybase SQL Anywhere. Y/N SQL Anywhere ODBC client ?
sybase C Sybase. Y/N Sybase client Unix and Windows. Unix hints.

測試狀態欄的代碼說明如下:

A=已經經過很多人驗證及測試,可靠度最高。
B=已經測試並使用了,但可能仍有一些功能沒有達成。
C=使用者自行配置或試用的驅動程式,可能沒有完全支援ADODB的功能。

"RecordCount()支援與否",指的是RecordCount()函數是否會回傳用SELECT指令取得的記錄筆數(不支援時傳回-1)。如果這個欄位的值出現了 Y/N ,那表示當全域變數 $ADODB_COUNTER=true 時,會以模擬的方式取得,而這是預設值。要注意的是,如果你預測記錄筆數會很大時,最好把這個值設為false,也就是關掉這個模擬功能,因為這會耗掉非常多的記憶體,以做為快取之用。由於這個變數在每次執行時都會檢查,所以你可以選擇性的使用或不使用。

所有支援$ADODB_FETCH_MODE的資料庫都支援 ADODB_FETCH_NUM(以欄位順序存取) 及 ADODB_FETCH_ASSOC(以欄位名稱存取),兩種模式。而將值設為 ADODB_FETCH_DEFAULT(資料庫預設模式存取),則是由資料庫的功能來決定的,所以不具備可攜性,而 ADODB_FETCH_BOTH(雙模式存取) 也一樣。


學習手冊

範例 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');

參考手冊

以[]包起來的參數為選用參數,可有可無。

共用變數

$ADODB_COUNTRECS

當本變數($ADODB_COUNTRECS)被設為 true 時,如果資料庫驅動程式介面(API)不支援回傳被 SELECT 指令所選取的資料筆數,那麼 RecordCount() 函數將會自動模擬,並回傳正確的資料筆數,預設值即為 true。模擬方式是建立一個記憶體暫存區來放置這些資料,因此當取回的資料筆數很大時,會佔用很大量的記憶體。當設定本變數值為 false 時,會有最好的效能。本變數在每次執行查訊時都會自動檢查,所以你可以依實際需要在每次查詢前進行設定。

$ADODB_CACHE_DIR

如果你使用了資料集快取功能,那麼那些快取資料都會被置放到這個變數所指定的目錄裡。所以當你要使用諸如 CacheExecute() 函數前,你應該要先設定好本變數。期於安全的考量,如果你要使用 $ADODB_CACHE_DIR,我們建議你將在 php.ini 裡的 register_globals 設成 off。

$ADODB_FETCH_MODE

這個共用變數決定了資料集以那種方式將資料傳給陣列。資料集在被建立時(如 Execute()或SelectLimit())會把本變數($ADODB_FETCH_MODE)的值保存下來,而隨後本變數($ADODB_FETCH_MODE)的任何改變都不會影響到現存的資料集,只有在以後資料集被建立起來時才會改變。

以下為為已定義的常數:

define('ADODB_FETCH_DEFAULT',0);
define('ADODB_FETCH_NUM',1);
define('ADODB_FETCH_ASSOC',2);
define('ADODB_FETCH_BOTH',3);

以下為一個使用的例子:

$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); # 顯示 array([0]=>'v0',[1] =>'v1')
print_r($rs2->fields); # 顯示 array(['col1']=>'v0',['col2'] =>'v1')

在本範例中,如你所見兩個資料集在被Execute()建立時,會依據 $ADODB_FERCH_MODE 的值來決定儲存及使用的存取模式。

如果沒有任何的模式被設定,預設值則是 ADODB_FETCH_DEFAULT。呈現的模式則依據資料庫驅動程式而有所不同。為了可攜性,我們建議你固定為 ADODB_FETCH_NUM 及 ADODB_FETCH_ASSOC,因為有許多驅動程式並不支援 ADODB_FETCH_BOTH 。


ADOConnection

提供連結資料庫,執行SQL指令以及一組准格式化的SQL相關函數等功能的物件。

ADOConnection 屬性

databaseType: 要連結的資料庫系統名稱,如 odbc,mssql,mysql…等。詳細內容請參考上表。

dataProvider: 下層的資料庫結結機制,除了使用 odbcado 外,一般正常會設為 native

host: 資料庫主機名稱,可用IP或來源名稱(DSN)進行連結。如203.74.225.22 , dbs1.nukepro.com , "localhost" , "odbc_dsn1"

database: 資料庫或連結名稱,如果使用了 ado,則會控制 ado 資料提供驅動程式(ado data provider)。

user: 登入時的 ID,密碼則基於安全考量沒有保留。

raiseErrorFn: 允許你定義一個錯誤處理函數,請參考 ADOdb-errorhandler.inc.php 的範例.

debug: 被設定為 true 時,會顯示除錯訊息。

concat_operator: 連結運算元,一般會設為 '+' 或 '||'。這個運算元是為了在 SQL 裡連結字串的。會在 Concat 函數中被用到。

fmtDate: 日期格式,在DBDate函數中會使用到,做為送日期資料到資料庫的依據。在Access格式為'#Y-m-d#',在MySQL格式為"\Y-m-d\"。

fmtTimeStamp: 時間格式,在 DBTimeStamp 函數中要送時間資料到資料庫時會使用到。

true: 資料中真值的表現方式,如在Foxpro用'T',MS SQL用'1'。

false: 資料中假值的表現方式,如在Foxpro用'F',MS SQL用'0'。

replaceQuote: 這個字串用來處理逸出符號。例如在 Microsoft SQL 裡的雙引號,MySQL裡的反斜線符號。主要使用於 qstr

autoCommit: 設定是否啟動自動交易模式,預設值為 true。

charSet: 設定使用的字元集,目前只有 interbase 支援。

metaTablesSQL: 使用SQL指令,以回傳一份可用的資料表清單。例如在 MySQL 裡的 SHOW TABLES。

genID: 如果資料庫有支援的話,這裡會存放由GetID()所取得的最後值。

cacheSecs: 快取資料集的秒數。用於當使用者利用 CacheExecute() 或 CacheSeletLimit() 函數,又沒有設定 $secs2cache 參數時的預設值。

sysDate: 利用資料庫函數去取得目前的日期和時間。會使用到原生的日期時間標記格式。


ADOConnection 主要函數

ADOConnection( )

建構函數,請不要直接呼叫,使用 ADONewConnection() 來代替。

Connect($host,[$user],[$password],[$database])

對伺服器或資料來源 $host 非持續性連結,使用者認證代碼為 $user ,密碼為 $password ,如果伺服器支援多資料庫,則指定連結到資料庫 $database

連結成功回傳 true , 失敗則回傳 false 。

注意:如果你使用的是 Microsoft ADO,而非 OLEDB,你可以設定 $database 參數為你正在使用的 OLEDB 資料供應器。

PostgreSQL:另一種選擇性的連結方法是將標準的PostgreSQL連結字串放在 $host 參數里,那麼其它的參數都會被呼略。

對於 Oracle 及 Oci8,有兩個方法可以連結。第一,使用你定義的區域 tnsnames.ora 裡的 TNS 名稱,將這個名稱放在 $database 參數里,然後將 $host 設為 false。另一種方法,設定 $host 為伺服器,而 $database 則設成資料庫 SID ,這將會不透過 tnsnames.ora 連結。

範例:

$conn->Connect(false, 'scott', 'tiger', 'name_in_tnsnames'); # 使用 tnsnames.ora
$conn->Connect('server:1521', 'scott', 'tiger', 'OracleSID'); # 不使用 tnsnames.ora

還有許多的資料庫連結範例在網站 php.weblogs.com/ADOdb 以及在本版所附的 testdatabase.inc.php 檔案裡。

PConnect($host,[$user],[$password],[$database])

對伺服器或資料來源 $host 持續性連結,使用者認證代碼為 $user ,密碼為 $password ,如果伺服器支援多資料庫,則指定連結到資料庫 $database

連結成功回傳 true , 失敗則回傳 false 。其它資料請參考 Connect()。

Execute($sql,$inputarr=false)

執行 SQL 指令 $sql ,如果成功,就回傳一個對應的 ADORecordSet 物件。要注意的是這個指令如果執行成功時,一定會回傳一個資料集,即使是執行 insert 或 update 指令也一樣。

回傳對應的 ADORecordSet 物件。例如,如果連結的是 mysql ,那麼 ADORecordSet_mysql 將會被回傳。當SQL指令執行失敗時會回傳 false 值。

$inputarr 參數則用來做為傳入的結合變數。以下是 Oracle 的範例:

$conn->Execute("SELECT * FROM TABLE WHERE COND=:val", array('val'=> $val));

另一個例子,使用 ODBC ,以 '?' 符號做為協定。

$conn->Execute("SELECT * FROM TABLE WHERE COND=?", array($val));

結合變數(Binding variables)
變數的結合可以加速SQL指令編譯及快取的速度,產生較佳的效能。目前只有 Oracle 及 ODBC 支援變數結合。 ODBC 類的 ? 結合在不支援的資料庫裡,是以模擬的方式來做到的。

變數結合在 odbc 及 oci8po 驅動程式裡的用法。

$rs = $db->Execute('select * from table where val=?', array('10'));

變數結合在 oci8 驅動程式裡的用法。

$rs = $db->Execute('select name from table where val=:key',array('key' => 10));

CacheExecute($secs2cache,$sql,$inputarr=false)

類似於 Execute 函數,除了將資料集暫存在 $ADODB_CACHE_DIR 指定的目錄裡 $secs2cache 秒外。如果 CacheExecute() 被相同的參數、資料庫、使用者ID及密碼,而且快取也沒有過期,那麼快取中的資料集將會被傳回。

include('ADOdb.inc.php');
include('tohtml.inc.php');
$ADODB_CACHE_DIR = '/usr/local/ADOdbcache';
$conn = &ADONewConnection('mysql');
$conn->PConnect('localhost','userid','password','database');
$rs = $conn->CacheExecute(15, 'select * from table'); # 快取15秒
rs2html($rs); /* recordset to html table */

另外,從ADODB 1.80 版起,$secs2cache 參數成為選擇性(也就是可以不加)

$conn->Connect(...);
$conn->cacheSecs = 3600*24; // cache 24 hours
$rs = $conn->CacheExecute('select * from table');

如果 CacheExecute() 被多次呼叫,而且資料集也持續在快取中,$secs2cache 參數不會延長被快取的資料集保留時間(因為會被呼略掉),CacheExecute()只能使用在 SELECT 指令上。

效能備註:我曾經作了一些效能測試,並且發現這些快取的效益極為顯著。尤其是在資料庫伺服器運作效率慢於WEB伺服器或資料庫的負荷非常重的時候。ADODB的快取好在它減少了資料庫伺服器的負荷。當然,如果你的資料庫伺服器負荷不大,而且運作速度也比WEB伺服器快,那快取反而會降低效能。

SelectLimit($sql,$numrows=-1,$offset=-1,$inputarr=false)

執行成功會回傳一個資料集。完成一個SELECT指令,類似於 PostgreSQL中 SELECT 指令裡的LIMIT $numrows OFFSET $offset 宣告。

在 PostgreSQL,SELECT * FROM TABLE LIMIT 3 將會只傳回從頭開始的三筆記錄。相同的,$connection->SelectLimit('SELECT * FROM TABLE',3)也有同樣的意思。

而 SELECT * FROM TABLE LIMIT 3 OFFSET 2 將會回傳記錄 3,4及5三筆(也就是在記錄2之後,回傳三筆記錄)。相同的,在ADODB裡是以 $connection->SelectLimit('SELECT * FROM TABLE',3,2) 來做的。

要注意,LIMIT宣告,在MySQL裡是相反位置的。你可以設定 $connection->SelectLimit('select * from table',-1,10) 去取得從第11筆起到最後一筆的記錄。

最後一個參數 $inputarr 是針對支援變數結合功能的資料庫,像 Oracle oci8。這個大大的減少了 SQL 編譯的負荷。底下是 Oracle 範例:

$conn->SelectLimit("SELECT * FROM TABLE WHERE COND=:val", 100,-1,array('val'=> $val));

oci8po 驅動程式(oracle portable driver)使用更為標準的變數結合:

$conn->SelectLimit("SELECT * FROM TABLE WHERE COND=?", 100,-1,array('val'=> $val));

Ron Wilson 報告說 SelectLimit 在SQL指令有含 UNION 時會無效,並且建議了針對 mssql 的對策:

> 事實上,我發現一個可以立即最佳化的建構 Select Union 方法。這適用於 MS-SQL,至於 其它資料庫是否適合,就不確定了。當更新求助檔時,你可以參考這個範例。注意,這個方 法不適用於 MySQL。
>
> 改變:
> Select column1 From table1
> Union
> Select column2 From table2
>
> 成為:
> Select * From (
> Select column1 From table1
> Union
> Select column2 From table2
> )
> As dummytable
>
> Ron

CacheSelectLimit($secs2cache, $sql, $numrows=-1,$offset=-1,$inputarr=false)

類似於 SelectLimit,除了將資料集暫存在 $ADODB_CACHE_DIR 指定的目錄裡 $secs2cache 秒外。

自 1.80版起,$secs2cache成為了選擇性參數:

$conn->Connect(...);
$conn->cacheSecs = 3600*24; // 快取24小時
$rs = $conn->CacheSelectLimit('select * from table',10);

CacheFlush($sql)

更新(刪除)以 $sql 指令存放在 $ADODB_CACHE_DIR 指定目錄內的全部快取資料集。如果你企圖更新所有的快取資料集,請執行如下的PHP指令碼(僅針對 Unix 有效):system("rm -f find ".ADODB_CACH_DIR." -name ADODB_*.cache") ;

ErrorMsg()

回傳最後狀態或是錯誤訊息。即使沒有錯誤發生,本函數也會回傳一個字串。一般情況下,你不需要呼叫這個函數,除非ADODB函數因為錯誤狀態回傳了false值。

注意:如果 debug 旗標被啟動了,SQL 錯誤訊息將會在Execute函數被呼叫時發生錯誤後出現。

ErrorNo()

回傳最後的錯誤號碼。注意一點,舊版本的 PHP(4.0.6以前),不支援ODBC的錯誤編號。一般情況下,你不需要呼叫這個函數,除非ADODB函數因為錯誤狀態回傳了false值。

GenID($seqName = 'ADOdbseq',$startID=1)

產生一個順序號碼(在mssql是一個整數值)。對 interbase,mysql,postgresql,oci8,oci8po,ODBC核心類驅動程式(如 access,vfp,db2等等) 都支援。使用 $seqName做為順序名。如果資料庫沒有值,那麼GenID()將會自動為你產生一個序號(產生使用者 id 時允許如此),換句話說,你必需自行建立序號。

如果你的資料庫驅動程式要模擬序號,資料表的名稱就是序號名(sequence name),而這個資料表必需有一個欄位"id",而其資料型別為整數,或你需要更大些的 numeric(16)。

對於沒有支援序號原生功能的ODBC及資料庫(如 mssql,mysql),我們對每一個序號建立一個資料表。如果序號沒有被預先定義,那啟如的號碼值就設定成 $startID。

注意,mssql驅動程式的 GenID()會產生一個16位元的GUID。自1.90版起,我們將回傳整數。

UpdateBlob($table,$column,$val,$where)

允許你以 $where 條件儲存一個BLOB(存在 $val裡的)值到 $table 裡的 $column 欄位。

例:

# for oracle
$conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, empty_blob())');
$conn->UpdateBlob('blobtable','blobcol',$blobvalue,'id=1');

# non oracle databases
$conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
$conn->UpdateBlob('blobtable','blobcol',$blobvalue,'id=1');

如果成功,會回傳 true ,否則回傳 false 值。目前有 MySQL, PostgreSQL, Oci8, Oci8po 及 Interbase 支援。其它驅動程式可能有效,仍在持續開發中。

要注意,在PHP 4.1.0 以前的版本,當 Interbase的 blob 值被 SELECT 取回值時,它仍需要被解碼,請使用 $connection->DecodeBlob($blob); 以還原它的內容。

UpdateClob($table,$column,$val,$where)

允許你以 $where 條件儲存一個BLOB(存在 $val裡的)值到 $table 裡的 $column 欄位。類似於 UpdateBlog,但主要針對文字大型檔案物件。

例:

# for oracle
$conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, empty_clob())');
$conn->UpdateBlob('clobtable','clobcol',$clobvalue,'id=1');

# non oracle databases
$conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)');
$conn->UpdateBlob('clobtable','clobcol',$clobvalue,'id=1');

UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')

如同 UpdateBlob ,但我們將值改成一個檔案路徑,將整個檔案存入。

成功回傳 true 否則為 false。

GetUpdateSQL(&$rs, $arrFields, $forceUpdate=false,$magicq=false)

建立一個 SQL 以更新一個被給予的資料集 $rs ,被修改的欄位存放在陣列 $arrFields中(這個陣列必需是具名陣列,欄位名為索引,值為修正值),會與原來的資料集做一個比較,如果 $forceUpdate被設為 true,那麼即使 $arrFields與 $rs->fields完全相同,也會產生出更新的SQL指令。資料集必需在連結狀態。$magicq 被用於指出魔術引號功能是否被啟動。

GetInsertSQL(&$rs, $arrFields,$magicq=false)

建立一個 SQL 以新增一筆記錄到被給予的資料集 $rs。這個查詢必需是在連結狀態。$magicq 被用於指出魔術引號功能是否被啟動。

PageExecute($sql, $nrows, $page, $inputarr=false)

使用資料集的頁碼功能,參數 $page 是以 1 為啟使值,請參考範例 8.

CachePageExecute($secs2cache, $sql, $nrows, $page, $inputarr=false)

使用資料集的頁碼功能,參數 $page 是以 1 為啟使值,請參考範例 8.PageExecute 的快取版。

Close( )

關閉資料庫的連結。PHP4 以資料庫連結結束時不需要特別去清除而享有盛名,因為其參考計數機制會自動幫我們清除掉。

BeginTrans( )

啟始一筆交易。會關閉自動結案功能。執行成功會回傳 true 。如果不支援交易功能,部份資料庫會一直傳回 false 值。Interbase,Oracle 及 MSSQL 支援交易機制。請注意,因為 PHP 4.02 版的臭蟲,交易支援在微軟的 ADO 上是無效的。你必需使用你關連式資料庫的原生交易支援功能。當連結結束時,任何開啟的交易都會被還原。

CommitTrans( )

成功的結束一次交易。如果成功,回傳 true。如果資料庫並不支援交易功能,那麼就只會傳回 true ,以表示資料總是交易成功的。

RollbackTrans( )

結束一次交易,恢復所有改變。執行成功會回傳 true 。如果資料庫並不支援交易功能,那麼就只會傳回 false ,以表示資料總是不能恢復。

GetOne($sql)

Executes the SQL and returns the first field of the first row as an array. The recordset and remaining rows are discarded for you automatically. If an error occur, false is returned.

執行SQL指令,並且以陣列的方式回傳第一筆記錄的第一個欄位。資料集及其餘的記錄將會被自動清除,如果發生錯誤,就回傳 false 值。

譯者註:這個功能在驗證某筆記錄在不在特別有用,可以減少系統記憶體及資源的用量。

GetRow($sql)

執行SQL指令,並且以陣列的方式回傳第一筆記錄。資料集及其餘的記錄將會被自動清除,如果發生錯誤,就回傳 false 值。

Prepare($sql )

預先編譯一個SQL查詢,以便於重覆執行。如果有任何語法錯誤,Prepare()不會顯示任合錯誤,但允許 Execute() 去取得及顯示錯誤。內部實作支援 interbase ,oci8 及選擇性的 ODBC-based 驅動程式。其餘的都是以模擬的方式支援。在模擬的情況下,使用 Prepare() 對效能的增進沒有任何效果。

回傳一個包含了原始描述為第一個陣列元素的陣列,其餘的元素內容則視驅動程式而定。如果有錯誤或是模擬方式的 Prepare(),會回傳原來的 $sql 字串。那是因為所有的錯誤處理都被集中到 Execute() 裡去了。

範例 :

$stmt = $DB->Prepare('insert into table (col1,col2) values (?,?)');
for ($i=0; $i < $max; $i++)
    $DB->Execute($stmt,array((string) rand(), $i));

PrepareSP($sql)

在 mssql 驅動程式裡,預編譯預儲程式必需要透過一個特別的函數來呼叫 mssql_init(),這個動作目前由本函數來處理了。PrepareSP() 可以在所有的驅動程式由被呼叫,而且以呼叫 Prepare() 的方式來模擬。使用範例請參考以下的 Parameter() 說明。

和上面的 Prepare() 回傳一樣的陣列或 $sql 字串。

Parameter($stmt, $var, $name, $isOutput=false, $maxLen = 4000, $type = false )

在運作中增加一個結合參數。目前相容於 Microsoft SQL 及 Oracle oci8。以下是參數說明:


$stmt 由 Prepare() 或 PrepareSP() 回傳的指令。
$var 要結合的 PHP 變數。
$name 要結合的預儲程序的變數名。
[$isOutput] 設定參數傳導的方向,0/false = IN 1=OUT 2= IN/OUT 。 在 oci8 中這個參數會被忽略,因為驅動程式會自動偵測。
[$maxLen] 參數變數的最大長度。
[$type] 參考 mssql_bindocibindbyname 在 PHP.NET 的文件說明以取得更多正確值的資訊。

在 mssql,$opt 可以被下列的元素所影響:mssql_bind and ocibindbyname 。 例如 ;

# @RETVAL = SP_RUNSOMETHING @myid,@group
$stmt = $db->PrepareSP('SP_RUNSOMETHING');
# note that the parameter name does not have @ in front!
$db->Parameter($stmt,$id,'myid');
$db->Parameter($stmt,$group,'group',false,64);
# return value in mssql - RETVAL is hard-coded name
$db->Parameter($stmt,$ret,'RETVAL',true);
$db->Execute($stmt);

一個 oci8 的例子:

# 對於 oracle, Prepare 及 PrepareSP 是相同的
$stmt = $db->PrepareSP(
        "declare ret integer;
    begin
        :RETVAL := SP_RUNSOMETHING(:myid,:group);
    end;");
$db->Parameter($stmt,$id,'myid');
$db->Parameter($stmt,$group,'group',false,64);
$db->Parameter($stmt,$ret,'RETVAL',true);
$db->Execute($stmt);

請注意,在 oci8 及 mssql 間只有語法上的不同,那是各資料庫實作 SQL 語法問題,ADODB 對於這一部份無能為力。

如果 $type 參數被設定成 false 。在 mssql ,$type 將會動態的由 PHP 變數傳來的型別決定(string => SQLCHAR, boolean =>SQLINT1, integer =>SQLINT4 或 float/double=>SQLFLT8),在 oci8,$type 可以被設成 OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) 及 OCI_B_ROWID (ROWID)。如果要傳入空值,使用 $db->Parameter($stmt, $null=null, 'param')。

最後,在 oci8,結合參數可以重覆被使用,而無需再一次呼叫 PrepareSP() 或 Parameters。但這對 mssql 是不行的。一個 oci8 的範例如下:

$id = 0; $i = 0;
$stmt = $db->PrepareSP( "update table set val=:i where id=:id");
$db->Parameter($stmt,$id,'id');
$db->Parameter($stmt,$i, 'i');
for ($cnt=0; $cnt < 1000; $cnt++) {
    $id = $cnt;
    $i = $cnt * $cnt; # oci8 下可以運作
    $db->Execute($stmt); }

Bind($stmt, $var, $size=4001, $type=false, $name=false)

這是一個低階函數,只有 oci8 驅動程式支援。只有你確定系統僅支援 Oracle 否則請避免使用它。Parameter() 函數是使用結合變數的另一個建議方式。

Bind() 允許你使用結合變數在你的 sql 敘述中。這裡結合一個PHP變數給一個在之前被 Prepare() 預先編譯的 Oracle sql 敘述裡定義的名稱。Oracle 以一個冒號為開頭來命名一個變數,而且 ADODB 需要一個被命名的變數去對應 :0,:1,:2,:3,等等。第一次被 Bind() 取得的將會代入 :0,而第二次將會代入 :1,依此類推。對 insert , select 及 update 指令,結合可以提供 100% 的效能提升。

在其餘的參數里,$size 設定資料儲存的暫存區大小,$type 是 OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) 及 OCI_B_ROWID (ROWID) 的類別選項。最後,代替使用預設的 :0,:1 等等名稱,你可以使用 $name 來定義你自己的連結名稱。

接下來的例子展示3個連結變數,使用 p1,p2及p3來結合。這些變數將會配到 :0 , :1 及 :2 。

$stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)");
$DB->Bind($stmt, $p1);
$DB->Bind($stmt, $p2);
$DB->Bind($stmt, $p3);
for ($i = 0; $i < $max; $i++) {
    $p1 = ?; $p2 = ?; $p3 = ?;
    $DB->Execute($stmt);
}

你也可以使用名稱變數:

$stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:name0, :name1, :name2)");
$DB->Bind($stmt, $p1, "name0");
$DB->Bind($stmt, $p2, "name1");
$DB->Bind($stmt, $p3, "name2");
for ($i = 0; $i < $max; $i++) {
    $p1 = ?; $p2 = ?; $p3 = ?;
    $DB->Execute($stmt);
}

ADOConnection 公用函數

BlankRecordSet([$queryid])

不再使用,本版已移除。

Concat($s1,$s2,....)

產生一個結合 $s1,$s2,..等 sql 字串的字串,使用了在 concat_operator 欄位定義的結合運算符號。如果結合運算符號不被使用,那這個函數將無效,例如 MySQL 。

本函數回傳含結合符號的字串。

DBDate($date)

格式化 $date 成資料庫可以接收的格式,這可以是一個 Unix 整數時間記錄格式或是一個 ISO 格式的 Y-m-d。使用 fmtDate 欄位所定義的格式。如果傳入的是 null 或是 false 或是 '' ,那將會轉成一個 SQL 的 null。

回傳一個日期字串。

DBTimeStamp($ts)

格式化時間記錄格式的 $ts 成資料庫可接受的格式。這可以是一個 Unix 整數時間記錄格式或是一個 ISO 格式的 Y-m-d。使用 fmtDate 欄位所定義的格式。如果傳入的是 null 或是 false 或是 '' ,那將會轉成一個 SQL 的 null。

回傳一個時間字串。

qstr($s,[$magic_quotes_enabled=false])

將一個字串放在引號內,以送到資料庫中。$magic_quotes_enabled 參數可能看起來很有趣,但這個想法是假設你已經用一個引號來處理了從 POST/GET 變數取來的字串後,然後以 get_magic_quotes_gpc() 做為第二個參數。這會確定這個變數不會被引號處理二次,一次被 qstr 處理,一次被 magic_quotes_gqc

例如: $s = $db->qstr(HTTP_GET_VARS['name'],get_magic_quotes_gpc());

回傳值是一個被引號處理過的字串。

Affected_Rows( )

回傳被SQL指令更新或被刪除掉的資料筆數。如果資料庫不支援,回傳一個 false 值。

目前 interbase/firebird 不支援本函數。

Insert_ID( )

回傳最後插入時的自動增進值 ID。如果系統不支援,回傳 false。

只支援有提供自動增進或物件 ID 的資料庫,目前像是 PostgreSQL, MySQL 以及 MSSQL 都有。PostgreSQL 回傳一個 OID,可以在資料庫重載入時改變。只有使用持續連結方式,當你完成一筆交易時,這個函數才會有精確的結果。這是因為被 Execute() 宣告的連結可能和下一個 Execute() 時用的連結不同。

MetaDatabases()

回傳一個在伺服器中的資料庫清單于陣列裡。首先你必需連結到伺服器。目前只支援 ODBC, MySQL 及 ADO。

MetaTables()

回傳目前資料庫中全部資料表名稱於一個陣列中。如果可能,這個陣列將會排除系統目錄資料表。

MetaColumns($table)

回傳一個 ADOFieldObject 的陣列,一個欄位物件對應到一個 $table 的所有行。目前 Sybase 不能辨別資料型別,ADO 不能辨識正確的資料型別(所以我們預設為 varchar)..

MetaColumnNames($table)

回傳 $table 的行名於一個陣列中。


ADORecordSet(資料集)

當一個SQL指令成功的被 ADOConnection->Execute($sql)執行後,一個 ADORecordSet 物件會被回傳回來。這個物件提供了一個虛擬的指標,所以我們可以移動它,從一筆到一筆。也提供一些函數,以取得欄位資訊和欄位類別,並有協助函數去格式化結果,以展示給使用者看。

ADORecordSet 屬性

fields: 包含了目前記錄的陣列。不是關連式陣列,但它的索引值是從 0 到 欄位數 - 1。請參考函數 Fields ,這個函數的動作就像是一個關連式陣列。

dataProvider: 連結資料庫的底層機制,正常設定為 native ,除非是使用 odbcado

blobSize: 一個 char , string 或者 varchar object 在被轉成 Blob 前的最大長度(Blob 在顯示時應該使用 textarea)。其它請參考 MetaType 函數。

sql: 儲存了建立本資料集所使用的 sql 指令。

canSeek: 如果 Move() 函數有作用,會被設成 true 。

EOF: 當指標被移動到最後一筆時,這個值會被設定成 true 。

ADORecordSet 函數

ADORecordSet( )

建構函數。一般來說你不需要自己呼叫這個函數。

GetAssoc([$force_array])

如果欄位數大於 2 ,那麼從資料集中產生一個關連式陣列。這個陣列是從目前的指標起一直到檔尾(EOF)。這個資料集的第一個欄位會成為陣列的索引。如果欄位數剛好是2,當這陣列被每一個鍵值所建立時,那麼索引會直接對應到值,除非 $force_array 被設成 true 。

範例:

以下是我們資料集的資料:

列1: Apple, Fruit, Edible
列2: Cactus, Plant, Inedible
列3: Rose, Flower, Edible

GetAssociation 將會產生一個如下的關聯式陣列:

Apple => [Fruit, Edible]
Cactus => [Plant, Inedible]
Rose => [Flower,Edible]

回傳值:

關連式陣列,錯誤則傳回 false 。

GetArray([$number_of_rows])

從目前指標位置產生一個陣列,索引值從 0 到 $number_of_rows - 1 。如果 $number_of_rows 沒有被定義,那會到檔尾(EOF)。

GetRows([$number_of_rows])

是 GetArray() 的同義函數,是為了與 Microsoft ADO 相容才有的。

GetMenu($name, [$default_str=''], [$blank1stItem=true], [$multiple_select=false], [$size=0], [$moreAttr=''])

建立一個 HTML 選單 (<select><option><option></select>) 。資料集的第一欄 (fields[0]) 將會作為 <option> 裡的顯示字串。如果資料集有超過一個以上的欄位,第二欄 (fields[1]) 將設定成回傳給WEB伺服器的值(即 value)。選單將被給予 $name 為名稱。

如果 $default_str 被定義了,那麼如果 $default_str == fields[0] , 那麼這個欄位將會被選取。 如果 $blank1stItem 為 true ,那第一個選項將會是空值。$Default_str 在對於可多選清單盒時,可以是一個陣列。

要產生一個選單區,設定 $size 為一個非 0 值(或者傳入 $default_str 為一個陣列)。如果 $multiple_select 為 true ,那麼一個選單區將會被產生成有 $size 個項目可見的選單(如果 $size == 0 那預設為 5 個),而且ADODB將會回傳一個陣列給伺服器。最後,你可以使用 $moreAttr 去增加其它的屬性,像是 javascript 或樣式表。

選單範例 1: GetMenu('menu1','A',true) 將會產生一個像這樣的選單 : A B C 這裡的資料 (A,1), (B,2), (C,3). 請參考 範例 5

選單範例 2: 相同的資料, GetMenu('menu1',array('A','B'),false) 將會產生一個 A 及 B 被選取的選單 : A B C

GetMenu2($name, [$default_str=''], [$blank1stItem=true], [$multiple_select=false], [$size=0], [$moreAttr=''])

近似於 GetMenu ,除了 $default_str 將會和 fields[1] 做比對,也就是選項值。

選單范例 3: 給予在範例 2 裡的資料 , GetMenu2('menu1',array('1','2'),false) 將會產生一個選單,A及B將會被選取。然而,這一次的被選取的比對基準是第二個欄位,也就是存放要被回傳給伺服器裡的值。

UserDate($str, [$fmt])

轉換日期字串 $str 為另一個格式,UserDate 呼叫 UnixDate 來解譯 $str ,而 $fmt 預設值是 Y-m-d 。

UserTimeStamp($str, [$fmt])

轉換時間字串 $str 為另一個格式,時間字串格式是 Y-m-d H:i:s , 像是 "2002-02-28 23:00:12"。UserTimeStamp 呼叫 UnixTimeStamp 來解譯 $str ,而 $fmt 預設值為 Y-m-d H:i:s 。

UnixDate($str)

將日期字串 $str 解譯,並且轉換成 unix mktime 格式(從 1970.01.01 00:00:00 起到現在的秒數)後傳回。預設日期是以 Y-m-d H:i:s 格式來傳入的。而對於 Sybase 及 Microsoft SQL Server 而言 M d Y 也是可以接受的(三個字元的月份表示法是被一個全域陣列所控制的,這個部份可能需要在地化 )。

自 1.91 版起,這個函數存在於 ADORecordSet 及 ADOConnection兩個地方。

UnixTimeStamp($str)

將時間字串 $str 解譯,並且轉換成 unix mktime 格式(從 1970.01.01 00:00:00 起到現在的秒數)後傳回。預設日期是以 Y-m-d H:i:s 格式來傳入的。而對於 Sybase 及 Microsoft SQL Server 而言 M d Y 也是可以接受的(三個字元的月份表示法是被一個全域陣列所控制的,這個部份可能需要在地化 )。

自 1.91 版起,這個函數存在於 ADORecordSet 及 ADOConnection兩個地方。

MoveNext( )

移動內部指標到下一筆,fields 陣列將會自動的更新。如果不能移動,會回傳 false 值,其它情況則會回傳 true 。

範例 :

$rs = $db->Execute($sql);
if ($rs)
    while (!$rs->EOF) {
        ProcessArray($rs->fields);
        $rs->MoveNext();
    }

Move($to)

移動內部指標到指定的列 ($to) 。 列數是零基的,例如,0是第一列。fields 陣列將會自動更新。對於不支援內部捲動的資料庫,ADODB將會自動模擬捲動。部份資料庫不支援向後捲動。對大多數的資料庫言,如果 $to 的位置在 EOF 之後,$to 將會被移動到資料集的最後一筆。有些無名的資料庫使用 odbc 時,可能會沒有動作。

注意:這個函數使用了絕對定址,不像 Microsoft 的 ADO。

回傳值是 true 或是 false。如果是 false ,這個內部指標在大多數的實際運作上並沒有移動,所以 AbsolutePosition() 將會回傳指標在執行 Move() 之前最後的位置

MoveFirst()

實際上是呼叫 Move(0) 。注意,有一些資料庫並不支援這個函數。

MoveLast()

實際上是呼叫 Move(RecordCount() - 1)。注意,有一些資料庫並不支援這個函數。

GetRowAssoc($toUpper=true)

這個函數並不能持續的以理想的方式維持關連陣列的內容(每換一筆記錄,就要重新執行一次)。使用 $ADODB_FETCH_MODE 共用變數來替代它。

回傳一個包含了目前記錄的關連式陣列,陣列的索引值就是欄位名。欄位名全都是大寫的,以便存取。要取得下一筆記錄,你要呼叫 MoveNext() 。

範例 :
Array ( [ID] => 1 [FIRSTNAME] => Caroline [LASTNAME] => Miranda [CREATED] => 2001-07-05 )

注意:不要同時使用 GetRowAssoc() 和 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC 。因為他們有相同的功能,會彼此交互干擾。

AbsolutePage($page=-1)

回傳目前的頁碼,需要先呼叫 PageExecute() / CachePageExecute() 。參考 Example 8

AtFirstPage($status='')

如果在第一頁,回傳 true (1基式),需要先呼叫 PageExecute() / CachePageExecute() 。參考 Example 8

AtLastPage($status='')

如果在最後一頁,回傳 true (1基式),需要先呼叫 PageExecute() / CachePageExecute() 。參考 Example 8

Fields($colname)

不鼓勵使用,請改以 $ADODB_FETCH_MODE 取代。

當使用原生函數庫時,有些資料庫函數回傳具名及索引雙陣列(如 MySQL)。GetRowAssoc() 並不回傳結合了具名及索引的陣列元素。

本函數回傳由 $colname 所指欄名,在目前記錄裡的的欄位值。

欄位名區分大小寫。

FetchRow()

回傳目前記錄內容的陣列,如果是檔尾(EOF),回傳 false 。注意:不要把 FetchRow 和 MoveNext() 混用。

用法 :

$rs = $db->Execute($sql);
    if ($rs)
        while ($arr = $rs->FetchRow()) {
            # process $arr
        }

FetchInto(&$array)

設定 $array 到目前的記錄裡。如果在檔尾(EOF),回傳 PEAR_Error 物件。如果成功,回傳 1 (DB_OK 常數)。

如果 PEAR 未定義,當 EOF 時回傳 false 。FetchRow() 很容易使用,請參考之前的例子。

FetchField($column_number)

回傳一個物件,包含了所指欄位的名稱,類別及最大長度。如果最大長度不能被明確決定,將會回傳 -1 。 行號是以 0 基為計算起點的,請參考 範例 2

FieldCount( )

回傳資料集裡欄位數。

RecordCount( )

回傳資料集裡的記錄筆數。如果無法從資料庫驅動程式API裡取得正確的數字,ADODB將會把所有的記錄內容,存放在記憶體裡,等全部取完後,再回傳記錄總筆數。這個記憶體可以藉由設定全域變數 $ADODB_COUNTERECS = false 而被取消(基於執行效能的理由)。當取消後,對某些資料庫,RecordCount() 將會回傳 -1 。相關支援狀況,請參考前面的資料庫支援表有詳細的說明。

RowCount 和 RecordCount 是同義函數。

PO_RecordCount($table, $where)

回傳在資料集裡的記錄筆數。如果資料庫不支援,那麼將回傳對 $table 資料表下達以 $where 為條件的 SELECT COUNT(*) 指令後回傳的值。

$numrows = $rs->PO_RecordCount("articles_table", "group=$group");

會回傳資料庫執行 SELECT COUNT(*) FROM articles_table WHERE group=$group 的結果。

FetchObject($toupper=true)

回傳目前的記錄為一個物件。如果 $toupper 為 true ,那麼物件欄位名將會設為大寫。注意:較新的 FetchNextObject() 是取得記錄物件較被建議的方式,請參看後續說明。

FetchNextObject($toupper=true)

取得目前的記錄成一個物件,並且自動移動到下一個記錄。如果在檔尾,回傳 false 。如果 $toupper 為 true ,那麼物件欄位名將會設為大寫。

$rs = $db->Execute('select firstname,lastname from table');
if ($rs) {
    while ($o = $rs->FetchNextObject()) {
        print "$o->FIRSTNAME, $o->LASTNAME<BR>";
    }
}

在使用 FetchNextObject() 時會影響效能,如果效能很重要,你應該使用 fields[] 陣列來存取。

CurrentRow( )

目傳目前資料集的記錄編號,0 表示是第一筆。

AbsolutePosition( )

和 CurrentRow 是相同的函數,是為了和 ADO 相容而存在的。

MetaType($nativeDBType[,$field_max_length],[$fieldobj])

設定資生資料庫裡的原生型別 $nativeDBType 為那一種通用資料型別,以及它的最大長度。請注意,如果長度未知,可以設為 -1 。欄位物件可以使用 $fieldobj 傳入。這對於像是 mysql 這一類欄位物件有較多屬性的資料庫來說,是很有用的。

使用欄位 blobsize 及比較 $field_max_length 去決定目前的欄位是否為 blob 。

回傳值:

  • C: character 欄位,應該使用 <input type="text"> 標記來取值。

  • X: 文字欄位(Text) , 長文字欄位,使用 <textarea> 標記來顯示資料。

  • B: Blob 欄位或者大型的二位元物件(像程式,圖檔等)。

  • D: 日期欄位

  • T: 時間欄位

  • L: 邏輯欄位(真假值)或位元欄位

  • N: 數字欄位,包含自動進位、編號、整數、浮點數、實數等。

  • I: 整數欄位

  • R: 序列欄位,包含了序列、自動增進整數,只對被選擇的資料庫作用。

Close( )

關閉目前的資料集。


function rs2html($adorecordset,[$tableheader_attributes], [$col_titles])

這是一個獨立的函數 (rs2heml = recordset to html) ,相當於 PHP 中的 odbc_result_all 函數。本函數會輸出一整個 ADORecordSet,$adorecordset 如同一個 HTML表格。$tableheader_attributes 允許你控制表格裡的參數如 cellpadding,cellspacing 及 border 等的屬性。最後,你可以透過 $col_titles 陣列,更換資料庫欄位名稱,使用你自己的欄位抬頭。這是設計用來快速除錯的機制,不是一個好的表格記錄瀏覽器。

要使用這個函數,你必需引入 tohtml.inc.php 。

rs2html 範例:

<?
include('tohtml.inc.php'); # load code common to ADOdb
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);
rs2html($rs,'border=2 cellpadding=3',array('Customer Name','Customer ID'));
?>

感謝
------------------

PHP ADODB 1.99版手冊中文翻譯 Tripc <tripc.tw@yahoo.com.tw>

摘自:http://www.codepub.com/online/adodb/adodb.html

2008年1月2日 星期三

[常識]yy[yonex]羽球線介紹




 彈性擊球音吸震性控制性耐久性
BG-6566668
BG-65TI77667
BG-65P77668
BG-6697775
BG-68TI98776
BG-70Pro76567
BG-75TI87568
BG-8087666
BG-8588776
BG-88TI77686
CBG-100869106


YONEX羽球線簡介

BG-65
粗度: 0.70mm
材料: 線芯材料為多層樹脂,外層材料為化學合成數脂編束纖維.
敘述: 耐磨性及經濟性極佳,歷來銷售量最大,深受羽球高手好評. 適合各種球員.
市價: 約100上下
使用感想: 夠經濟實惠, 怎麼用都行 .

BG-65Ti
粗度: 0.70mm
材料: 線芯材料為化學合成多層樹脂, 外層材料為樹脂編束纖維, 纖維表面採用新形氫鈦合金塗覆技術.
敘述: 彈性持久, 耐磨性極佳, 擊球感硬而有力, 可承受高羽線磅數. 適合攻擊型球員.
市價: 約150上下
使用感想: 這鈦線有夠滑, 感覺很不穩, 我個人比較不推薦此線. 不過此線可以穿高磅數, 適合喜愛高磅數的球友

BG-65Power
粗度: 0.70mm
材料: 線芯材料為多層樹脂, 外層材料為化學合成數脂編束纖維, 外層另有一層液晶塗料加強球線強度.
敘述: 耐磨, 可承受高磅數, 適合攻擊型球員.
市價: 約350上下 (日本限定線)
使用感想: 和65是一樣的構造, 只是外層多加了一層塗料. 但是價錢變成3倍. 使用起來沒有太大的差別. 不值得阿.

BG-66
粗度: 0.66mm
材料: 線芯材料為多層樹脂, 外層材料為化學合成數脂編束纖維.
敘述: 超細線徑使其具有絕佳的彈性跟吸震性能, 擊球音清脆響亮. 適合靈巧型球員.
市價: 約150上下
使用感想: 聲音超大聲, 只有一個爽字可形容. 但是易斷, 建議你去學穿線之後再來用此線比較好.

BG-68Ti
粗度: 0.68mm
材料: 線芯材料為化學合成多層樹脂, 外層材料為樹指編束纖維, 纖維表面採用新形氫鈦合金塗覆技術.
敘述: 高質量,高彈性, 擊球感堅硬有力, 最適合用於鈦拍. 適合防守型球員.
市價: 約180上下
使用感想: 剛開始很不習慣這個線的滑, 後來覺得還ok, 彈力和性能都屬上乘, 但是耐久度平平.

BG-70PRO
粗度: 0.70mm
材料: 線芯材料為多層樹脂, 外層材料為卵形化學合成數脂編束纖維,
敘述: 耐磨, 可長期保持穩定的羽線張力, 最適合大力擊球者和塑膠球使用者.
市價: 約180上下
使用感想: 聲音很鈍, 聽起來難聽, 雖然可以維持球線磅數, 但是用起來只能算是加強版的65.

BG-75Ti
粗度: 0.70mm
材料: 線芯材料為化學合成多層樹脂, 外層材料為卵形化學合成樹指編束纖維, 纖維表面採用新形氫鈦合金塗覆技術.
敘述: 高質量, 高彈性, 高耐久性, 擊球感堅硬有力, 適合進攻型球員.
市價: 約350上下 (日本限定線)
使用感想: 這個線有點像是加強版的65TI, 彈力不錯, 打球聲音也很好聽. 價錢稍貴.

BG-80
粗度: 0.68mm
材料: 線芯材料為新形高係數VECTRAN纖維, 外層材料為卵形樹指編束纖維.
敘述: 擊球具有極佳的彈性與爆發力, 適合靈巧型球員. 由於VECTRAN纖維的關係, 建議穿線磅數應比BG65低5~10%.
市價: 約180上下
使用感想: 擊球感有點像是68TI但是聲音不同, 也沒有那麼滑. 中規中矩的特色適合傳統型球員使用

BG-85
粗度: 0.67mm
材料: 線芯材料為新形高係數VECTRAN纖維, 外層材料為多層樹脂編束纖維.
敘述: 彈性好, 高速擊球感硬而有力. 適合技術型球員. 由於VECTRAN纖維的關係, 建議穿線磅數應比BG65低5~10%.
市價: 約180上下
使用感想: 彈性很好, 容易斷, 聲音好聽, 控球性佳. 可以說是物超所值, 台灣地區目前性能最好的球線.

BG-88Ti
粗度: 0.69mm
材料: 線芯材料為新型高係數VECTRAN纖維, 外層材料為卵形化學合成樹指編束纖維. 纖維表面採用新型氫鈦合金塗覆技術,
敘述: 控制性極佳, 適合控制型和技術型的球員. 由於VECTRAN纖維的關係, 建議穿線磅數應比BG65低5~10%.
市價: 約350上下 (日本限定線)
使用感想: 控制性超好, 球線表面粗, 有利於控球. 聲音普通, 價錢偏高, 除非大量購買, 不然用久了會破產.

CBG-100
粗度: 0.70mm
材料: 線芯材料為新型中空型尼龍纖維, 外層材料為雙層捲繞化學合成樹指編束, 外層另有一層高強度塗料以增加對球線的控制性.
敘述:控制性是目前最佳, 擊球感接近羊腸線, 適合控制型球員
市價: 約400上下 (日本限定線)
使用感想: 為了模仿羊腸線的球感而設計的球線, 控制性超強, 但是不適合爆力型球員. 需要小心使用. 價錢十分昂貴.

摘自:http://www.badmintonrepublic.com/phpbb/viewtopic.php?t=1347

[常識]羽球拍的定位 - 攻擊 / 防守

[名詞解釋]sandbox / 沙盒 / 沙箱

sandbox / 沙盒 / 沙箱在英語當中的含義原是指家庭當中給小孩子用於啟蒙教育的箱子,裏面有沙子和水,可以任由孩子發揮想像 力塑造自己想要的世界。後來延伸成為系統設計當中用於進行試驗的組成部分。它的意思是你可以在裏面充分試驗 ,而不會對箱子外面的世界造成破壞和干擾。

wibiya widget