資料視窗對象非常強大的原因之一就是能夠很容易地修改資料庫。當使用者修改了資料視窗中的資料,插入了新的資料行或者刪除了資料行以後,只要調用update()函數就可以將修改了的資料儲存到資料庫中。但是,這需要一個前提,就是必須設定資料視窗的修改屬性。
資料視窗要修改資料表,首先清楚資料視窗只能修改一個資料表。當資料視窗的資料來源於不止一個資料表時,可以用指令碼控制資料視窗的修改屬性來對資料表逐個進行修改,這種技術在後面有關章節介紹。下面介紹一次修改一個資料表的設定方法。
當資料視窗是用來接受使用者的手工錄入資料時,應該設定兩方面的屬性才能確保資料視窗能夠用來修改資料表。一個是修改資料視窗的修改屬性,另一個是使用者可以修改的欄位的相關屬性值。
首先介紹資料視窗的修改屬性的設定。在資料視窗畫板中,使用功能表項目Rows->Update Properties,彈出6-41所示的視窗。
資料視窗的所有修改屬性都集中在該視窗中。如果資料視窗對應的資料表中定義了主鍵或者惟一性索引,則資料視窗建立時預設的就是允許修改,並且正確設定了所有的修改屬性。否則就需要手工進行設定。前面介紹過,當增加、刪除或者重新選擇了欄位時,PowerBuilder將資料視窗的修改屬性置為不允許,這時也應該進行手工設定。
首先應該選中Allow Updates選項,只有選中該選項,才允許繼續進行其他屬性的設定。在Allow Updates右面的下拉式清單方塊叫做Table to Update,只能在該下拉式清單方塊中選擇一個,並且必須選擇一個資料表名,選中的表就是要被更新的表。
選中了Allow Updates屬性後,接下來就要指定在資料視窗中哪些列被更新。在Updateable Columns列表框中用按一下滑鼠被更新的欄位。當資料視窗中的欄位來自不止一個資料表時,這時一定要選擇同一個表中的欄位,因為一個資料視窗一次只能更新一個資料表。當資料視窗中增添了欄位時,新增添的欄位往往是不允許修改的,一定要在該列表框中選擇該欄位。
選擇了可以修改的欄位後,就應該在Unique Key Columns(s)列表框中選擇惟一標識一行的列。如果在定義資料表時定義了主鍵,單擊右面的Primary Key按鈕可以在該列表框中選中主鍵。
Where Clause for Update/Delete組框中包含了三個選項,用來配置如何在Update和Delete SQL語句中構造where字句的。這三個選項為資料庫加鎖提供了三種不同的選擇。當某行被選中時,使用者可以通過DataWindow對象來提供完整性保護,可以防止其他使用者檢索該行。這三個選項是:Key Columns、Key and Updateable Columns和Key and Modified Columns。下面分別詳細介紹。
1.Key Columns
當開發單使用者應用程式或者使用者都以加鎖方式訪問資料庫時可以選中該選項。該選項表示資料視窗只使用在Unique Key Column(s)列表框中指定的惟一列進行資料更新。使用這種方式來修改資料庫,並發性很高,不同的使用者都可以並發地訪問資料庫,但是資料的完整性卻非常差。因此要保證資料完整性,只有在單使用者應用程式或者加鎖訪問方式下才使用這種修改方式。
例如,在add_book(通訊錄)資料表中定義了5個欄位,id為主鍵,name、address、telephone、ICQ四個欄位為可修改欄位,某資料視窗包含這5個欄位並且使用Key Columns更新資料庫。有如下一條資料:
id:230602710327574
name:朱義
address:勝利油田
telephone:945-8557021
ICQ:39661314
假設甲使用者修改了這條資料,將name改為“郭寶利”,資料視窗產生如下的UPDATE語句:
update add_book
set name = "郭寶利"
where id = "230602710327574";
其中的where字句中只包含在Unique Key Columns中指定的欄位id,用該欄位來確定要修改資料庫中哪行資料。該update語句將成功執行。如果乙使用者要將address欄位修改為“冀東油田”,甲、乙使用者同時並發修改id為230602710327574的資料,都會修改成功,但會產生如下的資料:
id:230602710327574
name:郭寶利
address:冀東油田
telephone:945-8557021
ICQ:39661314
兩個人同時修改了一條記錄,本來地址是勝利油田的郭寶利卻成了冀東油田的了。
2.Key and Updateable Columns
這種修改方式是預設的修改方式,它用主鍵列和可以修改的列來建立where子句,具有很高的資料完整性,但是並發性卻不是太好。推薦使用這種修改方式。
像上面例子一樣,如果甲使用者做修改操作,儲存資料時將產生如下的SQL語句:
update add_book
set name = "郭寶利"
where id = "230602710327574"
and name = "朱義"
and address = "勝利油田"
and telephone = "945-8557021"
and ICQ = "39661314";
該SQL語句中的where子句包含了主鍵id和所有的可修改欄位。如果乙使用者是在甲儲存修改了的資料之前檢索的資料,當乙使用者要將address修改為“冀東油田”時,產生如下的SQL語句:
update add_book
set address = "冀東油田"
where id = "230602710327574"
and name = "朱義"
and address = "勝利油田"
and telephone = "945-8557021"
and ICQ = "39661314";
此時,由於甲使用者已經修改了資料,將name改成了“郭寶利”,所以乙使用者的where子句中指定的資料在資料庫中已經不存在了,乙的修改不成功,從而保證了資料的完整性。
3.Key and Modified Columns
該方法是上面兩種方法的折衷,當不同的使用者並發修改同一行資料的不同欄位時,都能成功修改,所以它的並發性有了一定的限制,資料的完整性比第一種修改方式有所提高。這種修改方式使用主鍵和資料發生了變化的列來產生where子句。同樣,在上面的例子中,甲使用者要將“朱義”修改為“郭寶利”會產生如下的SQL語句:
update add_book
set name = "郭寶利"
where id = "230602710327574"
and name = "朱義";
這時的where子句中只包含主鍵id和要修改的欄位name。如果此時乙使用者並發修改資料,要將id為“230602710327574”的使用者的address修改為“冀東油田”,乙使用者也會成功修改。
4.時間標記
如果資料庫管理系統支援時間標記,則可以在DataWindow對象的結果集中包含時間標記來獲得最大的資料完整性。PowerBuilder將自動為更新和刪除操作的where子句加上時間標記,而不顯示在可更新列的列表中。Oracle、SQL Server完全在伺服器上處理時間標記,在DataWindow中不要求有額外的工作。
5.Key Modification
該組框用來指定當使用者修改了主鍵時,資料視窗如何來更新資料表中的主鍵欄位。有兩種選擇,Use Delete then Insert和Use Update。
第一個選項是先刪除原有主索引值,然後再使用新的主索引值插入一個完整的行。使用這種更新主鍵的方式可以減少組織資料的工作量,但在資料庫中各個資料表之間存在父子制約關係,並且依賴該主鍵的外部鍵被指定為串聯刪除時,操作就不會成功的。因為串聯刪除方式要求當依賴主鍵的外部鍵有資料時就不能刪除主鍵。
當DBMS允許更新主鍵列時,可以使用該選項,該選項直接修改主索引值,所以防止了串聯刪除帶來的操作不成功的問題。
6.Identify Column
該下拉式清單方塊用於為下拉式清單方塊中所指定的列(通常是主鍵列)產生序號,若且唯若DBMS支援序號產生時該作用才有效。
當正確進行了上述所有操作後,單擊OK按鈕即完成了修改屬性的設定。如果資料視窗允許手工錄入資料,接下來就應該設定可修改欄位的相關屬性了。主要包括如下屬性:
l 欄位的Tab Order值。
l 欄位的Protect屬性。
l 欄位的DisplayOnly屬性。
l 欄位的Visible屬性。
上述屬性前3個中任意一個都可以讓使用者無法修改欄位中的資料;最後一個屬性決定欄位是否可見,不可見的欄位不管其他屬性如何設定,使用者都無法修改欄位中的資料。
首先介紹如何設定欄位的Tab Order值。使用功能表項目Format->Tab Order可以在Design視窗顯示各欄位的當前Tab Order值,用按一下滑鼠要修改Tab Order值的欄位,然後手工將Tab Order值改為非0即可。在設定Tab Order時要注意三點:
(1)使用者可以手工修改的欄位,其Tab Order值不能為0。
(2)在資料視窗修改屬性中,不允許修改的欄位其Tab Order值應該為0,或者其Display Only屬性應該選中。
(3)Tab Order取值決定欄位獲得焦點的順序。在資料視窗中使用Tab按鈕在欄位間切換時,Tab Order取值小的首先獲得焦點,最大的最後獲得焦點。
欄位的Protect屬性設定欄位是否被保護。如果該屬性設定為1,則不允許使用者修改欄位中的資料,即使Tab Order設定為非零。欄位的DisplayOnly屬性決定欄位中的內容是否只用來顯示,當屬性設定為1或者True時,欄位中的資料不允許使用者修改,不管其他幾個屬性是如何設定的。Protect屬性只能使用運算式,選中欄位後在屬性視窗General屬性中單擊右側的紅色小按鈕(如果已經有運算式,則按鈕為綠色),進入到運算式輸入對話方塊,輸入該屬性的運算式即可。比如,設定使用者不能修改欄位id原來的資料,可以輸入如下的運算式:
if(isRowNew(),0,1)
欄位的Display屬性在屬性視窗Edit中,選中該選項表示該欄位中的資料只用來顯示,不允許使用者修改。該屬性不能使用運算式。在PB中,編輯類型的控制項都有該屬性,並且屬性的作用也是相同的。
當欄位的Tab Order值為0時,肯定不能獲得焦點,但是非0時也不一定能獲得焦點,還得看欄位的Protect屬性是否設定為1;當欄位的Tab Order值不為0,Protect屬性不為1並且欄位的Visible屬性為True時,肯定可以獲得焦點。DisplayOnly屬性和焦點是否能夠獲得無關。