摘要:PowerBuilder環(huán)境下默認(rèn)只能更新一個(gè)數(shù)據(jù)表,如果數(shù)據(jù)窗口對(duì)象對(duì)應(yīng)多個(gè)表,則PowerBuilder定義每個(gè)表的所有列都不能夠更新,并且所有列的Tab值都為0,使用戶不能修改數(shù)據(jù)。本文提供了一種在PowerBuilder環(huán)境下多表同步更新的方案。
關(guān)鍵詞:PowerBuilder 多表更新 數(shù)據(jù)窗口對(duì)象
0 引言
當(dāng)一個(gè)數(shù)據(jù)窗口被創(chuàng)建時(shí),PowerBuilder會(huì)自動(dòng)地設(shè)置它的更新屬性為可更新或者不可更新,這取決于兩個(gè)標(biāo)準(zhǔn):一個(gè)是看這個(gè)數(shù)據(jù)窗口對(duì)象是否對(duì)應(yīng)一個(gè)表還是對(duì)應(yīng)多個(gè)表;另外一個(gè)是看表的主鍵是否被數(shù)據(jù)窗口對(duì)象選中。因?yàn)閿?shù)據(jù)窗口對(duì)象只能更新一個(gè)表,所以,如果數(shù)據(jù)窗口對(duì)象只對(duì)應(yīng)一個(gè)表,那么PowerBuilder就自動(dòng)定義這個(gè)表中的所有列都是可更新的,并且此時(shí)所有列的Tab值均不為0,以便用戶能夠修改數(shù)據(jù)。可是,如果數(shù)據(jù)窗口對(duì)象對(duì)應(yīng)多個(gè)表,則PowerBuilder定義每個(gè)表的所有列都不能夠更新,并且所有列的Tab值都為0,使用戶不能修改數(shù)據(jù)。
當(dāng)用戶的數(shù)據(jù)窗口對(duì)象對(duì)應(yīng)多個(gè)表時(shí),如果PowerBuilder設(shè)置的更新屬性不符合用戶的要求,也就是說(shuō)用戶想這個(gè)數(shù)據(jù)窗口對(duì)象能夠更新數(shù)據(jù)庫(kù),那么用戶必須手工修改數(shù)據(jù)窗口對(duì)象的更新屬性。
1 設(shè)置數(shù)據(jù)對(duì)象的更新屬性
要定義一個(gè)數(shù)據(jù)窗口對(duì)象的更新屬性,可以選擇Rows|
Update Properties菜單項(xiàng),將彈出Specify Update Properties對(duì)話框,如圖1所示。
對(duì)話框中各更新屬性的含義如下:
1.1 Allow Updates(允許更新)復(fù)選框:用于指定該數(shù)據(jù)窗口是否具有可更新能力,選中此復(fù)選框后,才可以設(shè)置其他屬性。
1.2 Table to Update(可更新的表)下拉列表框:每個(gè)數(shù)據(jù)窗口在每一時(shí)刻只可更新一個(gè)表的數(shù)據(jù)。此下拉列表框就是用來(lái)指定當(dāng)前數(shù)據(jù)窗口可更新的表。
1.3 Unique Key Columns(鍵列)列表框:鍵列用來(lái)標(biāo)識(shí)表中將被更新的記錄的一列或多列,PowerBuilder在生成數(shù)據(jù)庫(kù)的更新語(yǔ)句時(shí),將用這些鍵列構(gòu)成WHERE子句。鍵列可以是表的主鍵,也可以不是。
1.4 Updateable Columns(可更新列)列表框:用來(lái)設(shè)置當(dāng)前數(shù)據(jù)窗口對(duì)象當(dāng)前可更新的表中哪些字段具有可更新能力。如果某一列未被指定為可更新列,那么,即使在數(shù)據(jù)窗口中修改了此列的數(shù)據(jù),它也不會(huì)向數(shù)據(jù)庫(kù)提交。
1.5 Where Clause for Update/Delete(用于更新的WHERE子句)組框:該組框內(nèi)的三個(gè)單選按鈕提供了三種構(gòu)造Where 子句的方法。不同的Where子句可以提供不同級(jí)別的數(shù)據(jù)完整性保護(hù)。①Key Columns單選按鈕:是讓W(xué)here子句中只包括主鍵列。這些主鍵列在窗口的右下角的Unique Key Columns的列表框中指定。在這種情況下,PowerBuilder只把原來(lái)檢索出來(lái)的關(guān)鍵列的數(shù)值與數(shù)據(jù)庫(kù)中的關(guān)鍵列的數(shù)值進(jìn)行比較,如果這些值匹配,則能夠更新數(shù)據(jù)庫(kù)。②Key and Updateable Columns單選按鈕:是讓W(xué)here子句中只包括主鍵列和可更新列。主鍵列在Unique Key Columns的列表框中,所有可更新列在Updateable Columns列表框中選擇。在這種情況下,PowerBuilder把原來(lái)檢索出來(lái)的關(guān)鍵列和可更新列的數(shù)值同數(shù)據(jù)庫(kù)中這些列的值進(jìn)行比較,如果匹配,則能夠更新數(shù)據(jù)庫(kù)。③Key and Modified Columns單選按鈕:是讓W(xué)here子句中包括主鍵列和所有已經(jīng)做過(guò)修改的列,這種情況下,PowerBuilder把原來(lái)檢索出來(lái)的關(guān)鍵列和已經(jīng)更新的列的數(shù)值同數(shù)據(jù)庫(kù)中這些列的數(shù)值比較,如果自上次檢索以后,這些列中任意一列的值與數(shù)據(jù)庫(kù)中的值不匹配,則不能更新數(shù)據(jù)庫(kù)。
1.6 Key Modification(鍵列的更新)組框:該組框內(nèi)的兩個(gè)單選按鈕是用來(lái)決定當(dāng)關(guān)鍵字被更新時(shí)的更新方式。有兩種方式:Use Delete then Insert單選按鈕,先使用Delete語(yǔ)句刪除,然后再用Insert語(yǔ)句插入;Use Update單選按鈕是直接使用Update語(yǔ)句對(duì)主鍵列進(jìn)行更新。
①缺省設(shè)置是Use Delete then Insert,表示當(dāng)一個(gè)主鍵列被修改時(shí)先刪除這一條數(shù)據(jù),然后再用Insert語(yǔ)句插入數(shù)據(jù)到數(shù)據(jù)庫(kù)中。不過(guò)值得注意的是,如果有其他表的數(shù)據(jù)依賴于這個(gè)表的主鍵時(shí),例如一個(gè)公司的“學(xué)生信息表”是依賴“班級(jí)表”中的“班級(jí)編號(hào)”這個(gè)主鍵列,那么在使用Use Delete then Insert時(shí),首先會(huì)刪除“班級(jí)表”中的一條數(shù)據(jù),而且也會(huì)刪除“學(xué)生信息表”中與“班級(jí)表”中有相同的班級(jí)編號(hào)的那條數(shù)據(jù),這樣就會(huì)造成數(shù)據(jù)庫(kù)中數(shù)據(jù)的丟失,所以,在使用這個(gè)方式時(shí)應(yīng)該根據(jù)具體的應(yīng)用和數(shù)據(jù)庫(kù)設(shè)計(jì)來(lái)選擇。②Identify Column(標(biāo)識(shí)列)下拉列表框。許多數(shù)據(jù)庫(kù)管理系統(tǒng)支持這樣一種列。當(dāng)向表中插入一條新記錄時(shí),此列的值由數(shù)據(jù)庫(kù)管理系統(tǒng)自動(dòng)指定,稱之為標(biāo)識(shí)列。不同的數(shù)據(jù)庫(kù)管理系統(tǒng)支持的標(biāo)識(shí)列的類型也不同。例如,Adaptive Server Anywhere允許定義其值自動(dòng)增加的列。在Specify Update Properties對(duì)話框中可以指定一個(gè)標(biāo)識(shí)列。這樣,當(dāng)在數(shù)據(jù)窗口中新插入一列并提交后,PowerBuilder會(huì)自動(dòng)把此列的值帶回并顯示出來(lái)。否則,需要重新檢索才能看到此列的值。
2 多表更新解決方案
①創(chuàng)建數(shù)據(jù)窗口對(duì)象,選擇合適的數(shù)據(jù)源和顯示風(fēng)格,保證數(shù)據(jù)窗口具有更新能力。②選取多表中所需的數(shù)據(jù)項(xiàng)(各表的主鍵和非空列一定要包含進(jìn)去)。③修改所需數(shù)據(jù)項(xiàng)的Tab Order,保證其在數(shù)據(jù)窗口中是可修改的(TabOrder值不為0)。④選取菜單Rows|Update Properties,定義數(shù)據(jù)窗口的更新屬性(定義主表的列為可更新列)。⑤使用update(true,false)對(duì)主表進(jìn)行更新。⑥切換可更新的表(輔表)、主鍵、列,將主表的主鍵、列設(shè)為不可更新。⑦使用update()對(duì)輔表進(jìn)行更新。
3 實(shí)現(xiàn)數(shù)據(jù)同步更新
3.1 建庫(kù)建表。在一個(gè)數(shù)據(jù)窗口對(duì)象中實(shí)現(xiàn)對(duì)兩個(gè)表的數(shù)據(jù)更新主要是動(dòng)態(tài)修改數(shù)據(jù)窗口的Update屬性以及getitemstring()、setitem()函數(shù)的使用。以數(shù)據(jù)庫(kù)mydata.db中的數(shù)據(jù)表tabel1和table2為例,在庫(kù)中建表table1(班級(jí)表),表結(jié)構(gòu)如下:bjname(班級(jí)名稱)/char/20(主鍵)/不能為空,rs(人數(shù))/integer/不能為空,dy(導(dǎo)員)/char/8/允許為空,輸入記錄。建表table2(學(xué)生表),表結(jié)構(gòu)如下:xh(學(xué)號(hào))/char/6(主鍵)/不能為空,name(姓名)/char/8/不能為空,csrq(出生日期)/date/允許為空,bjname(班級(jí)名稱)/char/20/不能為空(外鍵),通過(guò)bjname與表table1建立鏈接。table1(班級(jí)表)為主表,table2(學(xué)生表)為輔表。即先輸入班級(jí)名稱,才能輸入該班級(jí)的學(xué)生,輸入記錄。
3.2 界面設(shè)計(jì)。設(shè)計(jì)多表更新窗口w_test,界面設(shè)計(jì)如圖2所示。
3.3 建立數(shù)據(jù)窗口對(duì)象。建立數(shù)據(jù)窗口對(duì)象d_update,風(fēng)格:Freeform,數(shù)據(jù)源:SQL Select,選擇數(shù)據(jù)表:table1、table2,選擇列xh,name,bjname(這三列來(lái)自table2),bjname,rs(這二列來(lái)自table1),單擊工具欄上的 鈕,修改各列的Tab Order值為10、20、30……依此類推,刪除table2_bjname列及該列的標(biāo)題,選取菜單Rows|Update Properties,按圖1所示設(shè)置各項(xiàng)更新屬性。設(shè)置數(shù)據(jù)窗口對(duì)象中所有標(biāo)題邊框?yàn)橥蛊?,所有列邊框?yàn)橄掳迹鶠樽髮?duì)齊。
3.4 關(guān)鍵代碼實(shí)現(xiàn)。在多表更新的操作中,除按3.3正確設(shè)置屬性外,還有一個(gè)關(guān)鍵環(huán)節(jié),就是代碼實(shí)現(xiàn)數(shù)據(jù)同步更新。圖2的“存盤”按鈕的Clicked事件的代碼為:
int n,row1
string bjm
n=dw_1.update(true,false)
if n>0 then
commit;
messagebox("提示","table1班級(jí)表存盤成功!")
else
rollback;
messagebox("提示","table1班級(jí)表存盤失??!")
end if
dw_1.object.datawindow.table.updatetable="table2" //切換更新數(shù)據(jù)表
dw_1.object.table2_xh.key="yes"http://設(shè)置可更新的主鍵
dw_1.object.table2_xh.update="yes"http://設(shè)置可更新字段
dw_1.object.table2_name.update="yes"
dw_1.object.table2_bjname.update="yes"
dw_1.object.table1_bjname.key="no"http://設(shè)置不可更新的主鍵
dw_1.object.table1_bjname.update="no"http://設(shè)置不可更新的字段
dw_1.object.table1_rs.update="no"
row1=dw_1.getrow()//獲取當(dāng)前行的行號(hào)
bjm=dw_1.getitemstring(row1,"table1_bjname")
dw_1.setitem(row1,"table2_bjname",bjm)
n=dw_1.update()
if n>0 then
commit;
messagebox("提示","table2學(xué)生表存盤成功!")
end if
4 結(jié)語(yǔ)
本文中數(shù)據(jù)源選擇SQL Select,每個(gè)數(shù)據(jù)列的名稱前都加了表名,刪除table2_bjname列,即刪除了table2表的bjname列,數(shù)據(jù)窗口中保留了table1表中的bjname列,使用getitemstring()函數(shù)取出輸入到table1的bjname值,用函數(shù)setitem()寫入到表table2中。
參考文獻(xiàn):
[1]柯建勛,蔡毅,鄧格林.PowerBuilder8.0基礎(chǔ)篇[M].北京:清華大學(xué)出版社,2002.
[2]柯建勛,張濤,邵亮.PowerBuilder8.0進(jìn)階篇[M].北京:清華大學(xué)出版社,2002.
[3]張偉聰.基于PowerBuilder的圖書(shū)館辦公自動(dòng)化系統(tǒng)設(shè)計(jì)[J].醫(yī)學(xué)信息,2006(09).
作者簡(jiǎn)介:
王超(1972-),女,遼寧朝陽(yáng)人,信息工程系副主任,副教授,研究方向:軟件開(kāi)發(fā)。