PB基礎(chǔ)知識(shí)版資料_第1頁(yè)
PB基礎(chǔ)知識(shí)版資料_第2頁(yè)
PB基礎(chǔ)知識(shí)版資料_第3頁(yè)
PB基礎(chǔ)知識(shí)版資料_第4頁(yè)
PB基礎(chǔ)知識(shí)版資料_第5頁(yè)
已閱讀5頁(yè),還剩120頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

PB基礎(chǔ)知識(shí)

.數(shù)據(jù)庫(kù)的事務(wù)管理

在數(shù)據(jù)庫(kù)中,所謂事務(wù)是指一組邏輯操作單元,使數(shù)據(jù)從一種狀態(tài)變換到另?種狀態(tài)。為

確保數(shù)據(jù)庫(kù)中數(shù)據(jù)的?致性,數(shù)據(jù)的操縱應(yīng)當(dāng)是離散的成組的邏輯單元:當(dāng)它全部完成時(shí),數(shù)

據(jù)的一致性可以保持,而當(dāng)這個(gè)單元中的一部分操作失敗,整個(gè)事務(wù)應(yīng)全部視為錯(cuò)誤,所有從

起始點(diǎn)以后的操作應(yīng)全部回退到開(kāi)始狀態(tài)。

對(duì)事務(wù)的操作是這樣進(jìn)行的:先定義開(kāi)始?個(gè)事務(wù),然后對(duì)數(shù)據(jù)作修改操作,這時(shí)如果提

交(COMMIT),這些修改就永久地保存下來(lái),如果回退(ROLLBACK),數(shù)據(jù)庫(kù)管理系統(tǒng)將放棄您所

作的所有修改而回到開(kāi)始事務(wù)時(shí)的狀態(tài)。此外有些數(shù)據(jù)庫(kù)支持事務(wù)的"存儲(chǔ)點(diǎn)(savepoint)這

一概念:即在一個(gè)事務(wù)進(jìn)程中任意一點(diǎn)您都可以進(jìn)行當(dāng)前狀態(tài)的存儲(chǔ),回退時(shí)只是回到你所設(shè)

定的存儲(chǔ)點(diǎn),而不必退回全部的事務(wù)。如果您的事務(wù)可以分成兒組對(duì)數(shù)據(jù)庫(kù)的修改,那就可以

設(shè)置多個(gè)存儲(chǔ)點(diǎn),根據(jù)需要您可以回退到任意一個(gè)存儲(chǔ)點(diǎn),而不使所有事務(wù)的修改數(shù)據(jù)全部丟

失。

正確地管理事務(wù)可以保證數(shù)據(jù)的完整性,當(dāng)您所做的工作全部完成和得到確認(rèn)之前,沒(méi)有

任何數(shù)據(jù)物理地寫(xiě)進(jìn)數(shù)據(jù)庫(kù)。讓我們來(lái)看這樣一個(gè)實(shí)例,我們有這樣一個(gè)銀行應(yīng)用系統(tǒng),前臺(tái)

使用者作出將儲(chǔ)戶甲的?百元存款劃歸儲(chǔ)戶乙?guī)は碌牟僮?在后臺(tái)的數(shù)據(jù)庫(kù)中,這兩個(gè)客戶的

記錄分儲(chǔ)在兩張表中,當(dāng)使用者在屏幕上作出如上操作時(shí),在后臺(tái)需要對(duì)兩張表進(jìn)行修改。如

果在數(shù)據(jù)庫(kù)中對(duì)甲用戶存款余款作減去一百元修改后,對(duì)乙用戶加一百元的操作修改卻失敗

時(shí),前張表也必須回到修改前的狀態(tài),否則數(shù)據(jù)庫(kù)的內(nèi)容不統(tǒng)一,甲儲(chǔ)戶白白損失一百元,信

息必然是不正確的。因此進(jìn)行事務(wù)管理是必須的。

傳統(tǒng)地,我們認(rèn)為?個(gè)事務(wù)包括了對(duì)一個(gè)或多個(gè)表的修改,而隨著分布式數(shù)據(jù)庫(kù)和數(shù)據(jù)倉(cāng)

庫(kù)的發(fā)展,事務(wù)可能包括了對(duì)一個(gè)或多個(gè)數(shù)據(jù)庫(kù)的修改。在上例中甲乙兩用戶就可能是異地

用戶,信息分儲(chǔ)在不同地域的不同數(shù)據(jù)庫(kù)中,上述的?個(gè)事務(wù)就涉及到了對(duì)不同數(shù)據(jù)庫(kù)的操

作。

PowerBuilder中的事務(wù)管理作為數(shù)據(jù)庫(kù)的前臺(tái)開(kāi)發(fā)工具PowerBuilder支持事務(wù)管理的

操作。在PowerBuilder中有一種稱作事務(wù)(transaction)的對(duì)象,這個(gè)對(duì)象是PowerBuilder應(yīng)

用與數(shù)據(jù)庫(kù)的通訊區(qū)域。PowerBuilder在應(yīng)用開(kāi)始時(shí)建立一個(gè)全局的事務(wù)對(duì)象SQLCA。山

于大多數(shù)的應(yīng)用只用到一個(gè)數(shù)據(jù)庫(kù),所以?般開(kāi)發(fā)者主要也只用SQLCA作為與唯一數(shù)據(jù)庫(kù)連

接的事務(wù)對(duì)象。

PowerScript中常用的事務(wù)管理的語(yǔ)句有四

個(gè):COMMITROLLBACK,CONNECT,DISCONNECT。

當(dāng)您需要應(yīng)用與數(shù)據(jù)庫(kù)建立連接時(shí)使用CONNECT這?操作命令,取消連接時(shí)執(zhí)行

DISCONNECT;這兩個(gè)命令一般分別用在應(yīng)用的開(kāi)始和結(jié)束,也就是Application的Open和

Close事件中。

當(dāng)一個(gè)事務(wù)的數(shù)據(jù)庫(kù)修改都成功地完成后,修改須提交給數(shù)據(jù)庫(kù),COMMIT語(yǔ)句是一個(gè)

舊事務(wù)結(jié)束和一個(gè)新事務(wù)開(kāi)始的界線。在修改被提交前,數(shù)據(jù)庫(kù)的數(shù)據(jù)并沒(méi)有被真正地修改,

這些修改被保留在某個(gè)工作區(qū),只有作修改的用戶才能看到這些被修改后的值,提交之后,則

所有的用戶就都可以看到新值了。

在事務(wù)的進(jìn)程中發(fā)生某些錯(cuò)誤,或者在操作中出于種種原因打算中止事務(wù),須用

ROLLBACK命令回退事務(wù),如果已作的操作不用ROLLBACK命令取消,這些操作必將錯(cuò)誤地作

為下一個(gè)事務(wù)的一部分而導(dǎo)致數(shù)據(jù)庫(kù)的混亂。

如果您使用的是多窗口的應(yīng)用,卻只用一個(gè)事務(wù)對(duì)象,就應(yīng)格外注意ROLLBACK和

COMMIT會(huì)影響事務(wù)的邏輯,致性。在某個(gè)窗口執(zhí)行的這兩個(gè)指令會(huì)使其他窗口應(yīng)用中所

進(jìn)行到一半的工作提交或回退。

在多用戶系統(tǒng)中,修改和提交的時(shí)間越接近,提交成功的可能性就越高。因?yàn)橐粋€(gè)事務(wù)中

所有的SQL語(yǔ)句全部執(zhí)行成功而提交卻失敗是完全可能發(fā)生的,例如在您的事務(wù)過(guò)程中,另--

個(gè)用戶修改了數(shù)據(jù)并提交,這很可能使您作出的修改無(wú)效,這時(shí)COMMIT將失敗,您必須回退

這一事務(wù)的全部。

事務(wù)對(duì)象的AutoCommit屬性事務(wù)對(duì)象有一個(gè)AutoCommit的屬性可以使開(kāi)發(fā)者簡(jiǎn)化

對(duì)事務(wù)管理的操作,這一布爾型的屬性可以用TRUE或FALSE來(lái)對(duì)其賦值。當(dāng)其為真

時(shí),PowerBuilder不通過(guò)其他額外的交互就將您的SQL語(yǔ)句傳輸給后臺(tái)數(shù)據(jù)庫(kù),而且執(zhí)行完畢

自動(dòng)提交。

當(dāng)然,您可以設(shè)置AutoCommit屬性為假(缺省值),使用COMMIT或ROLLBACK這樣的關(guān)

鍵詞提交或回退事務(wù)。在大多數(shù)應(yīng)用中,一部分的數(shù)據(jù)庫(kù)操作是要成組提交的,而另一些則不

