|
1.CLIENT/SERVER 到底是什么?
C/S屬于2-TIER系統(tǒng),適合于中小型應(yīng)用系統(tǒng)。大系統(tǒng)一般都用3-TIER了。 打個比方單機(jī)數(shù)據(jù)庫系統(tǒng)(比如VFP), 相當(dāng)于前店后庫.店里需要什么東西,得自己去庫房找,庫房管理也是有你自己進(jìn)行. 而C/S系統(tǒng)下,店和庫是相對獨(dú)立的,有一個專門的庫房管理(數(shù)據(jù)SERVER),店里需要什么,按照手續(xù)把單子給
庫房管理人員,由他們?nèi)ゲ僮? 因此可以看出C/S的優(yōu)點(diǎn): 支持多用戶; 更有效的數(shù)據(jù)管理,數(shù)據(jù)安全和可靠得多;遠(yuǎn)程使用數(shù)據(jù). 如果你是單機(jī)使用當(dāng)然沒有太大必要使用C/S了. 如果用VFP本身做C/S系統(tǒng), 效果不是很明顯,因?yàn)閂FP的數(shù)據(jù)管理功能不是很強(qiáng),比如加鎖解鎖都需要程序來操作. 我主要說的是VFP/sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)系統(tǒng). 2. sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺) sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)是微軟發(fā)布的RDBMS(關(guān)系數(shù)據(jù)庫管理系統(tǒng)), Oracle(大型網(wǎng)站數(shù)據(jù)庫平臺), INFOMIX,POWERBUILD,也都是類似的系統(tǒng). 他們就相當(dāng)于倉庫的管理系統(tǒng),但功能不僅僅是數(shù)據(jù)管理. 微軟的數(shù)據(jù)庫產(chǎn)品從功能和規(guī)模由小到大排列依次是: ACCESS, VFP, sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺). 稍微大一點(diǎn)的系統(tǒng),sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)是需要專人管理的,這就是DBA (DATABASE ADMINISTRATOR)的位置.現(xiàn)在北美人才市場上, DBA的工作比程序員的工作好找些. 工資比普通程序員略高, 工作穩(wěn)定性也強(qiáng)一些. sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)是一套大的軟件系統(tǒng),可以安裝在專門的NT數(shù)據(jù)SERVER上,也有個人版可以安裝在WIN95/98上, 主要是為了咱們這些程序員方便測試. 它的功能主要有這么幾塊: 數(shù)據(jù)庫的管理和維護(hù),用戶/安全管理, 數(shù)據(jù)的發(fā)布/轉(zhuǎn)換. 3. 用VFP/sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)做C/S系統(tǒng) VFP和sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)的搭配應(yīng)該是比較完美的, 但因?yàn)閂B才是微軟的主流產(chǎn)品(VB一直是微軟的,FOXPRO是后來才買的,后娘生的), 所以微軟從來沒有大力推薦或者宣傳過VFP, 而是把VFP獨(dú)有的數(shù)據(jù)庫技術(shù)融合到自己的其它產(chǎn)品里了: sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺), ODBC, OLE DB/ADO. 最近甚至把VFP從VISUAL STUDIO里獨(dú)立出來了. VFP和sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)的交流,可以通過3種方式進(jìn)行: A. 遠(yuǎn)程視圖 B. ADO控件 C. SPT (SQL PASS THROUGH) 3種方式各有優(yōu)缺點(diǎn), 而我最偏好第3種. 遠(yuǎn)程視圖和ADO都在VFP和sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)中間加了一個層次, 而這層次就相當(dāng)于一個黑箱,你不清楚它們到底怎么操作數(shù)據(jù)的,只需按照它們的規(guī)則進(jìn)行設(shè)置,使用 相應(yīng)的命令就可以. 反正我作為程序員,喜歡清楚地知道我的程序每一步都在干什么,所以我喜歡用SPT, 也從不用向?qū)斫⒈韱螆蟊硪活惖? SPT技術(shù)是通過VFP的函數(shù)SQLCONNECT()來和sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)建立連接, 然后用SQLEXEC()函數(shù)把要執(zhí)行的SQL命令 送到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)上去執(zhí)行, 所有對數(shù)據(jù)的操作都是通過這些SQL命令來進(jìn)行的. 每一個細(xì)節(jié)都由自己的代碼來控制. 4. VFP數(shù)據(jù)的升遷 VFP的數(shù)據(jù)庫,可以直接用VFP自帶的升遷向?qū)мD(zhuǎn)到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)上,但必須把所有的表都放到數(shù)據(jù)庫里,自由表不能直接升遷, 而實(shí)際上升遷上去的又只是表,數(shù)據(jù)庫本身不能轉(zhuǎn)到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)里. 感覺怪怪的. 也許是為了升遷索引或者關(guān)系吧. 要把VFP數(shù)據(jù)升遷到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)上, 必須先在sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)里建立相應(yīng)的數(shù)據(jù)庫. sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)的管理是通過ENTERPRISE MANAGER (EM)來進(jìn)行的. 通過它建立數(shù)據(jù)庫, 每個數(shù)據(jù)庫里可以包含 數(shù)據(jù)表,用戶/用戶群,視圖,存儲過程等等. 至于改用sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)后,原來的VFP程序是肯定需要修改的, 而且是比較大的改動. *************** 談?wù)刅FP和sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)搭配做C/S系統(tǒng) (二) --動態(tài)設(shè)置ODBC連接 1。設(shè)置ODBC數(shù)據(jù)源 VFP和sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)的連接是通過ODBC或者OLE DB(ADO)來進(jìn)行的??梢源蜷_控制面板的ODBC數(shù)據(jù)源進(jìn)行設(shè)置。但很多情況下,我們希望能在程序里動態(tài)設(shè)置數(shù)據(jù)源,一來可以不用去為每個用戶的機(jī)器手動設(shè)置, 二來為了數(shù)據(jù)的安全性,使用完后,希望把ODBC數(shù)據(jù)源刪掉。 下面的例子是用API函數(shù)來設(shè)置和刪除ODBC數(shù)據(jù)源。 函數(shù)名字是 SQLConfigDataSource,其中第二項參數(shù)是數(shù)字(1-增加 2-修改 3-刪除) DECLARE INTEGER SQLConfigDataSource IN odbccp32 INTEGER, INTEGER, STRING, STRING lnWindowHandle=0 lcODBCDriver='sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)' &&DRIVER類型 lcODBCName='SharedData' &&數(shù)據(jù)源名字 lcODBCDesc='Shared Data Source' &&數(shù)據(jù)源描述 lcODBCServer='DEVSQL' &&sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)名字 lcODBCDatabase='Shared' &&要連接的數(shù)據(jù)庫名字 **先試圖修改已有的ODBC,如果不存在,返回0。 lreturn=SQLConfigDataSource(lnWindowHandle, 2, lcODBCDriver, ; 'DSN=' + lcODBCName + CHR(0) ; + 'Description=' + lcODBCDesc + CHR(0) ; + 'Server=' + lcODBCServer + CHR(0) ; + 'Database=' + lcODBCDatabase + CHR(0)) IF lreturn=0 &&不存在 **添加新的ODBC lreturn=SQLConfigDataSource(lnWindowHandle, 1, lcODBCDriver, ; 'DSN=' + lcODBCName + CHR(0) ; + 'Description=' + lcODBCDesc + CHR(0) ; + 'Server=' + lcODBCServer + CHR(0) ; + 'Database=' + lcODBCDatabase + CHR(0)) IF lreturn=0 &&失敗 MessageBox('添加ODBC數(shù)據(jù)源失敗',16,'BUFFER') ENDIF ENDIF 2。刪除ODBC數(shù)據(jù)源 **用完后,可以在表單DESTROY事件里刪除ODBC。 如果不想重復(fù)設(shè)置參數(shù),可以把這些參數(shù)加到表單作為屬性。 DECLARE INTEGER SQLConfigDataSource IN odbccp32 INTEGER, INTEGER, STRING, STRING lnWindowHandle=0 lcODBCDriver='sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)' lcODBCName='SharedData' lcODBCDesc='Shared Data Source' lcODBCServer='DEVSQL' lcODBCDatabase='Shared' **先修改,或者其是否存在 lreturn=SQLConfigDataSource(lnWindowHandle, ; 2, lcODBCDriver, ; 'DSN=' + lcODBCName + CHR(0) ; + 'Description=' + lcODBCDesc + CHR(0) ; + 'Server=' + lcODBCServer + CHR(0) ; + 'Database=' + lcODBCDatabase + CHR(0)) IF lreturn=1 &&ODBC存在,刪除它 lreturn=SQLConfigDataSource(lnWindowHandle, ; 3, lcODBCDriver, ; 'DSN=' + lcODBCName + CHR(0) ; + 'Description=' + lcODBCDesc + CHR(0) ; + 'Server=' + lcODBCServer + CHR(0) ; + 'Database=' + lcODBCDatabase + CHR(0)) IF lreturn=0 MessageBox('刪除ODBC源失敗,16,'BUFFER') ENDIF ENDIF **清除DLL CLEAR DLLS 3. 從VFP連接到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺) lnHandle=SQLConnect("SharedData","用戶名”,“密碼”) If lnHandle>0 &&連接成功 **從庫里獲得數(shù)據(jù)(比如從EMP表里得到部門號為‘01’的職工) lnReturn=SQLExec(lnHandle,"Select * from Emp Where cDept='01'","CursorEmp") If lnReturn>0 &&運(yùn)行成功 Browse Else &&失敗 &&出錯處理 EndIf Else &&連接失敗 MessageBox("連接sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)失敗”,16,“BUFFER”) EndIf **用完連接后,最好馬上關(guān)閉,連接是很寶貴的資源,微軟是按連接數(shù)收費(fèi)的,而且每個連接會增加sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)的管理負(fù)擔(dān) =SQLDisconnect(lnHandle) *************** (續(xù)) (這些貼子必須連著看) 用SPT技術(shù)更新數(shù)據(jù)時,必須通過SQL命令進(jìn)行,SQL命令必須符合ANSI或者T-SQL(微軟的TRANSACTION SQL),因?yàn)槊钍峭ㄟ^VFP的SQLEXEC()函數(shù)送到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)去執(zhí)行的,語法必須遵守sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)的規(guī)則,而不是VFP的規(guī)則。不熟悉的人,最容易犯的錯誤就是把VFP的函數(shù)傳送到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)上執(zhí)行,結(jié)果總出錯。兩者大部分函數(shù)都是不一樣的。 比如ALLTRIM()是VFP的, sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)里是LTRIM()和RTRIM() VFP日期以{}分界,但sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)里不認(rèn),必須用單引號. 如果SQL命令里用到VFP程序里的變量,變量前必須加問號“?” 比如,更新一個表的字段 lcLName="Zhang" lcFName="San" lnReturn=SQLEXEC(連接句柄,“Update Emp Set cLName=?lcName, cFName=?lcFName Where cEmpNo='733000'") 如果返回值lnReturn>0,就更新成功了 插入記錄,或者逐條修改記錄時,只能每次操作一條記錄。 比如要把臨時表TmpEmp里的記錄加到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)的EMP表里,就得用循環(huán) Select TmpEmp Scan lnReturn=SQLEXEC(連接句柄,"Insert Into Emp (cEmpNo,cLName,cFName) values (?TmpEmp.cEmpNo,?cTmpEmp.cLName,?cTmpEmp.cFName)" EndScan *** 要得到sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)上某個表的結(jié)構(gòu),有兩種辦法,一是運(yùn)行sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)自帶的系統(tǒng)存儲過程。一是運(yùn)行一個SELECT命令。 比如要從sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺)得到EMP表的結(jié)構(gòu) lnReturn=SQLEXEC(連接句柄,"Select Top 0 * From Emp","TmpEmp") 返回的結(jié)果都是臨時表,是只讀的,要想變成可讀寫的,需要做點(diǎn)小變化: Select 0 Use DBF("TmpEmp") Again Alias Emp Use In TmpEmp 現(xiàn)在得到的EMP臨時表就是可讀寫的了。 *注 "Select Top 0 From Emp" 命令在VFP里是錯誤命令,但sql server(WINDOWS平臺上強(qiáng)大的數(shù)據(jù)庫平臺) SPT和使用視圖相比,優(yōu)點(diǎn)是每一步你都清楚自己在做什么,知道為什么命令會出錯。缺點(diǎn)是你需要多寫命令,多了解SQL SERVER的語法。 談?wù)刅FP和SQL SERVER搭配做C/S系統(tǒng) (五) --從VFP控制SQL SERVER事務(wù)處理和加鎖 **建立與SQL SERVER的連接 If lnHandle>0 && 設(shè)置成手工事務(wù)處理模式,由代碼來控制 **下面的命令從EMPPAY里選取記錄,并給該表加上獨(dú)占鎖(TABLELOCKX),一直到該事務(wù)結(jié)束(HOLDLOCK) ln1=SQLEXEC(lnHandle, "SELECT * FROM Emppay WITH (TABLOCKX, HOLDLOCK)","Emppay") **執(zhí)行其它命令,比如更新數(shù)據(jù) **如果所有命令都正確執(zhí)行了,則 ***如果要放棄整個事務(wù)處理,用 ***關(guān)閉連接,事務(wù)自動結(jié)束,鎖也解開 Else
****連接失敗 EndIf *** SQLSETPROP()函數(shù) 第3個參數(shù): 1 - 顯示登錄表單,如果登錄信息(用戶名,密碼)不完全 2 - 總顯示登錄表單 3 - 不顯示登錄表單 例如: 當(dāng)使用SPT技術(shù)時,為節(jié)約連接數(shù)減少服務(wù)器負(fù)擔(dān),需要經(jīng)常連接和斷開SQL SERVER,有時候你并不希望每次連接都讓用戶登錄,當(dāng)用戶首次登錄后,可以把名字和密碼存起來,以后的連接可以自動登錄了。 作為VFP程序員,我們深知索引對表的重要性,好的索引可以大大縮短程序讀取數(shù)據(jù)的時間。 1. 索引測試 從SQL SERVER程序組里或者ENTERPRISE MANAGER的TOOLS菜單上打開QUERY ANALYZER工具. 選一個沒有索引的大小適當(dāng)?shù)谋?然后執(zhí)行一條SELECT命令,你會看到運(yùn)行時間. select * from Chq where date >=′02/01/2001′ and date<=′02/28/2001′ 顯示的時間和讀寫情況: 然后我在CHQ表上對DATE字段建立索引,再運(yùn)行相同的SELECT, 得到如下結(jié)果: 比較兩個結(jié)果可以看出, 建立索引后,邏輯讀寫和預(yù)讀寫次數(shù)大大減少, 占用CPU時間從5.781秒減少到了0.704秒, 總運(yùn)行時間從23.526秒減少到6.432秒 2. 了解SQL SERVER的索引 SQL SERVER的數(shù)據(jù)文件和索引文件都是以頁為單位存放的,每頁是8K. 相當(dāng)于把磁盤劃分成8K大小的塊,以塊為單位存放數(shù)據(jù). SQL SERVER的索引有2大類, 不管是哪類索引,只要能到達(dá)目的,索引表達(dá)式(包含的字段)越簡單越有效. 什么字段作為物理索引最合適? 有兩個原則: 一是在根據(jù)范圍來選擇記錄時,哪個字段最有效, 二是在往磁盤上寫記錄是不會引起熱點(diǎn)(HOT SPOT). 我們用例子來看看這些原則怎么用. a. 用單據(jù)號, 其實(shí)這不是恰當(dāng)?shù)倪x擇. 因?yàn)楹苌儆懈鶕?jù)單據(jù)的范圍來選擇記錄的, 比如你很少用命令來查詢單據(jù)號大于或者小于某個值的記錄. 而且在輸入時,也比較容易產(chǎn)生熱點(diǎn), 因?yàn)椴迦氲挠涗浺话愣技釉诒砦?當(dāng)有大量用戶同時輸入時,會產(chǎn)生熱點(diǎn). 單據(jù)號不符合上面的2條原則. b. 用單據(jù)日期, 似乎是個比較適當(dāng)?shù)倪x擇. 因?yàn)榻?jīng)常需要用日期范圍來選擇記錄, 但同樣會因?yàn)榇罅坑脩敉瑫r輸入最新單據(jù)而在磁盤上引起熱點(diǎn). c. 用銷售地點(diǎn), 這應(yīng)該是最恰當(dāng)?shù)奈锢硭饕诉x了. 因?yàn)槲覀儠?jīng)常根據(jù)地點(diǎn)來選擇記錄, 而在同一時刻插入的記錄也不太可能來自同一個銷售地點(diǎn),避免了熱點(diǎn). 當(dāng)然,不同的環(huán)境下,你的選擇可能不同,比如你沒有成千上萬的用戶,就不太需要考慮熱點(diǎn)問題. 但要記住, 有唯一值的字段并不是物理索引的最佳選擇. 3. 選擇適當(dāng)?shù)腇illFactor 在SQL-CREATE INDEX命令里,有個FILLFACTOR選項, 這個選項對索引的效率是有很大作用的. 如果你的表經(jīng)常需要插入記錄, 選擇適當(dāng)?shù)腇ILLFACTOR就很重要了. 如果總是用100%, 當(dāng)你插入一個新記錄時, 由于每頁都是滿的, 就需要進(jìn)行分頁操作(把當(dāng)前頁分成2頁),頻繁的分頁操作會占用服務(wù)器的資源和時間,也降低索引文件的效率. 而如果你的FILLFACTOR不是100%,比如設(shè)為80%, 在插入新記錄時,由于當(dāng)前頁還有空間, 可以直接加入不需要分頁. 當(dāng)然, FILLFACTOR太低也會降低效率,因?yàn)槟菢拥脑?頁數(shù)就多了,搜索數(shù)據(jù)用的時間長,占用空間也多. 如果是只讀表,或者插入記錄很少的表,用100% FILLFACTOR最好. 對于經(jīng)常插入新記錄的表,需要定期重建索引, 因?yàn)樗饕募S著頁數(shù)的增加, 效率會越來越低. 因?yàn)樗饕际菢錉罱Y(jié)構(gòu), 當(dāng)下面的頁加得沒有規(guī)律時, 連接就會變亂, 重建索引可以重新整理樹狀結(jié)構(gòu). 4. 索引分析工具 在QUERY ANALYZER的QUERY菜單里,還有個選項PERFORM INDEX ANALYSIS. |
|
|