**Blob類型的資料用來儲存象大文本和圖象之類的資料,這種資料長度很大、幾乎沒有限制。而在PB中,沒有長度限制的對象僅此一種類型,是以它有特殊的處理方法。
Blob類型的資料沒有邊界限制,可以儲存一些普通類型的字段不能儲存的資訊。
以下情況下考慮使用Blob類型的字段:
a)要儲存OLE對象(如圖形、聲音等)時;
b)将大型的二進制對象存入資料庫中時:
c)當文本對象過大,以至于一般的字元串函數無法對其操作時;
d)資料庫中有PB不能支援的資料類型時。
普通類型的字段使用資料視窗,通過調用函數Update和Commit事務管理語句就可以保
存資料了。但Blod類型的資料非常龐大,是以這種類型字段的更新不能像普通的字段,隻能用其特有的語句進行更新。Updateblob的文法格式如下:
Updateblob 表名 set Blob類型字段名 =:Blob類型變量 where 子句;
上面的文法和Update文法類似,除了使用關鍵字Updateblob外,其他和Update文法都相同。
普通類型的字段顯示是通過資料視窗,調用Retrieve即可。但是,由于Blob類型的資料非常龐大,用戶端的主緩存區開辟多麼大的空間都不合适。PowerBuilder的解決方法是,不允許在資料視窗中放置Blob類型的字段,而是提供專用的提取Blob類型資料的語句。該語句文法如下:
Selectblob Blob類型的列名 into :Blob類型變量 from 表名 where 子句;
上面的文法同Select語句類似,隻是使用了關鍵字Selectblob。另外,Selectblob和
Updateblob中的where子句都必須隻能傳回一行資料,也就是說,一次隻能處理一個Blob類
型的資料。
關于Blob類型的處理隻能通過上面的兩個語句來進行。不像普通類型的字段那樣資料
的更新可以通過Insert語句實作。是以,在使用Updateblob語句之前,符合where子句條件
的資料已經存在了,并且隻存在一條資料。是以,如果想把大文本或者圖像等Blob類型的資料寫入資料庫,必須首先插入這條記錄的其他部分,然後再通過修改記錄的方式将Blob類型資料寫入。
*因為大文本對象特别龐大,當使用Updateblob時應該将事務對象的Autocommit設定為True,這很容易了解。因為這麼龐大的資料量要求一次送出,顯然多大的緩沖記憶體都不合适,隻能讓事務對象在合适的時候自動送出了。
*DBMS中的資料類型可以在PowerScript中與Blob資料類型相對應,如在Oracle對應為longraw,raw。在MS SQL Server中對應為image,text。在DB2/2中對應為N/A。
**執行個體
假設在一個應用系統中,進行合同管理時要儲存合同的原樣,以便以後的責任審查。用圖像掃描裝置将合同掃描成圖形檔案,以圖像方式儲存到資料庫中,這就涉及了Blob類型的處理該軟體實作時,最重要的首先是圖像的儲存,然後是圖像的顯示問題。
假設在視窗w_contract上左邊是dw_1,在dw_1上顯示合同中的相關資料,使用者選擇不同的資料行時,對應的合同文本顯示在picture控件p_1上;使用者點選“錄入合同文本”按鈕時打開w_htwb_input視窗選擇合同文本對應的圖形檔案名稱,傳回後根據該檔案大小進行相關處理,并儲存到資料庫中。
資料視窗dw_1從contract資料表中提取資料,該資料視窗中不包括Blob類型的字段htwb,其主鍵為合同編号(htbh)。當資料視窗的行焦點改變時讀取該行中的合同文本,并顯示在picture控件p_1上。在資料視窗的rowfocuschanged事件中編寫腳本如下:
blob lbb_pic //用來儲存圖檔
string ls_htbh //用來儲存合同編号
if currentrow <= 0 then return
this.selectrow(0,false)
this.selectrow(currentrow,true)
setpointer(hourglass!)
ls_htbh = trim(this.getitemstring(currentrow,"htbh"))
if len(ls_htbh) > 0 then
selectblob htwb into :lbb_pic from contract where htbh = :ls_htbh;
//讀取圖象
if len(lbb_pic) > 0 then
p_1.setpicture(lbb_pic)
else
beep(2)
messagebox("提示",ls_htbh + "号合同沒有錄入合同文本!",information!)
end if
enf if
setpointer(arrow!)
在“錄入合同文本”按鈕的clicked事件中編寫腳本,彈出另外一個response類型的視窗w_htwb_input,讓使用者在該視窗中選擇要錄入的合同文本的圖形檔案,傳回後讀取該檔案并儲存到資料庫中。因為fileread函數一次讀取的檔案不能大于32KB,如果大于32KB就隻能以32KB為機關分多次讀取。腳本如下:
string ls_pic,ls_htbh
integer li_i,li_fileptr,li_loops
long ll_filelen,ll_bytes_read,ll_new_pos
blob lbb_read,lbb_total
if dw_1.modifiedcount() <> 0 then //確定其他資料已經送出
beep(2)
messagebox("提示","請先儲存再錄入合同文本!",information!)
return
else //如果沒有修改過,則判斷是否有合同号(如果沒有合同号則肯定不能送出)
ls_htbh = trim(dw_1.getitemstring(dw_1.getrow(),"htbh"))
if len(ls_htbh) <= 0 then
beep(2)
messagebox("提示","必須首先錄入合同好,才能錄入合同文本!",stopsign!)
return
end if
end if
open(w_htbh_input) //打開合同文本錄入視窗
ls_pic = message.stringparm
setpointer(hourglass!)
ll_filelen = filelength(ls_pic) //擷取檔案的長度
li_fileptr = fileopen(ls_pic,streammode!,read!,lockread!)
if li_fileptr <> -1 then
beep(2)
messagebox("錯誤","圖形檔案打開錯誤!",information!)
return
end if
if_filelen > 32766 then
li_loops = (li_filelen - 1)/32766 + 1
else
li_loops = 1
end if
for li_i = 1 to li_loops
ll_bytes_read = fileread(li_fileptr,lbb_read)
lbb_total = lbb_total + lbb_read
ll_new_pos = ll_new_pos + ll_bytes_read
fileseek(li_fileptr,ll_new_pos,frombeginning!)
next
fileclose(li_fileptr)
setpicture(p_1,lbb_total)
sqlca.autocommit = true
updateblob contract set htwb = :lbb_total where htbh = :htbh_str;
sqlca.autocommit = false
if sqlca.sqlcode = -1 then
messagebox("失敗",sqlca.sqlerrtext)
elseif sqlca.sqlcode = 100 then
messagebox("失敗",ls_htbh + "号合同沒有找到!",information!)
end if
在視窗w_htwb_input視窗中,提供讓使用者選擇檔案名稱的功能。這部分的腳本比較簡單
并且也和Blob的處理關系不大,不再贅述。