用。因此我們可以利用AutoCommit的特性來(lái)確定事務(wù)的起點(diǎn),當(dāng)我們把AutoCommit的屬

性設(shè)為False時(shí),系統(tǒng)設(shè)定此時(shí)為事務(wù)的起點(diǎn)。當(dāng)AutoCommit設(shè)為真時(shí),系統(tǒng)自動(dòng)消取這一

事務(wù)。因此你可以先把AutoCommit設(shè)為真,當(dāng)您需要開(kāi)始一個(gè)事務(wù)時(shí),將其置為false,此刻

即為事務(wù)起始點(diǎn)。

PowerBuilder內(nèi)部這種事務(wù)管理的最大優(yōu)點(diǎn)是方便。您不去考慮整個(gè)事務(wù),而只需把您

所作的修改提交或滾回即可。但是方便與可控性總是矛盾的,在PowerBuilder中沒(méi)有存儲(chǔ)點(diǎn)

和嵌套事務(wù)管理的機(jī)制,即使您所使用的數(shù)據(jù)庫(kù)支持這些特性,在PowerBuilder中卻無(wú)法得以

體現(xiàn)。不過(guò)在普通的應(yīng)用中,存儲(chǔ)點(diǎn)和嵌套事務(wù)管理并不是必須的,一般的事務(wù)管理足以夠

用.

用數(shù)據(jù)庫(kù)的事務(wù)管理指令實(shí)現(xiàn)完全控制上述的事務(wù)管理方式盡管簡(jiǎn)單方便,但是在某些

應(yīng)用中,我們也的確需要利用所用的數(shù)據(jù)庫(kù)系統(tǒng)的嵌套事務(wù)和存儲(chǔ)點(diǎn)的特性,而PowerBuilder

內(nèi)部的事務(wù)管理沒(méi)有提供這樣的功能,您必須自己設(shè)計(jì)。

自己進(jìn)行事務(wù)管理的方式是直接使用數(shù)據(jù)庫(kù)本身的事務(wù)指令。當(dāng)您使用自己的管理方

式時(shí),就應(yīng)使PowerBuilder停止管理事務(wù),即設(shè)置AutoCommit為T(mén)RUE,系統(tǒng)內(nèi)部就不會(huì)自動(dòng)

建構(gòu)事務(wù)處理的命令了。實(shí)現(xiàn)人工事務(wù)管理的方式是采用EXECUTEIMMEDIATE這條

PowerBuilder指令來(lái)執(zhí)行任意的數(shù)據(jù)庫(kù)操作。你所需做的是將數(shù)據(jù)庫(kù)指令編輯成一個(gè)字符

串,您可以執(zhí)行任何的數(shù)據(jù)定義語(yǔ)句如建表、建主鍵、存儲(chǔ)過(guò)程等,例如您可以用

EXECUTEIMMEDIATEBEGINTRANSACTIONtransname

這樣的指令開(kāi)始一個(gè)事務(wù)。采用這種方法,只要您所用的數(shù)據(jù)庫(kù)支持嵌套事務(wù)和存儲(chǔ)點(diǎn)

等事務(wù)管理,我們通過(guò)PowerBuilder開(kāi)發(fā)出的應(yīng)用也就同樣可以實(shí)現(xiàn)。

在PowerBuilder中提供的事務(wù)管理的方法是多種多樣的,只要您靈活運(yùn)用,就一定能設(shè)計(jì)

出優(yōu)秀的數(shù)據(jù)庫(kù)應(yīng)用來(lái)。

3.PowerBuilder面向?qū)ο蟮某绦蛟O(shè)計(jì)

在PowerBuilder的應(yīng)用開(kāi)發(fā)中,運(yùn)用面向?qū)ο蠹夹g(shù)不是必須的,但是對(duì)于一個(gè)大型復(fù)雜應(yīng)用系

統(tǒng)的開(kāi)發(fā),如果采用了面向?qū)ο蠹夹g(shù),則開(kāi)發(fā)效率會(huì)大大提高。用PowerBuilder開(kāi)發(fā)的好

處是,即使您不懂得什么是面向?qū)ο蠹夹g(shù),您也可能會(huì)下意識(shí)地用到面向?qū)ο蠹夹g(shù)的一些特性,

但是如果您對(duì)這一技術(shù)有了充分的了解,那對(duì)您所設(shè)計(jì)程序的可重用性,可維護(hù)性和其他各方

面的質(zhì)量都會(huì)有大幅度提高。

PowerBuilder的對(duì)象

PowerBuilder對(duì)象有三個(gè)部分元素:屬性、函數(shù)和事件。(1)屬性:也就是數(shù)據(jù)。包括

系統(tǒng)屬性和用戶定義屬性兩類,描述該對(duì)象的各種特性。如在窗口對(duì)象中的系統(tǒng)屬性包括標(biāo)

題、高度、寬度等,用戶定義的屬性可以是實(shí)例變量或共享變量,對(duì)這種屬性的訪問(wèn)同系統(tǒng)屬

性相同,只是在封裝性上有所不同。⑵事件:PowerBuilder中的事件與Windows的事件

存在著映射關(guān)系。當(dāng)用戶的操作或系統(tǒng)本身產(chǎn)生了Windows的標(biāo)準(zhǔn)事件,就轉(zhuǎn)化成

PowerBuilder中的事件。例如命令按鈕有-一個(gè)叫Clicked事件,當(dāng)用戶按按鈕時(shí)觸發(fā),操作系

統(tǒng)首先檢測(cè)到鼠標(biāo)被點(diǎn)擊,并把Clicked這一消息轉(zhuǎn)給該按鈕,PowerBuilder運(yùn)行時(shí)的工作引

擎翻譯了這一事件,并執(zhí)行適當(dāng)?shù)腜owerScript語(yǔ)句。PowerBuilder中大部分的事件都是可以

映射成山用戶激發(fā)的Windows事件。另?類事件是用戶定義事件,這種事件是用戶聲明并

可以在任何時(shí)刻由用戶觸發(fā)的,PowerBuilder中保留了75個(gè)用戶事件可由程序員使用。

⑶函數(shù):用戶通過(guò)函數(shù)來(lái)使對(duì)象完成某些操作。PowerSoft公司建議用戶通過(guò)調(diào)用對(duì)象事件

和函數(shù)來(lái)修改對(duì)象而不要直接修改對(duì)象屬性,以滿足對(duì)象封裝的要求,例如采用Window.hidef)

而不要用Window.visible=false來(lái)使窗口不可見(jiàn)。

PowerBuilder面向?qū)ο蟮奶匦?/p>

提到一門(mén)語(yǔ)言的面向?qū)ο筇匦?它應(yīng)當(dāng)具有繼承性、多態(tài)性和封裝性,如缺少其中的一個(gè)

則只能稱其為基于對(duì)象的系統(tǒng),而不是面向?qū)ο蟮南到y(tǒng),而PowerBuilder則很好地具備了全部

三個(gè)特性。?繼承:PowerBuilder中,窗口、菜單和用戶對(duì)象是可以繼承的,而其他對(duì)

象則都不能。當(dāng)您繼承了?個(gè)對(duì)象,那您得到的子類將具有父類的屬性、實(shí)例變量、共享變

量、控件、用戶自定義事件、對(duì)象級(jí)函數(shù)、事件和代碼(script)。也就是說(shuō)當(dāng)您繼承了一個(gè)

類,您幾乎得到了這個(gè)類的全部,不過(guò)有一點(diǎn)值得注意,您不能在子類中刪除任何一個(gè)繼承到

的特性。在繼承了祖先類后,您可以在子類中擴(kuò)展或覆蓋祖先的元素。例如代碼,在

PowerBuilder中缺省的是采用擴(kuò)展方式,先執(zhí)行繼承到的祖先代碼,后執(zhí)行子類的擴(kuò)展代碼。

您也可以選擇菜單Compiler|OverrideAncestorScript選項(xiàng),只執(zhí)行子類的代碼,并可在代碼中

的任意位置調(diào)動(dòng)祖先代碼如重載函數(shù)是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特

CALLw_l::oPen?

性,即同一函數(shù)名卻有著不同的參數(shù)和返回值。在運(yùn)行時(shí),系統(tǒng)自動(dòng)尋找執(zhí)行參數(shù)相匹配的那

個(gè)函數(shù),例如我們常用的MessageBox。這個(gè)函數(shù)就有12個(gè)不同參數(shù)的重載函數(shù)。遺憾的是,

對(duì)PowerBuilder我們不能在同一個(gè)繼承對(duì)象中定義2個(gè)不同參數(shù)的重載函數(shù),只能在后繼的

類中定義重載函數(shù),這使我們對(duì)重載函數(shù)的定義帶來(lái)了很大的不便,這不能不說(shuō)是

PowerBuilder的缺陷。(不過(guò)在即將發(fā)布的PowerBuilder5.0中,正是支持了函數(shù)重載這?特

性。)對(duì)于對(duì)象的繼承,PowerBuilder中所有對(duì)象都有其共同的基類PowerObject,從這一

個(gè)基類下面分成繼承類GraphicObject和NonVisualObject等。它們的繼承關(guān)系和擴(kuò)展函數(shù)

及屬性如下表:?多態(tài)性:在PowerBuilder中有大量的多態(tài)函數(shù)如print。、

TriggerEvent()等,在運(yùn)行過(guò)程中,您只需要指出對(duì)象和函數(shù)名即可。在有些函數(shù)中,即使不知道

對(duì)象類,也可以用ClassName。函數(shù)得到對(duì)象類,或得到實(shí)例名,將對(duì)象名作為函數(shù)參數(shù)調(diào)用該

函數(shù)。?封裝性:封裝的目的是為了實(shí)現(xiàn)數(shù)據(jù)隱藏和數(shù)據(jù)保護(hù),封裝的目標(biāo)是為對(duì)象

提供?個(gè)對(duì)外操作的接口,使其他對(duì)象通過(guò)函數(shù)來(lái)訪問(wèn),而不允許直接操縱對(duì)象的屬性。在

PowerBuilder中有三種訪問(wèn)類型Public、Protect、Private,這三種訪問(wèn)控制類型可以用在對(duì)象

的變量和函數(shù)上,缺省的實(shí)例變量和對(duì)象函數(shù)都是public類型的。為了保護(hù)數(shù)據(jù),應(yīng)盡可能多

地使用private和protect類型,前者只允許對(duì)象內(nèi)部的元素來(lái)訪問(wèn),后者可以接受對(duì)象內(nèi)部和

繼承類的元素訪問(wèn)。

PowerBuilder面向?qū)ο蟪绦蛟O(shè)計(jì)的過(guò)程

事實(shí)上用戶在運(yùn)用PowerBuilder進(jìn)行程序設(shè)計(jì)的一開(kāi)始,就已經(jīng)開(kāi)始進(jìn)行對(duì)象類的設(shè)計(jì):

例如在建立窗口時(shí)可以用窗口畫(huà)筆建立一個(gè)新窗口,命名為建立的窗口就

(painter)w_empo

是從PowerBuilder的窗口對(duì)象繼承下來(lái)的,所以窗口會(huì)自動(dòng)具備一些屬性,例如X和Y的坐

標(biāo)、高度、寬度、窗口類型、標(biāo)題等。當(dāng)用窗口畫(huà)筆建立窗口時(shí),您給這些屬性賦了值,你還

可以增加窗口的函數(shù)和事件。當(dāng)窗口被保存時(shí),你就建立了一個(gè)新的窗口繼承類,稱

為:w_emp。輸出對(duì)象的句法顯示的部分程序如下:globaltypew_empfromWindow

intX=200

intY=233

intWidth=2405

intHeight=1285

booleanTitleBar=true

stringTitle="EmployeeMaintenance"

stringMenuName=,,m_emp"

longBackColor=12632256

booleanControlMenu=true

booleanMinBox=true

booleanMaxBox=true

booleanResizable=true

endtype

globalw_empw_emp請(qǐng)注意系統(tǒng)在這里做了什么:首先定義了w_emp窗口類是從

window類繼承而來(lái),接著定義這一對(duì)象類的各屬性值,在句法的最后一行聲明了一個(gè)全局變

量,變量的類型(對(duì)象類)是w_emp,變量名(對(duì)象實(shí)例)也是w_empo也就是說(shuō)在您建立了

w_emp這一窗口對(duì)象后,系統(tǒng)就具有了w_emp這一對(duì)象類和w_emp這一全局變量。這個(gè)

變量是引用變量,也就是在有些語(yǔ)言稱之為指針的變量類型。引用變量并不真正含有窗口實(shí)

例的屬性,而是包含了一個(gè)位置或是內(nèi)存中的一個(gè)地址,在那兒你可以找到實(shí)例的實(shí)際屬性和

程序。但在應(yīng)用的開(kāi)始時(shí)這?指針為空,因?yàn)樵趦?nèi)存中并沒(méi)有一個(gè)這樣的窗口實(shí)例。當(dāng)系統(tǒng)

執(zhí)行了Open(w_emp)后,系統(tǒng)在內(nèi)存中復(fù)制了一份w_emp對(duì)象類的拷貝或?qū)嵗?w_emp這一

參照變量指向了這一地址。由于窗口對(duì)象的visible等屬性都是Public類型,所以繼承類也都

具有了這些屬性。

2005011414:37:00

5.DataWindow的打印輸出

在PowerBuilder應(yīng)用程序的開(kāi)發(fā)中,各種報(bào)表的打印功能是必不可少的。PowerBuilder4.0提

供了大量與打印機(jī)進(jìn)行通信的內(nèi)部函數(shù),用于各種打印輸出。運(yùn)用這些函數(shù),您不僅可以打印

常見(jiàn)的DataWindow對(duì)象,還可以打印字符串、位圖、圖形對(duì)象,甚至是全屏。

DataWindow的兩種打印方法:在PowerBuilder中我們可以有兩種方法打印DataW

indows,.一種最簡(jiǎn)單的方法就是直接地將DataWindow提交給打印機(jī),另一種方法是將大量

的DataWindow(或混合其他的對(duì)象)放在一起作為一個(gè)單一的打印作業(yè)提交輸出。法一:

不指定打印作業(yè),而發(fā)送一個(gè)單?的DataWindow。將報(bào)表傳給打印機(jī)輸出的最簡(jiǎn)單的方式

是使用DataWindow對(duì)象的Print。函數(shù),您只需簡(jiǎn)單指明您打印的DataWindow控件的名字

就可以得到該DataWindow生成的報(bào)表了。例:dw_data.print({canceldialog})Print()

函數(shù)不需要任何參數(shù),但是它有一個(gè)可選參數(shù),可以控制PowerBuilder是否顯示PrintCancel

對(duì)話框窗口(缺省為自動(dòng)出現(xiàn),如圖1所示)。Canceldiabg參數(shù)是一個(gè)布爾型變量,其缺省值為

真。一Print:HPLaserJetHPonLPTl:Preparingpagelof2Cancel圖1:除非特別

指定,否則將在打印時(shí)缺省出現(xiàn)PrintCancel對(duì)話框。Print。函數(shù)還有一些格式可控制打印正

文字符串,但是它們要求首先打開(kāi)個(gè)打印作業(yè)。這些格式將在后面解釋。法二:集成多

個(gè)DataWindow作為一個(gè)打印作業(yè)。您可以將提交打印的多個(gè)DataWindow作為一個(gè)單一

的打印指令。為實(shí)現(xiàn)這一功能必須打開(kāi)一個(gè)所謂打印作業(yè)(Printjob),即發(fā)送給打印機(jī)一個(gè)單

-工作單元,其中可以包含多個(gè)子任務(wù)。在PowerBuilder中」■個(gè)打印作'也由它的作業(yè)代號(hào)唯

一指定。我們使用PrintOpen({jobname})函數(shù)打開(kāi)一個(gè)作業(yè),并得到打印作業(yè)號(hào)。PrintOpen()

函數(shù)有一個(gè)可選參數(shù),就是打印作業(yè)名稱,這個(gè)作業(yè)名字將作為Windows3.x的PrintManager

作業(yè)集中的名字。當(dāng)您使用PrintOpen()函數(shù)時(shí),系統(tǒng)將另起一頁(yè)開(kāi)始打印。當(dāng)然在打印作業(yè)

中,您還可以使用其他函數(shù)換頁(yè),比如將在后面講述的PrintPage。函數(shù)。在您打開(kāi)了一個(gè)

作業(yè)號(hào)后,就可以在這個(gè)作業(yè)內(nèi)使用下列函數(shù)繼續(xù)其他各種各樣的打印項(xiàng)目。1)在打印

作業(yè)中加入字符串:我們也可以使用另外一個(gè)與Print。函數(shù)略微不同的函數(shù)來(lái)打印字符

串:PrintText(printJob_number,string,x,y{,font_number})這個(gè)函數(shù)將包含在string參

數(shù)中的正文字符串當(dāng)作?個(gè)對(duì)象進(jìn)行打印。這個(gè)打印的字符串在由X,Y參數(shù)(以千分之寸

為單位)指定的坐標(biāo)處開(kāi)始。font_number參數(shù)是??個(gè)可選參數(shù),缺省使用當(dāng)前字型,否則

font_number的值可以從0到8,0是打印機(jī)缺省的字型,18是使用后面講述的

PrintDefineFont()函數(shù)定義的字型。這個(gè)函數(shù)不像其他指定坐標(biāo)的函數(shù),它將改變打印光標(biāo)的

位置。這個(gè)函數(shù)的返回值是打印光標(biāo)的新X坐標(biāo),但它不改變Y坐標(biāo)。

在打印作業(yè)中打印對(duì)象

下面的這些函數(shù)可以使您在打開(kāi)的打印作業(yè)中打印不同的對(duì)象。這些函數(shù)中的任一個(gè)

指定X、Y坐標(biāo)的函數(shù)都不會(huì)改變當(dāng)前打印光標(biāo)位置。

objectname.Print(printjob_number,x,y{,width,height})這個(gè)函數(shù)可以將任何?個(gè)

object_name指定的對(duì)象放在print_job_number定義的打印作業(yè)中打印,這個(gè)對(duì)象可以是一

個(gè)窗口也可以是一個(gè)DragObject類的繼承類(包括了所有的窗口控件)。X、Y參數(shù)指定了一

頁(yè)中的坐標(biāo),您可以指出所打印對(duì)象出現(xiàn)的位置(以千分之一寸為單位)。Width和Height參

數(shù)是可選的參數(shù),用來(lái)指明你所需的打印對(duì)象的寬和高(仍以千分之一寸為單位)。如果缺

省,PowerBuilder將使用對(duì)象本身的尺、『打印。

RrintBitmap(printJob_number,bitmap,x,y,width,height)這個(gè)函數(shù)將在山X,Y參數(shù)(千分之

一寸為單位)指定的打印區(qū)域上打印一個(gè)位圖。bitmap參數(shù)是一個(gè)包含要打印位圖的文件名

的字符串(例:BRUSH.BMP)。Width和Height參數(shù)指定位圖顯示的寬和高,這個(gè)參數(shù)并不是可

選的。輸入0值,意味著位圖按它本身的值打印。

PrintDataWindow(printJob_number,datawindowcontrol)這個(gè)函數(shù)將一個(gè)DataWindow控

件的內(nèi)容作為這個(gè)指定的打印作業(yè)的?部分來(lái)打印。由于PowerBuilder使用在

DataWindow對(duì)象中定義的字型,PrintDefineFont()和PrintSetFont。函數(shù)不對(duì)其產(chǎn)生影響。

Powersoft建議如用PrintDataWindow,那么在這個(gè)打印作業(yè)中就不需要使用其它函數(shù)。因?yàn)?/p>

這個(gè)函數(shù)將使用整張紙,每一次調(diào)用PrintDataWidnow,您打印的下一項(xiàng)都將另起一頁(yè)。

這個(gè)函數(shù)將打印一指定寬度的線。這條

PrintLine(PrintJob_number,XI,Y1,X2,Y2,thickness)

線將在由XI,Y1參數(shù)(以千分之一寸為單位)指定的坐標(biāo)處開(kāi)始,在由X2,Y2參數(shù)(也以千分之

一寸為單位)指定的坐標(biāo)處結(jié)束。thickness參數(shù)是一個(gè)整型變量,它指定了這條線的寬度,以

千分之一一寸為單位。PrintOval(printJob_number,x,y,width,height,thickness)這個(gè)函數(shù)

打印一個(gè)橢圓(如果寬度和高度相同則形成一個(gè)圓)它的輪廓線的寬度由thickness指定。橢

圓都由一個(gè)想象的邊框包圍,X,Y參數(shù)指定了這個(gè)界框的左上角的位置(千分之一寸為單

位),width,heigh為這個(gè)邊框的高和寬。

除了它是打印一個(gè)矩形外,這個(gè)函

PrintRect(printJob_number,x,y,width,height,thickness)

數(shù)與PrintOval。函數(shù)完全一樣。

PrintRoundRect(print_job_number,x,y,width,height,thickness)除了它是打印一個(gè)圓角矩形

外,這個(gè)函數(shù)與PrintOval()函數(shù)完全一樣。

2005011414:37:00

利用SetActionCode函數(shù)控制DataWindow

DataWindow控件的一些事件有一個(gè)動(dòng)作碼操縱這個(gè)事件之后的缺省動(dòng)作。在Pow

erBuilder4.0中我們可以使用SetActionCode函數(shù),來(lái)設(shè)置這個(gè)動(dòng)作碼的值以控制在這些事件

發(fā)生后的處理過(guò)程。(在PowerBuilder。中,由于事件可以有返回?cái)?shù)值,所以采用返回一-個(gè)整

型數(shù)值來(lái)取代SetActionCode函數(shù),比如使用returnl取代SetActionCode⑴,但基本的使用規(guī)

則兩者是相同的。)DataWindow控件中下列事件使用動(dòng)作碼:CLICKEDDBERROR

ITEMCHANGEDITEMERRORPRINTPAGERETRIEVEROWRETRIEVESTART

UPDATESTART有效的動(dòng)作碼值和應(yīng)當(dāng)?shù)奶幚磉^(guò)程隨事件的不同而不同。

ClickedEvent

無(wú)論何時(shí),當(dāng)用戶在DataWindow控件上點(diǎn)擊時(shí),CLICKED事件被觸發(fā)。如果點(diǎn)擊在--個(gè)

有效的行上,那么DataWindow將自動(dòng)把此行作為當(dāng)前行。如果你不想換行,就可以使用

SetActionCode來(lái)停止。。進(jìn)行換行和CLICKED事件。(缺省)1停止處理CLICKED事

件。例如:下面一段代碼只允許用戶點(diǎn)擊在自己的用戶號(hào)上?!–lickedEvent

//We'llassumethereisaninstancevariablewiththecurrentuser's//UserlD:stringis_user_id

longll_rowstringls_user_idH_row=GetClickedRow()

//Noneedtocontinueiftheuserdidn'tclickonavalidrowifll_row<lthenreturnendif

ls_userJd=GetltemString(ll_row/,user_id")

//IftheuserjdisnotthecurrentuserthendisallowrowchangeiflsuseridOisuseridthen

beep(l)SetActionCode(l)returnendif

ItemChangedEvent

DataWindowlTEMCHANGED事件可以有幾種不同的操作:接受前一字段的新值,因有錯(cuò)誤

而拒絕接受新值,拒絕新值但是繼續(xù)其它的處理過(guò)程。這些值如下:。接受新的數(shù)據(jù)值。

(缺省)1拒絕新的數(shù)據(jù)值。(啟動(dòng)ItemError事件)2拒絕新的數(shù)據(jù)值但是焦點(diǎn)改變。

在ITEMCHANGED事件中使用SetActionCode函數(shù)可以進(jìn)行多字段的交叉確認(rèn)。例如,銀行

系統(tǒng)中為確認(rèn)Accountstatus是否可以轉(zhuǎn)為Inactive,就需檢驗(yàn)Balance字段是否為零:

//ItemChangedEventDecimal(2)ld_balance//CustomerAccountBalance

Longll_currow//CurrentRowNumber

Stringls__column_name//Thenameofthecolumnthatchanged

Stringls_status//CustomerAccountStatusll_currow=this.GetRow()

ls_column_name=this.GetColumnName()CHOOSECASEIs_column_name

CASE"STATUSnls_status=this.GetText()//IfSTATUSisInactiveIFIs_status='T'THEN

ld_balance=this.GetltemDecimal(ll_currow,"BALANCE")IFId_balanceOOTHEN

//SETANERRORthis.SetActionCode(l)RETURNELSE//ACCERTTHEVALUE

this.SetActionCode(0)/*notrequiredsinceOisdefault*/RETURNENDIFENDIF

ENDCHOOSE在程序中,SetActionCode函數(shù)不一定要在最后一行,但是由于其他

DataWindow函數(shù)可能會(huì)重置動(dòng)作碼。為了避免這個(gè)問(wèn)題,一般在SetActionCode后面立即執(zhí)

行Return結(jié)束這個(gè)程序段。在ITEMCHANGED事件中使用SetActionCode函數(shù)用途是

可以給該字段一個(gè)新值,而不是用戶輸入的那樣。例如:用戶將日期輸入為星期日,但是我們

希望將其改為在此之后的第一個(gè)非休息日。實(shí)現(xiàn)這一功能并不像想象的那樣簡(jiǎn)單:

//ItemChangedEventdateldt_process//processdatelongll_currow//CurrentRowNumber

stringls_column_name//ThenameofthecolumnthatchangedH_currow=this.GetRow()

ls_column_name=this.GetColumnName()CHOOSECASEIs__column_name

CASE"process_date"ldt_process=f_get_next_bus_date(date(this.GetText()))錯(cuò)誤

this.SetText(ldt_process)this.AcceptText()...執(zhí)行上述代碼,系統(tǒng)將進(jìn)入死循環(huán)。

因?yàn)橛肁cceptText函數(shù)改變?nèi)掌诘耐瑫r(shí),也觸發(fā)ITEMCHANGED事件,只是當(dāng)前列仍在process

data列上,這樣就導(dǎo)致堆棧溢出。因此在ITEMCHANGED事件中不能使用AcceptText函數(shù),應(yīng)

使用我們這里介紹的SetActionCode這--函數(shù)來(lái)完成這一功能:CASE"process_date"

ldt_process=f_get_next_bus_date(date(this.GetText()))正確

this.SetltemText(ll_currow,"process_date",ldt_process)//setvalueinbuffer

this.SetActionCode(2)//rejecteditcontrolvalueRETURN在PrimarylBuffer中將

process_date的值置為ldt_process,SetActionCode(2)摒棄用戶在edit控件中輸入的值(星期

日),并允許改變焦點(diǎn)(沒(méi)有錯(cuò)誤發(fā)生)。

ItemErrorEvent

在任何時(shí)候,當(dāng)一個(gè)DateWindow列沒(méi)有通過(guò)有效性檢驗(yàn)或者這個(gè)值在ITEMCHANGED

事件中被拒絕時(shí),ITEMERROR事件啟動(dòng)。如同ITEMCHANGED事件一樣,它的動(dòng)作碼也可以設(shè)

置為接受或拒絕這個(gè)字段的新輸入值。它還可以在拒絕新值時(shí),決定是否取消錯(cuò)誤信息框的

顯示。ITEMERROR事件的動(dòng)作碼可以是:0拒絕新的數(shù)據(jù)值并且顯示錯(cuò)誤信息乂缺省)

1拒絕新的數(shù)據(jù)值而不顯示錯(cuò)誤信息;2接受新的數(shù)據(jù)值;3拒絕新的數(shù)據(jù)值但是允

許改變焦點(diǎn)。如果我們想要在一特定區(qū)域顯示一個(gè)用戶自定義的錯(cuò)誤信息來(lái)代替

PowerBuilder本身錯(cuò)誤信息框,我們可以使用SetActionCode來(lái)取消標(biāo)準(zhǔn)的信息框。例如,在

前面例子中,當(dāng)收支差額不是0是0時(shí),我們就可以用這一方法顯示一個(gè)錯(cuò)誤信息:

//ItemErrorEventLongll_Currow/*CurrentRowNumber*/

Stringls_column_name/*Thenameofthecolumnthatchanged*/ll_currow=this.GetRow()

ls_column_name=this.GetColumnNameCHOOSECASEs_column_nameCASE"status"

MessageBox("Error",''Accountcannotbechangedtolnactive"+"Balanceisnotzero.")

this.SetActionCode(l)RETURN...ENDCHOOSE在ITEMERROR事件中使用

SetActionCode,我們就可以有選擇地忽略DataWindow對(duì)象的一個(gè)列中輸入的有效性規(guī)則。

例如,在收支差額中,我們有下面這個(gè)有效性規(guī)則:Real(GetText())<=10000客戶收支

差額不應(yīng)超過(guò)10,000元,如果我們?cè)试S使用公司帳戶的客戶可以超過(guò)10,000,我們可以使用

如下方式:"ItemErrorEventCHOOSECASEIs_column_nameCASE"balance"

//Allowbalanceover$10,000onCorportateaccountsIFId_balancenot<

=10000ANDIs_type="C"this.SetActionCode(2)RETURNENDIF...我們也可

以像前面ITEMCHANGED事件那樣在PrinaryiBuffer中拒絕新輸入的值并填入新值,只是在這

里將動(dòng)作碼置為3。

DBErrorEvent

在執(zhí)行了dw.Retrieve,dw.Update()函數(shù)或嵌入式SQL語(yǔ)句并發(fā)生了一個(gè)數(shù)據(jù)庫(kù)錯(cuò)誤

(SQLCode等于1)時(shí),觸發(fā)DBError事件。許多PowerBuilder的開(kāi)發(fā)商都在為這種情況設(shè)計(jì)

了標(biāo)準(zhǔn)的數(shù)據(jù)庫(kù)錯(cuò)誤信息顯示。為了使PowerBuilder不顯示缺省的數(shù)據(jù)庫(kù)錯(cuò)誤信息,我們可

以使用SetActioncode。DBError事件的動(dòng)作碼值如下:。顯示錯(cuò)誤信息。(缺省)1不

顯示錯(cuò)誤信息。例如:〃DBErroreventMessageBox,數(shù)據(jù)庫(kù)錯(cuò)誤“,"錯(cuò)誤值

"+string(this.DBErrorCode)+&"錯(cuò)誤信息為/+this.DBEirorMessage(),StopSign!)

//SupressPBgeneratedDBErrorMessage.this.SetActionCode(l)return

PrintPage

PRINTPAGE事件是在執(zhí)行dw.Print。函數(shù)之后,數(shù)據(jù)傳送給打印機(jī)之前觸發(fā)。當(dāng)打印一個(gè)

DataWindow時(shí),你可在打印之前設(shè)置動(dòng)作碼來(lái)跳過(guò)一頁(yè)。PRINTPAGE事件的動(dòng)作碼如下:

0不跳過(guò)一頁(yè);(缺省)1跳過(guò)一頁(yè)。如您打算打印時(shí)跳過(guò)一頁(yè),你可以在中PRINTPAGE

編碼如下:〃Printpageeventthis.SetActionCode⑴

RetrieveRow

從數(shù)據(jù)庫(kù)服務(wù)器中每次接受了一行記錄均啟動(dòng)REIRIEVEROW事件。在這個(gè)事件中,你可

以設(shè)置一動(dòng)作碼來(lái)停止檢索。下面是RETRIEVEROW事件的有效動(dòng)作碼:0繼續(xù)。(缺省)

1停止檢索。如果一個(gè)DataWindow將命中很多行,并且你希望在檢索到一定量后停

止。你可以在RETRIEVEROW事件中使用SetActionCode://RetrieveRowevent

//lnstancevariableLongil_count...IFil_count++>100THEN

//Maximumrowsretrieved^tipretrievalthis.SetActionCode(l)RETURNENDIF當(dāng)

用來(lái)給被檢索行計(jì)數(shù)的臨時(shí)變量il_count的值超過(guò)100時(shí),檢索將停止。注意:在

RETRIEVEROW事件中存在代碼,那么檢索每一行都會(huì)觸發(fā)事件,這將降低檢索的速度。

RetrievestartRETRIEVESTART事件在dw.Retrieve()函數(shù)之后,產(chǎn)生SQL傳送給服務(wù)器之前

觸發(fā)。在?些特定場(chǎng)合可能需要在開(kāi)始?個(gè)檢索之前停止它。在Retrievestart事件中

的動(dòng)作碼:0繼續(xù)。(缺省)1不檢索。例如:我們讓一個(gè)用戶輸入檢索標(biāo)準(zhǔn)的窗

口,在RETRIEVESTART中判斷返回行數(shù)是否太多,以決定停止檢索并且讓用戶縮小檢索范圍。

//RetrieveStarteventlntli_count/*ExpectedRetrieveCount*/...

//GetcountofRowstoberetrieved...IFIi_count>1000THEN

,,,,

MessageBox(Stop","Pleasenarrowyoursearchzstop!)This.SetActionCode⑴RETURN

ENDIF...

UpdateStart

這一在執(zhí)行Update。函數(shù)之后,產(chǎn)生的修改SQL語(yǔ)句傳送給服務(wù)器之前觸發(fā)。通過(guò)

設(shè)置這一動(dòng)作碼,你可以阻止修改傳送給服務(wù)器。UPDATESTART事件的動(dòng)作碼如下:0繼

續(xù)。(缺省)1不修改。如果你要阻止執(zhí)行修改語(yǔ)句,在UPDATESTART事件中使用下

列代碼:〃UpdateStartevent...this.SetActionCode(l)RETURN...

綜述

在很多情況下,設(shè)置動(dòng)作碼是非常有用的。這里的例子,讓你對(duì)其中幾種情況有一個(gè)了

解。當(dāng)你對(duì)使用PowerScript編碼有了更多的經(jīng)驗(yàn)后,你會(huì)發(fā)現(xiàn)SetActionCode是非常有用

的。

2005011414:37:00

DataWindow的數(shù)據(jù)緩沖區(qū)

DATAWINDOW的四個(gè)緩站區(qū)

在PowerBuilder中,DataWindow是用戶前端用來(lái)存儲(chǔ)、操縱數(shù)據(jù)的對(duì)象。在每一個(gè)

DataWindow對(duì)象中有4個(gè)二維表作為數(shù)據(jù)緩沖區(qū),用來(lái)存儲(chǔ)查詢到的數(shù)據(jù)。用戶在

DataWindow中對(duì)數(shù)據(jù)處理系統(tǒng)內(nèi)部的操作實(shí)際上都是將數(shù)據(jù)在這幾個(gè)緩沖區(qū)中進(jìn)行的修

改和移動(dòng),最后在用戶提交數(shù)據(jù)庫(kù)時(shí),系統(tǒng)根據(jù)這四個(gè)緩沖區(qū)中的信息形成SQL的IN

SERT,UPDATE,DELETE等語(yǔ)句。這四個(gè)緩沖區(qū)是:

PrimaryBuffer

這個(gè)緩沖區(qū)是存放填充窗口中DataWindow控件中數(shù)據(jù)的,調(diào)用DataWindow的

Retrieve。函數(shù)和InsertRow。函數(shù)可以將數(shù)據(jù)填入這個(gè)緩沖區(qū)中。當(dāng)使用有關(guān)DataWindow

刪除和過(guò)濾函數(shù)時(shí),相應(yīng)記錄將從這一緩沖區(qū)中刪除。而在執(zhí)行DataWindow的Update。函

數(shù)時(shí),PowerBuilder將查看這一緩沖區(qū)中的記錄,以形成SQLINSERT和UPDATE語(yǔ)句。

DeleteBuffer

這個(gè)緩沖區(qū)保存的是用DeleteRow()函數(shù)從PrimaryBuffer中刪除的記錄,執(zhí)行Update。函

數(shù)時(shí),系統(tǒng)根據(jù)這一緩沖區(qū)的記錄形成DELETE語(yǔ)句。

FilterBuffer

這個(gè)緩沖區(qū)存儲(chǔ)的是從OriginalBuffer使用Filter。函數(shù)過(guò)濾到PrimaryBuffer中后剩余的

記錄。

OriginalBuffer

這一緩沖區(qū)存儲(chǔ)的是DataWindow最初執(zhí)行retrieve。函數(shù)時(shí)得到的全部記錄。當(dāng)提交

數(shù)據(jù)庫(kù)時(shí),根據(jù)PrimaryBuffer生成的UPDATE語(yǔ)句和根據(jù)DeleteBuffer生成的DELETE語(yǔ)句都

要依據(jù)這一緩沖區(qū)來(lái)構(gòu)造這些SQL語(yǔ)句中的Where子句。OriginalBuffer由

PowerBuilder內(nèi)部維護(hù),PowerBuilder所提供的任何函數(shù)都無(wú)法改變它的值,不過(guò)通過(guò)

PowerBuilder所提供的Getltem…系列的函數(shù)可以讀出DataWindow最初從數(shù)據(jù)庫(kù)中查到的

原始值。通過(guò)這些函數(shù)我們可以編程實(shí)現(xiàn)所謂的"Undo"功能,并且得到在使用樂(lè)觀鎖時(shí)形成

提交數(shù)據(jù)庫(kù)的WHERE子句。如果您當(dāng)前使用的DataWindow沒(méi)有設(shè)置修改的權(quán)力,您

將不能對(duì)Delete緩沖區(qū)和Original緩沖進(jìn)行操作,而且當(dāng)調(diào)用Update。時(shí)也將引起系統(tǒng)錯(cuò)

誤。

數(shù)據(jù)緩沖區(qū)的狀態(tài)值

PrimaryBuffer和DeleteBuffer都有行級(jí)和列級(jí)的狀態(tài)值,這個(gè)狀態(tài)值是一個(gè)枚舉類型。

在提交時(shí)由該行的狀態(tài)值來(lái)決定是否要產(chǎn)生SQL語(yǔ)句,其中PrimaryBuffer產(chǎn)生的是INSERT

和UPDATE語(yǔ)句,而DeleteBuffer產(chǎn)生的是DELETE語(yǔ)句。我們用GetltemStatus()函數(shù)和

SetltemStatus。函數(shù)可以對(duì)這一狀態(tài)值作操縱。這一枚舉狀態(tài)有以下四種:?NotModified!

一該行或行的值為查詢所得,沒(méi)有發(fā)生改變。?DataModified!該行或列的值

為查詢所得,發(fā)生了改變。?New!該行或列為?插入的新行,數(shù)據(jù)沒(méi)有發(fā)生改變(數(shù)

據(jù)為空或缺省值)。,NewModified!該行或列為?插入的新行,數(shù)據(jù)發(fā)生改變。改

變是通過(guò)用戶鍵盤(pán)輸入或調(diào)用了Setltem。函數(shù)。讓我們來(lái)看下面這一實(shí)例:我們有

這樣一張表,表中有三個(gè)字段,其中ITEM是主鍵。ITEMCHAR(5);NAMECHAR(20);

QUANTITYINTo在Script中我們查詢這張表的記錄,得到以下這些信息存儲(chǔ)了在Primary

和OrigianalBuffer中,其中的行號(hào)是緩沖區(qū)加上的。在窗口中,我們編程過(guò)濾掉數(shù)量為0

的行,并且加上一個(gè)空行:dw_l.SetFilter("quantity=O")dw_l.Filter))

dw_l.lnsertRow()這時(shí)PrimaryBuffer的狀態(tài)為:在FilterBuffer中的記錄為:用戶

在新插入行中輸入數(shù)據(jù),刪除了第3行數(shù)據(jù),并修改了第2行數(shù)據(jù)。當(dāng)他離開(kāi)這個(gè)

DataWindow時(shí),Primary和Delete緩沖區(qū)的狀態(tài)如下:這時(shí)執(zhí)行dw_l.update。函數(shù),系統(tǒng)

將基于這兩個(gè)緩沖區(qū)生成SQL語(yǔ)句。在PrimaryBuffer中,狀態(tài)為NotModified和New!

的行將被忽略而不產(chǎn)生SQL語(yǔ)句。狀態(tài)為DataModified的行將產(chǎn)生UPDATE語(yǔ)句,狀態(tài)為

NewModified的行將產(chǎn)生INSERT語(yǔ)句,在Delete緩沖區(qū)中的行將產(chǎn)生DELETE語(yǔ)句。

四個(gè)緩沖區(qū)在編程中的運(yùn)用

某些DataWindow控件的函數(shù)有指定DataWindow緩沖區(qū)的功能。如果缺省,則表示

Primary緩沖區(qū)。下列是可以指定緩沖區(qū)的函數(shù):?GetltemStatus。,GetNextModified()

,GetUpdateStatusf),SetltemStatus()此外還有Getltem…系列的函數(shù),用以查詢

DataWindow中的值。這些函數(shù)有:?GetltemDate(),GetltemDataTime(),

GetltemDecimal()?GetltemNumber。,GetltemStringO,GetltemTime()

Getltem…系列函數(shù)也可以指定緩沖區(qū),而且可以允許您指定查詢的是當(dāng)前值還是原始值(最

初從數(shù)據(jù)庫(kù)中查到的值)。如:dW-l.GetltemStringfl/'name",Primary!,TRUE)使用

DataWindow的Reset。函數(shù)和Retrieve。函數(shù)以及改變DataObject屬性時(shí),系統(tǒng)將重置這幾個(gè)

緩沖區(qū)。當(dāng)用戶插入一個(gè)新行時(shí),編程者往往要自動(dòng)在新插入行中的某些列中插入一些

缺省的數(shù)據(jù)值。這時(shí),用戶并沒(méi)有對(duì)數(shù)據(jù)作任何修改??墒窃谟脩粢P(guān)閉這一窗口時(shí),如果在

CloseQuery事件中用ModifiedCount()函數(shù)查看數(shù)據(jù)是否修改,得到的結(jié)果顯然是有所改變。

用戶將得到一個(gè)提示信息框:"是否打算保存所作的修改?是/否/取消"這顯然是不適合

的:而且如果用戶選擇的是保存時(shí),這些原應(yīng)是空記錄的行也成為了有內(nèi)容的行,系統(tǒng)將其形

成SQL的INSERT語(yǔ)句提交數(shù)據(jù)庫(kù),這樣的結(jié)果更為惡劣。為改變這狀況,我們可以用

SetltemStatus()函數(shù)將該行的狀態(tài)改為New!。即當(dāng)有新行插入并且設(shè)置了缺省值之后,該行

的狀態(tài)值為New!。下面的程序就可以得到如上的功能。〃lnsertanewrowindw_:l

longl_Rowl_Row=dw_l,lnsertRow(dw_l,GetRow())

dw_l,Setltem(l_Row/'discount_pct",0,10)//

SetthrowstatustoNewisothattheCloseQuerycheckwillonlydetectuserentries.

dw_l.SetltemStatus(l_Row,0,Primary!,New!)使用SetltemStatus函數(shù)時(shí)有一些狀態(tài)轉(zhuǎn)換的

限制,下表中顯示的是將原來(lái)的狀態(tài)改變?yōu)榱硪粻顟B(tài)時(shí),會(huì)產(chǎn)生的影響。若表中為N。,則說(shuō)明

用這?函數(shù)進(jìn)行這樣的設(shè)置無(wú)效;若表中給出了不同的狀態(tài),則該狀態(tài)是對(duì)您指定的狀態(tài)的替

代。當(dāng)一個(gè)狀態(tài)的改變不能允許時(shí),可以多次調(diào)用SetltemStatus以得到期望的狀態(tài)。例

如,從New!狀態(tài)不能改成NotModified!狀態(tài),可將其改成DataModified!狀態(tài),然后再改成

NotModified!狀態(tài)。

2005011414:38:00

游標(biāo)的使用

提到游標(biāo)這個(gè)詞,人們想到的是在屏幕上一個(gè)閃動(dòng)的方框,用以指示用戶將要輸入字符的位

置。而在關(guān)系型數(shù)據(jù)庫(kù)的SQL語(yǔ)言中,游標(biāo)卻有另外的含義,它是存放結(jié)果集的數(shù)據(jù)對(duì)象。

為什么要用到游標(biāo)

在某些PowerBuilder應(yīng)用程序的開(kāi)發(fā)中,您可能根本用不到游標(biāo)這樣一個(gè)對(duì)象。因?yàn)樵?/p>

其它工具開(kāi)發(fā)中很多需用游標(biāo)實(shí)現(xiàn)的工作,在PowerBuilder中卻已有DataWindow來(lái)代勞

了。事實(shí)上,DataWindow不僅可以替代游標(biāo)進(jìn)行從后臺(tái)數(shù)據(jù)庫(kù)查詢多條記錄的復(fù)雜操作,而

且還遠(yuǎn)不止這些。但是同DataWindow和DataStore相比,游標(biāo)也有其自身的優(yōu)點(diǎn),比如系統(tǒng)

資源占用少,操作靈活,可根據(jù)需要定義變量類型如全局、實(shí)例或局部類型和訪問(wèn)類型如私有

或公共等。

游標(biāo)的操作

使用游標(biāo)有四種基本的步驟:聲明游標(biāo)、打開(kāi)游標(biāo)、提取數(shù)據(jù)、關(guān)閉游標(biāo)。

聲明游標(biāo)

象使用其它類型的變量一樣,使用一個(gè)游標(biāo)之前,首先應(yīng)當(dāng)聲明它。游標(biāo)的聲明包括兩個(gè)

部分:游標(biāo)的名稱;這個(gè)游標(biāo)所用到的SQL語(yǔ)句。如要聲明一個(gè)叫作CustomerCursor的游標(biāo)

用以查詢地址在北京的客戶的姓名、帳號(hào)及其余額,您可以編寫(xiě)如下代碼:

DECLARECustomerCursorCURSORFORSELECTacct_no,name,balanceFROMcustomer

WHEREprovince="北京";在游標(biāo)的聲明中有一點(diǎn)值得注意的是,如同其它變量的聲明一樣,

聲明游標(biāo)的這一段代碼行是不執(zhí)行的,您不能將debug時(shí)的斷點(diǎn)設(shè)在這一代碼行上,也不能用

IF...ENDIF語(yǔ)句來(lái)聲明兩個(gè)同名的游標(biāo),如下列的代碼就是錯(cuò)誤的。IFIs_prov="北京

"THENDECLARECustomerCursorCURSORFORSELECTacct_no,name,balance

FROMcustomerWHEREprovince=":|匕京";ELSE

DECLARECustomerCursorCURSORFORSELECTacct_no,name,balanceFROMcustomer

WHEREprovince〈〉"北京";ENDIF

打開(kāi)游標(biāo)

聲明了游標(biāo)后在作其它操作之前,必須打開(kāi)它。打開(kāi)游標(biāo)是執(zhí)行與其相關(guān)的一段SQL語(yǔ)

句,例如打開(kāi)上例聲明的一個(gè)游標(biāo),我們只需鍵入:OPENCustomerCursor;由于打開(kāi)游

標(biāo)是對(duì)數(shù)據(jù)庫(kù)進(jìn)行一些SQLSELECT的操作,它將耗費(fèi)一段時(shí)間,主要取決于您使用的系統(tǒng)性能

和這條語(yǔ)句的復(fù)雜程度。如果執(zhí)行的時(shí)間較長(zhǎng),可以考慮將屏幕上顯示的鼠標(biāo)改為

hourglasso提取數(shù)據(jù)當(dāng)用OPEN語(yǔ)句打開(kāi)了游標(biāo)并在數(shù)據(jù)庫(kù)中執(zhí)行了查詢后,您不

能立即利用在查詢結(jié)果集中的數(shù)據(jù)、您必須用FETCH語(yǔ)句來(lái)取得數(shù)據(jù)。,條FETCH語(yǔ)句一

次可以將一條記錄放入程序員指定的變量中。事實(shí)上,FETCH語(yǔ)句是游標(biāo)使用的核心。在

DataWindow和DataStore中,執(zhí)行了Retrieve。函數(shù)以后,查詢的所有結(jié)果全部可以得到;而使

用游標(biāo),我們只能逐條記錄地得到查詢結(jié)果。已經(jīng)聲明并打開(kāi)??個(gè)游標(biāo)后,我們就可以將

數(shù)據(jù)放入任意的變量中。在FETCH語(yǔ)句中您可以指定游標(biāo)的名稱和目標(biāo)變量的名稱。如下

例:FETCHCustmerCursorINTIs_acct_no,:ls_name,:ll_balance;從語(yǔ)法上

講,上面所述的就是一條合法的取數(shù)據(jù)的語(yǔ)句,但是?般我們使用游標(biāo)卻還應(yīng)當(dāng)包括其它的部

分。正如我們前面所談到的,游標(biāo)只能一次從后臺(tái)數(shù)據(jù)庫(kù)中取一條記錄,而在多數(shù)情況下,我

們所想要作的是在數(shù)據(jù)庫(kù)中從第一條記錄開(kāi)始提取,一直到結(jié)束。所以我們一般要將游標(biāo)提

取數(shù)據(jù)的語(yǔ)句放在一個(gè)循環(huán)體內(nèi),直至將結(jié)果集中的全部數(shù)據(jù)提取后,跳出循環(huán)圈。通過(guò)檢測(cè)

SQLCA.SQLCODE的值,可以得知最后一條FETCH語(yǔ)句是否成功。一般,當(dāng)SQLCODE值為0時(shí)

表明一切正常,100表示L1經(jīng)取到了結(jié)果集的末尾,而其它值均表明操作出了問(wèn)題,這樣我們可

以編寫(xiě)以下的代碼:lb_continue=Truell_total=0DOWHILEIb_continue

FETCHCustomerCursorINTIs_acct_no,:ls_name,:ll_balance;

lfsqlca.sqlcode=OThenll_total+=ll_balanceElselb_continue=FalseEndlf

LOOP循環(huán)體的結(jié)構(gòu)有多種,這里提到的是最常見(jiàn)的一種。也有的程序員喜愛(ài)將一條

FETCH語(yǔ)句放在循環(huán)體的前面,循環(huán)體內(nèi)再放置另外一條FETCH語(yǔ)句,并檢測(cè)SQLCA.SQLCODE

是否為100?但是這樣做,維護(hù)時(shí)需同時(shí)修改兩條FETCH語(yǔ)句,稍麻煩了些。

關(guān)閉游標(biāo)

在游標(biāo)操作的最后請(qǐng)不要忘記關(guān)閉游標(biāo),這是一個(gè)好的編程習(xí)慣,以使系統(tǒng)釋放游標(biāo)占用

的資源。關(guān)閉游標(biāo)的語(yǔ)句很簡(jiǎn)單:CLOSECustomerCursor;

使用Where子句子

我們可以動(dòng)態(tài)地定義游標(biāo)中的Where子句的參數(shù),例如在本例中我們是直接定義了查詢

省份是北京的記錄,但也許在應(yīng)用中我們要使用一個(gè)下拉式列表框,由用戶來(lái)選擇要查詢的省

份,我們?cè)撛鯓幼瞿??我們?cè)谇懊嬖?jīng)提到過(guò),DECLARE語(yǔ)句的作用只是定義一個(gè)游標(biāo),在

OPEN語(yǔ)句中這個(gè)游標(biāo)才會(huì)真正地被執(zhí)行。了解了這些,我們就可以很方便地實(shí)現(xiàn)這樣的功

能,在DECLARE的Where子句中加入變量作參數(shù),如下所示:

DECLARECustomerCursorCURSORFORSELCECTacct_no,name,balanceFROMcustomer

WHEREprovince=:ls_province;〃定義ls_province的值OPENCustomerCursor;

游標(biāo)的類型

同其它變量一樣,我們也可以定義游標(biāo)的訪問(wèn)類型:全局、共享、實(shí)例或局部,游標(biāo)變量

的命名規(guī)范建議也同其它變量一樣。

游標(biāo)的高級(jí)技巧

盡管目前基于SQL語(yǔ)句的后臺(tái)數(shù)據(jù)庫(kù)所支持的語(yǔ)言都大致相當(dāng),但對(duì)游標(biāo)的支持卻有著

一些差異,例如對(duì)滾動(dòng)游標(biāo)支持。所謂滾動(dòng)游標(biāo),就是程序員可以指定游標(biāo)向前后任意一個(gè)方

向滾動(dòng)。如在Informix中,您甚至還可以將游標(biāo)滾向結(jié)果集開(kāi)頭或末尾,使用的語(yǔ)句分別是

FETCHFIRST,FETCHLAST.FETCHPRIOR和FETCHNEXT。當(dāng)程序員用FETCH語(yǔ)句,其缺省是指

FETCHNEXT,由于滾動(dòng)是在數(shù)據(jù)庫(kù)后臺(tái)實(shí)現(xiàn)的,所以滾動(dòng)游標(biāo)為用戶編程提供了極大的方

便。對(duì)游標(biāo)支持的另一個(gè)不同是可修改游標(biāo)。上述游標(biāo)的使用都是指只讀游標(biāo),而象

Oracle.Sybase等數(shù)據(jù)庫(kù)卻另外支持可作修改的游標(biāo)。使用這樣的數(shù)據(jù)庫(kù),您可以修改或刪

除當(dāng)前游標(biāo)所在的行。例如修改當(dāng)前游標(biāo)所在行的用戶的余額,我們可以如下操作:

UPDATEcustomerSETbalance=1000WHERECURRENTofcustomerCursor;刪除當(dāng)前行

的操作如下:DELETEFROMCustomerWHERECURRENTOFCustomerCursor;但是如果

您當(dāng)前使用的數(shù)據(jù)庫(kù)是Sybase,您需要修改數(shù)據(jù)庫(kù)的參數(shù),將游標(biāo)可修改的值定為1,才能執(zhí)行

上述操作。這一賦值在連接數(shù)據(jù)庫(kù)的前后進(jìn)行均可。SQLCA.DBParm="Cursorllpdate=l"

另外一個(gè)內(nèi)容是動(dòng)態(tài)游標(biāo),也就是說(shuō)您可以運(yùn)行過(guò)程中動(dòng)態(tài)地形成游標(biāo)的SELECT語(yǔ)句。這

同在PowerBuilder中動(dòng)態(tài)地使用嵌入式SQL一樣,需要用到DynamicStagingArea等數(shù)據(jù)類型,

這已超出了本節(jié)的范圍。

2005011414:38:00

資源管理

內(nèi)存漏洞

我們?cè)谏掀诘摹额A(yù)裝入對(duì)象》一文中提到了關(guān)于內(nèi)存漏洞(MemoryLeak)的問(wèn)題。內(nèi)存漏

洞是程序員和用戶都很關(guān)心的問(wèn)題。一個(gè)對(duì)象被裝入并且分配了內(nèi)存,而在對(duì)象被關(guān)閉卻

沒(méi)有釋放分配的內(nèi)存,這時(shí)一個(gè)內(nèi)存漏洞就產(chǎn)生了。在開(kāi)發(fā)工具中也會(huì)有內(nèi)存漏洞,這是

我們無(wú)法控制的,但是我們必須注意我們自己的代碼所造成的內(nèi)存漏洞。最有可能造成內(nèi)

存漏洞的是使用CREATE語(yǔ)句創(chuàng)建一個(gè)對(duì)象后沒(méi)有對(duì)應(yīng)的DESTROY語(yǔ)句消除。無(wú)論何時(shí),

您用CREATE函數(shù)創(chuàng)建了一個(gè)對(duì)象,您就必須負(fù)責(zé)在該對(duì)象執(zhí)行完成之后釋放分配的內(nèi)存。

例:我創(chuàng)建了我自己的一個(gè)transaction對(duì)象:

TransactionMy_Transaction

My_transaction=CREATETransaction

當(dāng)我用完這個(gè)對(duì)象后,我應(yīng)該清除該對(duì)象:

DESTROYMyTransaction

(注:SQLCA是由您的應(yīng)用自動(dòng)創(chuàng)建同時(shí)也自動(dòng)關(guān)閉。)內(nèi)存漏洞的出現(xiàn)經(jīng)常是與開(kāi)發(fā)者

使用了非可視化用戶對(duì)象有關(guān)。因?yàn)檫@種對(duì)象只能用CREATE語(yǔ)句創(chuàng)建它的一個(gè)實(shí)例,因此

如不對(duì)其使用DESTROY語(yǔ)句消除,則必然導(dǎo)致錯(cuò)誤。另外一個(gè)有關(guān)的是用OpenUserObject

或OpenUserObjectWithParm函數(shù)創(chuàng)建的動(dòng)態(tài)用戶對(duì)象,這些對(duì)象同樣要求您在結(jié)束使用它

們時(shí)用相應(yīng)的ClosellserObject函數(shù)。我們知道,PowerBuilder能夠自動(dòng)清除放在一個(gè)窗口

中的常規(guī)對(duì)象,但它為什么不能在應(yīng)用結(jié)束時(shí)自動(dòng)清除用戶自己創(chuàng)建的對(duì)象呢?因?yàn)?/p>

PowerBuilder僅能清除控件列表中的對(duì)象,而且只有一個(gè)對(duì)象(如窗口)及其表面的那些

對(duì)象才會(huì)列在控件列表當(dāng)中(包括不可見(jiàn)的對(duì)象)。而動(dòng)態(tài)的用戶對(duì)象和非可視化對(duì)象,

與PowerBuilder全局對(duì)象的實(shí)例(transactions、error、message等等)一樣,是在對(duì)象的

控制列表已經(jīng)創(chuàng)建后加到對(duì)象上的。關(guān)閉父對(duì)象時(shí),系統(tǒng)并不知道要清除這些動(dòng)態(tài)加入的

對(duì)象。如果您沒(méi)有手工消除它們,它們將?直保持打開(kāi)狀態(tài),并常駐在內(nèi)存中,直到使用

工具來(lái)清除,或者關(guān)閉Windows系統(tǒng)。使用象Windows3.1ResourceKit中提供的內(nèi)存資源

監(jiān)控器這樣的工具,能使您在測(cè)試過(guò)程中檢查資源以確定資源按照預(yù)想的那樣被釋放。

內(nèi)存管理

在Windows3.x平臺(tái)上,開(kāi)發(fā)人員編譯時(shí)會(huì)遇到這樣的問(wèn)題:機(jī)器里有32M內(nèi)存,而且只

有兩個(gè)應(yīng)用在運(yùn)行,可是PowerBuilder■卻總是提示內(nèi)存不足(OutofMemory)。而用戶在

使用某應(yīng)用軟件時(shí),也會(huì)同樣出現(xiàn)內(nèi)存不足的問(wèn)題,于是用戶只得關(guān)閉其它的應(yīng)用,直到

發(fā)現(xiàn)關(guān)閉了某一程序釋放了足夠的內(nèi)存空間可供PowerBuilder運(yùn)行起來(lái)為止。于是用戶開(kāi)

始抱怨開(kāi)發(fā)者,而開(kāi)發(fā)者開(kāi)始抱怨PowerBuilder。其實(shí)在多數(shù)情況下,他們都不應(yīng)該受責(zé)

備,問(wèn)題的根源出在W

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論